From 261508183c249dcec737448dde3aad7399f4668c Mon Sep 17 00:00:00 2001 From: Navya Sree Arugonda <67328292+Navya-arugonda@users.noreply.github.com> Date: Fri, 10 Oct 2025 12:24:31 -0500 Subject: [PATCH 001/174] fix(auth): export MISSING_PASSWORD in AuthErrorCodes (#9297) --- .changeset/metal-lies-compete.md | 6 ++++++ common/api-review/auth.api.md | 1 + docs-devsite/auth.md | 1 + packages/auth/src/core/errors.ts | 1 + 4 files changed, 9 insertions(+) create mode 100644 .changeset/metal-lies-compete.md diff --git a/.changeset/metal-lies-compete.md b/.changeset/metal-lies-compete.md new file mode 100644 index 0000000000..5a086a9e12 --- /dev/null +++ b/.changeset/metal-lies-compete.md @@ -0,0 +1,6 @@ +--- +'@firebase/auth': patch +'firebase': patch +--- + +Export MISSING_PASSWORD via AuthErrorCodes in @firebase/auth. diff --git a/common/api-review/auth.api.md b/common/api-review/auth.api.md index 0c9625a90e..4253aa36db 100644 --- a/common/api-review/auth.api.md +++ b/common/api-review/auth.api.md @@ -195,6 +195,7 @@ export const AuthErrorCodes: { readonly MISSING_MFA_INFO: "auth/missing-multi-factor-info"; readonly MISSING_MFA_SESSION: "auth/missing-multi-factor-session"; readonly MISSING_PHONE_NUMBER: "auth/missing-phone-number"; + readonly MISSING_PASSWORD: "auth/missing-password"; readonly MISSING_SESSION_INFO: "auth/missing-verification-id"; readonly MODULE_DESTROYED: "auth/app-deleted"; readonly NEED_CONFIRMATION: "auth/account-exists-with-different-credential"; diff --git a/docs-devsite/auth.md b/docs-devsite/auth.md index 1b3938ef4e..97c1205227 100644 --- a/docs-devsite/auth.md +++ b/docs-devsite/auth.md @@ -1914,6 +1914,7 @@ AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY: { readonly MISSING_MFA_INFO: "auth/missing-multi-factor-info"; readonly MISSING_MFA_SESSION: "auth/missing-multi-factor-session"; readonly MISSING_PHONE_NUMBER: "auth/missing-phone-number"; + readonly MISSING_PASSWORD: "auth/missing-password"; readonly MISSING_SESSION_INFO: "auth/missing-verification-id"; readonly MODULE_DESTROYED: "auth/app-deleted"; readonly NEED_CONFIRMATION: "auth/account-exists-with-different-credential"; diff --git a/packages/auth/src/core/errors.ts b/packages/auth/src/core/errors.ts index 0e7fb53059..12c7c87c2b 100644 --- a/packages/auth/src/core/errors.ts +++ b/packages/auth/src/core/errors.ts @@ -560,6 +560,7 @@ export const AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY = { MISSING_MFA_INFO: 'auth/missing-multi-factor-info', MISSING_MFA_SESSION: 'auth/missing-multi-factor-session', MISSING_PHONE_NUMBER: 'auth/missing-phone-number', + MISSING_PASSWORD: 'auth/missing-password', MISSING_SESSION_INFO: 'auth/missing-verification-id', MODULE_DESTROYED: 'auth/app-deleted', NEED_CONFIRMATION: 'auth/account-exists-with-different-credential', From c8263c471db4df1b0e23f0d2a11c69fd6b920e2e Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 16 Oct 2025 09:37:34 -0700 Subject: [PATCH 002/174] feat(ai): make generateContent methods return inferenceSource (#9315) --- .changeset/smooth-parrots-speak.md | 6 +++ common/api-review/ai.api.md | 11 +++++ .../ai.enhancedgeneratecontentresponse.md | 14 ++++++ docs-devsite/ai.md | 31 +++++++++++++ packages/ai/src/methods/generate-content.ts | 11 ++--- .../ai/src/requests/hybrid-helpers.test.ts | 28 ++++++++---- packages/ai/src/requests/hybrid-helpers.ts | 45 +++++++++++++++---- packages/ai/src/requests/response-helpers.ts | 7 ++- .../ai/src/requests/stream-reader.test.ts | 28 +++++++++++- packages/ai/src/requests/stream-reader.ts | 29 ++++++++---- packages/ai/src/types/enums.ts | 18 ++++++++ packages/ai/src/types/responses.ts | 7 +++ 12 files changed, 201 insertions(+), 34 deletions(-) create mode 100644 .changeset/smooth-parrots-speak.md diff --git a/.changeset/smooth-parrots-speak.md b/.changeset/smooth-parrots-speak.md new file mode 100644 index 0000000000..49a7b10c73 --- /dev/null +++ b/.changeset/smooth-parrots-speak.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +Add `inferenceSource` to the response from `generateContent` and `generateContentStream`. This property indicates whether on-device or in-cloud inference was used to generate the result. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index debea0a854..f3113e0ac2 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -256,6 +256,8 @@ export { Date_2 as Date } // @public export interface EnhancedGenerateContentResponse extends GenerateContentResponse { functionCalls: () => FunctionCall[] | undefined; + // @beta + inferenceSource?: InferenceSource; inlineDataParts: () => InlineDataPart[] | undefined; text: () => string; thoughtSummary: () => string | undefined; @@ -816,6 +818,15 @@ export const InferenceMode: { // @beta export type InferenceMode = (typeof InferenceMode)[keyof typeof InferenceMode]; +// @beta +export const InferenceSource: { + readonly ON_DEVICE: "on_device"; + readonly IN_CLOUD: "in_cloud"; +}; + +// @beta +export type InferenceSource = (typeof InferenceSource)[keyof typeof InferenceSource]; + // @public export interface InlineDataPart { // (undocumented) diff --git a/docs-devsite/ai.enhancedgeneratecontentresponse.md b/docs-devsite/ai.enhancedgeneratecontentresponse.md index 9e947add0c..609196d603 100644 --- a/docs-devsite/ai.enhancedgeneratecontentresponse.md +++ b/docs-devsite/ai.enhancedgeneratecontentresponse.md @@ -24,6 +24,7 @@ export interface EnhancedGenerateContentResponse extends GenerateContentResponse | Property | Type | Description | | --- | --- | --- | | [functionCalls](./ai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponsefunctioncalls) | () => [FunctionCall](./ai.functioncall.md#functioncall_interface)\[\] \| undefined | Aggregates and returns every [FunctionCall](./ai.functioncall.md#functioncall_interface) from the first candidate of [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | +| [inferenceSource](./ai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponseinferencesource) | [InferenceSource](./ai.md#inferencesource) | (Public Preview) Indicates whether inference happened on-device or in-cloud. | | [inlineDataParts](./ai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponseinlinedataparts) | () => [InlineDataPart](./ai.inlinedatapart.md#inlinedatapart_interface)\[\] \| undefined | Aggregates and returns every [InlineDataPart](./ai.inlinedatapart.md#inlinedatapart_interface) from the first candidate of [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | | [text](./ai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponsetext) | () => string | Returns the text string from the response, if available. Throws if the prompt or candidate was blocked. | | [thoughtSummary](./ai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponsethoughtsummary) | () => string \| undefined | Aggregates and returns every [TextPart](./ai.textpart.md#textpart_interface) with their thought property set to true from the first candidate of [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | @@ -38,6 +39,19 @@ Aggregates and returns every [FunctionCall](./ai.functioncall.md#functioncall_in functionCalls: () => FunctionCall[] | undefined; ``` +## EnhancedGenerateContentResponse.inferenceSource + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Indicates whether inference happened on-device or in-cloud. + +Signature: + +```typescript +inferenceSource?: InferenceSource; +``` + ## EnhancedGenerateContentResponse.inlineDataParts Aggregates and returns every [InlineDataPart](./ai.inlinedatapart.md#inlinedatapart_interface) from the first candidate of [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index db6148ee88..fabdbc5cc5 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -162,6 +162,7 @@ The Firebase AI Web SDK. | [ImagenPersonFilterLevel](./ai.md#imagenpersonfilterlevel) | A filter level controlling whether generation of images containing people or faces is allowed.See the personGeneration documentation for more details. | | [ImagenSafetyFilterLevel](./ai.md#imagensafetyfilterlevel) | A filter level controlling how aggressively to filter sensitive content.Text prompts provided as inputs and images (generated or uploaded) through Imagen on Vertex AI are assessed against a list of safety filters, which include 'harmful categories' (for example, violence, sexual, derogatory, and toxic). This filter level controls how aggressively to filter out potentially harmful content from responses. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) and the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters) for more details. | | [InferenceMode](./ai.md#inferencemode) | (Public Preview) Determines whether inference happens on-device or in-cloud. | +| [InferenceSource](./ai.md#inferencesource) | (Public Preview) Indicates whether inference happened on-device or in-cloud. | | [Language](./ai.md#language) | (Public Preview) The programming language of the code. | | [LiveResponseType](./ai.md#liveresponsetype) | (Public Preview) The types of responses that can be returned by [LiveSession.receive()](./ai.livesession.md#livesessionreceive). | | [Modality](./ai.md#modality) | Content part modality. | @@ -189,6 +190,7 @@ The Firebase AI Web SDK. | [ImagenPersonFilterLevel](./ai.md#imagenpersonfilterlevel) | A filter level controlling whether generation of images containing people or faces is allowed.See the personGeneration documentation for more details. | | [ImagenSafetyFilterLevel](./ai.md#imagensafetyfilterlevel) | A filter level controlling how aggressively to filter sensitive content.Text prompts provided as inputs and images (generated or uploaded) through Imagen on Vertex AI are assessed against a list of safety filters, which include 'harmful categories' (for example, violence, sexual, derogatory, and toxic). This filter level controls how aggressively to filter out potentially harmful content from responses. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) and the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters) for more details. | | [InferenceMode](./ai.md#inferencemode) | (Public Preview) Determines whether inference happens on-device or in-cloud. | +| [InferenceSource](./ai.md#inferencesource) | (Public Preview) Indicates whether inference happened on-device or in-cloud. | | [Language](./ai.md#language) | (Public Preview) The programming language of the code. | | [LanguageModelMessageContentValue](./ai.md#languagemodelmessagecontentvalue) | (Public Preview) Content formats that can be provided as on-device message content. | | [LanguageModelMessageRole](./ai.md#languagemodelmessagerole) | (Public Preview) Allowable roles for on-device language model usage. | @@ -643,6 +645,22 @@ InferenceMode: { } ``` +## InferenceSource + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Indicates whether inference happened on-device or in-cloud. + +Signature: + +```typescript +InferenceSource: { + readonly ON_DEVICE: "on_device"; + readonly IN_CLOUD: "in_cloud"; +} +``` + ## Language > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -926,6 +944,19 @@ Determines whether inference happens on-device or in-cloud. export type InferenceMode = (typeof InferenceMode)[keyof typeof InferenceMode]; ``` +## InferenceSource + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Indicates whether inference happened on-device or in-cloud. + +Signature: + +```typescript +export type InferenceSource = (typeof InferenceSource)[keyof typeof InferenceSource]; +``` + ## Language > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/packages/ai/src/methods/generate-content.ts b/packages/ai/src/methods/generate-content.ts index 0e65b47934..a2fb29e20d 100644 --- a/packages/ai/src/methods/generate-content.ts +++ b/packages/ai/src/methods/generate-content.ts @@ -57,14 +57,14 @@ export async function generateContentStream( chromeAdapter?: ChromeAdapter, requestOptions?: RequestOptions ): Promise { - const response = await callCloudOrDevice( + const callResult = await callCloudOrDevice( params, chromeAdapter, () => chromeAdapter!.generateContentStream(params), () => generateContentStreamOnCloud(apiSettings, model, params, requestOptions) ); - return processStream(response, apiSettings); // TODO: Map streaming responses + return processStream(callResult.response, apiSettings); // TODO: Map streaming responses } async function generateContentOnCloud( @@ -93,18 +93,19 @@ export async function generateContent( chromeAdapter?: ChromeAdapter, requestOptions?: RequestOptions ): Promise { - const response = await callCloudOrDevice( + const callResult = await callCloudOrDevice( params, chromeAdapter, () => chromeAdapter!.generateContent(params), () => generateContentOnCloud(apiSettings, model, params, requestOptions) ); const generateContentResponse = await processGenerateContentResponse( - response, + callResult.response, apiSettings ); const enhancedResponse = createEnhancedContentResponse( - generateContentResponse + generateContentResponse, + callResult.inferenceSource ); return { response: enhancedResponse diff --git a/packages/ai/src/requests/hybrid-helpers.test.ts b/packages/ai/src/requests/hybrid-helpers.test.ts index a758f34ad2..33e83c0469 100644 --- a/packages/ai/src/requests/hybrid-helpers.test.ts +++ b/packages/ai/src/requests/hybrid-helpers.test.ts @@ -18,7 +18,12 @@ import { use, expect } from 'chai'; import { SinonStub, SinonStubbedInstance, restore, stub } from 'sinon'; import { callCloudOrDevice } from './hybrid-helpers'; -import { GenerateContentRequest, InferenceMode, AIErrorCode } from '../types'; +import { + GenerateContentRequest, + InferenceMode, + AIErrorCode, + InferenceSource +} from '../types'; import { AIError } from '../errors'; import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; @@ -58,7 +63,8 @@ describe('callCloudOrDevice', () => { onDeviceCall, inCloudCall ); - expect(result).to.equal('in-cloud-response'); + expect(result.response).to.equal('in-cloud-response'); + expect(result.inferenceSource).to.equal(InferenceSource.IN_CLOUD); expect(inCloudCall).to.have.been.calledOnce; expect(onDeviceCall).to.not.have.been.called; }); @@ -76,7 +82,8 @@ describe('callCloudOrDevice', () => { onDeviceCall, inCloudCall ); - expect(result).to.equal('on-device-response'); + expect(result.response).to.equal('on-device-response'); + expect(result.inferenceSource).to.equal(InferenceSource.ON_DEVICE); expect(onDeviceCall).to.have.been.calledOnce; expect(inCloudCall).to.not.have.been.called; }); @@ -89,7 +96,8 @@ describe('callCloudOrDevice', () => { onDeviceCall, inCloudCall ); - expect(result).to.equal('in-cloud-response'); + expect(result.response).to.equal('in-cloud-response'); + expect(result.inferenceSource).to.equal(InferenceSource.IN_CLOUD); expect(inCloudCall).to.have.been.calledOnce; expect(onDeviceCall).to.not.have.been.called; }); @@ -108,7 +116,8 @@ describe('callCloudOrDevice', () => { onDeviceCall, inCloudCall ); - expect(result).to.equal('on-device-response'); + expect(result.response).to.equal('on-device-response'); + expect(result.inferenceSource).to.equal(InferenceSource.ON_DEVICE); expect(onDeviceCall).to.have.been.calledOnce; expect(inCloudCall).to.not.have.been.called; }); @@ -136,7 +145,8 @@ describe('callCloudOrDevice', () => { onDeviceCall, inCloudCall ); - expect(result).to.equal('in-cloud-response'); + expect(result.response).to.equal('in-cloud-response'); + expect(result.inferenceSource).to.equal(InferenceSource.IN_CLOUD); expect(inCloudCall).to.have.been.calledOnce; expect(onDeviceCall).to.not.have.been.called; }); @@ -154,7 +164,8 @@ describe('callCloudOrDevice', () => { onDeviceCall, inCloudCall ); - expect(result).to.equal('in-cloud-response'); + expect(result.response).to.equal('in-cloud-response'); + expect(result.inferenceSource).to.equal(InferenceSource.IN_CLOUD); expect(inCloudCall).to.have.been.calledOnce; expect(onDeviceCall).to.not.have.been.called; }); @@ -169,7 +180,8 @@ describe('callCloudOrDevice', () => { onDeviceCall, inCloudCall ); - expect(result).to.equal('on-device-response'); + expect(result.response).to.equal('on-device-response'); + expect(result.inferenceSource).to.equal(InferenceSource.ON_DEVICE); expect(inCloudCall).to.have.been.calledOnce; expect(onDeviceCall).to.have.been.calledOnce; }); diff --git a/packages/ai/src/requests/hybrid-helpers.ts b/packages/ai/src/requests/hybrid-helpers.ts index 3140594c00..b37505bf93 100644 --- a/packages/ai/src/requests/hybrid-helpers.ts +++ b/packages/ai/src/requests/hybrid-helpers.ts @@ -20,7 +20,8 @@ import { GenerateContentRequest, InferenceMode, AIErrorCode, - ChromeAdapter + ChromeAdapter, + InferenceSource } from '../types'; import { ChromeAdapterImpl } from '../methods/chrome-adapter'; @@ -33,6 +34,11 @@ const errorsCausingFallback: AIErrorCode[] = [ AIErrorCode.API_NOT_ENABLED ]; +interface CallResult { + response: Response; + inferenceSource: InferenceSource; +} + /** * Dispatches a request to the appropriate backend (on-device or in-cloud) * based on the inference mode. @@ -48,35 +54,56 @@ export async function callCloudOrDevice( chromeAdapter: ChromeAdapter | undefined, onDeviceCall: () => Promise, inCloudCall: () => Promise -): Promise { +): Promise> { if (!chromeAdapter) { - return inCloudCall(); + return { + response: await inCloudCall(), + inferenceSource: InferenceSource.IN_CLOUD + }; } switch ((chromeAdapter as ChromeAdapterImpl).mode) { case InferenceMode.ONLY_ON_DEVICE: if (await chromeAdapter.isAvailable(request)) { - return onDeviceCall(); + return { + response: await onDeviceCall(), + inferenceSource: InferenceSource.ON_DEVICE + }; } throw new AIError( AIErrorCode.UNSUPPORTED, 'Inference mode is ONLY_ON_DEVICE, but an on-device model is not available.' ); case InferenceMode.ONLY_IN_CLOUD: - return inCloudCall(); + return { + response: await inCloudCall(), + inferenceSource: InferenceSource.IN_CLOUD + }; case InferenceMode.PREFER_IN_CLOUD: try { - return await inCloudCall(); + return { + response: await inCloudCall(), + inferenceSource: InferenceSource.IN_CLOUD + }; } catch (e) { if (e instanceof AIError && errorsCausingFallback.includes(e.code)) { - return onDeviceCall(); + return { + response: await onDeviceCall(), + inferenceSource: InferenceSource.ON_DEVICE + }; } throw e; } case InferenceMode.PREFER_ON_DEVICE: if (await chromeAdapter.isAvailable(request)) { - return onDeviceCall(); + return { + response: await onDeviceCall(), + inferenceSource: InferenceSource.ON_DEVICE + }; } - return inCloudCall(); + return { + response: await inCloudCall(), + inferenceSource: InferenceSource.IN_CLOUD + }; default: throw new AIError( AIErrorCode.ERROR, diff --git a/packages/ai/src/requests/response-helpers.ts b/packages/ai/src/requests/response-helpers.ts index 930bfabb2a..bb3748f6bc 100644 --- a/packages/ai/src/requests/response-helpers.ts +++ b/packages/ai/src/requests/response-helpers.ts @@ -25,7 +25,8 @@ import { ImagenInlineImage, AIErrorCode, InlineDataPart, - Part + Part, + InferenceSource } from '../types'; import { AIError } from '../errors'; import { logger } from '../logger'; @@ -66,7 +67,8 @@ function hasValidCandidates(response: GenerateContentResponse): boolean { * other modifications that improve usability. */ export function createEnhancedContentResponse( - response: GenerateContentResponse + response: GenerateContentResponse, + inferenceSource: InferenceSource = InferenceSource.IN_CLOUD ): EnhancedGenerateContentResponse { /** * The Vertex AI backend omits default values. @@ -79,6 +81,7 @@ export function createEnhancedContentResponse( } const responseWithHelpers = addHelpers(response); + responseWithHelpers.inferenceSource = inferenceSource; return responseWithHelpers; } diff --git a/packages/ai/src/requests/stream-reader.test.ts b/packages/ai/src/requests/stream-reader.test.ts index 2e50bbb3d3..ca3c2cdcfe 100644 --- a/packages/ai/src/requests/stream-reader.test.ts +++ b/packages/ai/src/requests/stream-reader.test.ts @@ -34,7 +34,8 @@ import { HarmCategory, HarmProbability, SafetyRating, - AIErrorCode + AIErrorCode, + InferenceSource } from '../types'; import { AIError } from '../errors'; import { ApiSettings } from '../types/internal'; @@ -61,6 +62,7 @@ describe('getResponseStream', () => { .map(v => JSON.stringify(v)) .map(v => 'data: ' + v + '\r\n\r\n') .join('') + // @ts-ignore ).pipeThrough(new TextDecoderStream('utf8', { fatal: true })); const responseStream = getResponseStream<{ text: string }>(inputStream); const reader = responseStream.getReader(); @@ -88,9 +90,33 @@ describe('processStream', () => { const result = processStream(fakeResponse as Response, fakeApiSettings); for await (const response of result.stream) { expect(response.text()).to.not.be.empty; + expect(response.inferenceSource).to.equal(InferenceSource.IN_CLOUD); } const aggregatedResponse = await result.response; expect(aggregatedResponse.text()).to.include('Cheyenne'); + expect(aggregatedResponse.inferenceSource).to.equal( + InferenceSource.IN_CLOUD + ); + }); + it('streaming response - short - on-device', async () => { + const fakeResponse = getMockResponseStreaming( + 'vertexAI', + 'streaming-success-basic-reply-short.txt' + ); + const result = processStream( + fakeResponse as Response, + fakeApiSettings, + InferenceSource.ON_DEVICE + ); + for await (const response of result.stream) { + expect(response.text()).to.not.be.empty; + expect(response.inferenceSource).to.equal(InferenceSource.ON_DEVICE); + } + const aggregatedResponse = await result.response; + expect(aggregatedResponse.text()).to.include('Cheyenne'); + expect(aggregatedResponse.inferenceSource).to.equal( + InferenceSource.ON_DEVICE + ); }); it('streaming response - long', async () => { const fakeResponse = getMockResponseStreaming( diff --git a/packages/ai/src/requests/stream-reader.ts b/packages/ai/src/requests/stream-reader.ts index 042c052fa8..b4968969be 100644 --- a/packages/ai/src/requests/stream-reader.ts +++ b/packages/ai/src/requests/stream-reader.ts @@ -28,7 +28,11 @@ import { createEnhancedContentResponse } from './response-helpers'; import * as GoogleAIMapper from '../googleai-mappers'; import { GoogleAIGenerateContentResponse } from '../types/googleai'; import { ApiSettings } from '../types/internal'; -import { BackendType, URLContextMetadata } from '../public-types'; +import { + BackendType, + InferenceSource, + URLContextMetadata +} from '../public-types'; const responseLineRE = /^data\: (.*)(?:\n\n|\r\r|\r\n\r\n)/; @@ -42,7 +46,8 @@ const responseLineRE = /^data\: (.*)(?:\n\n|\r\r|\r\n\r\n)/; */ export function processStream( response: Response, - apiSettings: ApiSettings + apiSettings: ApiSettings, + inferenceSource?: InferenceSource ): GenerateContentStreamResult { const inputStream = response.body!.pipeThrough( new TextDecoderStream('utf8', { fatal: true }) @@ -51,14 +56,15 @@ export function processStream( getResponseStream(inputStream); const [stream1, stream2] = responseStream.tee(); return { - stream: generateResponseSequence(stream1, apiSettings), - response: getResponsePromise(stream2, apiSettings) + stream: generateResponseSequence(stream1, apiSettings, inferenceSource), + response: getResponsePromise(stream2, apiSettings, inferenceSource) }; } async function getResponsePromise( stream: ReadableStream, - apiSettings: ApiSettings + apiSettings: ApiSettings, + inferenceSource?: InferenceSource ): Promise { const allResponses: GenerateContentResponse[] = []; const reader = stream.getReader(); @@ -71,7 +77,10 @@ async function getResponsePromise( generateContentResponse as GoogleAIGenerateContentResponse ); } - return createEnhancedContentResponse(generateContentResponse); + return createEnhancedContentResponse( + generateContentResponse, + inferenceSource + ); } allResponses.push(value); @@ -80,7 +89,8 @@ async function getResponsePromise( async function* generateResponseSequence( stream: ReadableStream, - apiSettings: ApiSettings + apiSettings: ApiSettings, + inferenceSource?: InferenceSource ): AsyncGenerator { const reader = stream.getReader(); while (true) { @@ -94,10 +104,11 @@ async function* generateResponseSequence( enhancedResponse = createEnhancedContentResponse( GoogleAIMapper.mapGenerateContentResponse( value as GoogleAIGenerateContentResponse - ) + ), + inferenceSource ); } else { - enhancedResponse = createEnhancedContentResponse(value); + enhancedResponse = createEnhancedContentResponse(value, inferenceSource); } const firstCandidate = enhancedResponse.candidates?.[0]; diff --git a/packages/ai/src/types/enums.ts b/packages/ai/src/types/enums.ts index cd7029df3b..f7c55d5e4c 100644 --- a/packages/ai/src/types/enums.ts +++ b/packages/ai/src/types/enums.ts @@ -379,6 +379,24 @@ export const InferenceMode = { */ export type InferenceMode = (typeof InferenceMode)[keyof typeof InferenceMode]; +/** + * Indicates whether inference happened on-device or in-cloud. + * + * @beta + */ +export const InferenceSource = { + 'ON_DEVICE': 'on_device', + 'IN_CLOUD': 'in_cloud' +} as const; + +/** + * Indicates whether inference happened on-device or in-cloud. + * + * @beta + */ +export type InferenceSource = + (typeof InferenceSource)[keyof typeof InferenceSource]; + /** * Represents the result of the code execution. * diff --git a/packages/ai/src/types/responses.ts b/packages/ai/src/types/responses.ts index 8b8e135167..ec06592f90 100644 --- a/packages/ai/src/types/responses.ts +++ b/packages/ai/src/types/responses.ts @@ -22,6 +22,7 @@ import { HarmCategory, HarmProbability, HarmSeverity, + InferenceSource, Modality } from './enums'; @@ -88,6 +89,12 @@ export interface EnhancedGenerateContentResponse * set to `true`. */ thoughtSummary: () => string | undefined; + /** + * Indicates whether inference happened on-device or in-cloud. + * + * @beta + */ + inferenceSource?: InferenceSource; } /** From 44d9891f93298ab4bcef5170c40c235831af0276 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 20 Oct 2025 09:01:17 -0700 Subject: [PATCH 003/174] Fix logic for merging default onDeviceParams with user-provided onDeviceParams (#9314) --- .changeset/rare-hats-know.md | 5 ++ .../methods/chrome-adapter-browser.test.ts | 57 +++++++++++++++++++ packages/ai/src/methods/chrome-adapter.ts | 26 +++++++-- 3 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 .changeset/rare-hats-know.md diff --git a/.changeset/rare-hats-know.md b/.changeset/rare-hats-know.md new file mode 100644 index 0000000000..68fafc7849 --- /dev/null +++ b/.changeset/rare-hats-know.md @@ -0,0 +1,5 @@ +--- +'@firebase/ai': patch +--- + +Fix logic for merging default `onDeviceParams` with user-provided `onDeviceParams`. diff --git a/packages/ai/src/methods/chrome-adapter-browser.test.ts b/packages/ai/src/methods/chrome-adapter-browser.test.ts index 5d5b2344ab..e37a08bf1a 100644 --- a/packages/ai/src/methods/chrome-adapter-browser.test.ts +++ b/packages/ai/src/methods/chrome-adapter-browser.test.ts @@ -78,6 +78,63 @@ describe('ChromeAdapter', () => { expectedInputs: [{ type: 'image' }] }); }); + it('sets image as expected input type by default even if other onDeviceParams params are set', async () => { + const languageModelProvider = { + availability: () => Promise.resolve(Availability.AVAILABLE) + } as LanguageModel; + const availabilityStub = stub( + languageModelProvider, + 'availability' + ).resolves(Availability.AVAILABLE); + const adapter = new ChromeAdapterImpl( + languageModelProvider, + InferenceMode.PREFER_ON_DEVICE, + { + promptOptions: {} + } + ); + await adapter.isAvailable({ + contents: [ + { + role: 'user', + parts: [{ text: 'hi' }] + } + ] + }); + expect(availabilityStub).to.have.been.calledWith({ + expectedInputs: [{ type: 'image' }] + }); + }); + it('sets image as expected input type by default even if other createOptions params are set', async () => { + const languageModelProvider = { + availability: () => Promise.resolve(Availability.AVAILABLE) + } as LanguageModel; + const availabilityStub = stub( + languageModelProvider, + 'availability' + ).resolves(Availability.AVAILABLE); + const adapter = new ChromeAdapterImpl( + languageModelProvider, + InferenceMode.PREFER_ON_DEVICE, + { + createOptions: { + topK: 22 + } + } + ); + await adapter.isAvailable({ + contents: [ + { + role: 'user', + parts: [{ text: 'hi' }] + } + ] + }); + expect(availabilityStub).to.have.been.calledWith({ + topK: 22, + expectedInputs: [{ type: 'image' }] + }); + }); it('honors explicitly set expected inputs', async () => { const languageModelProvider = { availability: () => Promise.resolve(Availability.AVAILABLE) diff --git a/packages/ai/src/methods/chrome-adapter.ts b/packages/ai/src/methods/chrome-adapter.ts index a0ab509e33..839276814b 100644 --- a/packages/ai/src/methods/chrome-adapter.ts +++ b/packages/ai/src/methods/chrome-adapter.ts @@ -31,11 +31,15 @@ import { ChromeAdapter } from '../types/chrome-adapter'; import { Availability, LanguageModel, + LanguageModelExpected, LanguageModelMessage, LanguageModelMessageContent, LanguageModelMessageRole } from '../types/language-model'; +// Defaults to support image inputs for convenience. +const defaultExpectedInputs: LanguageModelExpected[] = [{ type: 'image' }]; + /** * Defines an inference "backend" that uses Chrome's on-device model, * and encapsulates logic for detecting when on-device inference is @@ -47,16 +51,28 @@ export class ChromeAdapterImpl implements ChromeAdapter { private isDownloading = false; private downloadPromise: Promise | undefined; private oldSession: LanguageModel | undefined; + onDeviceParams: OnDeviceParams = { + createOptions: { + expectedInputs: defaultExpectedInputs + } + }; constructor( public languageModelProvider: LanguageModel, public mode: InferenceMode, - public onDeviceParams: OnDeviceParams = { - createOptions: { - // Defaults to support image inputs for convenience. - expectedInputs: [{ type: 'image' }] + onDeviceParams?: OnDeviceParams + ) { + if (onDeviceParams) { + this.onDeviceParams = onDeviceParams; + if (!this.onDeviceParams.createOptions) { + this.onDeviceParams.createOptions = { + expectedInputs: defaultExpectedInputs + }; + } else if (!this.onDeviceParams.createOptions.expectedInputs) { + this.onDeviceParams.createOptions.expectedInputs = + defaultExpectedInputs; } } - ) {} + } /** * Checks if a given request can be made on-device. From 91c218db2d14cb4f1b978b9073510b8bc8f91233 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 20 Oct 2025 09:01:52 -0700 Subject: [PATCH 004/174] feat(auth): export beta tagged symbols to public typings (#9313) --- .changeset/angry-apples-think.md | 5 +++++ packages/auth/api-extractor.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/angry-apples-think.md diff --git a/.changeset/angry-apples-think.md b/.changeset/angry-apples-think.md new file mode 100644 index 0000000000..dbc41380ab --- /dev/null +++ b/.changeset/angry-apples-think.md @@ -0,0 +1,5 @@ +--- +'@firebase/auth': patch +--- + +Expose `browserCookiePersistence` beta feature in public typings. diff --git a/packages/auth/api-extractor.json b/packages/auth/api-extractor.json index 8b44b43f4d..85e6f846d5 100644 --- a/packages/auth/api-extractor.json +++ b/packages/auth/api-extractor.json @@ -4,6 +4,6 @@ "dtsRollup": { "enabled": true, "untrimmedFilePath": "/dist/.d.ts", - "publicTrimmedFilePath": "/dist/-public.d.ts" + "betaTrimmedFilePath": "/dist/-public.d.ts" } } From 22e0a1adbc994196690bd020472d119c1a3d200b Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Mon, 20 Oct 2025 12:20:33 -0400 Subject: [PATCH 005/174] feat(ai): Add `LiveSession` realtime APIs (#9291) --- .changeset/dull-ligers-bow.md | 7 + common/api-review/ai.api.md | 5 + docs-devsite/ai.livesession.md | 130 ++++++++++++- packages/ai/integration/live.test.ts | 39 ++++ .../src/methods/live-session-helpers.test.ts | 6 +- .../ai/src/methods/live-session-helpers.ts | 2 +- packages/ai/src/methods/live-session.test.ts | 36 ++++ packages/ai/src/methods/live-session.ts | 180 ++++++++++++++---- packages/ai/src/types/live-responses.ts | 9 +- 9 files changed, 367 insertions(+), 47 deletions(-) create mode 100644 .changeset/dull-ligers-bow.md diff --git a/.changeset/dull-ligers-bow.md b/.changeset/dull-ligers-bow.md new file mode 100644 index 0000000000..13606d73f9 --- /dev/null +++ b/.changeset/dull-ligers-bow.md @@ -0,0 +1,7 @@ +--- +'firebase': minor +'@firebase/ai': minor +--- + +Deprecate `sendMediaChunks()` and `sendMediaStream()`. Instead, use the new methods added to the `LiveSession` class. +Add `sendTextRealtime()`, `sendAudioReatime()`, and `sendVideoRealtime()` to the `LiveSession` class. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index f3113e0ac2..48347b8d65 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -1005,9 +1005,14 @@ export class LiveSession { isClosed: boolean; receive(): AsyncGenerator; send(request: string | Array, turnComplete?: boolean): Promise; + sendAudioRealtime(blob: GenerativeContentBlob): Promise; sendFunctionResponses(functionResponses: FunctionResponse[]): Promise; + // @deprecated sendMediaChunks(mediaChunks: GenerativeContentBlob[]): Promise; + // @deprecated (undocumented) sendMediaStream(mediaChunkStream: ReadableStream): Promise; + sendTextRealtime(text: string): Promise; + sendVideoRealtime(blob: GenerativeContentBlob): Promise; } // @public diff --git a/docs-devsite/ai.livesession.md b/docs-devsite/ai.livesession.md index 558c5eb3bd..2f05fbc924 100644 --- a/docs-devsite/ai.livesession.md +++ b/docs-devsite/ai.livesession.md @@ -39,9 +39,12 @@ export declare class LiveSession | [close()](./ai.livesession.md#livesessionclose) | | (Public Preview) Closes this session. All methods on this session will throw an error once this resolves. | | [receive()](./ai.livesession.md#livesessionreceive) | | (Public Preview) Yields messages received from the server. This can only be used by one consumer at a time. | | [send(request, turnComplete)](./ai.livesession.md#livesessionsend) | | (Public Preview) Sends content to the server. | +| [sendAudioRealtime(blob)](./ai.livesession.md#livesessionsendaudiorealtime) | | (Public Preview) Sends audio data to the server in realtime. | | [sendFunctionResponses(functionResponses)](./ai.livesession.md#livesessionsendfunctionresponses) | | (Public Preview) Sends function responses to the server. | | [sendMediaChunks(mediaChunks)](./ai.livesession.md#livesessionsendmediachunks) | | (Public Preview) Sends realtime input to the server. | -| [sendMediaStream(mediaChunkStream)](./ai.livesession.md#livesessionsendmediastream) | | (Public Preview) Sends a stream of [GenerativeContentBlob](./ai.generativecontentblob.md#generativecontentblob_interface). | +| [sendMediaStream(mediaChunkStream)](./ai.livesession.md#livesessionsendmediastream) | | (Public Preview) | +| [sendTextRealtime(text)](./ai.livesession.md#livesessionsendtextrealtime) | | (Public Preview) Sends text to the server in realtime. | +| [sendVideoRealtime(blob)](./ai.livesession.md#livesessionsendvideorealtime) | | (Public Preview) Sends video data to the server in realtime. | ## LiveSession.inConversation @@ -135,6 +138,45 @@ Promise<void> If this session has been closed. +## LiveSession.sendAudioRealtime() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Sends audio data to the server in realtime. + +The server requires that the audio data is base64-encoded 16-bit PCM at 16kHz little-endian. + +Signature: + +```typescript +sendAudioRealtime(blob: GenerativeContentBlob): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| blob | [GenerativeContentBlob](./ai.generativecontentblob.md#generativecontentblob_interface) | The base64-encoded PCM data to send to the server in realtime. | + +Returns: + +Promise<void> + +#### Exceptions + +If this session has been closed. + +### Example + + +```javascript +// const pcmData = ... base64-encoded 16-bit PCM at 16kHz little-endian. +const blob = { mimeType: "audio/pcm", data: pcmData }; +liveSession.sendAudioRealtime(blob); + +``` + ## LiveSession.sendFunctionResponses() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -167,6 +209,11 @@ If this session has been closed. > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > +> Warning: This API is now obsolete. +> +> Use `sendTextRealtime()`, `sendAudioRealtime()`, and `sendVideoRealtime()` instead. +> + Sends realtime input to the server. Signature: @@ -194,7 +241,12 @@ If this session has been closed. > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Sends a stream of [GenerativeContentBlob](./ai.generativecontentblob.md#generativecontentblob_interface). +> Warning: This API is now obsolete. +> +> Use `sendTextRealtime()`, `sendAudioRealtime()`, and `sendVideoRealtime()` instead. +> +> Sends a stream of [GenerativeContentBlob](./ai.generativecontentblob.md#generativecontentblob_interface). +> Signature: @@ -216,3 +268,77 @@ Promise<void> If this session has been closed. +## LiveSession.sendTextRealtime() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Sends text to the server in realtime. + +Signature: + +```typescript +sendTextRealtime(text: string): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| text | string | The text data to send. | + +Returns: + +Promise<void> + +#### Exceptions + +If this session has been closed. + +### Example + + +```javascript +liveSession.sendTextRealtime("Hello, how are you?"); + +``` + +## LiveSession.sendVideoRealtime() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Sends video data to the server in realtime. + +The server requires that the video is sent as individual video frames at 1 FPS. It is recommended to set `mimeType` to `image/jpeg`. + +Signature: + +```typescript +sendVideoRealtime(blob: GenerativeContentBlob): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| blob | [GenerativeContentBlob](./ai.generativecontentblob.md#generativecontentblob_interface) | The base64-encoded video data to send to the server in realtime. | + +Returns: + +Promise<void> + +#### Exceptions + +If this session has been closed. + +### Example + + +```javascript +// const videoFrame = ... base64-encoded JPEG data +const blob = { mimeType: "image/jpeg", data: videoFrame }; +liveSession.sendVideoRealtime(blob); + +``` + diff --git a/packages/ai/integration/live.test.ts b/packages/ai/integration/live.test.ts index caa18970ab..0af5bef224 100644 --- a/packages/ai/integration/live.test.ts +++ b/packages/ai/integration/live.test.ts @@ -154,6 +154,45 @@ describe('Live', function () { }); }); + describe('sendTextRealtime()', () => { + it('should send a single text chunk and receive a response', async () => { + const model = getLiveGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: textLiveGenerationConfig + }); + const session = await model.connect(); + const responsePromise = nextTurnText(session.receive()); + + await session.sendTextRealtime('Are you an AI? Yes or No.'); + + const responseText = await responsePromise; + expect(responseText).to.include('Yes'); + + await session.close(); + }); + }); + + describe('sendAudioRealtime()', () => { + it('should send a single audio chunk and receive a response', async () => { + const model = getLiveGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: textLiveGenerationConfig + }); + const session = await model.connect(); + const responsePromise = nextTurnText(session.receive()); + + await session.sendAudioRealtime({ + data: HELLO_AUDIO_PCM_BASE64, // "Hey, can you hear me?" + mimeType: 'audio/pcm' + }); + + const responseText = await responsePromise; + expect(responseText).to.include('Yes'); + + await session.close(); + }); + }); + describe('sendMediaChunks()', () => { it('should send a single audio chunk and receive a response', async () => { const model = getLiveGenerativeModel(testConfig.ai, { diff --git a/packages/ai/src/methods/live-session-helpers.test.ts b/packages/ai/src/methods/live-session-helpers.test.ts index cad0475b35..a62315c701 100644 --- a/packages/ai/src/methods/live-session-helpers.test.ts +++ b/packages/ai/src/methods/live-session-helpers.test.ts @@ -65,7 +65,7 @@ class MockLiveSession { isClosed = false; inConversation = false; send = sinon.stub(); - sendMediaChunks = sinon.stub(); + sendAudioRealtime = sinon.stub(); sendFunctionResponses = sinon.stub(); messageGenerator = new MockMessageGenerator(); receive = (): MockMessageGenerator => this.messageGenerator; @@ -226,8 +226,8 @@ describe('Audio Conversation Helpers', () => { await clock.tickAsync(1); - expect(liveSession.sendMediaChunks).to.have.been.calledOnce; - const [sentChunk] = liveSession.sendMediaChunks.getCall(0).args[0]; + expect(liveSession.sendAudioRealtime).to.have.been.calledOnce; + const sentChunk = liveSession.sendAudioRealtime.getCall(0).args[0]; expect(sentChunk.mimeType).to.equal('audio/pcm'); expect(sentChunk.data).to.be.a('string'); await controller.stop(); diff --git a/packages/ai/src/methods/live-session-helpers.ts b/packages/ai/src/methods/live-session-helpers.ts index b3907d6219..cb3be493f5 100644 --- a/packages/ai/src/methods/live-session-helpers.ts +++ b/packages/ai/src/methods/live-session-helpers.ts @@ -184,7 +184,7 @@ export class AudioConversationRunner { mimeType: 'audio/pcm', data: base64 }; - void this.liveSession.sendMediaChunks([chunk]); + void this.liveSession.sendAudioRealtime(chunk); }; } diff --git a/packages/ai/src/methods/live-session.test.ts b/packages/ai/src/methods/live-session.test.ts index 7454b1208c..428e92ec77 100644 --- a/packages/ai/src/methods/live-session.test.ts +++ b/packages/ai/src/methods/live-session.test.ts @@ -110,6 +110,42 @@ describe('LiveSession', () => { }); }); + describe('sendTextRealtime()', () => { + it('should send a correctly formatted realtimeInput message', async () => { + const text = 'foo'; + await session.sendTextRealtime(text); + expect(mockHandler.send).to.have.been.calledOnce; + const sentData = JSON.parse(mockHandler.send.getCall(0).args[0]); + expect(sentData).to.deep.equal({ + realtimeInput: { text } + }); + }); + }); + + describe('sendAudioRealtime()', () => { + it('should send a correctly formatted realtimeInput message', async () => { + const blob = { data: 'abcdef', mimeType: 'audio/pcm' }; + await session.sendAudioRealtime(blob); + expect(mockHandler.send).to.have.been.calledOnce; + const sentData = JSON.parse(mockHandler.send.getCall(0).args[0]); + expect(sentData).to.deep.equal({ + realtimeInput: { audio: blob } + }); + }); + }); + + describe('sendVideoRealtime()', () => { + it('should send a correctly formatted realtimeInput message', async () => { + const blob = { data: 'abcdef', mimeType: 'image/jpeg' }; + await session.sendVideoRealtime(blob); + expect(mockHandler.send).to.have.been.calledOnce; + const sentData = JSON.parse(mockHandler.send.getCall(0).args[0]); + expect(sentData).to.deep.equal({ + realtimeInput: { video: blob } + }); + }); + }); + describe('sendMediaChunks()', () => { it('should send a correctly formatted realtimeInput message', async () => { const chunks = [{ data: 'base64', mimeType: 'audio/webm' }]; diff --git a/packages/ai/src/methods/live-session.ts b/packages/ai/src/methods/live-session.ts index 92d325e2f0..1db5e3d4dd 100644 --- a/packages/ai/src/methods/live-session.ts +++ b/packages/ai/src/methods/live-session.ts @@ -96,14 +96,19 @@ export class LiveSession { } /** - * Sends realtime input to the server. + * Sends text to the server in realtime. * - * @param mediaChunks - The media chunks to send. + * @example + * ```javascript + * liveSession.sendTextRealtime("Hello, how are you?"); + * ``` + * + * @param text - The text data to send. * @throws If this session has been closed. * * @beta */ - async sendMediaChunks(mediaChunks: GenerativeContentBlob[]): Promise { + async sendTextRealtime(text: string): Promise { if (this.isClosed) { throw new AIError( AIErrorCode.REQUEST_ERROR, @@ -111,27 +116,33 @@ export class LiveSession { ); } - // The backend does not support sending more than one mediaChunk in one message. - // Work around this limitation by sending mediaChunks in separate messages. - mediaChunks.forEach(mediaChunk => { - const message: _LiveClientRealtimeInput = { - realtimeInput: { mediaChunks: [mediaChunk] } - }; - this.webSocketHandler.send(JSON.stringify(message)); - }); + const message: _LiveClientRealtimeInput = { + realtimeInput: { + text + } + }; + this.webSocketHandler.send(JSON.stringify(message)); } /** - * Sends function responses to the server. + * Sends audio data to the server in realtime. * - * @param functionResponses - The function responses to send. + * @remarks The server requires that the audio data is base64-encoded 16-bit PCM at 16kHz + * little-endian. + * + * @example + * ```javascript + * // const pcmData = ... base64-encoded 16-bit PCM at 16kHz little-endian. + * const blob = { mimeType: "audio/pcm", data: pcmData }; + * liveSession.sendAudioRealtime(blob); + * ``` + * + * @param blob - The base64-encoded PCM data to send to the server in realtime. * @throws If this session has been closed. * * @beta */ - async sendFunctionResponses( - functionResponses: FunctionResponse[] - ): Promise { + async sendAudioRealtime(blob: GenerativeContentBlob): Promise { if (this.isClosed) { throw new AIError( AIErrorCode.REQUEST_ERROR, @@ -139,25 +150,32 @@ export class LiveSession { ); } - const message: _LiveClientToolResponse = { - toolResponse: { - functionResponses + const message: _LiveClientRealtimeInput = { + realtimeInput: { + audio: blob } }; this.webSocketHandler.send(JSON.stringify(message)); } /** - * Sends a stream of {@link GenerativeContentBlob}. + * Sends video data to the server in realtime. * - * @param mediaChunkStream - The stream of {@link GenerativeContentBlob} to send. + * @remarks The server requires that the video is sent as individual video frames at 1 FPS. It + * is recommended to set `mimeType` to `image/jpeg`. + * + * @example + * ```javascript + * // const videoFrame = ... base64-encoded JPEG data + * const blob = { mimeType: "image/jpeg", data: videoFrame }; + * liveSession.sendVideoRealtime(blob); + * ``` + * @param blob - The base64-encoded video data to send to the server in realtime. * @throws If this session has been closed. * * @beta */ - async sendMediaStream( - mediaChunkStream: ReadableStream - ): Promise { + async sendVideoRealtime(blob: GenerativeContentBlob): Promise { if (this.isClosed) { throw new AIError( AIErrorCode.REQUEST_ERROR, @@ -165,25 +183,38 @@ export class LiveSession { ); } - const reader = mediaChunkStream.getReader(); - while (true) { - try { - const { done, value } = await reader.read(); + const message: _LiveClientRealtimeInput = { + realtimeInput: { + video: blob + } + }; + this.webSocketHandler.send(JSON.stringify(message)); + } - if (done) { - break; - } else if (!value) { - throw new Error('Missing chunk in reader, but reader is not done.'); - } + /** + * Sends function responses to the server. + * + * @param functionResponses - The function responses to send. + * @throws If this session has been closed. + * + * @beta + */ + async sendFunctionResponses( + functionResponses: FunctionResponse[] + ): Promise { + if (this.isClosed) { + throw new AIError( + AIErrorCode.REQUEST_ERROR, + 'This LiveSession has been closed and cannot be used.' + ); + } - await this.sendMediaChunks([value]); - } catch (e) { - // Re-throw any errors that occur during stream consumption or sending. - const message = - e instanceof Error ? e.message : 'Error processing media stream.'; - throw new AIError(AIErrorCode.REQUEST_ERROR, message); + const message: _LiveClientToolResponse = { + toolResponse: { + functionResponses } - } + }; + this.webSocketHandler.send(JSON.stringify(message)); } /** @@ -259,4 +290,73 @@ export class LiveSession { await this.webSocketHandler.close(1000, 'Client closed session.'); } } + + /** + * Sends realtime input to the server. + * + * @deprecated Use `sendTextRealtime()`, `sendAudioRealtime()`, and `sendVideoRealtime()` instead. + * + * @param mediaChunks - The media chunks to send. + * @throws If this session has been closed. + * + * @beta + */ + async sendMediaChunks(mediaChunks: GenerativeContentBlob[]): Promise { + if (this.isClosed) { + throw new AIError( + AIErrorCode.REQUEST_ERROR, + 'This LiveSession has been closed and cannot be used.' + ); + } + + // The backend does not support sending more than one mediaChunk in one message. + // Work around this limitation by sending mediaChunks in separate messages. + mediaChunks.forEach(mediaChunk => { + const message: _LiveClientRealtimeInput = { + realtimeInput: { mediaChunks: [mediaChunk] } + }; + this.webSocketHandler.send(JSON.stringify(message)); + }); + } + + /** + * @deprecated Use `sendTextRealtime()`, `sendAudioRealtime()`, and `sendVideoRealtime()` instead. + * + * Sends a stream of {@link GenerativeContentBlob}. + * + * @param mediaChunkStream - The stream of {@link GenerativeContentBlob} to send. + * @throws If this session has been closed. + * + * @beta + */ + async sendMediaStream( + mediaChunkStream: ReadableStream + ): Promise { + if (this.isClosed) { + throw new AIError( + AIErrorCode.REQUEST_ERROR, + 'This LiveSession has been closed and cannot be used.' + ); + } + + const reader = mediaChunkStream.getReader(); + while (true) { + try { + const { done, value } = await reader.read(); + + if (done) { + break; + } else if (!value) { + throw new Error('Missing chunk in reader, but reader is not done.'); + } + + await this.sendMediaChunks([value]); + } catch (e) { + // Re-throw any errors that occur during stream consumption or sending. + const message = + e instanceof Error ? e.message : 'Error processing media stream.'; + throw new AIError(AIErrorCode.REQUEST_ERROR, message); + } + } + } } diff --git a/packages/ai/src/types/live-responses.ts b/packages/ai/src/types/live-responses.ts index d1870fa109..6b69a0ea35 100644 --- a/packages/ai/src/types/live-responses.ts +++ b/packages/ai/src/types/live-responses.ts @@ -44,7 +44,14 @@ export interface _LiveClientContent { // eslint-disable-next-line @typescript-eslint/naming-convention export interface _LiveClientRealtimeInput { realtimeInput: { - mediaChunks: GenerativeContentBlob[]; + text?: string; + audio?: GenerativeContentBlob; + video?: GenerativeContentBlob; + + /** + * @deprecated Use `text`, `audio`, and `video` instead. + */ + mediaChunks?: GenerativeContentBlob[]; }; } From 8209266c625c2c08effd8d0d4c82af72439a0f9c Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 21 Oct 2025 14:05:09 -0400 Subject: [PATCH 006/174] test(ai): Update mock responses to v15 (#9328) --- scripts/update_vertexai_responses.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_vertexai_responses.sh b/scripts/update_vertexai_responses.sh index f6557ab0c0..d32a7c83fc 100755 --- a/scripts/update_vertexai_responses.sh +++ b/scripts/update_vertexai_responses.sh @@ -17,7 +17,7 @@ # This script replaces mock response files for Vertex AI unit tests with a fresh # clone of the shared repository of Vertex AI test data. -RESPONSES_VERSION='v14.*' # The major version of mock responses to use +RESPONSES_VERSION='v15.*' # The major version of mock responses to use REPO_NAME="vertexai-sdk-test-data" REPO_LINK="https://github.com/FirebaseExtended/$REPO_NAME.git" From bc5a7c4a74e72e9218d1435bfe50711c77b47cbd Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 28 Oct 2025 12:14:23 -0400 Subject: [PATCH 007/174] feat(ai): Add Live API transcriptions (#9330) --- .changeset/fast-rocks-sing.md | 6 +++ common/api-review/ai.api.md | 13 +++++ docs-devsite/_toc.yaml | 4 ++ docs-devsite/ai.audiotranscriptionconfig.md | 19 +++++++ docs-devsite/ai.livegenerationconfig.md | 32 ++++++++++++ docs-devsite/ai.liveservercontent.md | 28 +++++++++++ docs-devsite/ai.md | 2 + docs-devsite/ai.transcription.md | 41 +++++++++++++++ packages/ai/integration/live.test.ts | 50 +++++++++++++++++++ .../src/models/live-generative-model.test.ts | 31 ++++++++++++ .../ai/src/models/live-generative-model.ts | 14 +++++- packages/ai/src/types/live-responses.ts | 25 +++++++++- packages/ai/src/types/requests.ts | 23 +++++++++ packages/ai/src/types/responses.ts | 23 +++++++++ 14 files changed, 307 insertions(+), 4 deletions(-) create mode 100644 .changeset/fast-rocks-sing.md create mode 100644 docs-devsite/ai.audiotranscriptionconfig.md create mode 100644 docs-devsite/ai.transcription.md diff --git a/.changeset/fast-rocks-sing.md b/.changeset/fast-rocks-sing.md new file mode 100644 index 0000000000..ccbc997da3 --- /dev/null +++ b/.changeset/fast-rocks-sing.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/ai': minor +--- + +Add support for audio transcriptions in the Live API. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 48347b8d65..a13fcb9cdf 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -92,6 +92,10 @@ export interface AudioConversationController { stop: () => Promise; } +// @public +export interface AudioTranscriptionConfig { +} + // @public export abstract class Backend { protected constructor(type: BackendType); @@ -922,7 +926,9 @@ export interface LanguageModelPromptOptions { // @beta export interface LiveGenerationConfig { frequencyPenalty?: number; + inputAudioTranscription?: AudioTranscriptionConfig; maxOutputTokens?: number; + outputAudioTranscription?: AudioTranscriptionConfig; presencePenalty?: number; responseModalities?: ResponseModality[]; speechConfig?: SpeechConfig; @@ -975,8 +981,10 @@ export type LiveResponseType = (typeof LiveResponseType)[keyof typeof LiveRespon // @beta export interface LiveServerContent { + inputTranscription?: Transcription; interrupted?: boolean; modelTurn?: Content; + outputTranscription?: Transcription; turnComplete?: boolean; // (undocumented) type: 'serverContent'; @@ -1342,6 +1350,11 @@ export interface ToolConfig { functionCallingConfig?: FunctionCallingConfig; } +// @beta +export interface Transcription { + text?: string; +} + // @public export type TypedSchema = IntegerSchema | NumberSchema | StringSchema | BooleanSchema | ObjectSchema | ArraySchema | AnyOfSchema; diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index 04d65f6c33..4f3bb1f3ca 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -18,6 +18,8 @@ toc: path: /docs/reference/js/ai.arrayschema.md - title: AudioConversationController path: /docs/reference/js/ai.audioconversationcontroller.md + - title: AudioTranscriptionConfig + path: /docs/reference/js/ai.audiotranscriptionconfig.md - title: Backend path: /docs/reference/js/ai.backend.md - title: BaseParams @@ -202,6 +204,8 @@ toc: path: /docs/reference/js/ai.thinkingconfig.md - title: ToolConfig path: /docs/reference/js/ai.toolconfig.md + - title: Transcription + path: /docs/reference/js/ai.transcription.md - title: URLContext path: /docs/reference/js/ai.urlcontext.md - title: URLContextMetadata diff --git a/docs-devsite/ai.audiotranscriptionconfig.md b/docs-devsite/ai.audiotranscriptionconfig.md new file mode 100644 index 0000000000..ff53c9061e --- /dev/null +++ b/docs-devsite/ai.audiotranscriptionconfig.md @@ -0,0 +1,19 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# AudioTranscriptionConfig interface +The audio transcription configuration. + +Signature: + +```typescript +export interface AudioTranscriptionConfig +``` diff --git a/docs-devsite/ai.livegenerationconfig.md b/docs-devsite/ai.livegenerationconfig.md index 1a920afa1e..2e842a3431 100644 --- a/docs-devsite/ai.livegenerationconfig.md +++ b/docs-devsite/ai.livegenerationconfig.md @@ -26,7 +26,9 @@ export interface LiveGenerationConfig | Property | Type | Description | | --- | --- | --- | | [frequencyPenalty](./ai.livegenerationconfig.md#livegenerationconfigfrequencypenalty) | number | (Public Preview) Frequency penalties. | +| [inputAudioTranscription](./ai.livegenerationconfig.md#livegenerationconfiginputaudiotranscription) | [AudioTranscriptionConfig](./ai.audiotranscriptionconfig.md#audiotranscriptionconfig_interface) | (Public Preview) Enables transcription of audio input.When enabled, the model will respond with transcriptions of your audio input in the inputTranscriptions property in [LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) messages. Note that the transcriptions are broken up across messages, so you may only receive small amounts of text per message. For example, if you ask the model "How are you today?", the model may transcribe that input across three messages, broken up as "How a", "re yo", "u today?". | | [maxOutputTokens](./ai.livegenerationconfig.md#livegenerationconfigmaxoutputtokens) | number | (Public Preview) Specifies the maximum number of tokens that can be generated in the response. The number of tokens per word varies depending on the language outputted. Is unbounded by default. | +| [outputAudioTranscription](./ai.livegenerationconfig.md#livegenerationconfigoutputaudiotranscription) | [AudioTranscriptionConfig](./ai.audiotranscriptionconfig.md#audiotranscriptionconfig_interface) | (Public Preview) Enables transcription of audio input.When enabled, the model will respond with transcriptions of its audio output in the outputTranscription property in [LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) messages. Note that the transcriptions are broken up across messages, so you may only receive small amounts of text per message. For example, if the model says "How are you today?", the model may transcribe that output across three messages, broken up as "How a", "re yo", "u today?". | | [presencePenalty](./ai.livegenerationconfig.md#livegenerationconfigpresencepenalty) | number | (Public Preview) Positive penalties. | | [responseModalities](./ai.livegenerationconfig.md#livegenerationconfigresponsemodalities) | [ResponseModality](./ai.md#responsemodality)\[\] | (Public Preview) The modalities of the response. | | [speechConfig](./ai.livegenerationconfig.md#livegenerationconfigspeechconfig) | [SpeechConfig](./ai.speechconfig.md#speechconfig_interface) | (Public Preview) Configuration for speech synthesis. | @@ -47,6 +49,21 @@ Frequency penalties. frequencyPenalty?: number; ``` +## LiveGenerationConfig.inputAudioTranscription + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Enables transcription of audio input. + +When enabled, the model will respond with transcriptions of your audio input in the `inputTranscriptions` property in [LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) messages. Note that the transcriptions are broken up across messages, so you may only receive small amounts of text per message. For example, if you ask the model "How are you today?", the model may transcribe that input across three messages, broken up as "How a", "re yo", "u today?". + +Signature: + +```typescript +inputAudioTranscription?: AudioTranscriptionConfig; +``` + ## LiveGenerationConfig.maxOutputTokens > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -60,6 +77,21 @@ Specifies the maximum number of tokens that can be generated in the response. Th maxOutputTokens?: number; ``` +## LiveGenerationConfig.outputAudioTranscription + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Enables transcription of audio input. + +When enabled, the model will respond with transcriptions of its audio output in the `outputTranscription` property in [LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) messages. Note that the transcriptions are broken up across messages, so you may only receive small amounts of text per message. For example, if the model says "How are you today?", the model may transcribe that output across three messages, broken up as "How a", "re yo", "u today?". + +Signature: + +```typescript +outputAudioTranscription?: AudioTranscriptionConfig; +``` + ## LiveGenerationConfig.presencePenalty > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/ai.liveservercontent.md b/docs-devsite/ai.liveservercontent.md index f9c3ca1de7..6162601b8c 100644 --- a/docs-devsite/ai.liveservercontent.md +++ b/docs-devsite/ai.liveservercontent.md @@ -25,11 +25,26 @@ export interface LiveServerContent | Property | Type | Description | | --- | --- | --- | +| [inputTranscription](./ai.liveservercontent.md#liveservercontentinputtranscription) | [Transcription](./ai.transcription.md#transcription_interface) | (Public Preview) Transcription of the audio that was input to the model. | | [interrupted](./ai.liveservercontent.md#liveservercontentinterrupted) | boolean | (Public Preview) Indicates whether the model was interrupted by the client. An interruption occurs when the client sends a message before the model finishes it's turn. This is undefined if the model was not interrupted. | | [modelTurn](./ai.liveservercontent.md#liveservercontentmodelturn) | [Content](./ai.content.md#content_interface) | (Public Preview) The content that the model has generated as part of the current conversation with the user. | +| [outputTranscription](./ai.liveservercontent.md#liveservercontentoutputtranscription) | [Transcription](./ai.transcription.md#transcription_interface) | (Public Preview) Transcription of the audio output from the model. | | [turnComplete](./ai.liveservercontent.md#liveservercontentturncomplete) | boolean | (Public Preview) Indicates whether the turn is complete. This is undefined if the turn is not complete. | | [type](./ai.liveservercontent.md#liveservercontenttype) | 'serverContent' | (Public Preview) | +## LiveServerContent.inputTranscription + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Transcription of the audio that was input to the model. + +Signature: + +```typescript +inputTranscription?: Transcription; +``` + ## LiveServerContent.interrupted > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -56,6 +71,19 @@ The content that the model has generated as part of the current conversation wit modelTurn?: Content; ``` +## LiveServerContent.outputTranscription + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Transcription of the audio output from the model. + +Signature: + +```typescript +outputTranscription?: Transcription; +``` + ## LiveServerContent.turnComplete > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index fabdbc5cc5..79902cab4e 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -56,6 +56,7 @@ The Firebase AI Web SDK. | [AI](./ai.ai.md#ai_interface) | An instance of the Firebase AI SDK.Do not create this instance directly. Instead, use [getAI()](./ai.md#getai_a94a413). | | [AIOptions](./ai.aioptions.md#aioptions_interface) | Options for initializing the AI service using [getAI()](./ai.md#getai_a94a413). This allows specifying which backend to use (Vertex AI Gemini API or Gemini Developer API) and configuring its specific options (like location for Vertex AI). | | [AudioConversationController](./ai.audioconversationcontroller.md#audioconversationcontroller_interface) | (Public Preview) A controller for managing an active audio conversation. | +| [AudioTranscriptionConfig](./ai.audiotranscriptionconfig.md#audiotranscriptionconfig_interface) | The audio transcription configuration. | | [BaseParams](./ai.baseparams.md#baseparams_interface) | Base parameters for a number of methods. | | [ChromeAdapter](./ai.chromeadapter.md#chromeadapter_interface) | (Public Preview) Defines an inference "backend" that uses Chrome's on-device model, and encapsulates logic for detecting when on-device inference is possible.These methods should not be called directly by the user. | | [Citation](./ai.citation.md#citation_interface) | A single citation. | @@ -134,6 +135,7 @@ The Firebase AI Web SDK. | [TextPart](./ai.textpart.md#textpart_interface) | Content part interface if the part represents a text string. | | [ThinkingConfig](./ai.thinkingconfig.md#thinkingconfig_interface) | Configuration for "thinking" behavior of compatible Gemini models.Certain models utilize a thinking process before generating a response. This allows them to reason through complex problems and plan a more coherent and accurate answer. | | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. | +| [Transcription](./ai.transcription.md#transcription_interface) | (Public Preview) Transcription of audio. This can be returned from a [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) if transcription is enabled with the inputAudioTranscription or outputAudioTranscription properties on the [LiveGenerationConfig](./ai.livegenerationconfig.md#livegenerationconfig_interface). | | [URLContext](./ai.urlcontext.md#urlcontext_interface) | (Public Preview) Specifies the URL Context configuration. | | [URLContextMetadata](./ai.urlcontextmetadata.md#urlcontextmetadata_interface) | (Public Preview) Metadata related to [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface). | | [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface) | (Public Preview) A tool that allows you to provide additional context to the models in the form of public web URLs. By including URLs in your request, the Gemini model will access the content from those pages to inform and enhance its response. | diff --git a/docs-devsite/ai.transcription.md b/docs-devsite/ai.transcription.md new file mode 100644 index 0000000000..7ab6a360d5 --- /dev/null +++ b/docs-devsite/ai.transcription.md @@ -0,0 +1,41 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Transcription interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Transcription of audio. This can be returned from a [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) if transcription is enabled with the `inputAudioTranscription` or `outputAudioTranscription` properties on the [LiveGenerationConfig](./ai.livegenerationconfig.md#livegenerationconfig_interface). + +Signature: + +```typescript +export interface Transcription +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [text](./ai.transcription.md#transcriptiontext) | string | (Public Preview) The text transcription of the audio. | + +## Transcription.text + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The text transcription of the audio. + +Signature: + +```typescript +text?: string; +``` diff --git a/packages/ai/integration/live.test.ts b/packages/ai/integration/live.test.ts index 0af5bef224..6b50fe6522 100644 --- a/packages/ai/integration/live.test.ts +++ b/packages/ai/integration/live.test.ts @@ -270,6 +270,56 @@ describe('Live', function () { }); }); + describe('Transcripts', async () => { + it('should receive transcript of audio input', async () => { + const model = getLiveGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: { + responseModalities: [ResponseModality.AUDIO], + inputAudioTranscription: {}, + outputAudioTranscription: {} + } + }); + const session = await model.connect(); + const stream = session.receive(); + + await session.sendAudioRealtime({ + data: HELLO_AUDIO_PCM_BASE64, + mimeType: 'audio/pcm' + }); + + let aggregatedInputTranscription = ''; + let aggregatedOutputTranscription = ''; + let result = await stream.next(); + while (!result.done) { + const chunk = result.value as + | LiveServerContent + | LiveServerToolCall + | LiveServerToolCallCancellation; + if (chunk.type === 'serverContent') { + if (chunk.turnComplete) { + break; + } + + if (chunk.inputTranscription) { + aggregatedInputTranscription += chunk.inputTranscription?.text; + } + if (chunk.outputTranscription) { + aggregatedOutputTranscription += + chunk.outputTranscription?.text; + } + } + + result = await stream.next(); + } + + expect(aggregatedInputTranscription).to.not.be.empty; + expect(aggregatedOutputTranscription).to.not.be.empty; + + await session.close(); + }); + }); + /** * These tests are currently very unreliable. Their behavior seems to change frequently. * Skipping them for now. diff --git a/packages/ai/src/models/live-generative-model.test.ts b/packages/ai/src/models/live-generative-model.test.ts index 495f340b84..a899e0b39f 100644 --- a/packages/ai/src/models/live-generative-model.test.ts +++ b/packages/ai/src/models/live-generative-model.test.ts @@ -168,4 +168,35 @@ describe('LiveGenerativeModel', () => { mockHandler.simulateServerMessage({ setupComplete: true }); await connectPromise; }); + it('connect() should deconstruct generationConfig to send transcription configs in top level setup', async () => { + const model = new LiveGenerativeModel( + fakeAI, + { + model: 'gemini-pro', + generationConfig: { + temperature: 0.8, + inputAudioTranscription: {}, + outputAudioTranscription: {} + }, + systemInstruction: { role: 'system', parts: [{ text: 'Be a pirate' }] } + }, + mockHandler + ); + const connectPromise = model.connect(); + + // Wait for setup message + await clock.runAllAsync(); + + const sentData = JSON.parse(mockHandler.send.getCall(0).args[0]); + // inputAudioTranscription and outputAudioTranscription should be at the top-level setup message, + // rather than in the generationConfig. + expect(sentData.setup.generationConfig).to.deep.equal({ temperature: 0.8 }); + expect(sentData.setup.inputAudioTranscription).to.deep.equal({}); + expect(sentData.setup.outputAudioTranscription).to.deep.equal({}); + expect(sentData.setup.systemInstruction.parts[0].text).to.equal( + 'Be a pirate' + ); + mockHandler.simulateServerMessage({ setupComplete: true }); + await connectPromise; + }); }); diff --git a/packages/ai/src/models/live-generative-model.ts b/packages/ai/src/models/live-generative-model.ts index 251df09520..a89921070e 100644 --- a/packages/ai/src/models/live-generative-model.ts +++ b/packages/ai/src/models/live-generative-model.ts @@ -86,13 +86,23 @@ export class LiveGenerativeModel extends AIModel { fullModelPath = `projects/${this._apiSettings.project}/locations/${this._apiSettings.location}/${this.model}`; } + // inputAudioTranscription and outputAudioTranscription are on the generation config in the public API, + // but the backend expects them to be in the `setup` message. + const { + inputAudioTranscription, + outputAudioTranscription, + ...generationConfig + } = this.generationConfig; + const setupMessage: _LiveClientSetup = { setup: { model: fullModelPath, - generationConfig: this.generationConfig, + generationConfig, tools: this.tools, toolConfig: this.toolConfig, - systemInstruction: this.systemInstruction + systemInstruction: this.systemInstruction, + inputAudioTranscription, + outputAudioTranscription } }; diff --git a/packages/ai/src/types/live-responses.ts b/packages/ai/src/types/live-responses.ts index 6b69a0ea35..3bdb32c126 100644 --- a/packages/ai/src/types/live-responses.ts +++ b/packages/ai/src/types/live-responses.ts @@ -21,7 +21,13 @@ import { GenerativeContentBlob, Part } from './content'; -import { LiveGenerationConfig, Tool, ToolConfig } from './requests'; +import { + AudioTranscriptionConfig, + LiveGenerationConfig, + Tool, + ToolConfig +} from './requests'; +import { Transcription } from './responses'; /** * User input that is sent to the model. @@ -33,6 +39,8 @@ export interface _LiveClientContent { clientContent: { turns: [Content]; turnComplete: boolean; + inputTranscription?: Transcription; + outputTranscription?: Transcription; }; } @@ -74,9 +82,22 @@ export interface _LiveClientToolResponse { export interface _LiveClientSetup { setup: { model: string; - generationConfig?: LiveGenerationConfig; + generationConfig?: _LiveGenerationConfig; tools?: Tool[]; toolConfig?: ToolConfig; systemInstruction?: string | Part | Content; + inputAudioTranscription?: AudioTranscriptionConfig; + outputAudioTranscription?: AudioTranscriptionConfig; }; } + +/** + * The Live Generation Config. + * + * The public API ({@link LiveGenerationConfig}) has `inputAudioTranscription` and `outputAudioTranscription`, + * but the server expects these fields to be in the top-level `setup` message. This was a conscious API decision. + */ +export type _LiveGenerationConfig = Omit< + LiveGenerationConfig, + 'inputAudioTranscription' | 'outputAudioTranscription' +>; diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index 1e5fa36742..6e5d214768 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -184,6 +184,24 @@ export interface LiveGenerationConfig { * The modalities of the response. */ responseModalities?: ResponseModality[]; + /** + * Enables transcription of audio input. + * + * When enabled, the model will respond with transcriptions of your audio input in the `inputTranscriptions` property + * in {@link LiveServerContent} messages. Note that the transcriptions are broken up across + * messages, so you may only receive small amounts of text per message. For example, if you ask the model + * "How are you today?", the model may transcribe that input across three messages, broken up as "How a", "re yo", "u today?". + */ + inputAudioTranscription?: AudioTranscriptionConfig; + /** + * Enables transcription of audio input. + * + * When enabled, the model will respond with transcriptions of its audio output in the `outputTranscription` property + * in {@link LiveServerContent} messages. Note that the transcriptions are broken up across + * messages, so you may only receive small amounts of text per message. For example, if the model says + * "How are you today?", the model may transcribe that output across three messages, broken up as "How a", "re yo", "u today?". + */ + outputAudioTranscription?: AudioTranscriptionConfig; } /** @@ -478,3 +496,8 @@ export interface SpeechConfig { */ voiceConfig?: VoiceConfig; } + +/** + * The audio transcription configuration. + */ +export interface AudioTranscriptionConfig {} diff --git a/packages/ai/src/types/responses.ts b/packages/ai/src/types/responses.ts index ec06592f90..be56d0d2ba 100644 --- a/packages/ai/src/types/responses.ts +++ b/packages/ai/src/types/responses.ts @@ -553,6 +553,29 @@ export interface LiveServerContent { * model was not interrupted. */ interrupted?: boolean; + /** + * Transcription of the audio that was input to the model. + */ + inputTranscription?: Transcription; + /** + * Transcription of the audio output from the model. + */ + outputTranscription?: Transcription; +} + +/** + * Transcription of audio. This can be returned from a {@link LiveGenerativeModel} if transcription + * is enabled with the `inputAudioTranscription` or `outputAudioTranscription` properties on + * the {@link LiveGenerationConfig}. + * + * @beta + */ + +export interface Transcription { + /** + * The text transcription of the audio. + */ + text?: string; } /** From 6e0e303173c93646c07b9138c7bed8749b514e8f Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 28 Oct 2025 14:00:29 -0700 Subject: [PATCH 008/174] test(ai): Fix node tests (#9350) --- common/api-review/ai.api.md | 2 + packages/ai/src/api-browser.test.ts | 48 +++++++++++++++++++ packages/ai/src/api.test.ts | 17 +------ packages/ai/src/factory-node.ts | 46 ++++++++++++++++++ packages/ai/src/index.node.ts | 28 ++--------- packages/ai/src/methods/chat-session.test.ts | 10 +--- packages/ai/src/methods/count-tokens.test.ts | 17 ++----- packages/ai/src/methods/count-tokens.ts | 5 +- .../ai/src/methods/generate-content.test.ts | 9 +--- .../ai/src/models/generative-model.test.ts | 13 ++--- .../ai/src/requests/hybrid-helpers.test.ts | 4 +- packages/ai/src/requests/hybrid-helpers.ts | 7 +-- packages/ai/src/service.ts | 11 +++-- packages/ai/src/types/chrome-adapter.ts | 5 ++ .../test-utils/get-fake-firebase-services.ts | 25 +++++++--- 15 files changed, 150 insertions(+), 97 deletions(-) create mode 100644 packages/ai/src/api-browser.test.ts create mode 100644 packages/ai/src/factory-node.ts diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index a13fcb9cdf..08a12efc36 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -157,6 +157,8 @@ export interface ChromeAdapter { generateContent(request: GenerateContentRequest): Promise; generateContentStream(request: GenerateContentRequest): Promise; isAvailable(request: GenerateContentRequest): Promise; + // @internal (undocumented) + mode: InferenceMode; } // @public diff --git a/packages/ai/src/api-browser.test.ts b/packages/ai/src/api-browser.test.ts new file mode 100644 index 0000000000..74cfea05f4 --- /dev/null +++ b/packages/ai/src/api-browser.test.ts @@ -0,0 +1,48 @@ +/** + * @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. + */ +import { getAI, getGenerativeModel } from './api'; +import { expect } from 'chai'; +import { InferenceMode } from './public-types'; +import { getFullApp } from '../test-utils/get-fake-firebase-services'; +import { DEFAULT_HYBRID_IN_CLOUD_MODEL } from './constants'; +import { factory } from './factory-browser'; + +/** + * Browser-only top level API tests using a factory that provides + * a ChromeAdapter. + */ +describe('Top level API', () => { + describe('getAI()', () => { + it('getGenerativeModel with HybridParams sets a default model', () => { + const ai = getAI(getFullApp({ apiKey: 'key', appId: 'id' }, factory)); + const genModel = getGenerativeModel(ai, { + mode: InferenceMode.ONLY_ON_DEVICE + }); + expect(genModel.model).to.equal( + `models/${DEFAULT_HYBRID_IN_CLOUD_MODEL}` + ); + }); + it('getGenerativeModel with HybridParams honors a model override', () => { + const ai = getAI(getFullApp({ apiKey: 'key', appId: 'id' }, factory)); + const genModel = getGenerativeModel(ai, { + mode: InferenceMode.PREFER_ON_DEVICE, + inCloudParams: { model: 'my-model' } + }); + expect(genModel.model).to.equal('models/my-model'); + }); + }); +}); diff --git a/packages/ai/src/api.test.ts b/packages/ai/src/api.test.ts index 65ecbbdcba..3854f010fc 100644 --- a/packages/ai/src/api.test.ts +++ b/packages/ai/src/api.test.ts @@ -29,7 +29,7 @@ import { AI } from './public-types'; import { GenerativeModel } from './models/generative-model'; import { GoogleAIBackend, VertexAIBackend } from './backend'; import { getFullApp } from '../test-utils/get-fake-firebase-services'; -import { AI_TYPE, DEFAULT_HYBRID_IN_CLOUD_MODEL } from './constants'; +import { AI_TYPE } from './constants'; const fakeAI: AI = { app: { @@ -144,21 +144,6 @@ describe('Top level API', () => { expect(genModel).to.be.an.instanceOf(GenerativeModel); expect(genModel.model).to.equal('publishers/google/models/my-model'); }); - it('getGenerativeModel with HybridParams sets a default model', () => { - const genModel = getGenerativeModel(fakeAI, { - mode: 'only_on_device' - }); - expect(genModel.model).to.equal( - `publishers/google/models/${DEFAULT_HYBRID_IN_CLOUD_MODEL}` - ); - }); - it('getGenerativeModel with HybridParams honors a model override', () => { - const genModel = getGenerativeModel(fakeAI, { - mode: 'prefer_on_device', - inCloudParams: { model: 'my-model' } - }); - expect(genModel.model).to.equal('publishers/google/models/my-model'); - }); it('getImagenModel throws if no model is provided', () => { try { getImagenModel(fakeAI, {} as ImagenModelParams); diff --git a/packages/ai/src/factory-node.ts b/packages/ai/src/factory-node.ts new file mode 100644 index 0000000000..212ca18a82 --- /dev/null +++ b/packages/ai/src/factory-node.ts @@ -0,0 +1,46 @@ +/** + * @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. + */ + +import { + ComponentContainer, + InstanceFactoryOptions +} from '@firebase/component'; +import { AIError } from './errors'; +import { decodeInstanceIdentifier } from './helpers'; +import { AIService } from './service'; +import { AIErrorCode } from './types'; + +export function factory( + container: ComponentContainer, + { instanceIdentifier }: InstanceFactoryOptions +): AIService { + if (!instanceIdentifier) { + throw new AIError( + AIErrorCode.ERROR, + 'AIService instance identifier is undefined.' + ); + } + + const backend = decodeInstanceIdentifier(instanceIdentifier); + + // getImmediate for FirebaseApp will always succeed + const app = container.getProvider('app').getImmediate(); + const auth = container.getProvider('auth-internal'); + const appCheckProvider = container.getProvider('app-check-internal'); + + return new AIService(app, backend, auth, appCheckProvider); +} diff --git a/packages/ai/src/index.node.ts b/packages/ai/src/index.node.ts index bb05fdcea4..07d95e7d30 100644 --- a/packages/ai/src/index.node.ts +++ b/packages/ai/src/index.node.ts @@ -22,36 +22,16 @@ */ import { registerVersion, _registerComponent } from '@firebase/app'; -import { AIService } from './service'; import { AI_TYPE } from './constants'; import { Component, ComponentType } from '@firebase/component'; import { name, version } from '../package.json'; -import { decodeInstanceIdentifier } from './helpers'; -import { AIError } from './errors'; -import { AIErrorCode } from './public-types'; +import { factory } from './factory-node'; function registerAI(): void { _registerComponent( - new Component( - AI_TYPE, - (container, { instanceIdentifier }) => { - if (!instanceIdentifier) { - throw new AIError( - AIErrorCode.ERROR, - 'AIService instance identifier is undefined.' - ); - } - - const backend = decodeInstanceIdentifier(instanceIdentifier); - - // getImmediate for FirebaseApp will always succeed - const app = container.getProvider('app').getImmediate(); - const auth = container.getProvider('auth-internal'); - const appCheckProvider = container.getProvider('app-check-internal'); - return new AIService(app, backend, auth, appCheckProvider); - }, - ComponentType.PUBLIC - ).setMultipleInstances(true) + new Component(AI_TYPE, factory, ComponentType.PUBLIC).setMultipleInstances( + true + ) ); registerVersion(name, version, 'node'); diff --git a/packages/ai/src/methods/chat-session.test.ts b/packages/ai/src/methods/chat-session.test.ts index e92aa057af..1273d02876 100644 --- a/packages/ai/src/methods/chat-session.test.ts +++ b/packages/ai/src/methods/chat-session.test.ts @@ -20,11 +20,11 @@ import { match, restore, stub, useFakeTimers } from 'sinon'; import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; import * as generateContentMethods from './generate-content'; -import { Content, GenerateContentStreamResult, InferenceMode } from '../types'; +import { Content, GenerateContentStreamResult } from '../types'; import { ChatSession } from './chat-session'; import { ApiSettings } from '../types/internal'; import { VertexAIBackend } from '../backend'; -import { ChromeAdapterImpl } from './chrome-adapter'; +import { fakeChromeAdapter } from '../../test-utils/get-fake-firebase-services'; use(sinonChai); use(chaiAsPromised); @@ -37,12 +37,6 @@ const fakeApiSettings: ApiSettings = { backend: new VertexAIBackend() }; -const fakeChromeAdapter = new ChromeAdapterImpl( - // @ts-expect-error - undefined, - InferenceMode.PREFER_ON_DEVICE -); - describe('ChatSession', () => { afterEach(() => { restore(); diff --git a/packages/ai/src/methods/count-tokens.test.ts b/packages/ai/src/methods/count-tokens.test.ts index aabf06a841..84976d00ac 100644 --- a/packages/ai/src/methods/count-tokens.test.ts +++ b/packages/ai/src/methods/count-tokens.test.ts @@ -27,7 +27,7 @@ import { ApiSettings } from '../types/internal'; import { Task } from '../requests/request'; import { mapCountTokensRequest } from '../googleai-mappers'; import { GoogleAIBackend, VertexAIBackend } from '../backend'; -import { ChromeAdapterImpl } from './chrome-adapter'; +import { fakeChromeAdapter } from '../../test-utils/get-fake-firebase-services'; use(sinonChai); use(chaiAsPromised); @@ -52,12 +52,6 @@ const fakeRequestParams: CountTokensRequest = { contents: [{ parts: [{ text: 'hello' }], role: 'user' }] }; -const fakeChromeAdapter = new ChromeAdapterImpl( - // @ts-expect-error - undefined, - InferenceMode.PREFER_ON_DEVICE -); - describe('countTokens()', () => { afterEach(() => { restore(); @@ -197,11 +191,10 @@ describe('countTokens()', () => { }); }); it('throws if mode is ONLY_ON_DEVICE', async () => { - const chromeAdapter = new ChromeAdapterImpl( - // @ts-expect-error - undefined, - InferenceMode.ONLY_ON_DEVICE - ); + const chromeAdapter = { + ...fakeChromeAdapter, + mode: InferenceMode.ONLY_ON_DEVICE + }; await expect( countTokens(fakeApiSettings, 'model', fakeRequestParams, chromeAdapter) ).to.be.rejectedWith( diff --git a/packages/ai/src/methods/count-tokens.ts b/packages/ai/src/methods/count-tokens.ts index ecd86a8291..c6041a0bb9 100644 --- a/packages/ai/src/methods/count-tokens.ts +++ b/packages/ai/src/methods/count-tokens.ts @@ -28,7 +28,6 @@ import { ApiSettings } from '../types/internal'; import * as GoogleAIMapper from '../googleai-mappers'; import { BackendType } from '../public-types'; import { ChromeAdapter } from '../types/chrome-adapter'; -import { ChromeAdapterImpl } from './chrome-adapter'; export async function countTokensOnCloud( apiSettings: ApiSettings, @@ -61,9 +60,7 @@ export async function countTokens( chromeAdapter?: ChromeAdapter, requestOptions?: RequestOptions ): Promise { - if ( - (chromeAdapter as ChromeAdapterImpl)?.mode === InferenceMode.ONLY_ON_DEVICE - ) { + if (chromeAdapter?.mode === InferenceMode.ONLY_ON_DEVICE) { throw new AIError( AIErrorCode.UNSUPPORTED, 'countTokens() is not supported for on-device models.' diff --git a/packages/ai/src/methods/generate-content.test.ts b/packages/ai/src/methods/generate-content.test.ts index 40dc7c7b36..33a9ae5f5e 100644 --- a/packages/ai/src/methods/generate-content.test.ts +++ b/packages/ai/src/methods/generate-content.test.ts @@ -28,7 +28,6 @@ import { HarmBlockMethod, HarmBlockThreshold, HarmCategory, - InferenceMode, Language, Outcome } from '../types'; @@ -37,17 +36,11 @@ import { Task } from '../requests/request'; import { AIError } from '../api'; import { mapGenerateContentRequest } from '../googleai-mappers'; import { GoogleAIBackend, VertexAIBackend } from '../backend'; -import { ChromeAdapterImpl } from './chrome-adapter'; +import { fakeChromeAdapter } from '../../test-utils/get-fake-firebase-services'; use(sinonChai); use(chaiAsPromised); -const fakeChromeAdapter = new ChromeAdapterImpl( - // @ts-expect-error - undefined, - InferenceMode.PREFER_ON_DEVICE -); - const fakeApiSettings: ApiSettings = { apiKey: 'key', project: 'my-project', diff --git a/packages/ai/src/models/generative-model.test.ts b/packages/ai/src/models/generative-model.test.ts index bcd78d746d..90399e6811 100644 --- a/packages/ai/src/models/generative-model.test.ts +++ b/packages/ai/src/models/generative-model.test.ts @@ -20,7 +20,8 @@ import { FunctionCallingMode, AI, InferenceMode, - AIErrorCode + AIErrorCode, + ChromeAdapter } from '../public-types'; import * as request from '../requests/request'; import { SinonStub, match, restore, stub } from 'sinon'; @@ -30,9 +31,9 @@ import { } from '../../test-utils/mock-response'; import sinonChai from 'sinon-chai'; import { VertexAIBackend } from '../backend'; -import { ChromeAdapterImpl } from '../methods/chrome-adapter'; import { AIError } from '../errors'; import chaiAsPromised from 'chai-as-promised'; +import { fakeChromeAdapter } from '../../test-utils/get-fake-firebase-services'; use(sinonChai); use(chaiAsPromised); @@ -51,12 +52,6 @@ const fakeAI: AI = { location: 'us-central1' }; -const fakeChromeAdapter = new ChromeAdapterImpl( - // @ts-expect-error - undefined, - InferenceMode.PREFER_ON_DEVICE -); - describe('GenerativeModel', () => { it('passes params through to generateContent', async () => { const genModel = new GenerativeModel( @@ -436,7 +431,7 @@ describe('GenerativeModel', () => { describe('GenerativeModel dispatch logic', () => { let makeRequestStub: SinonStub; - let mockChromeAdapter: ChromeAdapterImpl; + let mockChromeAdapter: ChromeAdapter; function stubMakeRequest(stream?: boolean): void { if (stream) { diff --git a/packages/ai/src/requests/hybrid-helpers.test.ts b/packages/ai/src/requests/hybrid-helpers.test.ts index 33e83c0469..d5d1369131 100644 --- a/packages/ai/src/requests/hybrid-helpers.test.ts +++ b/packages/ai/src/requests/hybrid-helpers.test.ts @@ -22,18 +22,18 @@ import { GenerateContentRequest, InferenceMode, AIErrorCode, + ChromeAdapter, InferenceSource } from '../types'; import { AIError } from '../errors'; import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; -import { ChromeAdapterImpl } from '../methods/chrome-adapter'; use(sinonChai); use(chaiAsPromised); describe('callCloudOrDevice', () => { - let chromeAdapter: SinonStubbedInstance; + let chromeAdapter: SinonStubbedInstance; let onDeviceCall: SinonStub; let inCloudCall: SinonStub; let request: GenerateContentRequest; diff --git a/packages/ai/src/requests/hybrid-helpers.ts b/packages/ai/src/requests/hybrid-helpers.ts index b37505bf93..2697216cd8 100644 --- a/packages/ai/src/requests/hybrid-helpers.ts +++ b/packages/ai/src/requests/hybrid-helpers.ts @@ -23,7 +23,6 @@ import { ChromeAdapter, InferenceSource } from '../types'; -import { ChromeAdapterImpl } from '../methods/chrome-adapter'; const errorsCausingFallback: AIErrorCode[] = [ // most network errors @@ -61,7 +60,7 @@ export async function callCloudOrDevice( inferenceSource: InferenceSource.IN_CLOUD }; } - switch ((chromeAdapter as ChromeAdapterImpl).mode) { + switch (chromeAdapter.mode) { case InferenceMode.ONLY_ON_DEVICE: if (await chromeAdapter.isAvailable(request)) { return { @@ -107,9 +106,7 @@ export async function callCloudOrDevice( default: throw new AIError( AIErrorCode.ERROR, - `Unexpected infererence mode: ${ - (chromeAdapter as ChromeAdapterImpl).mode - }` + `Unexpected infererence mode: ${chromeAdapter.mode}` ); } } diff --git a/packages/ai/src/service.ts b/packages/ai/src/service.ts index 0beb8dda1c..a862f19422 100644 --- a/packages/ai/src/service.ts +++ b/packages/ai/src/service.ts @@ -16,7 +16,13 @@ */ import { FirebaseApp, _FirebaseService } from '@firebase/app'; -import { AI, AIOptions, InferenceMode, OnDeviceParams } from './public-types'; +import { + AI, + AIOptions, + ChromeAdapter, + InferenceMode, + OnDeviceParams +} from './public-types'; import { AppCheckInternalComponentName, FirebaseAppCheckInternal @@ -27,7 +33,6 @@ import { FirebaseAuthInternalName } from '@firebase/auth-interop-types'; import { Backend, VertexAIBackend } from './backend'; -import { ChromeAdapterImpl } from './methods/chrome-adapter'; export class AIService implements AI, _FirebaseService { auth: FirebaseAuthInternal | null; @@ -44,7 +49,7 @@ export class AIService implements AI, _FirebaseService { mode: InferenceMode, window?: Window, params?: OnDeviceParams - ) => ChromeAdapterImpl | undefined + ) => ChromeAdapter | undefined ) { const appCheck = appCheckProvider?.getImmediate({ optional: true }); const auth = authProvider?.getImmediate({ optional: true }); diff --git a/packages/ai/src/types/chrome-adapter.ts b/packages/ai/src/types/chrome-adapter.ts index fc33325217..a026b8a1a4 100644 --- a/packages/ai/src/types/chrome-adapter.ts +++ b/packages/ai/src/types/chrome-adapter.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { InferenceMode } from './enums'; import { CountTokensRequest, GenerateContentRequest } from './requests'; /** @@ -27,6 +28,10 @@ import { CountTokensRequest, GenerateContentRequest } from './requests'; * @beta */ export interface ChromeAdapter { + /** + * @internal + */ + mode: InferenceMode; /** * Checks if the on-device model is capable of handling a given * request. diff --git a/packages/ai/test-utils/get-fake-firebase-services.ts b/packages/ai/test-utils/get-fake-firebase-services.ts index 63789c1a00..f639d919ed 100644 --- a/packages/ai/test-utils/get-fake-firebase-services.ts +++ b/packages/ai/test-utils/get-fake-firebase-services.ts @@ -21,10 +21,11 @@ import { _registerComponent, _addOrOverwriteComponent } from '@firebase/app'; -import { Component, ComponentType } from '@firebase/component'; +import { Component, ComponentType, InstanceFactory } from '@firebase/component'; import { FirebaseAppCheckInternal } from '@firebase/app-check-interop-types'; import { AI_TYPE } from '../src/constants'; -import { factory } from '../src/factory-browser'; +import { factory as factoryNode } from '../src/factory-node'; +import { ChromeAdapter, InferenceMode } from '../src/types'; const fakeConfig = { projectId: 'projectId', @@ -34,10 +35,13 @@ const fakeConfig = { storageBucket: 'storageBucket' }; -export function getFullApp(fakeAppParams?: { - appId?: string; - apiKey?: string; -}): FirebaseApp { +export function getFullApp( + fakeAppParams?: { + appId?: string; + apiKey?: string; + }, + factory: InstanceFactory<'AI'> = factoryNode +): FirebaseApp { _registerComponent( new Component(AI_TYPE, factory, ComponentType.PUBLIC).setMultipleInstances( true @@ -69,3 +73,12 @@ export function getFullApp(fakeAppParams?: { ); return app; } + +export const fakeChromeAdapter: ChromeAdapter = { + mode: InferenceMode.PREFER_ON_DEVICE, + // Individual tests may stub this to resolve true as needed. + isAvailable: () => Promise.resolve(false), + generateContent: () => Promise.resolve({} as Response), + generateContentStream: () => Promise.resolve({} as Response), + countTokens: () => Promise.resolve({} as Response) +}; From 1f44435d676a163420c4b4e4d24630dfcea52573 Mon Sep 17 00:00:00 2001 From: Google Open Source Bot Date: Thu, 30 Oct 2025 08:36:18 -0700 Subject: [PATCH 009/174] Version Packages (#9353) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/angry-apples-think.md | 5 ----- .changeset/dull-ligers-bow.md | 7 ------- .changeset/fast-rocks-sing.md | 6 ------ .changeset/metal-lies-compete.md | 6 ------ .changeset/rare-hats-know.md | 5 ----- .changeset/smooth-parrots-speak.md | 6 ------ integration/compat-interop/package.json | 8 ++++---- integration/firestore/package.json | 2 +- integration/messaging/package.json | 2 +- packages/ai/CHANGELOG.md | 15 +++++++++++++++ packages/ai/package.json | 4 ++-- packages/analytics-compat/package.json | 2 +- packages/analytics/package.json | 2 +- packages/app-check-compat/package.json | 2 +- packages/app-check/package.json | 2 +- packages/app-compat/CHANGELOG.md | 7 +++++++ packages/app-compat/package.json | 4 ++-- packages/app/CHANGELOG.md | 6 ++++++ packages/app/package.json | 2 +- packages/auth-compat/CHANGELOG.md | 7 +++++++ packages/auth-compat/package.json | 6 +++--- packages/auth/CHANGELOG.md | 8 ++++++++ packages/auth/package.json | 4 ++-- packages/data-connect/package.json | 2 +- packages/database-compat/package.json | 2 +- packages/database/package.json | 2 +- packages/firebase/CHANGELOG.md | 22 ++++++++++++++++++++++ packages/firebase/package.json | 12 ++++++------ packages/firestore-compat/package.json | 2 +- packages/firestore/package.json | 6 +++--- packages/functions-compat/package.json | 2 +- packages/functions/package.json | 2 +- packages/installations-compat/package.json | 2 +- packages/installations/package.json | 2 +- packages/messaging-compat/package.json | 2 +- packages/messaging/package.json | 2 +- packages/performance-compat/package.json | 2 +- packages/performance/package.json | 2 +- packages/remote-config-compat/package.json | 2 +- packages/remote-config/package.json | 2 +- packages/storage-compat/package.json | 4 ++-- packages/storage/package.json | 4 ++-- packages/template/package.json | 2 +- repo-scripts/size-analysis/package.json | 2 +- 44 files changed, 114 insertions(+), 84 deletions(-) delete mode 100644 .changeset/angry-apples-think.md delete mode 100644 .changeset/dull-ligers-bow.md delete mode 100644 .changeset/fast-rocks-sing.md delete mode 100644 .changeset/metal-lies-compete.md delete mode 100644 .changeset/rare-hats-know.md delete mode 100644 .changeset/smooth-parrots-speak.md diff --git a/.changeset/angry-apples-think.md b/.changeset/angry-apples-think.md deleted file mode 100644 index dbc41380ab..0000000000 --- a/.changeset/angry-apples-think.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/auth': patch ---- - -Expose `browserCookiePersistence` beta feature in public typings. diff --git a/.changeset/dull-ligers-bow.md b/.changeset/dull-ligers-bow.md deleted file mode 100644 index 13606d73f9..0000000000 --- a/.changeset/dull-ligers-bow.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'firebase': minor -'@firebase/ai': minor ---- - -Deprecate `sendMediaChunks()` and `sendMediaStream()`. Instead, use the new methods added to the `LiveSession` class. -Add `sendTextRealtime()`, `sendAudioReatime()`, and `sendVideoRealtime()` to the `LiveSession` class. diff --git a/.changeset/fast-rocks-sing.md b/.changeset/fast-rocks-sing.md deleted file mode 100644 index ccbc997da3..0000000000 --- a/.changeset/fast-rocks-sing.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/ai': minor ---- - -Add support for audio transcriptions in the Live API. diff --git a/.changeset/metal-lies-compete.md b/.changeset/metal-lies-compete.md deleted file mode 100644 index 5a086a9e12..0000000000 --- a/.changeset/metal-lies-compete.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/auth': patch -'firebase': patch ---- - -Export MISSING_PASSWORD via AuthErrorCodes in @firebase/auth. diff --git a/.changeset/rare-hats-know.md b/.changeset/rare-hats-know.md deleted file mode 100644 index 68fafc7849..0000000000 --- a/.changeset/rare-hats-know.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/ai': patch ---- - -Fix logic for merging default `onDeviceParams` with user-provided `onDeviceParams`. diff --git a/.changeset/smooth-parrots-speak.md b/.changeset/smooth-parrots-speak.md deleted file mode 100644 index 49a7b10c73..0000000000 --- a/.changeset/smooth-parrots-speak.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -Add `inferenceSource` to the response from `generateContent` and `generateContentStream`. This property indicates whether on-device or in-cloud inference was used to generate the result. diff --git a/integration/compat-interop/package.json b/integration/compat-interop/package.json index a88d4734e5..9660e71e65 100644 --- a/integration/compat-interop/package.json +++ b/integration/compat-interop/package.json @@ -8,12 +8,12 @@ "test:debug": "karma start --browsers Chrome --auto-watch" }, "dependencies": { - "@firebase/app": "0.14.4", - "@firebase/app-compat": "0.5.4", + "@firebase/app": "0.14.5", + "@firebase/app-compat": "0.5.5", "@firebase/analytics": "0.10.19", "@firebase/analytics-compat": "0.2.25", - "@firebase/auth": "1.11.0", - "@firebase/auth-compat": "0.6.0", + "@firebase/auth": "1.11.1", + "@firebase/auth-compat": "0.6.1", "@firebase/functions": "0.13.1", "@firebase/functions-compat": "0.4.1", "@firebase/messaging": "0.12.23", diff --git a/integration/firestore/package.json b/integration/firestore/package.json index c050d38ec9..26e7f66f19 100644 --- a/integration/firestore/package.json +++ b/integration/firestore/package.json @@ -14,7 +14,7 @@ "test:memory:debug": "yarn build:memory; karma start --auto-watch --browsers Chrome" }, "dependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "@firebase/firestore": "4.9.2" }, "devDependencies": { diff --git a/integration/messaging/package.json b/integration/messaging/package.json index 5c8358e662..1c633bede9 100644 --- a/integration/messaging/package.json +++ b/integration/messaging/package.json @@ -9,7 +9,7 @@ "test:manual": "mocha --exit" }, "devDependencies": { - "firebase": "12.4.0", + "firebase": "12.5.0", "chai": "4.5.0", "chromedriver": "119.0.1", "express": "4.21.2", diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index af19b6f354..1c3959ccdf 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,5 +1,20 @@ # @firebase/ai +## 2.5.0 + +### Minor Changes + +- [`22e0a1a`](https://github.com/firebase/firebase-js-sdk/commit/22e0a1adbc994196690bd020472d119c1a3d200b) [#9291](https://github.com/firebase/firebase-js-sdk/pull/9291) - Deprecate `sendMediaChunks()` and `sendMediaStream()`. Instead, use the new methods added to the `LiveSession` class. + Add `sendTextRealtime()`, `sendAudioReatime()`, and `sendVideoRealtime()` to the `LiveSession` class. + +- [`bc5a7c4`](https://github.com/firebase/firebase-js-sdk/commit/bc5a7c4a74e72e9218d1435bfe50711c77b47cbd) [#9330](https://github.com/firebase/firebase-js-sdk/pull/9330) - Add support for audio transcriptions in the Live API. + +- [`c8263c4`](https://github.com/firebase/firebase-js-sdk/commit/c8263c471db4df1b0e23f0d2a11c69fd6b920e2e) [#9315](https://github.com/firebase/firebase-js-sdk/pull/9315) - Add `inferenceSource` to the response from `generateContent` and `generateContentStream`. This property indicates whether on-device or in-cloud inference was used to generate the result. + +### Patch Changes + +- [`44d9891`](https://github.com/firebase/firebase-js-sdk/commit/44d9891f93298ab4bcef5170c40c235831af0276) [#9314](https://github.com/firebase/firebase-js-sdk/pull/9314) - Fix logic for merging default `onDeviceParams` with user-provided `onDeviceParams`. + ## 2.4.0 ### Minor Changes diff --git a/packages/ai/package.json b/packages/ai/package.json index c5a27484c3..dcb6f11fdb 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/ai", - "version": "2.4.0", + "version": "2.5.0", "description": "The Firebase AI SDK", "author": "Firebase (https://firebase.google.com/)", "engines": { @@ -60,7 +60,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/analytics-compat/package.json b/packages/analytics-compat/package.json index a4c07015fe..f06c82a554 100644 --- a/packages/analytics-compat/package.json +++ b/packages/analytics-compat/package.json @@ -22,7 +22,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.4", + "@firebase/app-compat": "0.5.5", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/analytics/package.json b/packages/analytics/package.json index b5dd7e377e..66fb8b4230 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -47,7 +47,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "@rollup/plugin-commonjs": "21.1.0", diff --git a/packages/app-check-compat/package.json b/packages/app-check-compat/package.json index a2fc5b7b78..a510523e5a 100644 --- a/packages/app-check-compat/package.json +++ b/packages/app-check-compat/package.json @@ -43,7 +43,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.4", + "@firebase/app-compat": "0.5.5", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-check/package.json b/packages/app-check/package.json index 5700ea8934..cb1ad6909e 100644 --- a/packages/app-check/package.json +++ b/packages/app-check/package.json @@ -44,7 +44,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-compat/CHANGELOG.md b/packages/app-compat/CHANGELOG.md index 5d1f234c05..822ae9c1cd 100644 --- a/packages/app-compat/CHANGELOG.md +++ b/packages/app-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/app-compat +## 0.5.5 + +### Patch Changes + +- Updated dependencies []: + - @firebase/app@0.14.5 + ## 0.5.4 ### Patch Changes diff --git a/packages/app-compat/package.json b/packages/app-compat/package.json index 548e57cad5..c1ad275214 100644 --- a/packages/app-compat/package.json +++ b/packages/app-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-compat", - "version": "0.5.4", + "version": "0.5.5", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,7 +37,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "@firebase/util": "1.13.0", "@firebase/logger": "0.5.0", "@firebase/component": "0.7.0", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index b72699ffe2..a370d88e79 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/app +## 0.14.5 + +### Patch Changes + +- Update SDK_VERSION. + ## 0.14.4 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index aef76c7da8..c695239580 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app", - "version": "0.14.4", + "version": "0.14.5", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", diff --git a/packages/auth-compat/CHANGELOG.md b/packages/auth-compat/CHANGELOG.md index 401045ee12..c8024cbe85 100644 --- a/packages/auth-compat/CHANGELOG.md +++ b/packages/auth-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/auth-compat +## 0.6.1 + +### Patch Changes + +- Updated dependencies [[`91c218d`](https://github.com/firebase/firebase-js-sdk/commit/91c218db2d14cb4f1b978b9073510b8bc8f91233), [`2615081`](https://github.com/firebase/firebase-js-sdk/commit/261508183c249dcec737448dde3aad7399f4668c)]: + - @firebase/auth@1.11.1 + ## 0.6.0 ### Minor Changes diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index 0db3546ce9..47f326fd71 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth-compat", - "version": "0.6.0", + "version": "0.6.1", "description": "FirebaseAuth compatibility package that uses API style compatible with Firebase@8 and prior versions", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -49,7 +49,7 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/auth": "1.11.0", + "@firebase/auth": "1.11.1", "@firebase/auth-types": "0.13.0", "@firebase/component": "0.7.0", "@firebase/util": "1.13.0", @@ -57,7 +57,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.4", + "@firebase/app-compat": "0.5.5", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/auth/CHANGELOG.md b/packages/auth/CHANGELOG.md index 6439b54248..298371600d 100644 --- a/packages/auth/CHANGELOG.md +++ b/packages/auth/CHANGELOG.md @@ -1,5 +1,13 @@ # @firebase/auth +## 1.11.1 + +### Patch Changes + +- [`91c218d`](https://github.com/firebase/firebase-js-sdk/commit/91c218db2d14cb4f1b978b9073510b8bc8f91233) [#9313](https://github.com/firebase/firebase-js-sdk/pull/9313) - Expose `browserCookiePersistence` beta feature in public typings. + +- [`2615081`](https://github.com/firebase/firebase-js-sdk/commit/261508183c249dcec737448dde3aad7399f4668c) [#9297](https://github.com/firebase/firebase-js-sdk/pull/9297) (fixes [#9270](https://github.com/firebase/firebase-js-sdk/issues/9270)) - Export MISSING_PASSWORD via AuthErrorCodes in @firebase/auth. + ## 1.11.0 ### Minor Changes diff --git a/packages/auth/package.json b/packages/auth/package.json index e21a6385df..c515d4a193 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth", - "version": "1.11.0", + "version": "1.11.1", "description": "The Firebase Authenticaton component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/node/index.js", @@ -131,7 +131,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-strip": "2.1.0", "@types/express": "4.17.21", diff --git a/packages/data-connect/package.json b/packages/data-connect/package.json index 18dbb00e43..bf1fc8ce33 100644 --- a/packages/data-connect/package.json +++ b/packages/data-connect/package.json @@ -55,7 +55,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/database-compat/package.json b/packages/database-compat/package.json index 8fd65a1efe..1f4e0f55b7 100644 --- a/packages/database-compat/package.json +++ b/packages/database-compat/package.json @@ -57,7 +57,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.4", + "@firebase/app-compat": "0.5.5", "typescript": "5.5.4" }, "repository": { diff --git a/packages/database/package.json b/packages/database/package.json index 411a6bcfcd..4d7f3d18db 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -57,7 +57,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/firebase/CHANGELOG.md b/packages/firebase/CHANGELOG.md index 622cfef4d9..eb85a4d474 100644 --- a/packages/firebase/CHANGELOG.md +++ b/packages/firebase/CHANGELOG.md @@ -1,5 +1,27 @@ # firebase +## 12.5.0 + +### Minor Changes + +- [`22e0a1a`](https://github.com/firebase/firebase-js-sdk/commit/22e0a1adbc994196690bd020472d119c1a3d200b) [#9291](https://github.com/firebase/firebase-js-sdk/pull/9291) - Deprecate `sendMediaChunks()` and `sendMediaStream()`. Instead, use the new methods added to the `LiveSession` class. + Add `sendTextRealtime()`, `sendAudioReatime()`, and `sendVideoRealtime()` to the `LiveSession` class. + +- [`bc5a7c4`](https://github.com/firebase/firebase-js-sdk/commit/bc5a7c4a74e72e9218d1435bfe50711c77b47cbd) [#9330](https://github.com/firebase/firebase-js-sdk/pull/9330) - Add support for audio transcriptions in the Live API. + +- [`c8263c4`](https://github.com/firebase/firebase-js-sdk/commit/c8263c471db4df1b0e23f0d2a11c69fd6b920e2e) [#9315](https://github.com/firebase/firebase-js-sdk/pull/9315) - Add `inferenceSource` to the response from `generateContent` and `generateContentStream`. This property indicates whether on-device or in-cloud inference was used to generate the result. + +### Patch Changes + +- [`2615081`](https://github.com/firebase/firebase-js-sdk/commit/261508183c249dcec737448dde3aad7399f4668c) [#9297](https://github.com/firebase/firebase-js-sdk/pull/9297) (fixes [#9270](https://github.com/firebase/firebase-js-sdk/issues/9270)) - Export MISSING_PASSWORD via AuthErrorCodes in @firebase/auth. + +- Updated dependencies [[`91c218d`](https://github.com/firebase/firebase-js-sdk/commit/91c218db2d14cb4f1b978b9073510b8bc8f91233), [`22e0a1a`](https://github.com/firebase/firebase-js-sdk/commit/22e0a1adbc994196690bd020472d119c1a3d200b), [`bc5a7c4`](https://github.com/firebase/firebase-js-sdk/commit/bc5a7c4a74e72e9218d1435bfe50711c77b47cbd), [`2615081`](https://github.com/firebase/firebase-js-sdk/commit/261508183c249dcec737448dde3aad7399f4668c), [`44d9891`](https://github.com/firebase/firebase-js-sdk/commit/44d9891f93298ab4bcef5170c40c235831af0276), [`c8263c4`](https://github.com/firebase/firebase-js-sdk/commit/c8263c471db4df1b0e23f0d2a11c69fd6b920e2e)]: + - @firebase/auth@1.11.1 + - @firebase/app@0.14.5 + - @firebase/ai@2.5.0 + - @firebase/auth-compat@0.6.1 + - @firebase/app-compat@0.5.5 + ## 12.4.0 ### Minor Changes diff --git a/packages/firebase/package.json b/packages/firebase/package.json index ae6c20b239..d8e9b5d5c4 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -1,6 +1,6 @@ { "name": "firebase", - "version": "12.4.0", + "version": "12.5.0", "description": "Firebase JavaScript library for web and Node.js", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -399,12 +399,12 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/ai": "2.4.0", - "@firebase/app": "0.14.4", - "@firebase/app-compat": "0.5.4", + "@firebase/ai": "2.5.0", + "@firebase/app": "0.14.5", + "@firebase/app-compat": "0.5.5", "@firebase/app-types": "0.9.3", - "@firebase/auth": "1.11.0", - "@firebase/auth-compat": "0.6.0", + "@firebase/auth": "1.11.1", + "@firebase/auth-compat": "0.6.1", "@firebase/data-connect": "0.3.11", "@firebase/database": "1.1.0", "@firebase/database-compat": "2.1.0", diff --git a/packages/firestore-compat/package.json b/packages/firestore-compat/package.json index be610b3b7d..07d80f462e 100644 --- a/packages/firestore-compat/package.json +++ b/packages/firestore-compat/package.json @@ -53,7 +53,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.4", + "@firebase/app-compat": "0.5.5", "@types/eslint": "7.29.0", "rollup": "2.79.2", "rollup-plugin-sourcemaps": "0.6.3", diff --git a/packages/firestore/package.json b/packages/firestore/package.json index fc04516212..1a7bb7da1b 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -112,9 +112,9 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.4", - "@firebase/app-compat": "0.5.4", - "@firebase/auth": "1.11.0", + "@firebase/app": "0.14.5", + "@firebase/app-compat": "0.5.5", + "@firebase/auth": "1.11.1", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", "@types/eslint": "7.29.0", diff --git a/packages/functions-compat/package.json b/packages/functions-compat/package.json index 00f065b2b3..c64d29d4ea 100644 --- a/packages/functions-compat/package.json +++ b/packages/functions-compat/package.json @@ -29,7 +29,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.4", + "@firebase/app-compat": "0.5.5", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/functions/package.json b/packages/functions/package.json index 99f5059fb0..4a85faa985 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -49,7 +49,7 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/installations-compat/package.json b/packages/installations-compat/package.json index c5ff66cd0d..20e21e0d8a 100644 --- a/packages/installations-compat/package.json +++ b/packages/installations-compat/package.json @@ -44,7 +44,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app-compat": "0.5.4", + "@firebase/app-compat": "0.5.5", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/installations/package.json b/packages/installations/package.json index ced645951a..9ae0bb0a09 100644 --- a/packages/installations/package.json +++ b/packages/installations/package.json @@ -49,7 +49,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/messaging-compat/package.json b/packages/messaging-compat/package.json index 2279cce7c2..92a6f8fba1 100644 --- a/packages/messaging-compat/package.json +++ b/packages/messaging-compat/package.json @@ -44,7 +44,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.4", + "@firebase/app-compat": "0.5.5", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", "ts-essentials": "9.4.2", diff --git a/packages/messaging/package.json b/packages/messaging/package.json index 12a85d5045..bd87ae31fc 100644 --- a/packages/messaging/package.json +++ b/packages/messaging/package.json @@ -60,7 +60,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/performance-compat/package.json b/packages/performance-compat/package.json index b0d17ef589..94050c1ed3 100644 --- a/packages/performance-compat/package.json +++ b/packages/performance-compat/package.json @@ -51,7 +51,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.4" + "@firebase/app-compat": "0.5.5" }, "repository": { "directory": "packages/performance-compat", diff --git a/packages/performance/package.json b/packages/performance/package.json index 302a33531c..125d3f084f 100644 --- a/packages/performance/package.json +++ b/packages/performance/package.json @@ -47,7 +47,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/remote-config-compat/package.json b/packages/remote-config-compat/package.json index 07180167c4..dbf19c1830 100644 --- a/packages/remote-config-compat/package.json +++ b/packages/remote-config-compat/package.json @@ -50,7 +50,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.4" + "@firebase/app-compat": "0.5.5" }, "repository": { "directory": "packages/remote-config-compat", diff --git a/packages/remote-config/package.json b/packages/remote-config/package.json index 74cdac9756..d02f746ed2 100644 --- a/packages/remote-config/package.json +++ b/packages/remote-config/package.json @@ -48,7 +48,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/storage-compat/package.json b/packages/storage-compat/package.json index 0ba6213cfa..19a5f352b7 100644 --- a/packages/storage-compat/package.json +++ b/packages/storage-compat/package.json @@ -44,8 +44,8 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.4", - "@firebase/auth-compat": "0.6.0", + "@firebase/app-compat": "0.5.5", + "@firebase/auth-compat": "0.6.1", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/storage/package.json b/packages/storage/package.json index 312f284fdd..2b0df30704 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -54,8 +54,8 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.4", - "@firebase/auth": "1.11.0", + "@firebase/app": "0.14.5", + "@firebase/auth": "1.11.1", "rollup": "2.79.2", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", diff --git a/packages/template/package.json b/packages/template/package.json index bad73496ca..635f4f451c 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -48,7 +48,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index 162a491eac..78a2f87e21 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -40,7 +40,7 @@ "yargs": "17.7.2" }, "devDependencies": { - "@firebase/app": "0.14.4", + "@firebase/app": "0.14.5", "@firebase/logger": "0.5.0", "@types/webpack": "5.28.5" }, From c47bd7175bf11fba1840ad789294238e0614e57d Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Thu, 30 Oct 2025 12:23:31 -0700 Subject: [PATCH 010/174] Fixed onComplete for FDC (#9349) --- .changeset/spotty-shirts-design.md | 5 + common/api-review/data-connect.api.md | 10 -- packages/data-connect/src/api.browser.ts | 1 + packages/data-connect/src/api/DataConnect.ts | 6 +- packages/data-connect/src/api/query.ts | 10 +- .../src/core/AppCheckTokenProvider.ts | 6 +- .../data-connect/src/core/QueryManager.ts | 15 ++- packages/data-connect/src/network/fetch.ts | 6 +- .../src/network/transport/rest.ts | 4 +- .../data-connect/src/util/validateArgs.ts | 2 +- .../data-connect/test/unit/queries.test.ts | 98 ++++++++++++++++++- packages/data-connect/tsconfig.json | 2 +- .../emulators/dataconnect-emulator.ts | 2 +- 13 files changed, 134 insertions(+), 33 deletions(-) create mode 100644 .changeset/spotty-shirts-design.md diff --git a/.changeset/spotty-shirts-design.md b/.changeset/spotty-shirts-design.md new file mode 100644 index 0000000000..77c6a8c830 --- /dev/null +++ b/.changeset/spotty-shirts-design.md @@ -0,0 +1,5 @@ +--- +"@firebase/data-connect": patch +--- + +Fixed issue where onComplete wasn't triggering when the user calls `unsubscribe` on a subscription. diff --git a/common/api-review/data-connect.api.md b/common/api-review/data-connect.api.md index 9e3d242487..27a9d4af20 100644 --- a/common/api-review/data-connect.api.md +++ b/common/api-review/data-connect.api.md @@ -109,16 +109,6 @@ export interface DataConnectResult extends OpResult { ref: OperationRef; } -// @public -export interface DataConnectSubscription { - // (undocumented) - errCallback?: (e?: DataConnectError) => void; - // (undocumented) - unsubscribe: () => void; - // (undocumented) - userCallback: OnResultSubscription; -} - // @public (undocumented) export type DataSource = typeof SOURCE_CACHE | typeof SOURCE_SERVER; diff --git a/packages/data-connect/src/api.browser.ts b/packages/data-connect/src/api.browser.ts index 1ffcb8d164..d31c325353 100644 --- a/packages/data-connect/src/api.browser.ts +++ b/packages/data-connect/src/api.browser.ts @@ -102,6 +102,7 @@ export function subscribe( return ref.dataConnect._queryManager.addSubscription( ref, onResult, + onComplete, onError, initialCache ); diff --git a/packages/data-connect/src/api/DataConnect.ts b/packages/data-connect/src/api/DataConnect.ts index b731136378..15e713ba23 100644 --- a/packages/data-connect/src/api/DataConnect.ts +++ b/packages/data-connect/src/api/DataConnect.ts @@ -198,6 +198,7 @@ export class DataConnect { // @internal enableEmulator(transportOptions: TransportOptions): void { if ( + this._transportOptions && this._initialized && !areTransportOptionsEqual(this._transportOptions, transportOptions) ) { @@ -314,7 +315,10 @@ export function validateDCOptions(dcOptions: ConnectorConfig): boolean { throw new DataConnectError(Code.INVALID_ARGUMENT, 'DC Option Required'); } fields.forEach(field => { - if (dcOptions[field] === null || dcOptions[field] === undefined) { + if ( + dcOptions[field as keyof ConnectorConfig] === null || + dcOptions[field as keyof ConnectorConfig] === undefined + ) { throw new DataConnectError(Code.INVALID_ARGUMENT, `${field} Required`); } }); diff --git a/packages/data-connect/src/api/query.ts b/packages/data-connect/src/api/query.ts index a1cd072616..43683cafd6 100644 --- a/packages/data-connect/src/api/query.ts +++ b/packages/data-connect/src/api/query.ts @@ -39,14 +39,6 @@ export type OnErrorSubscription = (err?: DataConnectError) => void; * Signature for unsubscribe from `subscribe` */ export type QueryUnsubscribe = () => void; -/** - * Representation of user provided subscription options. - */ -export interface DataConnectSubscription { - userCallback: OnResultSubscription; - errCallback?: (e?: DataConnectError) => void; - unsubscribe: () => void; -} /** * QueryRef object @@ -124,7 +116,7 @@ export function queryRef( dataConnect: dcInstance, refType: QUERY_STR, name: queryName, - variables + variables: variables as Variables }; } /** diff --git a/packages/data-connect/src/core/AppCheckTokenProvider.ts b/packages/data-connect/src/core/AppCheckTokenProvider.ts index 4b49a8f674..615b45f389 100644 --- a/packages/data-connect/src/core/AppCheckTokenProvider.ts +++ b/packages/data-connect/src/core/AppCheckTokenProvider.ts @@ -29,7 +29,7 @@ import { Provider } from '@firebase/component'; * Abstraction around AppCheck's token fetching capabilities. */ export class AppCheckTokenProvider { - private appCheck?: FirebaseAppCheckInternal; + private appCheck?: FirebaseAppCheckInternal | null; private serverAppAppCheckToken?: string; constructor( app: FirebaseApp, @@ -47,13 +47,13 @@ export class AppCheckTokenProvider { } } - getToken(): Promise { + getToken(): Promise { if (this.serverAppAppCheckToken) { return Promise.resolve({ token: this.serverAppAppCheckToken }); } if (!this.appCheck) { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { // Support delayed initialization of FirebaseAppCheck. This allows our // customers to initialize the RTDB SDK before initializing Firebase // AppCheck and ensures that all requests are authenticated if a token diff --git a/packages/data-connect/src/core/QueryManager.ts b/packages/data-connect/src/core/QueryManager.ts index 8b7c59aea8..109f1d105b 100644 --- a/packages/data-connect/src/core/QueryManager.ts +++ b/packages/data-connect/src/core/QueryManager.ts @@ -16,7 +16,7 @@ */ import { - DataConnectSubscription, + OnCompleteSubscription, OnErrorSubscription, OnResultSubscription, QueryPromise, @@ -39,6 +39,16 @@ import { setIfNotExists } from '../util/map'; import { Code, DataConnectError } from './error'; +/** + * Representation of user provided subscription options. + */ +interface DataConnectSubscription { + userCallback: OnResultSubscription; + errCallback?: (e?: DataConnectError) => void; + onCompleteCallback?: () => void; + unsubscribe: () => void; +} + interface TrackedQuery { ref: Omit, 'dataConnect'>; subscriptions: Array>; @@ -97,6 +107,7 @@ export class QueryManager { addSubscription( queryRef: OperationRef, onResultCallback: OnResultSubscription, + onCompleteCallback?: OnCompleteSubscription, onErrorCallback?: OnErrorSubscription, initialCache?: OpResult ): () => void { @@ -111,6 +122,7 @@ export class QueryManager { >; const subscription = { userCallback: onResultCallback, + onCompleteCallback, errCallback: onErrorCallback }; const unsubscribe = (): void => { @@ -118,6 +130,7 @@ export class QueryManager { trackedQuery.subscriptions = trackedQuery.subscriptions.filter( sub => sub !== subscription ); + onCompleteCallback?.(); }; if (initialCache && trackedQuery.currentCache !== initialCache) { logDebug('Initial cache found. Comparing dates.'); diff --git a/packages/data-connect/src/network/fetch.ts b/packages/data-connect/src/network/fetch.ts index 3e8e2cab47..62cef6fb22 100644 --- a/packages/data-connect/src/network/fetch.ts +++ b/packages/data-connect/src/network/fetch.ts @@ -56,9 +56,9 @@ export function dcFetch( url: string, body: DataConnectFetchBody, { signal }: AbortController, - appId: string | null, + appId: string | null | undefined, accessToken: string | null, - appCheckToken: string | null, + appCheckToken: string | null | undefined, _isUsingGen: boolean, _callerSdkType: CallerSdkType, _isUsingEmulator: boolean @@ -135,7 +135,7 @@ interface MessageObject { message?: string; } function getMessage(obj: MessageObject): string { - if ('message' in obj) { + if ('message' in obj && obj.message) { return obj.message; } return JSON.stringify(obj); diff --git a/packages/data-connect/src/network/transport/rest.ts b/packages/data-connect/src/network/transport/rest.ts index f16154dcb2..4a3af8ac41 100644 --- a/packages/data-connect/src/network/transport/rest.ts +++ b/packages/data-connect/src/network/transport/rest.ts @@ -34,7 +34,7 @@ export class RESTTransport implements DataConnectTransport { private _project = 'p'; private _serviceName: string; private _accessToken: string | null = null; - private _appCheckToken: string | null = null; + private _appCheckToken: string | null | undefined = null; private _lastToken: string | null = null; private _isUsingEmulator = false; constructor( @@ -106,7 +106,7 @@ export class RESTTransport implements DataConnectTransport { this._accessToken = newToken; } - async getWithAuth(forceToken = false): Promise { + async getWithAuth(forceToken = false): Promise { let starterPromise: Promise = new Promise(resolve => resolve(this._accessToken) ); diff --git a/packages/data-connect/src/util/validateArgs.ts b/packages/data-connect/src/util/validateArgs.ts index 15d1effa3d..e957786aa4 100644 --- a/packages/data-connect/src/util/validateArgs.ts +++ b/packages/data-connect/src/util/validateArgs.ts @@ -46,7 +46,7 @@ export function validateArgs( let realVars: Variables; if (dcOrVars && 'enableEmulator' in dcOrVars) { dcInstance = dcOrVars as DataConnect; - realVars = vars; + realVars = vars as Variables; } else { dcInstance = getDataConnect(connectorConfig); realVars = dcOrVars as Variables; diff --git a/packages/data-connect/test/unit/queries.test.ts b/packages/data-connect/test/unit/queries.test.ts index 68bd96268a..02d19bf856 100644 --- a/packages/data-connect/test/unit/queries.test.ts +++ b/packages/data-connect/test/unit/queries.test.ts @@ -20,15 +20,18 @@ import { expect } from 'chai'; import * as chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import * as sinon from 'sinon'; +import sinonChai from 'sinon-chai'; -import { DataConnectOptions } from '../../src'; +import { DataConnectOptions, QueryRef, queryRef, subscribe } from '../../src'; import { AuthTokenListener, AuthTokenProvider } from '../../src/core/FirebaseAuthProvider'; import { initializeFetch } from '../../src/network/fetch'; import { RESTTransport } from '../../src/network/transport/rest'; +import { initDatabase } from '../util'; chai.use(chaiAsPromised); +chai.use(sinonChai); const options: DataConnectOptions = { connector: 'c', location: 'l', @@ -61,10 +64,103 @@ const fakeFetchImpl = sinon.stub().returns( status: 401 } as Response) ); +interface PostVariables { + testId: string; +} +const TEST_ID = crypto.randomUUID(); +interface PostListResponse { + posts: Post[]; +} +interface Post { + id: string; + description: string; +} +function getPostsRef(): QueryRef { + const dc = initDatabase(); + return queryRef(dc, 'ListPosts', { + testId: TEST_ID + }); +} describe('Queries', () => { afterEach(() => { fakeFetchImpl.resetHistory(); }); + it('should call onComplete callback after subscribe is called', async () => { + const taskListQuery = getPostsRef(); + const onCompleteUserStub = sinon.stub(); + const unsubscribe = subscribe(taskListQuery, { + onNext: () => {}, + onComplete: onCompleteUserStub + }); + expect(onCompleteUserStub).to.not.have.been.called; + unsubscribe(); + expect(onCompleteUserStub).to.have.been.calledOnce; + }); + it('should call onErr callback after a 401 occurs', async () => { + const json = {}; + const throwErrorFakeImpl = sinon.stub().returns( + Promise.resolve({ + json: () => { + return Promise.resolve(json); + }, + status: 401 + } as Response) + ); + initializeFetch(throwErrorFakeImpl); + const taskListQuery = getPostsRef(); + const onErrStub = sinon.stub(); + let unsubscribeFn: (() => void) | null = null; + const promise = new Promise((resolve, reject) => { + unsubscribeFn = subscribe(taskListQuery, { + onNext: () => { + resolve(null); + }, + onComplete: () => {}, + onErr: err => { + onErrStub(); + reject(err); + } + }); + }); + expect(onErrStub).not.to.have.been.called; + await expect(promise).to.have.eventually.been.rejected; + expect(onErrStub).to.have.been.calledOnce; + unsubscribeFn!(); + }); + it('should call onErr callback after a graphql error occurs', async () => { + const json = { + errors: [{ something: 'abc' }] + }; + const throwErrorFakeImpl = sinon.stub().returns( + Promise.resolve({ + json: () => { + return Promise.resolve(json); + }, + status: 200 + } as Response) + ); + initializeFetch(throwErrorFakeImpl); + const taskListQuery = getPostsRef(); + const onErrStub = sinon.stub(); + let unsubscribeFn: (() => void) | null = null; + const promise = new Promise((resolve, reject) => { + unsubscribeFn = subscribe(taskListQuery, { + onNext: () => { + resolve(null); + }, + onComplete: () => {}, + onErr: err => { + onErrStub(); + reject(err); + } + }); + }); + expect(onErrStub).not.to.have.been.called; + await expect(promise).to.have.eventually.been.rejected; + expect(onErrStub).to.have.been.calledOnce; + unsubscribeFn!(); + initializeFetch(globalThis.fetch); + }); it('[QUERY] should retry auth whenever the fetcher returns with unauthorized', async () => { initializeFetch(fakeFetchImpl); const authProvider = new FakeAuthProvider(); diff --git a/packages/data-connect/tsconfig.json b/packages/data-connect/tsconfig.json index 58561f50f5..f97ac9fe89 100644 --- a/packages/data-connect/tsconfig.json +++ b/packages/data-connect/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../../config/tsconfig.base.json", "compilerOptions": { "outDir": "dist", - "strict": false + "strict": true }, "exclude": ["dist/**/*", "test/**/*"] } diff --git a/scripts/emulator-testing/emulators/dataconnect-emulator.ts b/scripts/emulator-testing/emulators/dataconnect-emulator.ts index 9dc6add5df..729889364d 100644 --- a/scripts/emulator-testing/emulators/dataconnect-emulator.ts +++ b/scripts/emulator-testing/emulators/dataconnect-emulator.ts @@ -18,7 +18,7 @@ import { platform } from 'os'; import { Emulator } from './emulator'; -const DATACONNECT_EMULATOR_VERSION = '1.9.2'; +const DATACONNECT_EMULATOR_VERSION = '2.15.1'; export class DataConnectEmulator extends Emulator { constructor(port = 9399) { From 0800a8bed01d602f73b92809b087c2ec732cc1c3 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Wed, 5 Nov 2025 14:05:43 -0500 Subject: [PATCH 011/174] test(ai): do not run browser tests when debugging node tests (#9363) --- .vscode/launch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 1f627304b6..8f132cbe5c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -17,7 +17,7 @@ "src/index.node.ts", "--timeout", "5000", - "src/**/*.test.ts" + "'src/**/!(*-browser)*.test.ts" ], "env": { "TS_NODE_COMPILER_OPTIONS": "{\"module\":\"commonjs\"}" From 6abe52967f3d1ca4a02d4469a14c6d692e1f3b31 Mon Sep 17 00:00:00 2001 From: Athira M Date: Tue, 11 Nov 2025 09:48:14 +0530 Subject: [PATCH 012/174] feat(rc): Web support for ABT & Rollouts (#9293) Provide experiment in details in fetch response and integrate with Google Analytics to create experiment related user properties --- .changeset/wild-snakes-bathe.md | 6 + common/api-review/remote-config.api.md | 17 +++ docs-devsite/_toc.yaml | 2 + docs-devsite/remote-config.fetchresponse.md | 13 ++ ...te-config.firebaseexperimentdescription.md | 78 ++++++++++++ docs-devsite/remote-config.md | 1 + packages/remote-config/src/abt/experiment.ts | 102 +++++++++++++++ packages/remote-config/src/api.ts | 10 +- .../remote-config/src/client/rest_client.ts | 8 +- packages/remote-config/src/errors.ts | 8 +- packages/remote-config/src/public_types.ts | 35 +++++- packages/remote-config/src/register.ts | 4 +- packages/remote-config/src/remote_config.ts | 8 +- packages/remote-config/src/storage/storage.ts | 9 ++ .../remote-config/test/abt/experiment.test.ts | 117 ++++++++++++++++++ packages/remote-config/test/api.test.ts | 14 ++- .../test/client/rest_client.test.ts | 26 +++- .../remote-config/test/remote_config.test.ts | 41 +++++- 18 files changed, 479 insertions(+), 20 deletions(-) create mode 100644 .changeset/wild-snakes-bathe.md create mode 100644 docs-devsite/remote-config.firebaseexperimentdescription.md create mode 100644 packages/remote-config/src/abt/experiment.ts create mode 100644 packages/remote-config/test/abt/experiment.test.ts diff --git a/.changeset/wild-snakes-bathe.md b/.changeset/wild-snakes-bathe.md new file mode 100644 index 0000000000..ffc35b4d3d --- /dev/null +++ b/.changeset/wild-snakes-bathe.md @@ -0,0 +1,6 @@ +--- +'@firebase/remote-config': minor +'firebase': minor +--- + +Web support for ABT and Rollouts diff --git a/common/api-review/remote-config.api.md b/common/api-review/remote-config.api.md index a9f5131e0b..29939b3ac5 100644 --- a/common/api-review/remote-config.api.md +++ b/common/api-review/remote-config.api.md @@ -41,6 +41,7 @@ export function fetchConfig(remoteConfig: RemoteConfig): Promise; export interface FetchResponse { config?: FirebaseRemoteConfigObject; eTag?: string; + experiments?: FirebaseExperimentDescription[]; status: number; templateVersion?: number; } @@ -51,6 +52,22 @@ export type FetchStatus = 'no-fetch-yet' | 'success' | 'failure' | 'throttle'; // @public export type FetchType = 'BASE' | 'REALTIME'; +// @public +export interface FirebaseExperimentDescription { + // (undocumented) + affectedParameterKeys?: string[]; + // (undocumented) + experimentId: string; + // (undocumented) + experimentStartTime: string; + // (undocumented) + timeToLiveMillis: string; + // (undocumented) + triggerTimeoutMillis: string; + // (undocumented) + variantId: string; +} + // @public export interface FirebaseRemoteConfigObject { // (undocumented) diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index 4f3bb1f3ca..c305bf9982 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -661,6 +661,8 @@ toc: path: /docs/reference/js/remote-config.customsignals.md - title: FetchResponse path: /docs/reference/js/remote-config.fetchresponse.md + - title: FirebaseExperimentDescription + path: /docs/reference/js/remote-config.firebaseexperimentdescription.md - title: FirebaseRemoteConfigObject path: /docs/reference/js/remote-config.firebaseremoteconfigobject.md - title: RemoteConfig diff --git a/docs-devsite/remote-config.fetchresponse.md b/docs-devsite/remote-config.fetchresponse.md index 1955dd4749..9c55c50e68 100644 --- a/docs-devsite/remote-config.fetchresponse.md +++ b/docs-devsite/remote-config.fetchresponse.md @@ -26,6 +26,7 @@ export interface FetchResponse | --- | --- | --- | | [config](./remote-config.fetchresponse.md#fetchresponseconfig) | [FirebaseRemoteConfigObject](./remote-config.firebaseremoteconfigobject.md#firebaseremoteconfigobject_interface) | Defines the map of parameters returned as "entries" in the fetch response body.

Only defined for 200 responses. | | [eTag](./remote-config.fetchresponse.md#fetchresponseetag) | string | Defines the ETag response header value.

Only defined for 200 and 304 responses. | +| [experiments](./remote-config.fetchresponse.md#fetchresponseexperiments) | [FirebaseExperimentDescription](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescription_interface)\[\] | Metadata for A/B testing and Remote Config Rollout experiments. | | [status](./remote-config.fetchresponse.md#fetchresponsestatus) | number | The HTTP status, which is useful for differentiating success responses with data from those without.

The Remote Config client is modeled after the native Fetch interface, so HTTP status is first-class.

Disambiguation: the fetch response returns a legacy "state" value that is redundant with the HTTP status code. The former is normalized into the latter. | | [templateVersion](./remote-config.fetchresponse.md#fetchresponsetemplateversion) | number | The version number of the config template fetched from the server. | @@ -53,6 +54,18 @@ Defines the ETag response header value. eTag?: string; ``` +## FetchResponse.experiments + +Metadata for A/B testing and Remote Config Rollout experiments. + +Only defined for 200 responses. + +Signature: + +```typescript +experiments?: FirebaseExperimentDescription[]; +``` + ## FetchResponse.status The HTTP status, which is useful for differentiating success responses with data from those without. diff --git a/docs-devsite/remote-config.firebaseexperimentdescription.md b/docs-devsite/remote-config.firebaseexperimentdescription.md new file mode 100644 index 0000000000..24c70690a2 --- /dev/null +++ b/docs-devsite/remote-config.firebaseexperimentdescription.md @@ -0,0 +1,78 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FirebaseExperimentDescription interface +Defines experiment and variant attached to a config parameter. + +Signature: + +```typescript +export interface FirebaseExperimentDescription +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [affectedParameterKeys](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptionaffectedparameterkeys) | string\[\] | | +| [experimentId](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptionexperimentid) | string | | +| [experimentStartTime](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptionexperimentstarttime) | string | | +| [timeToLiveMillis](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptiontimetolivemillis) | string | | +| [triggerTimeoutMillis](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptiontriggertimeoutmillis) | string | | +| [variantId](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptionvariantid) | string | | + +## FirebaseExperimentDescription.affectedParameterKeys + +Signature: + +```typescript +affectedParameterKeys?: string[]; +``` + +## FirebaseExperimentDescription.experimentId + +Signature: + +```typescript +experimentId: string; +``` + +## FirebaseExperimentDescription.experimentStartTime + +Signature: + +```typescript +experimentStartTime: string; +``` + +## FirebaseExperimentDescription.timeToLiveMillis + +Signature: + +```typescript +timeToLiveMillis: string; +``` + +## FirebaseExperimentDescription.triggerTimeoutMillis + +Signature: + +```typescript +triggerTimeoutMillis: string; +``` + +## FirebaseExperimentDescription.variantId + +Signature: + +```typescript +variantId: string; +``` diff --git a/docs-devsite/remote-config.md b/docs-devsite/remote-config.md index c9f803abf1..c3b5e4b5bf 100644 --- a/docs-devsite/remote-config.md +++ b/docs-devsite/remote-config.md @@ -42,6 +42,7 @@ The Firebase Remote Config Web SDK. This SDK does not work in a Node.js environm | [ConfigUpdateObserver](./remote-config.configupdateobserver.md#configupdateobserver_interface) | Observer interface for receiving real-time Remote Config update notifications.NOTE: Although an complete callback can be provided, it will never be called because the ConfigUpdate stream is never-ending. | | [CustomSignals](./remote-config.customsignals.md#customsignals_interface) | Defines the type for representing custom signals and their values.

The values in CustomSignals must be one of the following types:

  • string
  • number
  • null
| | [FetchResponse](./remote-config.fetchresponse.md#fetchresponse_interface) | Defines a successful response (200 or 304).

Modeled after the native Response interface, but simplified for Remote Config's use case. | +| [FirebaseExperimentDescription](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescription_interface) | Defines experiment and variant attached to a config parameter. | | [FirebaseRemoteConfigObject](./remote-config.firebaseremoteconfigobject.md#firebaseremoteconfigobject_interface) | Defines a self-descriptive reference for config key-value pairs. | | [RemoteConfig](./remote-config.remoteconfig.md#remoteconfig_interface) | The Firebase Remote Config service interface. | | [RemoteConfigOptions](./remote-config.remoteconfigoptions.md#remoteconfigoptions_interface) | Options for Remote Config initialization. | diff --git a/packages/remote-config/src/abt/experiment.ts b/packages/remote-config/src/abt/experiment.ts new file mode 100644 index 0000000000..d92d762f93 --- /dev/null +++ b/packages/remote-config/src/abt/experiment.ts @@ -0,0 +1,102 @@ +/** + * @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. + */ +import { Storage } from '../storage/storage'; +import { FirebaseExperimentDescription } from '../public_types'; +import { Provider } from '@firebase/component'; +import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types'; +import { Logger } from '@firebase/logger'; +import { RemoteConfig } from '../remote_config'; +import { ERROR_FACTORY, ErrorCode } from '../errors'; + +export class Experiment { + private storage: Storage; + private logger: Logger; + private analyticsProvider: Provider; + + constructor(rc: RemoteConfig) { + this.storage = rc._storage; + this.logger = rc._logger; + this.analyticsProvider = rc._analyticsProvider; + } + + async updateActiveExperiments( + latestExperiments: FirebaseExperimentDescription[] + ): Promise { + const currentActiveExperiments = + (await this.storage.getActiveExperiments()) || new Set(); + const experimentInfoMap = this.createExperimentInfoMap(latestExperiments); + this.addActiveExperiments(experimentInfoMap); + this.removeInactiveExperiments(currentActiveExperiments, experimentInfoMap); + return this.storage.setActiveExperiments(new Set(experimentInfoMap.keys())); + } + + private createExperimentInfoMap( + latestExperiments: FirebaseExperimentDescription[] + ): Map { + const experimentInfoMap = new Map(); + for (const experiment of latestExperiments) { + experimentInfoMap.set(experiment.experimentId, experiment); + } + return experimentInfoMap; + } + + private addActiveExperiments( + experimentInfoMap: Map + ): void { + const customProperty: Record = {}; + for (const [experimentId, experimentInfo] of experimentInfoMap.entries()) { + customProperty[`firebase${experimentId}`] = experimentInfo.variantId; + } + this.addExperimentToAnalytics(customProperty); + } + + private removeInactiveExperiments( + currentActiveExperiments: Set, + experimentInfoMap: Map + ): void { + const customProperty: Record = {}; + for (const experimentId of currentActiveExperiments) { + if (!experimentInfoMap.has(experimentId)) { + customProperty[`firebase${experimentId}`] = null; + } + } + this.addExperimentToAnalytics(customProperty); + } + + private addExperimentToAnalytics( + customProperty: Record + ): void { + if (Object.keys(customProperty).length === 0) { + return; + } + try { + const analytics = this.analyticsProvider.getImmediate({ optional: true }); + if (analytics) { + analytics.setUserProperties(customProperty); + analytics.logEvent(`set_firebase_experiment_state`); + } else { + this.logger.warn( + `Analytics import failed. Verify if you have imported Firebase Analytics in your app code.` + ); + } + } catch (error) { + throw ERROR_FACTORY.create(ErrorCode.ANALYTICS_UNAVAILABLE, { + originalErrorMessage: (error as Error)?.message + }); + } + } +} diff --git a/packages/remote-config/src/api.ts b/packages/remote-config/src/api.ts index 62dc2697a6..5533bf9129 100644 --- a/packages/remote-config/src/api.ts +++ b/packages/remote-config/src/api.ts @@ -36,6 +36,7 @@ import { ERROR_FACTORY, ErrorCode, hasErrorCode } from './errors'; import { RemoteConfig as RemoteConfigImpl } from './remote_config'; import { Value as ValueImpl } from './value'; import { LogLevel as FirebaseLogLevel } from '@firebase/logger'; +import { Experiment } from './abt/experiment'; /** * @@ -110,12 +111,19 @@ export async function activate(remoteConfig: RemoteConfig): Promise { // config. return false; } + const experiment = new Experiment(rc); + const updateActiveExperiments = lastSuccessfulFetchResponse.experiments + ? experiment.updateActiveExperiments( + lastSuccessfulFetchResponse.experiments + ) + : Promise.resolve(); await Promise.all([ rc._storageCache.setActiveConfig(lastSuccessfulFetchResponse.config), rc._storage.setActiveConfigEtag(lastSuccessfulFetchResponse.eTag), rc._storage.setActiveConfigTemplateVersion( lastSuccessfulFetchResponse.templateVersion - ) + ), + updateActiveExperiments ]); return true; } diff --git a/packages/remote-config/src/client/rest_client.ts b/packages/remote-config/src/client/rest_client.ts index 42b0cab27c..d5b0be92c3 100644 --- a/packages/remote-config/src/client/rest_client.ts +++ b/packages/remote-config/src/client/rest_client.ts @@ -18,7 +18,8 @@ import { CustomSignals, FetchResponse, - FirebaseRemoteConfigObject + FirebaseRemoteConfigObject, + FirebaseExperimentDescription } from '../public_types'; import { RemoteConfigFetchClient, @@ -143,6 +144,7 @@ export class RestClient implements RemoteConfigFetchClient { let config: FirebaseRemoteConfigObject | undefined; let state: string | undefined; let templateVersion: number | undefined; + let experiments: FirebaseExperimentDescription[] | undefined; // JSON parsing throws SyntaxError if the response body isn't a JSON string. // Requesting application/json and checking for a 200 ensures there's JSON data. @@ -158,6 +160,7 @@ export class RestClient implements RemoteConfigFetchClient { config = responseBody['entries']; state = responseBody['state']; templateVersion = responseBody['templateVersion']; + experiments = responseBody['experimentDescriptions']; } // Normalizes based on legacy state. @@ -168,6 +171,7 @@ export class RestClient implements RemoteConfigFetchClient { } else if (state === 'NO_TEMPLATE' || state === 'EMPTY_CONFIG') { // These cases can be fixed remotely, so normalize to safe value. config = {}; + experiments = []; } // Normalize to exception-based control flow for non-success cases. @@ -180,6 +184,6 @@ export class RestClient implements RemoteConfigFetchClient { }); } - return { status, eTag: responseEtag, config, templateVersion }; + return { status, eTag: responseEtag, config, templateVersion, experiments }; } } diff --git a/packages/remote-config/src/errors.ts b/packages/remote-config/src/errors.ts index dea9f43e92..06e226a0ab 100644 --- a/packages/remote-config/src/errors.ts +++ b/packages/remote-config/src/errors.ts @@ -37,7 +37,8 @@ export const enum ErrorCode { CONFIG_UPDATE_STREAM_ERROR = 'stream-error', CONFIG_UPDATE_UNAVAILABLE = 'realtime-unavailable', CONFIG_UPDATE_MESSAGE_INVALID = 'update-message-invalid', - CONFIG_UPDATE_NOT_FETCHED = 'update-not-fetched' + CONFIG_UPDATE_NOT_FETCHED = 'update-not-fetched', + ANALYTICS_UNAVAILABLE = 'analytics-unavailable' } const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = { @@ -84,7 +85,9 @@ const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = { [ErrorCode.CONFIG_UPDATE_MESSAGE_INVALID]: 'The stream invalidation message was unparsable: {$originalErrorMessage}', [ErrorCode.CONFIG_UPDATE_NOT_FETCHED]: - 'Unable to fetch the latest config: {$originalErrorMessage}' + 'Unable to fetch the latest config: {$originalErrorMessage}', + [ErrorCode.ANALYTICS_UNAVAILABLE]: + 'Connection to Firebase Analytics failed: {$originalErrorMessage}' }; // Note this is effectively a type system binding a code to params. This approach overlaps with the @@ -108,6 +111,7 @@ interface ErrorParams { [ErrorCode.CONFIG_UPDATE_UNAVAILABLE]: { originalErrorMessage: string }; [ErrorCode.CONFIG_UPDATE_MESSAGE_INVALID]: { originalErrorMessage: string }; [ErrorCode.CONFIG_UPDATE_NOT_FETCHED]: { originalErrorMessage: string }; + [ErrorCode.ANALYTICS_UNAVAILABLE]: { originalErrorMessage: string }; } export const ERROR_FACTORY = new ErrorFactory( diff --git a/packages/remote-config/src/public_types.ts b/packages/remote-config/src/public_types.ts index 964726a51f..fc23974ee3 100644 --- a/packages/remote-config/src/public_types.ts +++ b/packages/remote-config/src/public_types.ts @@ -59,6 +59,33 @@ export interface FirebaseRemoteConfigObject { [key: string]: string; } +/** + * Defines experiment and variant attached to a config parameter. + * + * @public + */ +export interface FirebaseExperimentDescription { + // A string of max length 22 characters and of format: _exp_ + experimentId: string; + + // The variant of the experiment assigned to the app instance. + variantId: string; + + // When the experiment was started. + experimentStartTime: string; + + // How long the experiment can remain in STANDBY state. Valid range from 1 ms + // to 6 months. + triggerTimeoutMillis: string; + + // How long the experiment can remain in ON state. Valid range from 1 ms to 6 + // months. + timeToLiveMillis: string; + + // Which all parameters are affected by this experiment. + affectedParameterKeys?: string[]; +} + /** * Defines a successful response (200 or 304). * @@ -99,8 +126,12 @@ export interface FetchResponse { */ templateVersion?: number; - // Note: we're not extracting experiment metadata until - // ABT and Analytics have Web SDKs. + /** + * Metadata for A/B testing and Remote Config Rollout experiments. + * + * @remarks Only defined for 200 responses. + */ + experiments?: FirebaseExperimentDescription[]; } /** diff --git a/packages/remote-config/src/register.ts b/packages/remote-config/src/register.ts index eade371ca8..0a34024622 100644 --- a/packages/remote-config/src/register.ts +++ b/packages/remote-config/src/register.ts @@ -66,6 +66,7 @@ export function registerRemoteConfig(): void { const installations = container .getProvider('installations-internal') .getImmediate(); + const analyticsProvider = container.getProvider('analytics-internal'); // Normalizes optional inputs. const { projectId, apiKey, appId } = app.options; @@ -127,7 +128,8 @@ export function registerRemoteConfig(): void { storageCache, storage, logger, - realtimeHandler + realtimeHandler, + analyticsProvider ); // Starts warming cache. diff --git a/packages/remote-config/src/remote_config.ts b/packages/remote-config/src/remote_config.ts index bd32c93830..aa9502262f 100644 --- a/packages/remote-config/src/remote_config.ts +++ b/packages/remote-config/src/remote_config.ts @@ -25,6 +25,8 @@ import { StorageCache } from './storage/storage_cache'; import { RemoteConfigFetchClient } from './client/remote_config_fetch_client'; import { Storage } from './storage/storage'; import { Logger } from '@firebase/logger'; +import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types'; +import { Provider } from '@firebase/component'; import { RealtimeHandler } from './client/realtime_handler'; const DEFAULT_FETCH_TIMEOUT_MILLIS = 60 * 1000; // One minute @@ -88,6 +90,10 @@ export class RemoteConfig implements RemoteConfigType { /** * @internal */ - readonly _realtimeHandler: RealtimeHandler + readonly _realtimeHandler: RealtimeHandler, + /** + * @internal + */ + readonly _analyticsProvider: Provider ) {} } diff --git a/packages/remote-config/src/storage/storage.ts b/packages/remote-config/src/storage/storage.ts index bd262d2996..9764b95991 100644 --- a/packages/remote-config/src/storage/storage.ts +++ b/packages/remote-config/src/storage/storage.ts @@ -71,6 +71,7 @@ export interface RealtimeBackoffMetadata { type ProjectNamespaceKeyFieldValue = | 'active_config' | 'active_config_etag' + | 'active_experiments' | 'last_fetch_status' | 'last_successful_fetch_timestamp_millis' | 'last_successful_fetch_response' @@ -165,6 +166,14 @@ export abstract class Storage { return this.set('active_config_etag', etag); } + getActiveExperiments(): Promise | undefined> { + return this.get>('active_experiments'); + } + + setActiveExperiments(experiments: Set): Promise { + return this.set>('active_experiments', experiments); + } + getThrottleMetadata(): Promise { return this.get('throttle_metadata'); } diff --git a/packages/remote-config/test/abt/experiment.test.ts b/packages/remote-config/test/abt/experiment.test.ts new file mode 100644 index 0000000000..43365d31f0 --- /dev/null +++ b/packages/remote-config/test/abt/experiment.test.ts @@ -0,0 +1,117 @@ +/** + * @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. + */ +import '../setup'; +import { expect } from 'chai'; +import * as sinon from 'sinon'; +import { Experiment } from '../../src/abt/experiment'; +import { FirebaseExperimentDescription } from '../../src/public_types'; +import { Storage } from '../../src/storage/storage'; +import { Provider } from '@firebase/component'; +import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types'; +import { Logger } from '@firebase/logger'; +import { RemoteConfig } from '../../src/remote_config'; + +describe('Experiment', () => { + const storage = {} as Storage; + const analyticsProvider = {} as Provider; + const logger = {} as Logger; + const rc = { + _storage: storage, + _analyticsProvider: analyticsProvider, + _logger: logger + } as RemoteConfig; + const experiment = new Experiment(rc); + + describe('updateActiveExperiments', () => { + beforeEach(() => { + storage.getActiveExperiments = sinon.stub(); + storage.setActiveExperiments = sinon.stub(); + analyticsProvider.getImmediate = sinon.stub().returns({ + setUserProperties: sinon.stub(), + logEvent: sinon.stub() + }); + }); + + it('adds new experiments to storage', async () => { + const latestExperiments: FirebaseExperimentDescription[] = [ + { + experimentId: '_exp_3', + variantId: '1', + experimentStartTime: '0', + triggerTimeoutMillis: '0', + timeToLiveMillis: '0' + }, + { + experimentId: '_exp_1', + variantId: '2', + experimentStartTime: '0', + triggerTimeoutMillis: '0', + timeToLiveMillis: '0' + }, + { + experimentId: '_exp_2', + variantId: '1', + experimentStartTime: '0', + triggerTimeoutMillis: '0', + timeToLiveMillis: '0' + } + ]; + const expectedStoredExperiments = new Set(['_exp_3', '_exp_1', '_exp_2']); + storage.getActiveExperiments = sinon + .stub() + .returns(new Set(['_exp_1', '_exp_2'])); + const analytics = analyticsProvider.getImmediate(); + + await experiment.updateActiveExperiments(latestExperiments); + + expect(storage.setActiveExperiments).to.have.been.calledWith( + expectedStoredExperiments + ); + expect(analytics.setUserProperties).to.have.been.calledWith({ + 'firebase_exp_3': '1', + 'firebase_exp_1': '2', + 'firebase_exp_2': '1' + }); + }); + + it('removes missing experiment in fetch response from storage', async () => { + const latestExperiments: FirebaseExperimentDescription[] = [ + { + experimentId: '_exp_1', + variantId: '2', + experimentStartTime: '0', + triggerTimeoutMillis: '0', + timeToLiveMillis: '0' + } + ]; + const expectedStoredExperiments = new Set(['_exp_1']); + storage.getActiveExperiments = sinon + .stub() + .returns(new Set(['_exp_1', '_exp_2'])); + const analytics = analyticsProvider.getImmediate(); + + await experiment.updateActiveExperiments(latestExperiments); + + expect(storage.setActiveExperiments).to.have.been.calledWith( + expectedStoredExperiments + ); + expect(analytics.setUserProperties).to.have.been.calledWith({ + 'firebase_exp_2': null + }); + }); + }); +}); diff --git a/packages/remote-config/test/api.test.ts b/packages/remote-config/test/api.test.ts index f38b4ca0be..54679199a8 100644 --- a/packages/remote-config/test/api.test.ts +++ b/packages/remote-config/test/api.test.ts @@ -68,7 +68,16 @@ describe('Remote Config API', () => { status: 200, eTag: 'asdf', config: { 'foobar': 'hello world' }, - templateVersion: 1 + templateVersion: 1, + experiments: [ + { + experimentId: '_exp_1', + variantId: '1', + experimentStartTime: '2025-04-06T14:13:57.597Z', + triggerTimeoutMillis: '15552000000', + timeToLiveMillis: '15552000000' + } + ] }; let fetchStub: sinon.SinonStub; @@ -106,7 +115,8 @@ describe('Remote Config API', () => { Promise.resolve({ entries: response.config, state: 'OK', - templateVersion: response.templateVersion + templateVersion: response.templateVersion, + experimentDescriptions: response.experiments }) } as Response) ); diff --git a/packages/remote-config/test/client/rest_client.test.ts b/packages/remote-config/test/client/rest_client.test.ts index bda6fbce01..d2284c4f8c 100644 --- a/packages/remote-config/test/client/rest_client.test.ts +++ b/packages/remote-config/test/client/rest_client.test.ts @@ -78,7 +78,16 @@ describe('RestClient', () => { eTag: 'etag', state: 'UPDATE', entries: { color: 'sparkling' }, - templateVersion: 1 + templateVersion: 1, + experimentDescriptions: [ + { + experimentId: '_exp_1', + variantId: '1', + experimentStartTime: '2025-04-06T14:13:57.597Z', + triggerTimeoutMillis: '15552000000', + timeToLiveMillis: '15552000000' + } + ] }; fetchStub.returns( @@ -90,7 +99,8 @@ describe('RestClient', () => { Promise.resolve({ entries: expectedResponse.entries, state: expectedResponse.state, - templateVersion: expectedResponse.templateVersion + templateVersion: expectedResponse.templateVersion, + experimentDescriptions: expectedResponse.experimentDescriptions }) } as Response) ); @@ -101,7 +111,8 @@ describe('RestClient', () => { status: expectedResponse.status, eTag: expectedResponse.eTag, config: expectedResponse.entries, - templateVersion: expectedResponse.templateVersion + templateVersion: expectedResponse.templateVersion, + experiments: expectedResponse.experimentDescriptions }); }); @@ -191,7 +202,8 @@ describe('RestClient', () => { status: 304, eTag: 'response-etag', config: undefined, - templateVersion: undefined + templateVersion: undefined, + experiments: undefined }); }); @@ -230,7 +242,8 @@ describe('RestClient', () => { status: 304, eTag: 'etag', config: undefined, - templateVersion: undefined + templateVersion: undefined, + experiments: undefined }); }); @@ -248,7 +261,8 @@ describe('RestClient', () => { status: 200, eTag: 'etag', config: {}, - templateVersion: undefined + templateVersion: undefined, + experiments: [] }); } }); diff --git a/packages/remote-config/test/remote_config.test.ts b/packages/remote-config/test/remote_config.test.ts index 1cc6b62717..de70e13dfc 100644 --- a/packages/remote-config/test/remote_config.test.ts +++ b/packages/remote-config/test/remote_config.test.ts @@ -46,6 +46,9 @@ import { import * as api from '../src/api'; import { fetchAndActivate } from '../src'; import { restore } from 'sinon'; +import { Experiment } from '../src/abt/experiment'; +import { Provider } from '@firebase/component'; +import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types'; import { RealtimeHandler } from '../src/client/realtime_handler'; describe('RemoteConfig', () => { @@ -70,6 +73,7 @@ describe('RemoteConfig', () => { let logger: Logger; let realtimeHandler: RealtimeHandler; let rc: RemoteConfigType; + let analyticsProvider: Provider; let getActiveConfigStub: sinon.SinonStub; let loggerDebugSpy: sinon.SinonSpy; @@ -81,6 +85,7 @@ describe('RemoteConfig', () => { client = {} as RemoteConfigFetchClient; storageCache = {} as StorageCache; storage = {} as Storage; + analyticsProvider = {} as Provider; realtimeHandler = {} as RealtimeHandler; logger = new Logger('package-name'); getActiveConfigStub = sinon.stub().returns(undefined); @@ -93,7 +98,8 @@ describe('RemoteConfig', () => { storageCache, storage, logger, - realtimeHandler + realtimeHandler, + analyticsProvider ); }); @@ -391,7 +397,18 @@ describe('RemoteConfig', () => { const CONFIG = { key: 'val' }; const NEW_ETAG = 'new_etag'; const TEMPLATE_VERSION = 1; + const EXPERIMENTS = [ + { + 'experimentId': '_exp_1', + 'variantId': '1', + 'experimentStartTime': '2025-04-06T14:13:57.597Z', + 'triggerTimeoutMillis': '15552000000', + 'timeToLiveMillis': '15552000000' + } + ]; + let sandbox: sinon.SinonSandbox; + let updateActiveExperimentsStub: sinon.SinonStub; let getLastSuccessfulFetchResponseStub: sinon.SinonStub; let getActiveConfigEtagStub: sinon.SinonStub; let getActiveConfigTemplateVersionStub: sinon.SinonStub; @@ -400,6 +417,11 @@ describe('RemoteConfig', () => { let setActiveConfigTemplateVersionStub: sinon.SinonStub; beforeEach(() => { + sandbox = sinon.createSandbox(); + updateActiveExperimentsStub = sandbox.stub( + Experiment.prototype, + 'updateActiveExperiments' + ); getLastSuccessfulFetchResponseStub = sinon.stub(); getActiveConfigEtagStub = sinon.stub(); getActiveConfigTemplateVersionStub = sinon.stub(); @@ -418,6 +440,14 @@ describe('RemoteConfig', () => { setActiveConfigTemplateVersionStub; }); + afterEach(() => { + sandbox.restore(); + }); + + afterEach(() => { + sandbox.restore(); + }); + it('does not activate if last successful fetch response is undefined', async () => { getLastSuccessfulFetchResponseStub.returns(Promise.resolve()); getActiveConfigEtagStub.returns(Promise.resolve(ETAG)); @@ -431,6 +461,7 @@ describe('RemoteConfig', () => { expect(storage.setActiveConfigEtag).to.not.have.been.called; expect(storageCache.setActiveConfig).to.not.have.been.called; expect(storage.setActiveConfigTemplateVersion).to.not.have.been.called; + expect(updateActiveExperimentsStub).to.not.have.been.called; }); it('does not activate if fetched and active etags are the same', async () => { @@ -449,6 +480,7 @@ describe('RemoteConfig', () => { expect(storage.setActiveConfigEtag).to.not.have.been.called; expect(storageCache.setActiveConfig).to.not.have.been.called; expect(storage.setActiveConfigTemplateVersion).to.not.have.been.called; + expect(updateActiveExperimentsStub).to.not.have.been.called; }); it('activates if fetched and active etags are different', async () => { @@ -456,7 +488,8 @@ describe('RemoteConfig', () => { Promise.resolve({ config: CONFIG, eTag: NEW_ETAG, - templateVersion: TEMPLATE_VERSION + templateVersion: TEMPLATE_VERSION, + experiments: EXPERIMENTS }) ); getActiveConfigEtagStub.returns(Promise.resolve(ETAG)); @@ -476,7 +509,8 @@ describe('RemoteConfig', () => { Promise.resolve({ config: CONFIG, eTag: NEW_ETAG, - templateVersion: TEMPLATE_VERSION + templateVersion: TEMPLATE_VERSION, + experiments: EXPERIMENTS }) ); getActiveConfigEtagStub.returns(Promise.resolve()); @@ -489,6 +523,7 @@ describe('RemoteConfig', () => { expect(storage.setActiveConfigTemplateVersion).to.have.been.calledWith( TEMPLATE_VERSION ); + expect(updateActiveExperimentsStub).to.have.been.calledWith(EXPERIMENTS); }); }); From f06cbf99b91bdea8d44b18c8ae8fc14b327105cd Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Wed, 12 Nov 2025 09:45:19 -0500 Subject: [PATCH 013/174] feat(ai): server prompt templates (#9351) --- .changeset/metal-ties-cry.md | 6 + common/api-review/ai.api.md | 37 +++ docs-devsite/_toc.yaml | 4 + docs-devsite/ai.md | 52 ++++ docs-devsite/ai.templategenerativemodel.md | 125 ++++++++ docs-devsite/ai.templateimagenmodel.md | 100 +++++++ packages/ai/integration/constants.ts | 2 +- .../ai/integration/prompt-templates.test.ts | 66 +++++ packages/ai/src/api.test.ts | 16 +- packages/ai/src/api.ts | 44 ++- packages/ai/src/backend.test.ts | 26 +- packages/ai/src/backend.ts | 40 ++- packages/ai/src/constants.ts | 3 + packages/ai/src/methods/count-tokens.test.ts | 57 ++-- packages/ai/src/methods/count-tokens.ts | 16 +- .../ai/src/methods/generate-content.test.ts | 233 +++++++++++---- packages/ai/src/methods/generate-content.ts | 81 +++++- packages/ai/src/models/ai-model.test.ts | 106 +------ packages/ai/src/models/ai-model.ts | 61 +--- .../ai/src/models/generative-model.test.ts | 95 +++--- packages/ai/src/models/imagen-model.test.ts | 28 +- packages/ai/src/models/imagen-model.ts | 30 +- .../models/template-generative-model.test.ts | 96 +++++++ .../src/models/template-generative-model.ts | 98 +++++++ .../src/models/template-imagen-model.test.ts | 139 +++++++++ .../ai/src/models/template-imagen-model.ts | 81 ++++++ packages/ai/src/models/utils.test.ts | 142 +++++++++ packages/ai/src/models/utils.ts | 78 +++++ packages/ai/src/requests/request.test.ts | 272 ++++++++++-------- packages/ai/src/requests/request.ts | 155 +++++----- 30 files changed, 1759 insertions(+), 530 deletions(-) create mode 100644 .changeset/metal-ties-cry.md create mode 100644 docs-devsite/ai.templategenerativemodel.md create mode 100644 docs-devsite/ai.templateimagenmodel.md create mode 100644 packages/ai/integration/prompt-templates.test.ts create mode 100644 packages/ai/src/models/template-generative-model.test.ts create mode 100644 packages/ai/src/models/template-generative-model.ts create mode 100644 packages/ai/src/models/template-imagen-model.test.ts create mode 100644 packages/ai/src/models/template-imagen-model.ts create mode 100644 packages/ai/src/models/utils.test.ts create mode 100644 packages/ai/src/models/utils.ts diff --git a/.changeset/metal-ties-cry.md b/.changeset/metal-ties-cry.md new file mode 100644 index 0000000000..f5b29675a6 --- /dev/null +++ b/.changeset/metal-ties-cry.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/ai': minor +--- + +Add support for server prompt templates. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 08a12efc36..2bf194fbaf 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -100,6 +100,10 @@ export interface AudioTranscriptionConfig { export abstract class Backend { protected constructor(type: BackendType); readonly backendType: BackendType; + // @internal (undocumented) + abstract _getModelPath(project: string, model: string): string; + // @internal (undocumented) + abstract _getTemplatePath(project: string, templateId: string): string; } // @public @@ -567,9 +571,19 @@ export function getImagenModel(ai: AI, modelParams: ImagenModelParams, requestOp // @beta export function getLiveGenerativeModel(ai: AI, modelParams: LiveModelParams): LiveGenerativeModel; +// @beta +export function getTemplateGenerativeModel(ai: AI, requestOptions?: RequestOptions): TemplateGenerativeModel; + +// @beta +export function getTemplateImagenModel(ai: AI, requestOptions?: RequestOptions): TemplateImagenModel; + // @public export class GoogleAIBackend extends Backend { constructor(); + // @internal (undocumented) + _getModelPath(project: string, model: string): string; + // @internal (undocumented) + _getTemplatePath(project: string, templateId: string): string; } // Warning: (ae-internal-missing-underscore) The name "GoogleAICitationMetadata" should be prefixed with an underscore because the declaration is marked as @internal @@ -1314,6 +1328,25 @@ export class StringSchema extends Schema { toJSON(): SchemaRequest; } +// @beta +export class TemplateGenerativeModel { + constructor(ai: AI, requestOptions?: RequestOptions); + // @internal (undocumented) + _apiSettings: ApiSettings; + generateContent(templateId: string, templateVariables: object): Promise; + generateContentStream(templateId: string, templateVariables: object): Promise; + requestOptions?: RequestOptions; +} + +// @beta +export class TemplateImagenModel { + constructor(ai: AI, requestOptions?: RequestOptions); + // @internal (undocumented) + _apiSettings: ApiSettings; + generateImages(templateId: string, templateVariables: object): Promise>; + requestOptions?: RequestOptions; +} + // @public export interface TextPart { // (undocumented) @@ -1412,6 +1445,10 @@ export interface UsageMetadata { // @public export class VertexAIBackend extends Backend { constructor(location?: string); + // @internal (undocumented) + _getModelPath(project: string, model: string): string; + // @internal (undocumented) + _getTemplatePath(project: string, templateId: string): string; readonly location: string; } diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index c305bf9982..f2689935a2 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -198,6 +198,10 @@ toc: path: /docs/reference/js/ai.startchatparams.md - title: StringSchema path: /docs/reference/js/ai.stringschema.md + - title: TemplateGenerativeModel + path: /docs/reference/js/ai.templategenerativemodel.md + - title: TemplateImagenModel + path: /docs/reference/js/ai.templateimagenmodel.md - title: TextPart path: /docs/reference/js/ai.textpart.md - title: ThinkingConfig diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index 79902cab4e..53e4057cad 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -22,6 +22,8 @@ The Firebase AI Web SDK. | [getGenerativeModel(ai, modelParams, requestOptions)](./ai.md#getgenerativemodel_c63f46a) | Returns a [GenerativeModel](./ai.generativemodel.md#generativemodel_class) class with methods for inference and other functionality. | | [getImagenModel(ai, modelParams, requestOptions)](./ai.md#getimagenmodel_e1f6645) | Returns an [ImagenModel](./ai.imagenmodel.md#imagenmodel_class) class with methods for using Imagen.Only Imagen 3 models (named imagen-3.0-*) are supported. | | [getLiveGenerativeModel(ai, modelParams)](./ai.md#getlivegenerativemodel_f2099ac) | (Public Preview) Returns a [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) class for real-time, bidirectional communication.The Live API is only supported in modern browser windows and Node >= 22. | +| [getTemplateGenerativeModel(ai, requestOptions)](./ai.md#gettemplategenerativemodel_9476bbc) | (Public Preview) Returns a [TemplateGenerativeModel](./ai.templategenerativemodel.md#templategenerativemodel_class) class for executing server-side templates. | +| [getTemplateImagenModel(ai, requestOptions)](./ai.md#gettemplateimagenmodel_9476bbc) | (Public Preview) Returns a [TemplateImagenModel](./ai.templateimagenmodel.md#templateimagenmodel_class) class for executing server-side Imagen templates. | | function(liveSession, ...) | | [startAudioConversation(liveSession, options)](./ai.md#startaudioconversation_01c8e7f) | (Public Preview) Starts a real-time, bidirectional audio conversation with the model. This helper function manages the complexities of microphone access, audio recording, playback, and interruptions. | @@ -47,6 +49,8 @@ The Firebase AI Web SDK. | [ObjectSchema](./ai.objectschema.md#objectschema_class) | Schema class for "object" types. The properties param must be a map of Schema objects. | | [Schema](./ai.schema.md#schema_class) | Parent class encompassing all Schema types, with static methods that allow building specific Schema types. This class can be converted with JSON.stringify() into a JSON string accepted by Vertex AI REST endpoints. (This string conversion is automatically done when calling SDK methods.) | | [StringSchema](./ai.stringschema.md#stringschema_class) | Schema class for "string" types. Can be used with or without enum values. | +| [TemplateGenerativeModel](./ai.templategenerativemodel.md#templategenerativemodel_class) | (Public Preview) [GenerativeModel](./ai.generativemodel.md#generativemodel_class) APIs that execute on a server-side template.This class should only be instantiated with [getTemplateGenerativeModel()](./ai.md#gettemplategenerativemodel_9476bbc). | +| [TemplateImagenModel](./ai.templateimagenmodel.md#templateimagenmodel_class) | (Public Preview) Class for Imagen model APIs that execute on a server-side template.This class should only be instantiated with [getTemplateImagenModel()](./ai.md#gettemplateimagenmodel_9476bbc). | | [VertexAIBackend](./ai.vertexaibackend.md#vertexaibackend_class) | Configuration class for the Vertex AI Gemini API.Use this with [AIOptions](./ai.aioptions.md#aioptions_interface) when initializing the AI service via [getAI()](./ai.md#getai_a94a413) to specify the Vertex AI Gemini API as the backend. | ## Interfaces @@ -341,6 +345,54 @@ export declare function getLiveGenerativeModel(ai: AI, modelParams: LiveModelPar If the `apiKey` or `projectId` fields are missing in your Firebase config. +### getTemplateGenerativeModel(ai, requestOptions) {:#gettemplategenerativemodel_9476bbc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns a [TemplateGenerativeModel](./ai.templategenerativemodel.md#templategenerativemodel_class) class for executing server-side templates. + +Signature: + +```typescript +export declare function getTemplateGenerativeModel(ai: AI, requestOptions?: RequestOptions): TemplateGenerativeModel; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ai | [AI](./ai.ai.md#ai_interface) | An [AI](./ai.ai.md#ai_interface) instance. | +| requestOptions | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) | Additional options to use when making requests. | + +Returns: + +[TemplateGenerativeModel](./ai.templategenerativemodel.md#templategenerativemodel_class) + +### getTemplateImagenModel(ai, requestOptions) {:#gettemplateimagenmodel_9476bbc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns a [TemplateImagenModel](./ai.templateimagenmodel.md#templateimagenmodel_class) class for executing server-side Imagen templates. + +Signature: + +```typescript +export declare function getTemplateImagenModel(ai: AI, requestOptions?: RequestOptions): TemplateImagenModel; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ai | [AI](./ai.ai.md#ai_interface) | An [AI](./ai.ai.md#ai_interface) instance. | +| requestOptions | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) | Additional options to use when making requests. | + +Returns: + +[TemplateImagenModel](./ai.templateimagenmodel.md#templateimagenmodel_class) + ## function(liveSession, ...) ### startAudioConversation(liveSession, options) {:#startaudioconversation_01c8e7f} diff --git a/docs-devsite/ai.templategenerativemodel.md b/docs-devsite/ai.templategenerativemodel.md new file mode 100644 index 0000000000..c115af62b1 --- /dev/null +++ b/docs-devsite/ai.templategenerativemodel.md @@ -0,0 +1,125 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# TemplateGenerativeModel class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +[GenerativeModel](./ai.generativemodel.md#generativemodel_class) APIs that execute on a server-side template. + +This class should only be instantiated with [getTemplateGenerativeModel()](./ai.md#gettemplategenerativemodel_9476bbc). + +Signature: + +```typescript +export declare class TemplateGenerativeModel +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(ai, requestOptions)](./ai.templategenerativemodel.md#templategenerativemodelconstructor) | | (Public Preview) Constructs a new instance of the TemplateGenerativeModel class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [requestOptions](./ai.templategenerativemodel.md#templategenerativemodelrequestoptions) | | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) | (Public Preview) Additional options to use when making requests. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [generateContent(templateId, templateVariables)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontent) | | (Public Preview) Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | +| [generateContentStream(templateId, templateVariables)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontentstream) | | (Public Preview) Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. | + +## TemplateGenerativeModel.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + + Constructs a new instance of the `TemplateGenerativeModel` class + +Signature: + +```typescript +constructor(ai: AI, requestOptions?: RequestOptions); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ai | [AI](./ai.ai.md#ai_interface) | | +| requestOptions | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) | | + +## TemplateGenerativeModel.requestOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Additional options to use when making requests. + +Signature: + +```typescript +requestOptions?: RequestOptions; +``` + +## TemplateGenerativeModel.generateContent() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). + +Signature: + +```typescript +generateContent(templateId: string, templateVariables: object): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| templateId | string | The ID of the server-side template to execute. | +| templateVariables | object | A key-value map of variables to populate the template with. | + +Returns: + +Promise<[GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface)> + +## TemplateGenerativeModel.generateContentStream() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. + +Signature: + +```typescript +generateContentStream(templateId: string, templateVariables: object): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| templateId | string | The ID of the server-side template to execute. | +| templateVariables | object | A key-value map of variables to populate the template with. | + +Returns: + +Promise<[GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface)> + diff --git a/docs-devsite/ai.templateimagenmodel.md b/docs-devsite/ai.templateimagenmodel.md new file mode 100644 index 0000000000..2d86071993 --- /dev/null +++ b/docs-devsite/ai.templateimagenmodel.md @@ -0,0 +1,100 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# TemplateImagenModel class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Class for Imagen model APIs that execute on a server-side template. + +This class should only be instantiated with [getTemplateImagenModel()](./ai.md#gettemplateimagenmodel_9476bbc). + +Signature: + +```typescript +export declare class TemplateImagenModel +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(ai, requestOptions)](./ai.templateimagenmodel.md#templateimagenmodelconstructor) | | (Public Preview) Constructs a new instance of the TemplateImagenModel class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [requestOptions](./ai.templateimagenmodel.md#templateimagenmodelrequestoptions) | | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) | (Public Preview) Additional options to use when making requests. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [generateImages(templateId, templateVariables)](./ai.templateimagenmodel.md#templateimagenmodelgenerateimages) | | (Public Preview) Makes a single call to the model and returns an object containing a single [ImagenGenerationResponse](./ai.imagengenerationresponse.md#imagengenerationresponse_interface). | + +## TemplateImagenModel.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + + Constructs a new instance of the `TemplateImagenModel` class + +Signature: + +```typescript +constructor(ai: AI, requestOptions?: RequestOptions); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ai | [AI](./ai.ai.md#ai_interface) | | +| requestOptions | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) | | + +## TemplateImagenModel.requestOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Additional options to use when making requests. + +Signature: + +```typescript +requestOptions?: RequestOptions; +``` + +## TemplateImagenModel.generateImages() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Makes a single call to the model and returns an object containing a single [ImagenGenerationResponse](./ai.imagengenerationresponse.md#imagengenerationresponse_interface). + +Signature: + +```typescript +generateImages(templateId: string, templateVariables: object): Promise>; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| templateId | string | The ID of the server-side template to execute. | +| templateVariables | object | A key-value map of variables to populate the template with. | + +Returns: + +Promise<[ImagenGenerationResponse](./ai.imagengenerationresponse.md#imagengenerationresponse_interface)<[ImagenInlineImage](./ai.imageninlineimage.md#imageninlineimage_interface)>> + diff --git a/packages/ai/integration/constants.ts b/packages/ai/integration/constants.ts index f4a74e7503..99a65f31c5 100644 --- a/packages/ai/integration/constants.ts +++ b/packages/ai/integration/constants.ts @@ -44,7 +44,7 @@ function formatConfigAsString(config: { ai: AI; model: string }): string { const backends: readonly Backend[] = [ new GoogleAIBackend(), - new VertexAIBackend() + new VertexAIBackend('global') ]; const backendNames: Map = new Map([ diff --git a/packages/ai/integration/prompt-templates.test.ts b/packages/ai/integration/prompt-templates.test.ts new file mode 100644 index 0000000000..3a7f903856 --- /dev/null +++ b/packages/ai/integration/prompt-templates.test.ts @@ -0,0 +1,66 @@ +/** + * @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. + */ + +import { expect } from 'chai'; +import { + BackendType, + getTemplateGenerativeModel, + getTemplateImagenModel +} from '../src'; +import { testConfigs } from './constants'; +import { STAGING_URL } from '../src/constants'; + +const templateBackendSuffix = ( + backendType: BackendType +): 'googleai' | 'vertexai' => + backendType === BackendType.GOOGLE_AI ? 'googleai' : 'vertexai'; + +describe('Prompt templates', function () { + this.timeout(20_000); + testConfigs.forEach(testConfig => { + describe(`${testConfig.toString()}`, () => { + describe('Generative Model', () => { + it('successfully generates content', async () => { + const model = getTemplateGenerativeModel(testConfig.ai, { + baseUrl: STAGING_URL + }); + const { response } = await model.generateContent( + `sassy-greeting-${templateBackendSuffix( + testConfig.ai.backend.backendType + )}`, + { name: 'John' } + ); + expect(response.text()).to.contain('John'); // Template asks to address directly by name + }); + }); + describe('Imagen model', async () => { + it('successfully generates images', async () => { + const model = getTemplateImagenModel(testConfig.ai, { + baseUrl: STAGING_URL + }); + const { images } = await model.generateImages( + `portrait-${templateBackendSuffix( + testConfig.ai.backend.backendType + )}`, + { animal: 'Rhino' } + ); + expect(images.length).to.equal(2); // We ask for two images in the prompt template + }); + }); + }); + }); +}); diff --git a/packages/ai/src/api.test.ts b/packages/ai/src/api.test.ts index 3854f010fc..3a56f3a8fe 100644 --- a/packages/ai/src/api.test.ts +++ b/packages/ai/src/api.test.ts @@ -22,7 +22,11 @@ import { LiveGenerativeModel, getGenerativeModel, getImagenModel, - getLiveGenerativeModel + getLiveGenerativeModel, + getTemplateGenerativeModel, + TemplateGenerativeModel, + getTemplateImagenModel, + TemplateImagenModel } from './api'; import { expect } from 'chai'; import { AI } from './public-types'; @@ -266,4 +270,14 @@ describe('Top level API', () => { 'publishers/google/models/my-model' ); }); + it('getTemplateGenerativeModel gets a TemplateGenerativeModel', () => { + expect(getTemplateGenerativeModel(fakeAI)).to.be.an.instanceOf( + TemplateGenerativeModel + ); + }); + it('getImagenModel gets a TemplateImagenModel', () => { + expect(getTemplateImagenModel(fakeAI)).to.be.an.instanceOf( + TemplateImagenModel + ); + }); }); diff --git a/packages/ai/src/api.ts b/packages/ai/src/api.ts index 6e56aea793..29614d88ce 100644 --- a/packages/ai/src/api.ts +++ b/packages/ai/src/api.ts @@ -39,12 +39,22 @@ import { import { encodeInstanceIdentifier } from './helpers'; import { GoogleAIBackend } from './backend'; import { WebSocketHandlerImpl } from './websocket'; +import { TemplateGenerativeModel } from './models/template-generative-model'; +import { TemplateImagenModel } from './models/template-imagen-model'; export { ChatSession } from './methods/chat-session'; export { LiveSession } from './methods/live-session'; export * from './requests/schema-builder'; export { ImagenImageFormat } from './requests/imagen-image-format'; -export { AIModel, GenerativeModel, LiveGenerativeModel, ImagenModel, AIError }; +export { + AIModel, + GenerativeModel, + LiveGenerativeModel, + ImagenModel, + TemplateGenerativeModel, + TemplateImagenModel, + AIError +}; export { Backend, VertexAIBackend, GoogleAIBackend } from './backend'; export { startAudioConversation, @@ -202,3 +212,35 @@ export function getLiveGenerativeModel( const webSocketHandler = new WebSocketHandlerImpl(); return new LiveGenerativeModel(ai, modelParams, webSocketHandler); } + +/** + * Returns a {@link TemplateGenerativeModel} class for executing server-side + * templates. + * + * @param ai - An {@link AI} instance. + * @param requestOptions - Additional options to use when making requests. + * + * @beta + */ +export function getTemplateGenerativeModel( + ai: AI, + requestOptions?: RequestOptions +): TemplateGenerativeModel { + return new TemplateGenerativeModel(ai, requestOptions); +} + +/** + * Returns a {@link TemplateImagenModel} class for executing server-side + * Imagen templates. + * + * @param ai - An {@link AI} instance. + * @param requestOptions - Additional options to use when making requests. + * + * @beta + */ +export function getTemplateImagenModel( + ai: AI, + requestOptions?: RequestOptions +): TemplateImagenModel { + return new TemplateImagenModel(ai, requestOptions); +} diff --git a/packages/ai/src/backend.test.ts b/packages/ai/src/backend.test.ts index 0c6609277e..46d6507a49 100644 --- a/packages/ai/src/backend.test.ts +++ b/packages/ai/src/backend.test.ts @@ -18,7 +18,7 @@ import { expect } from 'chai'; import { GoogleAIBackend, VertexAIBackend } from './backend'; import { BackendType } from './public-types'; -import { DEFAULT_LOCATION } from './constants'; +import { DEFAULT_API_VERSION, DEFAULT_LOCATION } from './constants'; describe('Backend', () => { describe('GoogleAIBackend', () => { @@ -26,6 +26,18 @@ describe('Backend', () => { const backend = new GoogleAIBackend(); expect(backend.backendType).to.equal(BackendType.GOOGLE_AI); }); + it('getModelPath', () => { + const backend = new GoogleAIBackend(); + expect(backend._getModelPath('my-project', 'model-name')).to.equal( + `/${DEFAULT_API_VERSION}/projects/my-project/model-name` + ); + }); + it('getTemplatePath', () => { + const backend = new GoogleAIBackend(); + expect(backend._getTemplatePath('my-project', 'template-id')).to.equal( + `/${DEFAULT_API_VERSION}/projects/my-project/templates/template-id` + ); + }); }); describe('VertexAIBackend', () => { it('set backendType to VERTEX_AI', () => { @@ -48,5 +60,17 @@ describe('Backend', () => { expect(backend.backendType).to.equal(BackendType.VERTEX_AI); expect(backend.location).to.equal(DEFAULT_LOCATION); }); + it('getModelPath', () => { + const backend = new VertexAIBackend(); + expect(backend._getModelPath('my-project', 'model-name')).to.equal( + `/${DEFAULT_API_VERSION}/projects/my-project/locations/${backend.location}/model-name` + ); + }); + it('getTemplatePath', () => { + const backend = new VertexAIBackend(); + expect(backend._getTemplatePath('my-project', 'template-id')).to.equal( + `/${DEFAULT_API_VERSION}/projects/my-project/locations/${backend.location}/templates/template-id` + ); + }); }); }); diff --git a/packages/ai/src/backend.ts b/packages/ai/src/backend.ts index 7209828122..2eaec59448 100644 --- a/packages/ai/src/backend.ts +++ b/packages/ai/src/backend.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { DEFAULT_LOCATION } from './constants'; +import { DEFAULT_API_VERSION, DEFAULT_LOCATION } from './constants'; import { BackendType } from './public-types'; /** @@ -39,6 +39,16 @@ export abstract class Backend { protected constructor(type: BackendType) { this.backendType = type; } + + /** + * @internal + */ + abstract _getModelPath(project: string, model: string): string; + + /** + * @internal + */ + abstract _getTemplatePath(project: string, templateId: string): string; } /** @@ -56,6 +66,20 @@ export class GoogleAIBackend extends Backend { constructor() { super(BackendType.GOOGLE_AI); } + + /** + * @internal + */ + _getModelPath(project: string, model: string): string { + return `/${DEFAULT_API_VERSION}/projects/${project}/${model}`; + } + + /** + * @internal + */ + _getTemplatePath(project: string, templateId: string): string { + return `/${DEFAULT_API_VERSION}/projects/${project}/templates/${templateId}`; + } } /** @@ -89,4 +113,18 @@ export class VertexAIBackend extends Backend { this.location = location; } } + + /** + * @internal + */ + _getModelPath(project: string, model: string): string { + return `/${DEFAULT_API_VERSION}/projects/${project}/locations/${this.location}/${model}`; + } + + /** + * @internal + */ + _getTemplatePath(project: string, templateId: string): string { + return `/${DEFAULT_API_VERSION}/projects/${project}/locations/${this.location}/templates/${templateId}`; + } } diff --git a/packages/ai/src/constants.ts b/packages/ai/src/constants.ts index 82482527f3..0a6f7e9143 100644 --- a/packages/ai/src/constants.ts +++ b/packages/ai/src/constants.ts @@ -23,6 +23,9 @@ export const DEFAULT_LOCATION = 'us-central1'; export const DEFAULT_DOMAIN = 'firebasevertexai.googleapis.com'; +export const STAGING_URL = + 'https://staging-firebasevertexai.sandbox.googleapis.com'; + export const DEFAULT_API_VERSION = 'v1beta'; export const PACKAGE_VERSION = version; diff --git a/packages/ai/src/methods/count-tokens.test.ts b/packages/ai/src/methods/count-tokens.test.ts index 84976d00ac..b3ed7f7fa4 100644 --- a/packages/ai/src/methods/count-tokens.test.ts +++ b/packages/ai/src/methods/count-tokens.test.ts @@ -71,16 +71,17 @@ describe('countTokens()', () => { fakeChromeAdapter ); expect(result.totalTokens).to.equal(6); - expect(result.totalBillableCharacters).to.equal(16); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.COUNT_TOKENS, - fakeApiSettings, - false, + { + model: 'model', + task: Task.COUNT_TOKENS, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: undefined + }, match((value: string) => { return value.includes('contents'); - }), - undefined + }) ); }); it('total tokens with modality details', async () => { @@ -102,14 +103,16 @@ describe('countTokens()', () => { expect(result.promptTokensDetails?.[0].modality).to.equal('IMAGE'); expect(result.promptTokensDetails?.[0].tokenCount).to.equal(1806); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.COUNT_TOKENS, - fakeApiSettings, - false, + { + model: 'model', + task: Task.COUNT_TOKENS, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: undefined + }, match((value: string) => { return value.includes('contents'); - }), - undefined + }) ); }); it('total tokens no billable characters', async () => { @@ -129,14 +132,16 @@ describe('countTokens()', () => { expect(result.totalTokens).to.equal(258); expect(result).to.not.have.property('totalBillableCharacters'); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.COUNT_TOKENS, - fakeApiSettings, - false, + { + model: 'model', + task: Task.COUNT_TOKENS, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: undefined + }, match((value: string) => { return value.includes('contents'); - }), - undefined + }) ); }); it('model not found', async () => { @@ -181,12 +186,14 @@ describe('countTokens()', () => { ); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.COUNT_TOKENS, - fakeGoogleAIApiSettings, - false, - JSON.stringify(mapCountTokensRequest(fakeRequestParams, 'model')), - undefined + { + model: 'model', + task: Task.COUNT_TOKENS, + apiSettings: fakeGoogleAIApiSettings, + stream: false, + requestOptions: undefined + }, + JSON.stringify(mapCountTokensRequest(fakeRequestParams, 'model')) ); }); }); diff --git a/packages/ai/src/methods/count-tokens.ts b/packages/ai/src/methods/count-tokens.ts index c6041a0bb9..20c633ee70 100644 --- a/packages/ai/src/methods/count-tokens.ts +++ b/packages/ai/src/methods/count-tokens.ts @@ -23,7 +23,7 @@ import { RequestOptions, AIErrorCode } from '../types'; -import { Task, makeRequest } from '../requests/request'; +import { makeRequest, Task } from '../requests/request'; import { ApiSettings } from '../types/internal'; import * as GoogleAIMapper from '../googleai-mappers'; import { BackendType } from '../public-types'; @@ -43,12 +43,14 @@ export async function countTokensOnCloud( body = JSON.stringify(params); } const response = await makeRequest( - model, - Task.COUNT_TOKENS, - apiSettings, - false, - body, - requestOptions + { + model, + task: Task.COUNT_TOKENS, + apiSettings, + stream: false, + requestOptions + }, + body ); return response.json(); } diff --git a/packages/ai/src/methods/generate-content.test.ts b/packages/ai/src/methods/generate-content.test.ts index 33a9ae5f5e..8a274c2441 100644 --- a/packages/ai/src/methods/generate-content.test.ts +++ b/packages/ai/src/methods/generate-content.test.ts @@ -19,9 +19,16 @@ import { expect, use } from 'chai'; import Sinon, { match, restore, stub } from 'sinon'; import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; -import { getMockResponse } from '../../test-utils/mock-response'; +import { + getMockResponse, + getMockResponseStreaming +} from '../../test-utils/mock-response'; import * as request from '../requests/request'; -import { generateContent } from './generate-content'; +import { + generateContent, + templateGenerateContent, + templateGenerateContentStream +} from './generate-content'; import { AIErrorCode, GenerateContentRequest, @@ -103,12 +110,14 @@ describe('generateContent()', () => { ); expect(result.response.text()).to.include('Mountain View, California'); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - JSON.stringify(fakeRequestParams), - undefined + { + model: 'model', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: undefined + }, + JSON.stringify(fakeRequestParams) ); }); it('long response', async () => { @@ -127,11 +136,14 @@ describe('generateContent()', () => { expect(result.response.text()).to.include('Use Freshly Ground Coffee'); expect(result.response.text()).to.include('30 minutes of brewing'); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - match.any + { + model: 'model', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: undefined + }, + JSON.stringify(fakeRequestParams) ); }); it('long response with token details', async () => { @@ -162,11 +174,14 @@ describe('generateContent()', () => { result.response.usageMetadata?.candidatesTokensDetails?.[0].tokenCount ).to.equal(76); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - match.any + { + model: 'model', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: undefined + }, + JSON.stringify(fakeRequestParams) ); }); it('citations', async () => { @@ -189,11 +204,14 @@ describe('generateContent()', () => { result.response.candidates?.[0].citationMetadata?.citations.length ).to.equal(3); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - match.any + { + model: 'model', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: undefined + }, + JSON.stringify(fakeRequestParams) ); }); it('google search grounding', async () => { @@ -236,11 +254,14 @@ describe('generateContent()', () => { .undefined; expect(makeRequestStub).to.be.calledWith( - 'model', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - match.any + { + model: 'model', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: undefined + }, + JSON.stringify(fakeRequestParams) ); it('url context', async () => { @@ -286,10 +307,12 @@ describe('generateContent()', () => { .be.undefined; expect(makeRequestStub).to.be.calledWith( - 'model', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, + { + model: 'model', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false + }, match.any ); }); @@ -328,11 +351,14 @@ describe('generateContent()', () => { ); expect(result.response.text).to.throw('SAFETY'); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - match.any + { + model: 'model', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: undefined + }, + JSON.stringify(fakeRequestParams) ); }); it('finishReason safety', async () => { @@ -350,11 +376,14 @@ describe('generateContent()', () => { ); expect(result.response.text).to.throw('SAFETY'); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - match.any + { + model: 'model', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: undefined + }, + JSON.stringify(fakeRequestParams) ); }); it('empty content', async () => { @@ -372,11 +401,14 @@ describe('generateContent()', () => { ); expect(result.response.text()).to.equal(''); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - match.any + { + model: 'model', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: undefined + }, + JSON.stringify(fakeRequestParams) ); }); it('empty part', async () => { @@ -410,11 +442,14 @@ describe('generateContent()', () => { ); expect(result.response.text()).to.include('Some text'); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - match.any + { + model: 'model', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: undefined + }, + JSON.stringify(fakeRequestParams) ); }); it('image rejected (400)', async () => { @@ -502,12 +537,14 @@ describe('generateContent()', () => { ); expect(makeRequestStub).to.be.calledWith( - 'model', - Task.GENERATE_CONTENT, - fakeGoogleAIApiSettings, - false, - JSON.stringify(mapGenerateContentRequest(fakeGoogleAIRequestParams)), - undefined + { + model: 'model', + task: Task.GENERATE_CONTENT, + apiSettings: fakeGoogleAIApiSettings, + stream: false, + requestOptions: match.any + }, + JSON.stringify(mapGenerateContentRequest(fakeGoogleAIRequestParams)) ); }); }); @@ -533,3 +570,83 @@ describe('generateContent()', () => { expect(generateContentStub).to.be.calledWith(fakeRequestParams); }); }); + +describe('templateGenerateContent', () => { + afterEach(() => { + restore(); + }); + it('should call makeRequest with correct parameters and process the response', async () => { + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-success-basic-reply-short.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const templateId = 'my-template'; + const templateParams = { name: 'world' }; + const requestOptions = { timeout: 5000 }; + + const result = await templateGenerateContent( + fakeApiSettings, + templateId, + templateParams, + requestOptions + ); + + expect(makeRequestStub).to.have.been.calledOnceWith( + { + task: 'templateGenerateContent', + templateId, + apiSettings: fakeApiSettings, + stream: false, + requestOptions + }, + JSON.stringify(templateParams) + ); + expect(result.response.text()).to.include('Mountain View, California'); + }); +}); + +describe('templateGenerateContentStream', () => { + afterEach(() => { + restore(); + }); + it('should call makeRequest with correct parameters for streaming', async () => { + const mockResponse = getMockResponseStreaming( + 'vertexAI', + 'streaming-success-basic-reply-short.txt' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const templateId = 'my-stream-template'; + const templateParams = { name: 'streaming world' }; + const requestOptions = { timeout: 10000 }; + + const result = await templateGenerateContentStream( + fakeApiSettings, + templateId, + templateParams, + requestOptions + ); + + expect(makeRequestStub).to.have.been.calledOnceWith( + { + task: 'templateStreamGenerateContent', + templateId, + apiSettings: fakeApiSettings, + stream: true, + requestOptions + }, + JSON.stringify(templateParams) + ); + + // Verify the stream processing part + for await (const item of result.stream) { + expect(item.text()).to.not.be.empty; + } + const response = await result.response; + expect(response.text()).to.include('Cheyenne'); + }); +}); diff --git a/packages/ai/src/methods/generate-content.ts b/packages/ai/src/methods/generate-content.ts index a2fb29e20d..fc6eac15c7 100644 --- a/packages/ai/src/methods/generate-content.ts +++ b/packages/ai/src/methods/generate-content.ts @@ -22,7 +22,11 @@ import { GenerateContentStreamResult, RequestOptions } from '../types'; -import { Task, makeRequest } from '../requests/request'; +import { + makeRequest, + ServerPromptTemplateTask, + Task +} from '../requests/request'; import { createEnhancedContentResponse } from '../requests/response-helpers'; import { processStream } from '../requests/stream-reader'; import { ApiSettings } from '../types/internal'; @@ -41,12 +45,14 @@ async function generateContentStreamOnCloud( params = GoogleAIMapper.mapGenerateContentRequest(params); } return makeRequest( - model, - Task.STREAM_GENERATE_CONTENT, - apiSettings, - /* stream */ true, - JSON.stringify(params), - requestOptions + { + task: Task.STREAM_GENERATE_CONTENT, + model, + apiSettings, + stream: true, + requestOptions + }, + JSON.stringify(params) ); } @@ -77,13 +83,62 @@ async function generateContentOnCloud( params = GoogleAIMapper.mapGenerateContentRequest(params); } return makeRequest( - model, - Task.GENERATE_CONTENT, - apiSettings, - /* stream */ false, - JSON.stringify(params), - requestOptions + { + model, + task: Task.GENERATE_CONTENT, + apiSettings, + stream: false, + requestOptions + }, + JSON.stringify(params) + ); +} + +export async function templateGenerateContent( + apiSettings: ApiSettings, + templateId: string, + templateParams: object, + requestOptions?: RequestOptions +): Promise { + const response = await makeRequest( + { + task: ServerPromptTemplateTask.TEMPLATE_GENERATE_CONTENT, + templateId, + apiSettings, + stream: false, + requestOptions + }, + JSON.stringify(templateParams) + ); + const generateContentResponse = await processGenerateContentResponse( + response, + apiSettings + ); + const enhancedResponse = createEnhancedContentResponse( + generateContentResponse + ); + return { + response: enhancedResponse + }; +} + +export async function templateGenerateContentStream( + apiSettings: ApiSettings, + templateId: string, + templateParams: object, + requestOptions?: RequestOptions +): Promise { + const response = await makeRequest( + { + task: ServerPromptTemplateTask.TEMPLATE_STREAM_GENERATE_CONTENT, + templateId, + apiSettings, + stream: true, + requestOptions + }, + JSON.stringify(templateParams) ); + return processStream(response, apiSettings); } export async function generateContent( diff --git a/packages/ai/src/models/ai-model.test.ts b/packages/ai/src/models/ai-model.test.ts index 2e8f8998c5..4786adc854 100644 --- a/packages/ai/src/models/ai-model.test.ts +++ b/packages/ai/src/models/ai-model.test.ts @@ -15,13 +15,10 @@ * limitations under the License. */ import { use, expect } from 'chai'; -import { AI, AIErrorCode } from '../public-types'; +import { AI } from '../public-types'; import sinonChai from 'sinon-chai'; -import { stub } from 'sinon'; import { AIModel } from './ai-model'; -import { AIError } from '../errors'; import { VertexAIBackend } from '../backend'; -import { AIService } from '../service'; use(sinonChai); @@ -69,105 +66,4 @@ describe('AIModel', () => { const testModel = new TestModel(fakeAI, 'tunedModels/my-model'); expect(testModel.model).to.equal('tunedModels/my-model'); }); - it('calls regular app check token when option is set', async () => { - const getTokenStub = stub().resolves(); - const getLimitedUseTokenStub = stub().resolves(); - const testModel = new TestModel( - //@ts-ignore - { - ...fakeAI, - options: { useLimitedUseAppCheckTokens: false }, - appCheck: { - getToken: getTokenStub, - getLimitedUseToken: getLimitedUseTokenStub - } - } as AIService, - 'models/my-model' - ); - if (testModel._apiSettings?.getAppCheckToken) { - await testModel._apiSettings.getAppCheckToken(); - } - expect(getTokenStub).to.be.called; - expect(getLimitedUseTokenStub).to.not.be.called; - getTokenStub.reset(); - getLimitedUseTokenStub.reset(); - }); - it('calls limited use token when option is set', async () => { - const getTokenStub = stub().resolves(); - const getLimitedUseTokenStub = stub().resolves(); - const testModel = new TestModel( - //@ts-ignore - { - ...fakeAI, - options: { useLimitedUseAppCheckTokens: true }, - appCheck: { - getToken: getTokenStub, - getLimitedUseToken: getLimitedUseTokenStub - } - } as AIService, - 'models/my-model' - ); - if (testModel._apiSettings?.getAppCheckToken) { - await testModel._apiSettings.getAppCheckToken(); - } - expect(getTokenStub).to.not.be.called; - expect(getLimitedUseTokenStub).to.be.called; - getTokenStub.reset(); - getLimitedUseTokenStub.reset(); - }); - it('throws if not passed an api key', () => { - const fakeAI: AI = { - app: { - name: 'DEFAULT', - automaticDataCollectionEnabled: true, - options: { - projectId: 'my-project' - } - }, - backend: new VertexAIBackend('us-central1'), - location: 'us-central1' - }; - try { - new TestModel(fakeAI, 'my-model'); - } catch (e) { - expect((e as AIError).code).to.equal(AIErrorCode.NO_API_KEY); - } - }); - it('throws if not passed a project ID', () => { - const fakeAI: AI = { - app: { - name: 'DEFAULT', - automaticDataCollectionEnabled: true, - options: { - apiKey: 'key' - } - }, - backend: new VertexAIBackend('us-central1'), - location: 'us-central1' - }; - try { - new TestModel(fakeAI, 'my-model'); - } catch (e) { - expect((e as AIError).code).to.equal(AIErrorCode.NO_PROJECT_ID); - } - }); - it('throws if not passed an app ID', () => { - const fakeAI: AI = { - app: { - name: 'DEFAULT', - automaticDataCollectionEnabled: true, - options: { - apiKey: 'key', - projectId: 'my-project' - } - }, - backend: new VertexAIBackend('us-central1'), - location: 'us-central1' - }; - try { - new TestModel(fakeAI, 'my-model'); - } catch (e) { - expect((e as AIError).code).to.equal(AIErrorCode.NO_APP_ID); - } - }); }); diff --git a/packages/ai/src/models/ai-model.ts b/packages/ai/src/models/ai-model.ts index 3fe202d5eb..e2bc70319d 100644 --- a/packages/ai/src/models/ai-model.ts +++ b/packages/ai/src/models/ai-model.ts @@ -15,11 +15,9 @@ * limitations under the License. */ -import { AIError } from '../errors'; -import { AIErrorCode, AI, BackendType } from '../public-types'; -import { AIService } from '../service'; +import { AI, BackendType } from '../public-types'; import { ApiSettings } from '../types/internal'; -import { _isFirebaseServerApp } from '@firebase/app'; +import { initApiSettings } from './utils'; /** * Base class for Firebase AI model APIs. @@ -59,56 +57,11 @@ export abstract class AIModel { * @internal */ protected constructor(ai: AI, modelName: string) { - if (!ai.app?.options?.apiKey) { - throw new AIError( - AIErrorCode.NO_API_KEY, - `The "apiKey" field is empty in the local Firebase config. Firebase AI requires this field to contain a valid API key.` - ); - } else if (!ai.app?.options?.projectId) { - throw new AIError( - AIErrorCode.NO_PROJECT_ID, - `The "projectId" field is empty in the local Firebase config. Firebase AI requires this field to contain a valid project ID.` - ); - } else if (!ai.app?.options?.appId) { - throw new AIError( - AIErrorCode.NO_APP_ID, - `The "appId" field is empty in the local Firebase config. Firebase AI requires this field to contain a valid app ID.` - ); - } else { - this._apiSettings = { - apiKey: ai.app.options.apiKey, - project: ai.app.options.projectId, - appId: ai.app.options.appId, - automaticDataCollectionEnabled: ai.app.automaticDataCollectionEnabled, - location: ai.location, - backend: ai.backend - }; - - if (_isFirebaseServerApp(ai.app) && ai.app.settings.appCheckToken) { - const token = ai.app.settings.appCheckToken; - this._apiSettings.getAppCheckToken = () => { - return Promise.resolve({ token }); - }; - } else if ((ai as AIService).appCheck) { - if (ai.options?.useLimitedUseAppCheckTokens) { - this._apiSettings.getAppCheckToken = () => - (ai as AIService).appCheck!.getLimitedUseToken(); - } else { - this._apiSettings.getAppCheckToken = () => - (ai as AIService).appCheck!.getToken(); - } - } - - if ((ai as AIService).auth) { - this._apiSettings.getAuthToken = () => - (ai as AIService).auth!.getToken(); - } - - this.model = AIModel.normalizeModelName( - modelName, - this._apiSettings.backend.backendType - ); - } + this._apiSettings = initApiSettings(ai); + this.model = AIModel.normalizeModelName( + modelName, + this._apiSettings.backend.backendType + ); } /** diff --git a/packages/ai/src/models/generative-model.test.ts b/packages/ai/src/models/generative-model.test.ts index 90399e6811..45430cb5f5 100644 --- a/packages/ai/src/models/generative-model.test.ts +++ b/packages/ai/src/models/generative-model.test.ts @@ -92,10 +92,13 @@ describe('GenerativeModel', () => { ); await genModel.generateContent('hello'); expect(makeRequestStub).to.be.calledWith( - 'publishers/google/models/my-model', - request.Task.GENERATE_CONTENT, - match.any, - false, + { + model: 'publishers/google/models/my-model', + task: request.Task.GENERATE_CONTENT, + apiSettings: match.any, + stream: false, + requestOptions: {} + }, match((value: string) => { return ( value.includes('myfunc') && @@ -104,8 +107,7 @@ describe('GenerativeModel', () => { value.includes(FunctionCallingMode.NONE) && value.includes('be friendly') ); - }), - {} + }) ); restore(); }); @@ -129,14 +131,16 @@ describe('GenerativeModel', () => { ); await genModel.generateContent('hello'); expect(makeRequestStub).to.be.calledWith( - 'publishers/google/models/my-model', - request.Task.GENERATE_CONTENT, - match.any, - false, + { + model: 'publishers/google/models/my-model', + task: request.Task.GENERATE_CONTENT, + apiSettings: match.any, + stream: false, + requestOptions: {} + }, match((value: string) => { return value.includes('be friendly'); - }), - {} + }) ); restore(); }); @@ -190,10 +194,13 @@ describe('GenerativeModel', () => { systemInstruction: { role: 'system', parts: [{ text: 'be formal' }] } }); expect(makeRequestStub).to.be.calledWith( - 'publishers/google/models/my-model', - request.Task.GENERATE_CONTENT, - match.any, - false, + { + model: 'publishers/google/models/my-model', + task: request.Task.GENERATE_CONTENT, + apiSettings: match.any, + stream: false, + requestOptions: {} + }, match((value: string) => { return ( value.includes('otherfunc') && @@ -202,8 +209,7 @@ describe('GenerativeModel', () => { value.includes(FunctionCallingMode.AUTO) && value.includes('be formal') ); - }), - {} + }) ); restore(); }); @@ -281,10 +287,13 @@ describe('GenerativeModel', () => { ); await genModel.startChat().sendMessage('hello'); expect(makeRequestStub).to.be.calledWith( - 'publishers/google/models/my-model', - request.Task.GENERATE_CONTENT, - match.any, - false, + { + model: 'publishers/google/models/my-model', + task: request.Task.GENERATE_CONTENT, + apiSettings: match.any, + stream: false, + requestOptions: {} + }, match((value: string) => { return ( value.includes('myfunc') && @@ -294,8 +303,7 @@ describe('GenerativeModel', () => { value.includes('be friendly') && value.includes('topK') ); - }), - {} + }) ); restore(); }); @@ -319,14 +327,16 @@ describe('GenerativeModel', () => { ); await genModel.startChat().sendMessage('hello'); expect(makeRequestStub).to.be.calledWith( - 'publishers/google/models/my-model', - request.Task.GENERATE_CONTENT, - match.any, - false, + { + model: 'publishers/google/models/my-model', + task: request.Task.GENERATE_CONTENT, + apiSettings: match.any, + stream: false, + requestOptions: {} + }, match((value: string) => { return value.includes('be friendly'); - }), - {} + }) ); restore(); }); @@ -382,10 +392,13 @@ describe('GenerativeModel', () => { }) .sendMessage('hello'); expect(makeRequestStub).to.be.calledWith( - 'publishers/google/models/my-model', - request.Task.GENERATE_CONTENT, - match.any, - false, + { + model: 'publishers/google/models/my-model', + task: request.Task.GENERATE_CONTENT, + apiSettings: match.any, + stream: false, + requestOptions: {} + }, match((value: string) => { return ( value.includes('otherfunc') && @@ -396,8 +409,7 @@ describe('GenerativeModel', () => { value.includes('image/png') && !value.includes('image/jpeg') ); - }), - {} + }) ); restore(); }); @@ -417,10 +429,13 @@ describe('GenerativeModel', () => { ); await genModel.countTokens('hello'); expect(makeRequestStub).to.be.calledWith( - 'publishers/google/models/my-model', - request.Task.COUNT_TOKENS, - match.any, - false, + { + model: 'publishers/google/models/my-model', + task: request.Task.COUNT_TOKENS, + apiSettings: match.any, + stream: false, + requestOptions: undefined + }, match((value: string) => { return value.includes('hello'); }) diff --git a/packages/ai/src/models/imagen-model.test.ts b/packages/ai/src/models/imagen-model.test.ts index f4121e18f2..68b6caca09 100644 --- a/packages/ai/src/models/imagen-model.test.ts +++ b/packages/ai/src/models/imagen-model.test.ts @@ -62,17 +62,19 @@ describe('ImagenModel', () => { const prompt = 'A photorealistic image of a toy boat at sea.'; await imagenModel.generateImages(prompt); expect(makeRequestStub).to.be.calledWith( - 'publishers/google/models/my-model', - request.Task.PREDICT, - match.any, - false, + { + model: 'publishers/google/models/my-model', + task: request.Task.PREDICT, + apiSettings: match.any, + stream: false, + requestOptions: undefined + }, match((value: string) => { return ( value.includes(`"prompt":"${prompt}"`) && value.includes(`"sampleCount":1`) ); - }), - undefined + }) ); restore(); }); @@ -102,10 +104,13 @@ describe('ImagenModel', () => { const prompt = 'A photorealistic image of a toy boat at sea.'; await imagenModel.generateImages(prompt); expect(makeRequestStub).to.be.calledWith( - 'publishers/google/models/my-model', - request.Task.PREDICT, - match.any, - false, + { + model: 'publishers/google/models/my-model', + task: request.Task.PREDICT, + apiSettings: match.any, + stream: false, + requestOptions: undefined + }, match((value: string) => { return ( value.includes( @@ -130,8 +135,7 @@ describe('ImagenModel', () => { JSON.stringify(imagenModel.safetySettings?.personFilterLevel) ) ); - }), - undefined + }) ); restore(); }); diff --git a/packages/ai/src/models/imagen-model.ts b/packages/ai/src/models/imagen-model.ts index a41a03f25c..567333ee64 100644 --- a/packages/ai/src/models/imagen-model.ts +++ b/packages/ai/src/models/imagen-model.ts @@ -16,7 +16,7 @@ */ import { AI } from '../public-types'; -import { Task, makeRequest } from '../requests/request'; +import { makeRequest, Task } from '../requests/request'; import { createPredictRequestBody } from '../requests/request-helpers'; import { handlePredictResponse } from '../requests/response-helpers'; import { @@ -109,12 +109,14 @@ export class ImagenModel extends AIModel { ...this.safetySettings }); const response = await makeRequest( - this.model, - Task.PREDICT, - this._apiSettings, - /* stream */ false, - JSON.stringify(body), - this.requestOptions + { + task: Task.PREDICT, + model: this.model, + apiSettings: this._apiSettings, + stream: false, + requestOptions: this.requestOptions + }, + JSON.stringify(body) ); return handlePredictResponse(response); } @@ -148,12 +150,14 @@ export class ImagenModel extends AIModel { ...this.safetySettings }); const response = await makeRequest( - this.model, - Task.PREDICT, - this._apiSettings, - /* stream */ false, - JSON.stringify(body), - this.requestOptions + { + task: Task.PREDICT, + model: this.model, + apiSettings: this._apiSettings, + stream: false, + requestOptions: this.requestOptions + }, + JSON.stringify(body) ); return handlePredictResponse(response); } diff --git a/packages/ai/src/models/template-generative-model.test.ts b/packages/ai/src/models/template-generative-model.test.ts new file mode 100644 index 0000000000..c3eb43af49 --- /dev/null +++ b/packages/ai/src/models/template-generative-model.test.ts @@ -0,0 +1,96 @@ +/** + * @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. + */ + +import { use, expect } from 'chai'; +import sinonChai from 'sinon-chai'; +import { restore, stub } from 'sinon'; +import { AI } from '../public-types'; +import { VertexAIBackend } from '../backend'; +import { TemplateGenerativeModel } from './template-generative-model'; +import * as generateContentMethods from '../methods/generate-content'; + +use(sinonChai); + +const fakeAI: AI = { + app: { + name: 'DEFAULT', + automaticDataCollectionEnabled: true, + options: { + apiKey: 'key', + projectId: 'my-project', + appId: 'my-appid' + } + }, + backend: new VertexAIBackend('us-central1'), + location: 'us-central1' +}; + +const TEMPLATE_ID = 'my-template'; +const TEMPLATE_VARS = { a: 1, b: '2' }; + +describe('TemplateGenerativeModel', () => { + afterEach(() => { + restore(); + }); + + describe('constructor', () => { + it('should initialize _apiSettings correctly', () => { + const model = new TemplateGenerativeModel(fakeAI); + expect(model._apiSettings.apiKey).to.equal('key'); + expect(model._apiSettings.project).to.equal('my-project'); + expect(model._apiSettings.appId).to.equal('my-appid'); + }); + }); + + describe('generateContent', () => { + it('should call templateGenerateContent with correct parameters', async () => { + const templateGenerateContentStub = stub( + generateContentMethods, + 'templateGenerateContent' + ).resolves({} as any); + const model = new TemplateGenerativeModel(fakeAI, { timeout: 5000 }); + + await model.generateContent(TEMPLATE_ID, TEMPLATE_VARS); + + expect(templateGenerateContentStub).to.have.been.calledOnceWith( + model._apiSettings, + TEMPLATE_ID, + { inputs: TEMPLATE_VARS }, + { timeout: 5000 } + ); + }); + }); + + describe('generateContentStream', () => { + it('should call templateGenerateContentStream with correct parameters', async () => { + const templateGenerateContentStreamStub = stub( + generateContentMethods, + 'templateGenerateContentStream' + ).resolves({} as any); + const model = new TemplateGenerativeModel(fakeAI, { timeout: 5000 }); + + await model.generateContentStream(TEMPLATE_ID, TEMPLATE_VARS); + + expect(templateGenerateContentStreamStub).to.have.been.calledOnceWith( + model._apiSettings, + TEMPLATE_ID, + { inputs: TEMPLATE_VARS }, + { timeout: 5000 } + ); + }); + }); +}); diff --git a/packages/ai/src/models/template-generative-model.ts b/packages/ai/src/models/template-generative-model.ts new file mode 100644 index 0000000000..ec9e653618 --- /dev/null +++ b/packages/ai/src/models/template-generative-model.ts @@ -0,0 +1,98 @@ +/** + * @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. + */ + +import { + templateGenerateContent, + templateGenerateContentStream +} from '../methods/generate-content'; +import { GenerateContentResult, RequestOptions } from '../types'; +import { AI, GenerateContentStreamResult } from '../public-types'; +import { ApiSettings } from '../types/internal'; +import { initApiSettings } from './utils'; + +/** + * {@link GenerativeModel} APIs that execute on a server-side template. + * + * This class should only be instantiated with {@link getTemplateGenerativeModel}. + * + * @beta + */ +export class TemplateGenerativeModel { + /** + * @internal + */ + _apiSettings: ApiSettings; + + /** + * Additional options to use when making requests. + */ + requestOptions?: RequestOptions; + + /** + * @hideconstructor + */ + constructor(ai: AI, requestOptions?: RequestOptions) { + this.requestOptions = requestOptions || {}; + this._apiSettings = initApiSettings(ai); + } + + /** + * Makes a single non-streaming call to the model and returns an object + * containing a single {@link GenerateContentResponse}. + * + * @param templateId - The ID of the server-side template to execute. + * @param templateVariables - A key-value map of variables to populate the + * template with. + * + * @beta + */ + async generateContent( + templateId: string, + templateVariables: object // anything! + ): Promise { + return templateGenerateContent( + this._apiSettings, + templateId, + { inputs: templateVariables }, + this.requestOptions + ); + } + + /** + * Makes a single streaming call to the model and returns an object + * containing an iterable stream that iterates over all chunks in the + * streaming response as well as a promise that returns the final aggregated + * response. + * + * @param templateId - The ID of the server-side template to execute. + * @param templateVariables - A key-value map of variables to populate the + * template with. + * + * @beta + */ + async generateContentStream( + templateId: string, + templateVariables: object + ): Promise { + return templateGenerateContentStream( + this._apiSettings, + templateId, + { inputs: templateVariables }, + this.requestOptions + ); + } +} diff --git a/packages/ai/src/models/template-imagen-model.test.ts b/packages/ai/src/models/template-imagen-model.test.ts new file mode 100644 index 0000000000..c053753ea0 --- /dev/null +++ b/packages/ai/src/models/template-imagen-model.test.ts @@ -0,0 +1,139 @@ +/** + * @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. + */ + +import { use, expect } from 'chai'; +import sinonChai from 'sinon-chai'; +import chaiAsPromised from 'chai-as-promised'; +import { restore, stub } from 'sinon'; +import { AI } from '../public-types'; +import { VertexAIBackend } from '../backend'; +import { TemplateImagenModel } from './template-imagen-model'; +import { AIError } from '../errors'; +import * as request from '../requests/request'; + +use(sinonChai); +use(chaiAsPromised); + +const fakeAI: AI = { + app: { + name: 'DEFAULT', + automaticDataCollectionEnabled: true, + options: { + apiKey: 'key', + projectId: 'my-project', + appId: 'my-appid' + } + }, + backend: new VertexAIBackend('us-central1'), + location: 'us-central1' +}; + +const TEMPLATE_ID = 'my-imagen-template'; +const TEMPLATE_VARS = { a: 1, b: '2' }; + +describe('TemplateImagenModel', () => { + afterEach(() => { + restore(); + }); + + describe('constructor', () => { + it('should initialize _apiSettings correctly', () => { + const model = new TemplateImagenModel(fakeAI); + expect(model._apiSettings.apiKey).to.equal('key'); + expect(model._apiSettings.project).to.equal('my-project'); + expect(model._apiSettings.appId).to.equal('my-appid'); + }); + }); + + describe('generateImages', () => { + it('should call makeRequest with correct parameters', async () => { + const makeRequestStub = stub(request, 'makeRequest').resolves({ + json: () => + Promise.resolve({ + predictions: [ + { + bytesBase64Encoded: + 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==', + mimeType: 'image/png' + } + ] + }) + } as Response); + const model = new TemplateImagenModel(fakeAI, { timeout: 5000 }); + + await model.generateImages(TEMPLATE_ID, TEMPLATE_VARS); + + expect(makeRequestStub).to.have.been.calledOnceWith( + { + task: 'templatePredict', + templateId: TEMPLATE_ID, + apiSettings: model._apiSettings, + stream: false, + requestOptions: { timeout: 5000 } + }, + JSON.stringify({ inputs: TEMPLATE_VARS }) + ); + }); + + it('should return the result of handlePredictResponse', async () => { + const mockPrediction = { + 'bytesBase64Encoded': + 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==', + 'mimeType': 'image/png' + }; + stub(request, 'makeRequest').resolves({ + json: () => Promise.resolve({ predictions: [mockPrediction] }) + } as Response); + + const model = new TemplateImagenModel(fakeAI); + const result = await model.generateImages(TEMPLATE_ID, TEMPLATE_VARS); + + expect(result.images).to.deep.equal([mockPrediction]); + }); + + it('should throw an AIError if the prompt is blocked', async () => { + const error = new AIError('fetch-error', 'Request failed'); + stub(request, 'makeRequest').rejects(error); + + const model = new TemplateImagenModel(fakeAI); + await expect( + model.generateImages(TEMPLATE_ID, TEMPLATE_VARS) + ).to.be.rejectedWith(error); + }); + + it('should handle responses with filtered images', async () => { + const mockPrediction = { + bytesBase64Encoded: 'iVBOR...ggg==', + mimeType: 'image/png' + }; + const filteredReason = 'This image was filtered for safety reasons.'; + stub(request, 'makeRequest').resolves({ + json: () => + Promise.resolve({ + predictions: [mockPrediction, { raiFilteredReason: filteredReason }] + }) + } as Response); + + const model = new TemplateImagenModel(fakeAI); + const result = await model.generateImages(TEMPLATE_ID, TEMPLATE_VARS); + + expect(result.images).to.have.lengthOf(1); + expect(result.images[0]).to.deep.equal(mockPrediction); + expect(result.filteredReason).to.equal(filteredReason); + }); + }); +}); diff --git a/packages/ai/src/models/template-imagen-model.ts b/packages/ai/src/models/template-imagen-model.ts new file mode 100644 index 0000000000..34325c711b --- /dev/null +++ b/packages/ai/src/models/template-imagen-model.ts @@ -0,0 +1,81 @@ +/** + * @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. + */ + +import { RequestOptions } from '../types'; +import { + AI, + ImagenGenerationResponse, + ImagenInlineImage +} from '../public-types'; +import { ApiSettings } from '../types/internal'; +import { makeRequest, ServerPromptTemplateTask } from '../requests/request'; +import { handlePredictResponse } from '../requests/response-helpers'; +import { initApiSettings } from './utils'; + +/** + * Class for Imagen model APIs that execute on a server-side template. + * + * This class should only be instantiated with {@link getTemplateImagenModel}. + * + * @beta + */ +export class TemplateImagenModel { + /** + * @internal + */ + _apiSettings: ApiSettings; + + /** + * Additional options to use when making requests. + */ + requestOptions?: RequestOptions; + + /** + * @hideconstructor + */ + constructor(ai: AI, requestOptions?: RequestOptions) { + this.requestOptions = requestOptions || {}; + this._apiSettings = initApiSettings(ai); + } + + /** + * Makes a single call to the model and returns an object containing a single + * {@link ImagenGenerationResponse}. + * + * @param templateId - The ID of the server-side template to execute. + * @param templateVariables - A key-value map of variables to populate the + * template with. + * + * @beta + */ + async generateImages( + templateId: string, + templateVariables: object + ): Promise> { + const response = await makeRequest( + { + task: ServerPromptTemplateTask.TEMPLATE_PREDICT, + templateId, + apiSettings: this._apiSettings, + stream: false, + requestOptions: this.requestOptions + }, + JSON.stringify({ inputs: templateVariables }) + ); + return handlePredictResponse(response); + } +} diff --git a/packages/ai/src/models/utils.test.ts b/packages/ai/src/models/utils.test.ts new file mode 100644 index 0000000000..42d1900727 --- /dev/null +++ b/packages/ai/src/models/utils.test.ts @@ -0,0 +1,142 @@ +/** + * @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. + */ +import { use, expect } from 'chai'; +import { AI, AIErrorCode } from '../public-types'; +import sinonChai from 'sinon-chai'; +import { stub } from 'sinon'; +import { AIError } from '../errors'; +import { VertexAIBackend } from '../backend'; +import { AIService } from '../service'; +import { initApiSettings } from './utils'; + +use(sinonChai); + +const fakeAI: AI = { + app: { + name: 'DEFAULT', + automaticDataCollectionEnabled: true, + options: { + apiKey: 'key', + projectId: 'my-project', + appId: 'my-appid' + } + }, + backend: new VertexAIBackend('us-central1'), + location: 'us-central1' +}; + +describe('initApiSettings', () => { + it('calls regular app check token when option is set', async () => { + const getTokenStub = stub().resolves(); + const getLimitedUseTokenStub = stub().resolves(); + const apiSettings = initApiSettings( + //@ts-ignore + { + ...fakeAI, + options: { useLimitedUseAppCheckTokens: false }, + appCheck: { + getToken: getTokenStub, + getLimitedUseToken: getLimitedUseTokenStub + } + } as AIService + ); + if (apiSettings?.getAppCheckToken) { + await apiSettings.getAppCheckToken(); + } + expect(getTokenStub).to.be.called; + expect(getLimitedUseTokenStub).to.not.be.called; + getTokenStub.reset(); + getLimitedUseTokenStub.reset(); + }); + it('calls limited use token when option is set', async () => { + const getTokenStub = stub().resolves(); + const getLimitedUseTokenStub = stub().resolves(); + const apiSettings = initApiSettings( + //@ts-ignore + { + ...fakeAI, + options: { useLimitedUseAppCheckTokens: true }, + appCheck: { + getToken: getTokenStub, + getLimitedUseToken: getLimitedUseTokenStub + } + } as AIService + ); + if (apiSettings?.getAppCheckToken) { + await apiSettings.getAppCheckToken(); + } + expect(getTokenStub).to.not.be.called; + expect(getLimitedUseTokenStub).to.be.called; + getTokenStub.reset(); + getLimitedUseTokenStub.reset(); + }); + it('throws if not passed an api key', () => { + const fakeAI: AI = { + app: { + name: 'DEFAULT', + automaticDataCollectionEnabled: true, + options: { + projectId: 'my-project' + } + }, + backend: new VertexAIBackend('us-central1'), + location: 'us-central1' + }; + try { + initApiSettings(fakeAI); + } catch (e) { + expect((e as AIError).code).to.equal(AIErrorCode.NO_API_KEY); + } + }); + it('throws if not passed a project ID', () => { + const fakeAI: AI = { + app: { + name: 'DEFAULT', + automaticDataCollectionEnabled: true, + options: { + apiKey: 'key' + } + }, + backend: new VertexAIBackend('us-central1'), + location: 'us-central1' + }; + try { + initApiSettings(fakeAI); + } catch (e) { + expect((e as AIError).code).to.equal(AIErrorCode.NO_PROJECT_ID); + } + }); + it('throws if not passed an app ID', () => { + const fakeAI: AI = { + app: { + name: 'DEFAULT', + automaticDataCollectionEnabled: true, + options: { + apiKey: 'key', + projectId: 'my-project' + } + }, + backend: new VertexAIBackend('us-central1'), + location: 'us-central1' + }; + try { + initApiSettings(fakeAI); + } catch (e) { + expect((e as AIError).code).to.equal(AIErrorCode.NO_APP_ID); + } + }); +}); diff --git a/packages/ai/src/models/utils.ts b/packages/ai/src/models/utils.ts new file mode 100644 index 0000000000..035ed3f734 --- /dev/null +++ b/packages/ai/src/models/utils.ts @@ -0,0 +1,78 @@ +/** + * @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. + */ + +import { _isFirebaseServerApp } from '@firebase/app'; +import { AIError } from '../errors'; +import { AI, AIErrorCode } from '../public-types'; +import { AIService } from '../service'; +import { ApiSettings } from '../types/internal'; + +/** + * Initializes an {@link ApiSettings} object from an {@link AI} instance. + * + * If this is a Server App, the {@link ApiSettings} object's `getAppCheckToken()` will resolve + * with the `FirebaseServerAppSettings.appCheckToken`, instead of requiring that an App Check + * instance is initialized. + */ +export function initApiSettings(ai: AI): ApiSettings { + if (!ai.app?.options?.apiKey) { + throw new AIError( + AIErrorCode.NO_API_KEY, + `The "apiKey" field is empty in the local Firebase config. Firebase AI requires this field to contain a valid API key.` + ); + } else if (!ai.app?.options?.projectId) { + throw new AIError( + AIErrorCode.NO_PROJECT_ID, + `The "projectId" field is empty in the local Firebase config. Firebase AI requires this field to contain a valid project ID.` + ); + } else if (!ai.app?.options?.appId) { + throw new AIError( + AIErrorCode.NO_APP_ID, + `The "appId" field is empty in the local Firebase config. Firebase AI requires this field to contain a valid app ID.` + ); + } + + const apiSettings: ApiSettings = { + apiKey: ai.app.options.apiKey, + project: ai.app.options.projectId, + appId: ai.app.options.appId, + automaticDataCollectionEnabled: ai.app.automaticDataCollectionEnabled, + location: ai.location, + backend: ai.backend + }; + + if (_isFirebaseServerApp(ai.app) && ai.app.settings.appCheckToken) { + const token = ai.app.settings.appCheckToken; + apiSettings.getAppCheckToken = () => { + return Promise.resolve({ token }); + }; + } else if ((ai as AIService).appCheck) { + if (ai.options?.useLimitedUseAppCheckTokens) { + apiSettings.getAppCheckToken = () => + (ai as AIService).appCheck!.getLimitedUseToken(); + } else { + apiSettings.getAppCheckToken = () => + (ai as AIService).appCheck!.getToken(); + } + } + + if ((ai as AIService).auth) { + apiSettings.getAuthToken = () => (ai as AIService).auth!.getToken(); + } + + return apiSettings; +} diff --git a/packages/ai/src/requests/request.test.ts b/packages/ai/src/requests/request.test.ts index 0d162906fd..a54ff521be 100644 --- a/packages/ai/src/requests/request.test.ts +++ b/packages/ai/src/requests/request.test.ts @@ -19,7 +19,13 @@ import { expect, use } from 'chai'; import { match, restore, stub } from 'sinon'; import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; -import { RequestUrl, Task, getHeaders, makeRequest } from './request'; +import { + RequestURL, + ServerPromptTemplateTask, + Task, + getHeaders, + makeRequest +} from './request'; import { ApiSettings } from '../types/internal'; import { DEFAULT_API_VERSION } from '../constants'; import { AIErrorCode } from '../types'; @@ -42,65 +48,77 @@ describe('request methods', () => { afterEach(() => { restore(); }); - describe('RequestUrl', () => { + describe('RequestURL', () => { it('stream', async () => { - const url = new RequestUrl( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - true, - {} - ); + const url = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: true, + requestOptions: {} + }); expect(url.toString()).to.include('models/model-name:generateContent'); - expect(url.toString()).to.not.include(fakeApiSettings); expect(url.toString()).to.include('alt=sse'); }); it('non-stream', async () => { - const url = new RequestUrl( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - {} - ); + const url = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: {} + }); expect(url.toString()).to.include('models/model-name:generateContent'); expect(url.toString()).to.not.include(fakeApiSettings); expect(url.toString()).to.not.include('alt=sse'); }); it('default apiVersion', async () => { - const url = new RequestUrl( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - {} - ); + const url = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: {} + }); expect(url.toString()).to.include(DEFAULT_API_VERSION); }); it('custom baseUrl', async () => { - const url = new RequestUrl( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - { baseUrl: 'https://my.special.endpoint' } - ); + const url = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: { baseUrl: 'https://my.special.endpoint' } + }); expect(url.toString()).to.include('https://my.special.endpoint'); }); it('non-stream - tunedModels/', async () => { - const url = new RequestUrl( - 'tunedModels/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - {} - ); + const url = new RequestURL({ + model: 'tunedModels/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: {} + }); expect(url.toString()).to.include( 'tunedModels/model-name:generateContent' ); expect(url.toString()).to.not.include(fakeApiSettings); expect(url.toString()).to.not.include('alt=sse'); }); + it('prompt server template', async () => { + const url = new RequestURL({ + templateId: 'my-template', + task: ServerPromptTemplateTask.TEMPLATE_GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: {} + }); + expect(url.toString()).to.include( + 'templates/my-template:templateGenerateContent' + ); + expect(url.toString()).to.not.include(fakeApiSettings); + }); }); describe('getHeaders', () => { const fakeApiSettings: ApiSettings = { @@ -112,13 +130,13 @@ describe('request methods', () => { getAuthToken: () => Promise.resolve({ accessToken: 'authtoken' }), getAppCheckToken: () => Promise.resolve({ token: 'appchecktoken' }) }; - const fakeUrl = new RequestUrl( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - true, - {} - ); + const fakeUrl = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: true, + requestOptions: {} + }); it('adds client headers', async () => { const headers = await getHeaders(fakeUrl); expect(headers.get('x-goog-api-client')).to.match( @@ -140,13 +158,13 @@ describe('request methods', () => { getAuthToken: () => Promise.resolve({ accessToken: 'authtoken' }), getAppCheckToken: () => Promise.resolve({ token: 'appchecktoken' }) }; - const fakeUrl = new RequestUrl( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - true, - {} - ); + const fakeUrl = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: true, + requestOptions: {} + }); const headers = await getHeaders(fakeUrl); expect(headers.get('X-Firebase-Appid')).to.equal('my-appid'); }); @@ -165,13 +183,13 @@ describe('request methods', () => { getAuthToken: () => Promise.resolve({ accessToken: 'authtoken' }), getAppCheckToken: () => Promise.resolve({ token: 'appchecktoken' }) }; - const fakeUrl = new RequestUrl( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - true, - {} - ); + const fakeUrl = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: true, + requestOptions: {} + }); const headers = await getHeaders(fakeUrl); expect(headers.get('X-Firebase-Appid')).to.be.null; }); @@ -180,44 +198,44 @@ describe('request methods', () => { expect(headers.get('X-Firebase-AppCheck')).to.equal('appchecktoken'); }); it('ignores app check token header if no appcheck service', async () => { - const fakeUrl = new RequestUrl( - 'models/model-name', - Task.GENERATE_CONTENT, - { + const fakeUrl = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: { apiKey: 'key', project: 'myproject', appId: 'my-appid', location: 'moon', backend: new VertexAIBackend() }, - true, - {} - ); + stream: true, + requestOptions: {} + }); const headers = await getHeaders(fakeUrl); expect(headers.has('X-Firebase-AppCheck')).to.be.false; }); it('ignores app check token header if returned token was undefined', async () => { - const fakeUrl = new RequestUrl( - 'models/model-name', - Task.GENERATE_CONTENT, - { + const fakeUrl = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: { apiKey: 'key', project: 'myproject', location: 'moon', //@ts-ignore getAppCheckToken: () => Promise.resolve() }, - true, - {} - ); + stream: true, + requestOptions: {} + }); const headers = await getHeaders(fakeUrl); expect(headers.has('X-Firebase-AppCheck')).to.be.false; }); it('ignores app check token header if returned token had error', async () => { - const fakeUrl = new RequestUrl( - 'models/model-name', - Task.GENERATE_CONTENT, - { + const fakeUrl = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: { apiKey: 'key', project: 'myproject', appId: 'my-appid', @@ -226,9 +244,9 @@ describe('request methods', () => { getAppCheckToken: () => Promise.resolve({ token: 'dummytoken', error: Error('oops') }) }, - true, - {} - ); + stream: true, + requestOptions: {} + }); const warnStub = stub(console, 'warn'); const headers = await getHeaders(fakeUrl); expect(headers.get('X-Firebase-AppCheck')).to.equal('dummytoken'); @@ -242,36 +260,36 @@ describe('request methods', () => { expect(headers.get('Authorization')).to.equal('Firebase authtoken'); }); it('ignores auth token header if no auth service', async () => { - const fakeUrl = new RequestUrl( - 'models/model-name', - Task.GENERATE_CONTENT, - { + const fakeUrl = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: { apiKey: 'key', project: 'myproject', appId: 'my-appid', location: 'moon', backend: new VertexAIBackend() }, - true, - {} - ); + stream: true, + requestOptions: {} + }); const headers = await getHeaders(fakeUrl); expect(headers.has('Authorization')).to.be.false; }); it('ignores auth token header if returned token was undefined', async () => { - const fakeUrl = new RequestUrl( - 'models/model-name', - Task.GENERATE_CONTENT, - { + const fakeUrl = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: { apiKey: 'key', project: 'myproject', location: 'moon', //@ts-ignore getAppCheckToken: () => Promise.resolve() }, - true, - {} - ); + stream: true, + requestOptions: {} + }); const headers = await getHeaders(fakeUrl); expect(headers.has('Authorization')).to.be.false; }); @@ -282,10 +300,12 @@ describe('request methods', () => { ok: true } as Response); const response = await makeRequest( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false + }, '' ); expect(fetchStub).to.be.calledOnce; @@ -300,14 +320,16 @@ describe('request methods', () => { try { await makeRequest( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, - '', { - timeout: 180000 - } + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + requestOptions: { + timeout: 180000 + } + }, + '' ); } catch (e) { expect((e as AIError).code).to.equal(AIErrorCode.FETCH_ERROR); @@ -328,10 +350,12 @@ describe('request methods', () => { } as Response); try { await makeRequest( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false + }, '' ); } catch (e) { @@ -353,10 +377,12 @@ describe('request methods', () => { } as Response); try { await makeRequest( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false + }, '' ); } catch (e) { @@ -391,10 +417,12 @@ describe('request methods', () => { } as Response); try { await makeRequest( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false + }, '' ); } catch (e) { @@ -420,10 +448,12 @@ describe('request methods', () => { ); try { await makeRequest( - 'models/model-name', - Task.GENERATE_CONTENT, - fakeApiSettings, - false, + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false + }, '' ); } catch (e) { diff --git a/packages/ai/src/requests/request.ts b/packages/ai/src/requests/request.ts index 90195b4b78..7664765ab0 100644 --- a/packages/ai/src/requests/request.ts +++ b/packages/ai/src/requests/request.ts @@ -1,6 +1,6 @@ /** * @license - * Copyright 2024 Google LLC + * 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. @@ -19,62 +19,87 @@ import { ErrorDetails, RequestOptions, AIErrorCode } from '../types'; import { AIError } from '../errors'; import { ApiSettings } from '../types/internal'; import { - DEFAULT_API_VERSION, DEFAULT_DOMAIN, DEFAULT_FETCH_TIMEOUT_MS, LANGUAGE_TAG, PACKAGE_VERSION } from '../constants'; import { logger } from '../logger'; -import { GoogleAIBackend, VertexAIBackend } from '../backend'; import { BackendType } from '../public-types'; -export enum Task { +export const enum Task { GENERATE_CONTENT = 'generateContent', STREAM_GENERATE_CONTENT = 'streamGenerateContent', COUNT_TOKENS = 'countTokens', PREDICT = 'predict' } -export class RequestUrl { +export const enum ServerPromptTemplateTask { + TEMPLATE_GENERATE_CONTENT = 'templateGenerateContent', + TEMPLATE_STREAM_GENERATE_CONTENT = 'templateStreamGenerateContent', + TEMPLATE_PREDICT = 'templatePredict' +} + +interface BaseRequestURLParams { + apiSettings: ApiSettings; + stream: boolean; + requestOptions?: RequestOptions; +} + +/** + * Parameters used to construct the URL of a request to use a model. + */ +interface ModelRequestURLParams extends BaseRequestURLParams { + task: Task; + model: string; + templateId?: never; +} + +/** + * Parameters used to construct the URL of a request to use server side prompt templates. + */ +interface TemplateRequestURLParams extends BaseRequestURLParams { + task: ServerPromptTemplateTask; + templateId: string; + model?: never; +} + +export class RequestURL { constructor( - public model: string, - public task: Task, - public apiSettings: ApiSettings, - public stream: boolean, - public requestOptions?: RequestOptions + public readonly params: ModelRequestURLParams | TemplateRequestURLParams ) {} + toString(): string { const url = new URL(this.baseUrl); // Throws if the URL is invalid - url.pathname = `/${this.apiVersion}/${this.modelPath}:${this.task}`; + url.pathname = this.pathname; url.search = this.queryParams.toString(); return url.toString(); } - private get baseUrl(): string { - return this.requestOptions?.baseUrl || `https://${DEFAULT_DOMAIN}`; - } - - private get apiVersion(): string { - return DEFAULT_API_VERSION; // TODO: allow user-set options if that feature becomes available - } - - private get modelPath(): string { - if (this.apiSettings.backend instanceof GoogleAIBackend) { - return `projects/${this.apiSettings.project}/${this.model}`; - } else if (this.apiSettings.backend instanceof VertexAIBackend) { - return `projects/${this.apiSettings.project}/locations/${this.apiSettings.backend.location}/${this.model}`; + private get pathname(): string { + // We need to construct a different URL if the request is for server side prompt templates, + // since the URL patterns are different. Server side prompt templates expect a templateId + // instead of a model name. + if (this.params.templateId) { + return `${this.params.apiSettings.backend._getTemplatePath( + this.params.apiSettings.project, + this.params.templateId + )}:${this.params.task}`; } else { - throw new AIError( - AIErrorCode.ERROR, - `Invalid backend: ${JSON.stringify(this.apiSettings.backend)}` - ); + return `${this.params.apiSettings.backend._getModelPath( + this.params.apiSettings.project, + (this.params as ModelRequestURLParams).model + )}:${this.params.task}`; } } + private get baseUrl(): string { + return this.params.requestOptions?.baseUrl ?? `https://${DEFAULT_DOMAIN}`; + } + private get queryParams(): URLSearchParams { const params = new URLSearchParams(); - if (this.stream) { + if (this.params.stream) { params.set('alt', 'sse'); } @@ -114,16 +139,16 @@ function getClientHeaders(): string { return loggingTags.join(' '); } -export async function getHeaders(url: RequestUrl): Promise { +export async function getHeaders(url: RequestURL): Promise { const headers = new Headers(); headers.append('Content-Type', 'application/json'); headers.append('x-goog-api-client', getClientHeaders()); - headers.append('x-goog-api-key', url.apiSettings.apiKey); - if (url.apiSettings.automaticDataCollectionEnabled) { - headers.append('X-Firebase-Appid', url.apiSettings.appId); + headers.append('x-goog-api-key', url.params.apiSettings.apiKey); + if (url.params.apiSettings.automaticDataCollectionEnabled) { + headers.append('X-Firebase-Appid', url.params.apiSettings.appId); } - if (url.apiSettings.getAppCheckToken) { - const appCheckToken = await url.apiSettings.getAppCheckToken(); + if (url.params.apiSettings.getAppCheckToken) { + const appCheckToken = await url.params.apiSettings.getAppCheckToken(); if (appCheckToken) { headers.append('X-Firebase-AppCheck', appCheckToken.token); if (appCheckToken.error) { @@ -134,8 +159,8 @@ export async function getHeaders(url: RequestUrl): Promise { } } - if (url.apiSettings.getAuthToken) { - const authToken = await url.apiSettings.getAuthToken(); + if (url.params.apiSettings.getAuthToken) { + const authToken = await url.params.apiSettings.getAuthToken(); if (authToken) { headers.append('Authorization', `Firebase ${authToken.accessToken}`); } @@ -144,55 +169,31 @@ export async function getHeaders(url: RequestUrl): Promise { return headers; } -export async function constructRequest( - model: string, - task: Task, - apiSettings: ApiSettings, - stream: boolean, - body: string, - requestOptions?: RequestOptions -): Promise<{ url: string; fetchOptions: RequestInit }> { - const url = new RequestUrl(model, task, apiSettings, stream, requestOptions); - return { - url: url.toString(), - fetchOptions: { - method: 'POST', - headers: await getHeaders(url), - body - } - }; -} - export async function makeRequest( - model: string, - task: Task, - apiSettings: ApiSettings, - stream: boolean, - body: string, - requestOptions?: RequestOptions + requestUrlParams: TemplateRequestURLParams | ModelRequestURLParams, + body: string ): Promise { - const url = new RequestUrl(model, task, apiSettings, stream, requestOptions); + const url = new RequestURL(requestUrlParams); let response; let fetchTimeoutId: string | number | NodeJS.Timeout | undefined; try { - const request = await constructRequest( - model, - task, - apiSettings, - stream, - body, - requestOptions - ); - // Timeout is 180s by default + const fetchOptions: RequestInit = { + method: 'POST', + headers: await getHeaders(url), + body + }; + + // Timeout is 180s by default. const timeoutMillis = - requestOptions?.timeout != null && requestOptions.timeout >= 0 - ? requestOptions.timeout + requestUrlParams.requestOptions?.timeout != null && + requestUrlParams.requestOptions.timeout >= 0 + ? requestUrlParams.requestOptions.timeout : DEFAULT_FETCH_TIMEOUT_MS; const abortController = new AbortController(); fetchTimeoutId = setTimeout(() => abortController.abort(), timeoutMillis); - request.fetchOptions.signal = abortController.signal; + fetchOptions.signal = abortController.signal; - response = await fetch(request.url, request.fetchOptions); + response = await fetch(url.toString(), fetchOptions); if (!response.ok) { let message = ''; let errorDetails; @@ -225,7 +226,7 @@ export async function makeRequest( `The Firebase AI SDK requires the Firebase AI ` + `API ('firebasevertexai.googleapis.com') to be enabled in your ` + `Firebase project. Enable this API by visiting the Firebase Console ` + - `at https://console.firebase.google.com/project/${url.apiSettings.project}/genai/ ` + + `at https://console.firebase.google.com/project/${url.params.apiSettings.project}/genai/ ` + `and clicking "Get started". If you enabled this API recently, ` + `wait a few minutes for the action to propagate to our systems and ` + `then retry.`, From 5c35f514c26f81e68cb100a01b83190f5aef9382 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 12 Nov 2025 10:07:13 -0800 Subject: [PATCH 014/174] Revert "feat(rc): Web support for ABT & Rollouts (#9293)" (#9374) This reverts commit 6abe52967f3d1ca4a02d4469a14c6d692e1f3b31. --- .changeset/wild-snakes-bathe.md | 6 - common/api-review/remote-config.api.md | 17 --- docs-devsite/_toc.yaml | 2 - docs-devsite/remote-config.fetchresponse.md | 13 -- ...te-config.firebaseexperimentdescription.md | 78 ------------ docs-devsite/remote-config.md | 1 - packages/remote-config/src/abt/experiment.ts | 102 --------------- packages/remote-config/src/api.ts | 10 +- .../remote-config/src/client/rest_client.ts | 8 +- packages/remote-config/src/errors.ts | 8 +- packages/remote-config/src/public_types.ts | 35 +----- packages/remote-config/src/register.ts | 4 +- packages/remote-config/src/remote_config.ts | 8 +- packages/remote-config/src/storage/storage.ts | 9 -- .../remote-config/test/abt/experiment.test.ts | 117 ------------------ packages/remote-config/test/api.test.ts | 14 +-- .../test/client/rest_client.test.ts | 26 +--- .../remote-config/test/remote_config.test.ts | 41 +----- 18 files changed, 20 insertions(+), 479 deletions(-) delete mode 100644 .changeset/wild-snakes-bathe.md delete mode 100644 docs-devsite/remote-config.firebaseexperimentdescription.md delete mode 100644 packages/remote-config/src/abt/experiment.ts delete mode 100644 packages/remote-config/test/abt/experiment.test.ts diff --git a/.changeset/wild-snakes-bathe.md b/.changeset/wild-snakes-bathe.md deleted file mode 100644 index ffc35b4d3d..0000000000 --- a/.changeset/wild-snakes-bathe.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/remote-config': minor -'firebase': minor ---- - -Web support for ABT and Rollouts diff --git a/common/api-review/remote-config.api.md b/common/api-review/remote-config.api.md index 29939b3ac5..a9f5131e0b 100644 --- a/common/api-review/remote-config.api.md +++ b/common/api-review/remote-config.api.md @@ -41,7 +41,6 @@ export function fetchConfig(remoteConfig: RemoteConfig): Promise; export interface FetchResponse { config?: FirebaseRemoteConfigObject; eTag?: string; - experiments?: FirebaseExperimentDescription[]; status: number; templateVersion?: number; } @@ -52,22 +51,6 @@ export type FetchStatus = 'no-fetch-yet' | 'success' | 'failure' | 'throttle'; // @public export type FetchType = 'BASE' | 'REALTIME'; -// @public -export interface FirebaseExperimentDescription { - // (undocumented) - affectedParameterKeys?: string[]; - // (undocumented) - experimentId: string; - // (undocumented) - experimentStartTime: string; - // (undocumented) - timeToLiveMillis: string; - // (undocumented) - triggerTimeoutMillis: string; - // (undocumented) - variantId: string; -} - // @public export interface FirebaseRemoteConfigObject { // (undocumented) diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index f2689935a2..92633c553a 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -665,8 +665,6 @@ toc: path: /docs/reference/js/remote-config.customsignals.md - title: FetchResponse path: /docs/reference/js/remote-config.fetchresponse.md - - title: FirebaseExperimentDescription - path: /docs/reference/js/remote-config.firebaseexperimentdescription.md - title: FirebaseRemoteConfigObject path: /docs/reference/js/remote-config.firebaseremoteconfigobject.md - title: RemoteConfig diff --git a/docs-devsite/remote-config.fetchresponse.md b/docs-devsite/remote-config.fetchresponse.md index 9c55c50e68..1955dd4749 100644 --- a/docs-devsite/remote-config.fetchresponse.md +++ b/docs-devsite/remote-config.fetchresponse.md @@ -26,7 +26,6 @@ export interface FetchResponse | --- | --- | --- | | [config](./remote-config.fetchresponse.md#fetchresponseconfig) | [FirebaseRemoteConfigObject](./remote-config.firebaseremoteconfigobject.md#firebaseremoteconfigobject_interface) | Defines the map of parameters returned as "entries" in the fetch response body.

Only defined for 200 responses. | | [eTag](./remote-config.fetchresponse.md#fetchresponseetag) | string | Defines the ETag response header value.

Only defined for 200 and 304 responses. | -| [experiments](./remote-config.fetchresponse.md#fetchresponseexperiments) | [FirebaseExperimentDescription](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescription_interface)\[\] | Metadata for A/B testing and Remote Config Rollout experiments. | | [status](./remote-config.fetchresponse.md#fetchresponsestatus) | number | The HTTP status, which is useful for differentiating success responses with data from those without.

The Remote Config client is modeled after the native Fetch interface, so HTTP status is first-class.

Disambiguation: the fetch response returns a legacy "state" value that is redundant with the HTTP status code. The former is normalized into the latter. | | [templateVersion](./remote-config.fetchresponse.md#fetchresponsetemplateversion) | number | The version number of the config template fetched from the server. | @@ -54,18 +53,6 @@ Defines the ETag response header value. eTag?: string; ``` -## FetchResponse.experiments - -Metadata for A/B testing and Remote Config Rollout experiments. - -Only defined for 200 responses. - -Signature: - -```typescript -experiments?: FirebaseExperimentDescription[]; -``` - ## FetchResponse.status The HTTP status, which is useful for differentiating success responses with data from those without. diff --git a/docs-devsite/remote-config.firebaseexperimentdescription.md b/docs-devsite/remote-config.firebaseexperimentdescription.md deleted file mode 100644 index 24c70690a2..0000000000 --- a/docs-devsite/remote-config.firebaseexperimentdescription.md +++ /dev/null @@ -1,78 +0,0 @@ -Project: /docs/reference/js/_project.yaml -Book: /docs/reference/_book.yaml -page_type: reference - -{% comment %} -DO NOT EDIT THIS FILE! -This is generated by the JS SDK team, and any local changes will be -overwritten. Changes should be made in the source code at -https://github.com/firebase/firebase-js-sdk -{% endcomment %} - -# FirebaseExperimentDescription interface -Defines experiment and variant attached to a config parameter. - -Signature: - -```typescript -export interface FirebaseExperimentDescription -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [affectedParameterKeys](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptionaffectedparameterkeys) | string\[\] | | -| [experimentId](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptionexperimentid) | string | | -| [experimentStartTime](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptionexperimentstarttime) | string | | -| [timeToLiveMillis](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptiontimetolivemillis) | string | | -| [triggerTimeoutMillis](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptiontriggertimeoutmillis) | string | | -| [variantId](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptionvariantid) | string | | - -## FirebaseExperimentDescription.affectedParameterKeys - -Signature: - -```typescript -affectedParameterKeys?: string[]; -``` - -## FirebaseExperimentDescription.experimentId - -Signature: - -```typescript -experimentId: string; -``` - -## FirebaseExperimentDescription.experimentStartTime - -Signature: - -```typescript -experimentStartTime: string; -``` - -## FirebaseExperimentDescription.timeToLiveMillis - -Signature: - -```typescript -timeToLiveMillis: string; -``` - -## FirebaseExperimentDescription.triggerTimeoutMillis - -Signature: - -```typescript -triggerTimeoutMillis: string; -``` - -## FirebaseExperimentDescription.variantId - -Signature: - -```typescript -variantId: string; -``` diff --git a/docs-devsite/remote-config.md b/docs-devsite/remote-config.md index c3b5e4b5bf..c9f803abf1 100644 --- a/docs-devsite/remote-config.md +++ b/docs-devsite/remote-config.md @@ -42,7 +42,6 @@ The Firebase Remote Config Web SDK. This SDK does not work in a Node.js environm | [ConfigUpdateObserver](./remote-config.configupdateobserver.md#configupdateobserver_interface) | Observer interface for receiving real-time Remote Config update notifications.NOTE: Although an complete callback can be provided, it will never be called because the ConfigUpdate stream is never-ending. | | [CustomSignals](./remote-config.customsignals.md#customsignals_interface) | Defines the type for representing custom signals and their values.

The values in CustomSignals must be one of the following types:

  • string
  • number
  • null
| | [FetchResponse](./remote-config.fetchresponse.md#fetchresponse_interface) | Defines a successful response (200 or 304).

Modeled after the native Response interface, but simplified for Remote Config's use case. | -| [FirebaseExperimentDescription](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescription_interface) | Defines experiment and variant attached to a config parameter. | | [FirebaseRemoteConfigObject](./remote-config.firebaseremoteconfigobject.md#firebaseremoteconfigobject_interface) | Defines a self-descriptive reference for config key-value pairs. | | [RemoteConfig](./remote-config.remoteconfig.md#remoteconfig_interface) | The Firebase Remote Config service interface. | | [RemoteConfigOptions](./remote-config.remoteconfigoptions.md#remoteconfigoptions_interface) | Options for Remote Config initialization. | diff --git a/packages/remote-config/src/abt/experiment.ts b/packages/remote-config/src/abt/experiment.ts deleted file mode 100644 index d92d762f93..0000000000 --- a/packages/remote-config/src/abt/experiment.ts +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @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. - */ -import { Storage } from '../storage/storage'; -import { FirebaseExperimentDescription } from '../public_types'; -import { Provider } from '@firebase/component'; -import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types'; -import { Logger } from '@firebase/logger'; -import { RemoteConfig } from '../remote_config'; -import { ERROR_FACTORY, ErrorCode } from '../errors'; - -export class Experiment { - private storage: Storage; - private logger: Logger; - private analyticsProvider: Provider; - - constructor(rc: RemoteConfig) { - this.storage = rc._storage; - this.logger = rc._logger; - this.analyticsProvider = rc._analyticsProvider; - } - - async updateActiveExperiments( - latestExperiments: FirebaseExperimentDescription[] - ): Promise { - const currentActiveExperiments = - (await this.storage.getActiveExperiments()) || new Set(); - const experimentInfoMap = this.createExperimentInfoMap(latestExperiments); - this.addActiveExperiments(experimentInfoMap); - this.removeInactiveExperiments(currentActiveExperiments, experimentInfoMap); - return this.storage.setActiveExperiments(new Set(experimentInfoMap.keys())); - } - - private createExperimentInfoMap( - latestExperiments: FirebaseExperimentDescription[] - ): Map { - const experimentInfoMap = new Map(); - for (const experiment of latestExperiments) { - experimentInfoMap.set(experiment.experimentId, experiment); - } - return experimentInfoMap; - } - - private addActiveExperiments( - experimentInfoMap: Map - ): void { - const customProperty: Record = {}; - for (const [experimentId, experimentInfo] of experimentInfoMap.entries()) { - customProperty[`firebase${experimentId}`] = experimentInfo.variantId; - } - this.addExperimentToAnalytics(customProperty); - } - - private removeInactiveExperiments( - currentActiveExperiments: Set, - experimentInfoMap: Map - ): void { - const customProperty: Record = {}; - for (const experimentId of currentActiveExperiments) { - if (!experimentInfoMap.has(experimentId)) { - customProperty[`firebase${experimentId}`] = null; - } - } - this.addExperimentToAnalytics(customProperty); - } - - private addExperimentToAnalytics( - customProperty: Record - ): void { - if (Object.keys(customProperty).length === 0) { - return; - } - try { - const analytics = this.analyticsProvider.getImmediate({ optional: true }); - if (analytics) { - analytics.setUserProperties(customProperty); - analytics.logEvent(`set_firebase_experiment_state`); - } else { - this.logger.warn( - `Analytics import failed. Verify if you have imported Firebase Analytics in your app code.` - ); - } - } catch (error) { - throw ERROR_FACTORY.create(ErrorCode.ANALYTICS_UNAVAILABLE, { - originalErrorMessage: (error as Error)?.message - }); - } - } -} diff --git a/packages/remote-config/src/api.ts b/packages/remote-config/src/api.ts index 5533bf9129..62dc2697a6 100644 --- a/packages/remote-config/src/api.ts +++ b/packages/remote-config/src/api.ts @@ -36,7 +36,6 @@ import { ERROR_FACTORY, ErrorCode, hasErrorCode } from './errors'; import { RemoteConfig as RemoteConfigImpl } from './remote_config'; import { Value as ValueImpl } from './value'; import { LogLevel as FirebaseLogLevel } from '@firebase/logger'; -import { Experiment } from './abt/experiment'; /** * @@ -111,19 +110,12 @@ export async function activate(remoteConfig: RemoteConfig): Promise { // config. return false; } - const experiment = new Experiment(rc); - const updateActiveExperiments = lastSuccessfulFetchResponse.experiments - ? experiment.updateActiveExperiments( - lastSuccessfulFetchResponse.experiments - ) - : Promise.resolve(); await Promise.all([ rc._storageCache.setActiveConfig(lastSuccessfulFetchResponse.config), rc._storage.setActiveConfigEtag(lastSuccessfulFetchResponse.eTag), rc._storage.setActiveConfigTemplateVersion( lastSuccessfulFetchResponse.templateVersion - ), - updateActiveExperiments + ) ]); return true; } diff --git a/packages/remote-config/src/client/rest_client.ts b/packages/remote-config/src/client/rest_client.ts index d5b0be92c3..42b0cab27c 100644 --- a/packages/remote-config/src/client/rest_client.ts +++ b/packages/remote-config/src/client/rest_client.ts @@ -18,8 +18,7 @@ import { CustomSignals, FetchResponse, - FirebaseRemoteConfigObject, - FirebaseExperimentDescription + FirebaseRemoteConfigObject } from '../public_types'; import { RemoteConfigFetchClient, @@ -144,7 +143,6 @@ export class RestClient implements RemoteConfigFetchClient { let config: FirebaseRemoteConfigObject | undefined; let state: string | undefined; let templateVersion: number | undefined; - let experiments: FirebaseExperimentDescription[] | undefined; // JSON parsing throws SyntaxError if the response body isn't a JSON string. // Requesting application/json and checking for a 200 ensures there's JSON data. @@ -160,7 +158,6 @@ export class RestClient implements RemoteConfigFetchClient { config = responseBody['entries']; state = responseBody['state']; templateVersion = responseBody['templateVersion']; - experiments = responseBody['experimentDescriptions']; } // Normalizes based on legacy state. @@ -171,7 +168,6 @@ export class RestClient implements RemoteConfigFetchClient { } else if (state === 'NO_TEMPLATE' || state === 'EMPTY_CONFIG') { // These cases can be fixed remotely, so normalize to safe value. config = {}; - experiments = []; } // Normalize to exception-based control flow for non-success cases. @@ -184,6 +180,6 @@ export class RestClient implements RemoteConfigFetchClient { }); } - return { status, eTag: responseEtag, config, templateVersion, experiments }; + return { status, eTag: responseEtag, config, templateVersion }; } } diff --git a/packages/remote-config/src/errors.ts b/packages/remote-config/src/errors.ts index 06e226a0ab..dea9f43e92 100644 --- a/packages/remote-config/src/errors.ts +++ b/packages/remote-config/src/errors.ts @@ -37,8 +37,7 @@ export const enum ErrorCode { CONFIG_UPDATE_STREAM_ERROR = 'stream-error', CONFIG_UPDATE_UNAVAILABLE = 'realtime-unavailable', CONFIG_UPDATE_MESSAGE_INVALID = 'update-message-invalid', - CONFIG_UPDATE_NOT_FETCHED = 'update-not-fetched', - ANALYTICS_UNAVAILABLE = 'analytics-unavailable' + CONFIG_UPDATE_NOT_FETCHED = 'update-not-fetched' } const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = { @@ -85,9 +84,7 @@ const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = { [ErrorCode.CONFIG_UPDATE_MESSAGE_INVALID]: 'The stream invalidation message was unparsable: {$originalErrorMessage}', [ErrorCode.CONFIG_UPDATE_NOT_FETCHED]: - 'Unable to fetch the latest config: {$originalErrorMessage}', - [ErrorCode.ANALYTICS_UNAVAILABLE]: - 'Connection to Firebase Analytics failed: {$originalErrorMessage}' + 'Unable to fetch the latest config: {$originalErrorMessage}' }; // Note this is effectively a type system binding a code to params. This approach overlaps with the @@ -111,7 +108,6 @@ interface ErrorParams { [ErrorCode.CONFIG_UPDATE_UNAVAILABLE]: { originalErrorMessage: string }; [ErrorCode.CONFIG_UPDATE_MESSAGE_INVALID]: { originalErrorMessage: string }; [ErrorCode.CONFIG_UPDATE_NOT_FETCHED]: { originalErrorMessage: string }; - [ErrorCode.ANALYTICS_UNAVAILABLE]: { originalErrorMessage: string }; } export const ERROR_FACTORY = new ErrorFactory( diff --git a/packages/remote-config/src/public_types.ts b/packages/remote-config/src/public_types.ts index fc23974ee3..964726a51f 100644 --- a/packages/remote-config/src/public_types.ts +++ b/packages/remote-config/src/public_types.ts @@ -59,33 +59,6 @@ export interface FirebaseRemoteConfigObject { [key: string]: string; } -/** - * Defines experiment and variant attached to a config parameter. - * - * @public - */ -export interface FirebaseExperimentDescription { - // A string of max length 22 characters and of format: _exp_ - experimentId: string; - - // The variant of the experiment assigned to the app instance. - variantId: string; - - // When the experiment was started. - experimentStartTime: string; - - // How long the experiment can remain in STANDBY state. Valid range from 1 ms - // to 6 months. - triggerTimeoutMillis: string; - - // How long the experiment can remain in ON state. Valid range from 1 ms to 6 - // months. - timeToLiveMillis: string; - - // Which all parameters are affected by this experiment. - affectedParameterKeys?: string[]; -} - /** * Defines a successful response (200 or 304). * @@ -126,12 +99,8 @@ export interface FetchResponse { */ templateVersion?: number; - /** - * Metadata for A/B testing and Remote Config Rollout experiments. - * - * @remarks Only defined for 200 responses. - */ - experiments?: FirebaseExperimentDescription[]; + // Note: we're not extracting experiment metadata until + // ABT and Analytics have Web SDKs. } /** diff --git a/packages/remote-config/src/register.ts b/packages/remote-config/src/register.ts index 0a34024622..eade371ca8 100644 --- a/packages/remote-config/src/register.ts +++ b/packages/remote-config/src/register.ts @@ -66,7 +66,6 @@ export function registerRemoteConfig(): void { const installations = container .getProvider('installations-internal') .getImmediate(); - const analyticsProvider = container.getProvider('analytics-internal'); // Normalizes optional inputs. const { projectId, apiKey, appId } = app.options; @@ -128,8 +127,7 @@ export function registerRemoteConfig(): void { storageCache, storage, logger, - realtimeHandler, - analyticsProvider + realtimeHandler ); // Starts warming cache. diff --git a/packages/remote-config/src/remote_config.ts b/packages/remote-config/src/remote_config.ts index aa9502262f..bd32c93830 100644 --- a/packages/remote-config/src/remote_config.ts +++ b/packages/remote-config/src/remote_config.ts @@ -25,8 +25,6 @@ import { StorageCache } from './storage/storage_cache'; import { RemoteConfigFetchClient } from './client/remote_config_fetch_client'; import { Storage } from './storage/storage'; import { Logger } from '@firebase/logger'; -import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types'; -import { Provider } from '@firebase/component'; import { RealtimeHandler } from './client/realtime_handler'; const DEFAULT_FETCH_TIMEOUT_MILLIS = 60 * 1000; // One minute @@ -90,10 +88,6 @@ export class RemoteConfig implements RemoteConfigType { /** * @internal */ - readonly _realtimeHandler: RealtimeHandler, - /** - * @internal - */ - readonly _analyticsProvider: Provider + readonly _realtimeHandler: RealtimeHandler ) {} } diff --git a/packages/remote-config/src/storage/storage.ts b/packages/remote-config/src/storage/storage.ts index 9764b95991..bd262d2996 100644 --- a/packages/remote-config/src/storage/storage.ts +++ b/packages/remote-config/src/storage/storage.ts @@ -71,7 +71,6 @@ export interface RealtimeBackoffMetadata { type ProjectNamespaceKeyFieldValue = | 'active_config' | 'active_config_etag' - | 'active_experiments' | 'last_fetch_status' | 'last_successful_fetch_timestamp_millis' | 'last_successful_fetch_response' @@ -166,14 +165,6 @@ export abstract class Storage { return this.set('active_config_etag', etag); } - getActiveExperiments(): Promise | undefined> { - return this.get>('active_experiments'); - } - - setActiveExperiments(experiments: Set): Promise { - return this.set>('active_experiments', experiments); - } - getThrottleMetadata(): Promise { return this.get('throttle_metadata'); } diff --git a/packages/remote-config/test/abt/experiment.test.ts b/packages/remote-config/test/abt/experiment.test.ts deleted file mode 100644 index 43365d31f0..0000000000 --- a/packages/remote-config/test/abt/experiment.test.ts +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @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. - */ -import '../setup'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; -import { Experiment } from '../../src/abt/experiment'; -import { FirebaseExperimentDescription } from '../../src/public_types'; -import { Storage } from '../../src/storage/storage'; -import { Provider } from '@firebase/component'; -import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types'; -import { Logger } from '@firebase/logger'; -import { RemoteConfig } from '../../src/remote_config'; - -describe('Experiment', () => { - const storage = {} as Storage; - const analyticsProvider = {} as Provider; - const logger = {} as Logger; - const rc = { - _storage: storage, - _analyticsProvider: analyticsProvider, - _logger: logger - } as RemoteConfig; - const experiment = new Experiment(rc); - - describe('updateActiveExperiments', () => { - beforeEach(() => { - storage.getActiveExperiments = sinon.stub(); - storage.setActiveExperiments = sinon.stub(); - analyticsProvider.getImmediate = sinon.stub().returns({ - setUserProperties: sinon.stub(), - logEvent: sinon.stub() - }); - }); - - it('adds new experiments to storage', async () => { - const latestExperiments: FirebaseExperimentDescription[] = [ - { - experimentId: '_exp_3', - variantId: '1', - experimentStartTime: '0', - triggerTimeoutMillis: '0', - timeToLiveMillis: '0' - }, - { - experimentId: '_exp_1', - variantId: '2', - experimentStartTime: '0', - triggerTimeoutMillis: '0', - timeToLiveMillis: '0' - }, - { - experimentId: '_exp_2', - variantId: '1', - experimentStartTime: '0', - triggerTimeoutMillis: '0', - timeToLiveMillis: '0' - } - ]; - const expectedStoredExperiments = new Set(['_exp_3', '_exp_1', '_exp_2']); - storage.getActiveExperiments = sinon - .stub() - .returns(new Set(['_exp_1', '_exp_2'])); - const analytics = analyticsProvider.getImmediate(); - - await experiment.updateActiveExperiments(latestExperiments); - - expect(storage.setActiveExperiments).to.have.been.calledWith( - expectedStoredExperiments - ); - expect(analytics.setUserProperties).to.have.been.calledWith({ - 'firebase_exp_3': '1', - 'firebase_exp_1': '2', - 'firebase_exp_2': '1' - }); - }); - - it('removes missing experiment in fetch response from storage', async () => { - const latestExperiments: FirebaseExperimentDescription[] = [ - { - experimentId: '_exp_1', - variantId: '2', - experimentStartTime: '0', - triggerTimeoutMillis: '0', - timeToLiveMillis: '0' - } - ]; - const expectedStoredExperiments = new Set(['_exp_1']); - storage.getActiveExperiments = sinon - .stub() - .returns(new Set(['_exp_1', '_exp_2'])); - const analytics = analyticsProvider.getImmediate(); - - await experiment.updateActiveExperiments(latestExperiments); - - expect(storage.setActiveExperiments).to.have.been.calledWith( - expectedStoredExperiments - ); - expect(analytics.setUserProperties).to.have.been.calledWith({ - 'firebase_exp_2': null - }); - }); - }); -}); diff --git a/packages/remote-config/test/api.test.ts b/packages/remote-config/test/api.test.ts index 54679199a8..f38b4ca0be 100644 --- a/packages/remote-config/test/api.test.ts +++ b/packages/remote-config/test/api.test.ts @@ -68,16 +68,7 @@ describe('Remote Config API', () => { status: 200, eTag: 'asdf', config: { 'foobar': 'hello world' }, - templateVersion: 1, - experiments: [ - { - experimentId: '_exp_1', - variantId: '1', - experimentStartTime: '2025-04-06T14:13:57.597Z', - triggerTimeoutMillis: '15552000000', - timeToLiveMillis: '15552000000' - } - ] + templateVersion: 1 }; let fetchStub: sinon.SinonStub; @@ -115,8 +106,7 @@ describe('Remote Config API', () => { Promise.resolve({ entries: response.config, state: 'OK', - templateVersion: response.templateVersion, - experimentDescriptions: response.experiments + templateVersion: response.templateVersion }) } as Response) ); diff --git a/packages/remote-config/test/client/rest_client.test.ts b/packages/remote-config/test/client/rest_client.test.ts index d2284c4f8c..bda6fbce01 100644 --- a/packages/remote-config/test/client/rest_client.test.ts +++ b/packages/remote-config/test/client/rest_client.test.ts @@ -78,16 +78,7 @@ describe('RestClient', () => { eTag: 'etag', state: 'UPDATE', entries: { color: 'sparkling' }, - templateVersion: 1, - experimentDescriptions: [ - { - experimentId: '_exp_1', - variantId: '1', - experimentStartTime: '2025-04-06T14:13:57.597Z', - triggerTimeoutMillis: '15552000000', - timeToLiveMillis: '15552000000' - } - ] + templateVersion: 1 }; fetchStub.returns( @@ -99,8 +90,7 @@ describe('RestClient', () => { Promise.resolve({ entries: expectedResponse.entries, state: expectedResponse.state, - templateVersion: expectedResponse.templateVersion, - experimentDescriptions: expectedResponse.experimentDescriptions + templateVersion: expectedResponse.templateVersion }) } as Response) ); @@ -111,8 +101,7 @@ describe('RestClient', () => { status: expectedResponse.status, eTag: expectedResponse.eTag, config: expectedResponse.entries, - templateVersion: expectedResponse.templateVersion, - experiments: expectedResponse.experimentDescriptions + templateVersion: expectedResponse.templateVersion }); }); @@ -202,8 +191,7 @@ describe('RestClient', () => { status: 304, eTag: 'response-etag', config: undefined, - templateVersion: undefined, - experiments: undefined + templateVersion: undefined }); }); @@ -242,8 +230,7 @@ describe('RestClient', () => { status: 304, eTag: 'etag', config: undefined, - templateVersion: undefined, - experiments: undefined + templateVersion: undefined }); }); @@ -261,8 +248,7 @@ describe('RestClient', () => { status: 200, eTag: 'etag', config: {}, - templateVersion: undefined, - experiments: [] + templateVersion: undefined }); } }); diff --git a/packages/remote-config/test/remote_config.test.ts b/packages/remote-config/test/remote_config.test.ts index de70e13dfc..1cc6b62717 100644 --- a/packages/remote-config/test/remote_config.test.ts +++ b/packages/remote-config/test/remote_config.test.ts @@ -46,9 +46,6 @@ import { import * as api from '../src/api'; import { fetchAndActivate } from '../src'; import { restore } from 'sinon'; -import { Experiment } from '../src/abt/experiment'; -import { Provider } from '@firebase/component'; -import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types'; import { RealtimeHandler } from '../src/client/realtime_handler'; describe('RemoteConfig', () => { @@ -73,7 +70,6 @@ describe('RemoteConfig', () => { let logger: Logger; let realtimeHandler: RealtimeHandler; let rc: RemoteConfigType; - let analyticsProvider: Provider; let getActiveConfigStub: sinon.SinonStub; let loggerDebugSpy: sinon.SinonSpy; @@ -85,7 +81,6 @@ describe('RemoteConfig', () => { client = {} as RemoteConfigFetchClient; storageCache = {} as StorageCache; storage = {} as Storage; - analyticsProvider = {} as Provider; realtimeHandler = {} as RealtimeHandler; logger = new Logger('package-name'); getActiveConfigStub = sinon.stub().returns(undefined); @@ -98,8 +93,7 @@ describe('RemoteConfig', () => { storageCache, storage, logger, - realtimeHandler, - analyticsProvider + realtimeHandler ); }); @@ -397,18 +391,7 @@ describe('RemoteConfig', () => { const CONFIG = { key: 'val' }; const NEW_ETAG = 'new_etag'; const TEMPLATE_VERSION = 1; - const EXPERIMENTS = [ - { - 'experimentId': '_exp_1', - 'variantId': '1', - 'experimentStartTime': '2025-04-06T14:13:57.597Z', - 'triggerTimeoutMillis': '15552000000', - 'timeToLiveMillis': '15552000000' - } - ]; - let sandbox: sinon.SinonSandbox; - let updateActiveExperimentsStub: sinon.SinonStub; let getLastSuccessfulFetchResponseStub: sinon.SinonStub; let getActiveConfigEtagStub: sinon.SinonStub; let getActiveConfigTemplateVersionStub: sinon.SinonStub; @@ -417,11 +400,6 @@ describe('RemoteConfig', () => { let setActiveConfigTemplateVersionStub: sinon.SinonStub; beforeEach(() => { - sandbox = sinon.createSandbox(); - updateActiveExperimentsStub = sandbox.stub( - Experiment.prototype, - 'updateActiveExperiments' - ); getLastSuccessfulFetchResponseStub = sinon.stub(); getActiveConfigEtagStub = sinon.stub(); getActiveConfigTemplateVersionStub = sinon.stub(); @@ -440,14 +418,6 @@ describe('RemoteConfig', () => { setActiveConfigTemplateVersionStub; }); - afterEach(() => { - sandbox.restore(); - }); - - afterEach(() => { - sandbox.restore(); - }); - it('does not activate if last successful fetch response is undefined', async () => { getLastSuccessfulFetchResponseStub.returns(Promise.resolve()); getActiveConfigEtagStub.returns(Promise.resolve(ETAG)); @@ -461,7 +431,6 @@ describe('RemoteConfig', () => { expect(storage.setActiveConfigEtag).to.not.have.been.called; expect(storageCache.setActiveConfig).to.not.have.been.called; expect(storage.setActiveConfigTemplateVersion).to.not.have.been.called; - expect(updateActiveExperimentsStub).to.not.have.been.called; }); it('does not activate if fetched and active etags are the same', async () => { @@ -480,7 +449,6 @@ describe('RemoteConfig', () => { expect(storage.setActiveConfigEtag).to.not.have.been.called; expect(storageCache.setActiveConfig).to.not.have.been.called; expect(storage.setActiveConfigTemplateVersion).to.not.have.been.called; - expect(updateActiveExperimentsStub).to.not.have.been.called; }); it('activates if fetched and active etags are different', async () => { @@ -488,8 +456,7 @@ describe('RemoteConfig', () => { Promise.resolve({ config: CONFIG, eTag: NEW_ETAG, - templateVersion: TEMPLATE_VERSION, - experiments: EXPERIMENTS + templateVersion: TEMPLATE_VERSION }) ); getActiveConfigEtagStub.returns(Promise.resolve(ETAG)); @@ -509,8 +476,7 @@ describe('RemoteConfig', () => { Promise.resolve({ config: CONFIG, eTag: NEW_ETAG, - templateVersion: TEMPLATE_VERSION, - experiments: EXPERIMENTS + templateVersion: TEMPLATE_VERSION }) ); getActiveConfigEtagStub.returns(Promise.resolve()); @@ -523,7 +489,6 @@ describe('RemoteConfig', () => { expect(storage.setActiveConfigTemplateVersion).to.have.been.calledWith( TEMPLATE_VERSION ); - expect(updateActiveExperimentsStub).to.have.been.calledWith(EXPERIMENTS); }); }); From 180b1ad9b66594526e2303c2029210eccc345198 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 12 Nov 2025 18:17:22 -0800 Subject: [PATCH 015/174] Fix functions deploy by upgrading to node 20 (#9377) --- .github/workflows/e2e-test.yml | 2 +- config/firebase.json | 2 +- config/functions/index.js | 2 +- config/functions/package.json | 2 +- scripts/ci-test/deploy-if-needed.ts | 4 +++- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index f9ac06ab9c..89ea939dce 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -68,7 +68,7 @@ jobs: pushd functions npm install popd - npx firebase-tools@13.0.2 deploy --only functions:callTest --project jscore-sandbox-141b5 --token $FIREBASE_CLI_TOKEN + npx firebase-tools@14.24.2 deploy --only functions:callTest --project jscore-sandbox-141b5 --token $FIREBASE_CLI_TOKEN working-directory: ./config env: FIREBASE_CLI_TOKEN: ${{ secrets.FIREBASE_CLI_TOKEN }} diff --git a/config/firebase.json b/config/firebase.json index ccf3b6fe78..9b1cdcd2e8 100644 --- a/config/firebase.json +++ b/config/firebase.json @@ -7,6 +7,6 @@ "indexes": "firestore.indexes.json" }, "functions": { - "runtime": "nodejs18" + "runtime": "nodejs20" } } diff --git a/config/functions/index.js b/config/functions/index.js index d4cd08998f..d992251caf 100644 --- a/config/functions/index.js +++ b/config/functions/index.js @@ -17,7 +17,7 @@ const assert = require('assert'); const cors = require('cors')({ origin: true }); -const functions = require('firebase-functions'); +const functions = require('firebase-functions/v1'); /* * These backend test helpers are copied from the iOS and Android SDKs, but are diff --git a/config/functions/package.json b/config/functions/package.json index 4b823c3de0..01e469968b 100644 --- a/config/functions/package.json +++ b/config/functions/package.json @@ -4,7 +4,7 @@ "dependencies": { "cors": "2.8.5", "firebase-admin": "11.11.1", - "firebase-functions": "3.24.1" + "firebase-functions": "^7.0.0" }, "private": true, "engines": { diff --git a/scripts/ci-test/deploy-if-needed.ts b/scripts/ci-test/deploy-if-needed.ts index 854d0ca3b0..ce4e8a4f7d 100644 --- a/scripts/ci-test/deploy-if-needed.ts +++ b/scripts/ci-test/deploy-if-needed.ts @@ -30,6 +30,7 @@ interface DeployOptions { token: string; cwd: string; only?: string; + force: boolean; } /** @@ -67,7 +68,8 @@ async function deployIfNeeded() { const deployOptions: DeployOptions = { project: config.projectId, token, - cwd: resolve(root, 'config') + cwd: resolve(root, 'config'), + force: true }; if (flags.length === 0) { console.log( From b228a2ab9ad950368d683b0a3efe3d2924854c25 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Thu, 13 Nov 2025 09:50:10 -0500 Subject: [PATCH 016/174] test(ai): update vertex ai live model name (#9376) --- packages/ai/integration/constants.ts | 2 +- packages/ai/integration/live.test.ts | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/ai/integration/constants.ts b/packages/ai/integration/constants.ts index 99a65f31c5..3e84f360a0 100644 --- a/packages/ai/integration/constants.ts +++ b/packages/ai/integration/constants.ts @@ -57,7 +57,7 @@ const modelNames: readonly string[] = ['gemini-2.0-flash', 'gemini-2.5-flash']; // The Live API requires a different set of models, and they're different for each backend. const liveModelNames: Map = new Map([ [BackendType.GOOGLE_AI, ['gemini-live-2.5-flash-preview']], - [BackendType.VERTEX_AI, ['gemini-2.0-flash-exp']] + [BackendType.VERTEX_AI, ['gemini-2.0-flash-live-preview-04-09']] ]); /** diff --git a/packages/ai/integration/live.test.ts b/packages/ai/integration/live.test.ts index 6b50fe6522..2a35795164 100644 --- a/packages/ai/integration/live.test.ts +++ b/packages/ai/integration/live.test.ts @@ -17,7 +17,6 @@ import { expect } from 'chai'; import { - BackendType, getLiveGenerativeModel, LiveGenerationConfig, LiveServerContent, @@ -81,9 +80,6 @@ describe('Live', function () { }; liveTestConfigs.forEach(testConfig => { - if (testConfig.ai.backend.backendType === BackendType.VERTEX_AI) { - return; - } describe(`${testConfig.toString()}`, () => { describe('Live', () => { it('should connect, send a message, receive a response, and close', async () => { From c77c9df1c2564ff58e93b8401d52dbbb1165e560 Mon Sep 17 00:00:00 2001 From: Google Open Source Bot Date: Thu, 13 Nov 2025 13:28:31 -0800 Subject: [PATCH 017/174] Version Packages (#9375) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/metal-ties-cry.md | 6 ------ .changeset/spotty-shirts-design.md | 5 ----- integration/compat-interop/package.json | 4 ++-- integration/firestore/package.json | 2 +- integration/messaging/package.json | 2 +- packages/ai/CHANGELOG.md | 6 ++++++ packages/ai/package.json | 4 ++-- packages/analytics-compat/package.json | 2 +- packages/analytics/package.json | 2 +- packages/app-check-compat/package.json | 2 +- packages/app-check/package.json | 2 +- packages/app-compat/CHANGELOG.md | 7 +++++++ packages/app-compat/package.json | 4 ++-- packages/app/CHANGELOG.md | 6 ++++++ packages/app/package.json | 2 +- packages/auth-compat/package.json | 2 +- packages/auth/package.json | 2 +- packages/data-connect/CHANGELOG.md | 6 ++++++ packages/data-connect/package.json | 4 ++-- packages/database-compat/package.json | 2 +- packages/database/package.json | 2 +- packages/firebase/CHANGELOG.md | 14 ++++++++++++++ packages/firebase/package.json | 10 +++++----- packages/firestore-compat/package.json | 2 +- packages/firestore/package.json | 4 ++-- packages/functions-compat/package.json | 2 +- packages/functions/package.json | 2 +- packages/installations-compat/package.json | 2 +- packages/installations/package.json | 2 +- packages/messaging-compat/package.json | 2 +- packages/messaging/package.json | 2 +- packages/performance-compat/package.json | 2 +- packages/performance/package.json | 2 +- packages/remote-config-compat/package.json | 2 +- packages/remote-config/package.json | 2 +- packages/storage-compat/package.json | 2 +- packages/storage/package.json | 2 +- packages/template/package.json | 2 +- repo-scripts/size-analysis/package.json | 2 +- 39 files changed, 80 insertions(+), 52 deletions(-) delete mode 100644 .changeset/metal-ties-cry.md delete mode 100644 .changeset/spotty-shirts-design.md diff --git a/.changeset/metal-ties-cry.md b/.changeset/metal-ties-cry.md deleted file mode 100644 index f5b29675a6..0000000000 --- a/.changeset/metal-ties-cry.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/ai': minor ---- - -Add support for server prompt templates. diff --git a/.changeset/spotty-shirts-design.md b/.changeset/spotty-shirts-design.md deleted file mode 100644 index 77c6a8c830..0000000000 --- a/.changeset/spotty-shirts-design.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@firebase/data-connect": patch ---- - -Fixed issue where onComplete wasn't triggering when the user calls `unsubscribe` on a subscription. diff --git a/integration/compat-interop/package.json b/integration/compat-interop/package.json index 9660e71e65..0703401f09 100644 --- a/integration/compat-interop/package.json +++ b/integration/compat-interop/package.json @@ -8,8 +8,8 @@ "test:debug": "karma start --browsers Chrome --auto-watch" }, "dependencies": { - "@firebase/app": "0.14.5", - "@firebase/app-compat": "0.5.5", + "@firebase/app": "0.14.6", + "@firebase/app-compat": "0.5.6", "@firebase/analytics": "0.10.19", "@firebase/analytics-compat": "0.2.25", "@firebase/auth": "1.11.1", diff --git a/integration/firestore/package.json b/integration/firestore/package.json index 26e7f66f19..b65148c5f5 100644 --- a/integration/firestore/package.json +++ b/integration/firestore/package.json @@ -14,7 +14,7 @@ "test:memory:debug": "yarn build:memory; karma start --auto-watch --browsers Chrome" }, "dependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "@firebase/firestore": "4.9.2" }, "devDependencies": { diff --git a/integration/messaging/package.json b/integration/messaging/package.json index 1c633bede9..0e4b008ee8 100644 --- a/integration/messaging/package.json +++ b/integration/messaging/package.json @@ -9,7 +9,7 @@ "test:manual": "mocha --exit" }, "devDependencies": { - "firebase": "12.5.0", + "firebase": "12.6.0", "chai": "4.5.0", "chromedriver": "119.0.1", "express": "4.21.2", diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 1c3959ccdf..08dd565f62 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/ai +## 2.6.0 + +### Minor Changes + +- [`f06cbf9`](https://github.com/firebase/firebase-js-sdk/commit/f06cbf99b91bdea8d44b18c8ae8fc14b327105cd) [#9351](https://github.com/firebase/firebase-js-sdk/pull/9351) - Add support for server prompt templates. + ## 2.5.0 ### Minor Changes diff --git a/packages/ai/package.json b/packages/ai/package.json index dcb6f11fdb..b7b690ea59 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/ai", - "version": "2.5.0", + "version": "2.6.0", "description": "The Firebase AI SDK", "author": "Firebase (https://firebase.google.com/)", "engines": { @@ -60,7 +60,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/analytics-compat/package.json b/packages/analytics-compat/package.json index f06c82a554..2c8ede4f84 100644 --- a/packages/analytics-compat/package.json +++ b/packages/analytics-compat/package.json @@ -22,7 +22,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.5", + "@firebase/app-compat": "0.5.6", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/analytics/package.json b/packages/analytics/package.json index 66fb8b4230..677a9e2580 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -47,7 +47,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "@rollup/plugin-commonjs": "21.1.0", diff --git a/packages/app-check-compat/package.json b/packages/app-check-compat/package.json index a510523e5a..b8e73ff73b 100644 --- a/packages/app-check-compat/package.json +++ b/packages/app-check-compat/package.json @@ -43,7 +43,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.5", + "@firebase/app-compat": "0.5.6", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-check/package.json b/packages/app-check/package.json index cb1ad6909e..aacb54e4c1 100644 --- a/packages/app-check/package.json +++ b/packages/app-check/package.json @@ -44,7 +44,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-compat/CHANGELOG.md b/packages/app-compat/CHANGELOG.md index 822ae9c1cd..c90d1c9fd0 100644 --- a/packages/app-compat/CHANGELOG.md +++ b/packages/app-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/app-compat +## 0.5.6 + +### Patch Changes + +- Updated dependencies []: + - @firebase/app@0.14.6 + ## 0.5.5 ### Patch Changes diff --git a/packages/app-compat/package.json b/packages/app-compat/package.json index c1ad275214..7363ffc438 100644 --- a/packages/app-compat/package.json +++ b/packages/app-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-compat", - "version": "0.5.5", + "version": "0.5.6", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,7 +37,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "@firebase/util": "1.13.0", "@firebase/logger": "0.5.0", "@firebase/component": "0.7.0", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index a370d88e79..4cb423c7ca 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/app +## 0.14.6 + +### Patch Changes + +- Update SDK_VERSION. + ## 0.14.5 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index c695239580..ffb2d04205 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app", - "version": "0.14.5", + "version": "0.14.6", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index 47f326fd71..507676b0b1 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -57,7 +57,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.5", + "@firebase/app-compat": "0.5.6", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/auth/package.json b/packages/auth/package.json index c515d4a193..2d9ed76a1e 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -131,7 +131,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-strip": "2.1.0", "@types/express": "4.17.21", diff --git a/packages/data-connect/CHANGELOG.md b/packages/data-connect/CHANGELOG.md index c62138b4d2..b9223f267c 100644 --- a/packages/data-connect/CHANGELOG.md +++ b/packages/data-connect/CHANGELOG.md @@ -1,5 +1,11 @@ ## Unreleased +## 0.3.12 + +### Patch Changes + +- [`c47bd71`](https://github.com/firebase/firebase-js-sdk/commit/c47bd7175bf11fba1840ad789294238e0614e57d) [#9349](https://github.com/firebase/firebase-js-sdk/pull/9349) (fixes [#9348](https://github.com/firebase/firebase-js-sdk/issues/9348)) - Fixed issue where onComplete wasn't triggering when the user calls `unsubscribe` on a subscription. + ## 0.3.11 ### Patch Changes diff --git a/packages/data-connect/package.json b/packages/data-connect/package.json index bf1fc8ce33..e4d540fc4b 100644 --- a/packages/data-connect/package.json +++ b/packages/data-connect/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/data-connect", - "version": "0.3.11", + "version": "0.3.12", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -55,7 +55,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/database-compat/package.json b/packages/database-compat/package.json index 1f4e0f55b7..f27b05590d 100644 --- a/packages/database-compat/package.json +++ b/packages/database-compat/package.json @@ -57,7 +57,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.5", + "@firebase/app-compat": "0.5.6", "typescript": "5.5.4" }, "repository": { diff --git a/packages/database/package.json b/packages/database/package.json index 4d7f3d18db..e870276bb4 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -57,7 +57,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/firebase/CHANGELOG.md b/packages/firebase/CHANGELOG.md index eb85a4d474..42b95f095d 100644 --- a/packages/firebase/CHANGELOG.md +++ b/packages/firebase/CHANGELOG.md @@ -1,5 +1,19 @@ # firebase +## 12.6.0 + +### Minor Changes + +- [`f06cbf9`](https://github.com/firebase/firebase-js-sdk/commit/f06cbf99b91bdea8d44b18c8ae8fc14b327105cd) [#9351](https://github.com/firebase/firebase-js-sdk/pull/9351) - Add support for server prompt templates. + +### Patch Changes + +- Updated dependencies [[`f06cbf9`](https://github.com/firebase/firebase-js-sdk/commit/f06cbf99b91bdea8d44b18c8ae8fc14b327105cd), [`c47bd71`](https://github.com/firebase/firebase-js-sdk/commit/c47bd7175bf11fba1840ad789294238e0614e57d)]: + - @firebase/app@0.14.6 + - @firebase/ai@2.6.0 + - @firebase/data-connect@0.3.12 + - @firebase/app-compat@0.5.6 + ## 12.5.0 ### Minor Changes diff --git a/packages/firebase/package.json b/packages/firebase/package.json index d8e9b5d5c4..69ca37b633 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -1,6 +1,6 @@ { "name": "firebase", - "version": "12.5.0", + "version": "12.6.0", "description": "Firebase JavaScript library for web and Node.js", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -399,13 +399,13 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/ai": "2.5.0", - "@firebase/app": "0.14.5", - "@firebase/app-compat": "0.5.5", + "@firebase/ai": "2.6.0", + "@firebase/app": "0.14.6", + "@firebase/app-compat": "0.5.6", "@firebase/app-types": "0.9.3", "@firebase/auth": "1.11.1", "@firebase/auth-compat": "0.6.1", - "@firebase/data-connect": "0.3.11", + "@firebase/data-connect": "0.3.12", "@firebase/database": "1.1.0", "@firebase/database-compat": "2.1.0", "@firebase/firestore": "4.9.2", diff --git a/packages/firestore-compat/package.json b/packages/firestore-compat/package.json index 07d80f462e..26c64617b9 100644 --- a/packages/firestore-compat/package.json +++ b/packages/firestore-compat/package.json @@ -53,7 +53,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.5", + "@firebase/app-compat": "0.5.6", "@types/eslint": "7.29.0", "rollup": "2.79.2", "rollup-plugin-sourcemaps": "0.6.3", diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 1a7bb7da1b..6c3a2eefaa 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -112,8 +112,8 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.5", - "@firebase/app-compat": "0.5.5", + "@firebase/app": "0.14.6", + "@firebase/app-compat": "0.5.6", "@firebase/auth": "1.11.1", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", diff --git a/packages/functions-compat/package.json b/packages/functions-compat/package.json index c64d29d4ea..81e52d2837 100644 --- a/packages/functions-compat/package.json +++ b/packages/functions-compat/package.json @@ -29,7 +29,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.5", + "@firebase/app-compat": "0.5.6", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/functions/package.json b/packages/functions/package.json index 4a85faa985..9c036e347a 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -49,7 +49,7 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/installations-compat/package.json b/packages/installations-compat/package.json index 20e21e0d8a..4fdb6c130a 100644 --- a/packages/installations-compat/package.json +++ b/packages/installations-compat/package.json @@ -44,7 +44,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app-compat": "0.5.5", + "@firebase/app-compat": "0.5.6", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/installations/package.json b/packages/installations/package.json index 9ae0bb0a09..2feb17e5d8 100644 --- a/packages/installations/package.json +++ b/packages/installations/package.json @@ -49,7 +49,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/messaging-compat/package.json b/packages/messaging-compat/package.json index 92a6f8fba1..f657f90c5e 100644 --- a/packages/messaging-compat/package.json +++ b/packages/messaging-compat/package.json @@ -44,7 +44,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.5", + "@firebase/app-compat": "0.5.6", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", "ts-essentials": "9.4.2", diff --git a/packages/messaging/package.json b/packages/messaging/package.json index bd87ae31fc..f2ac7689ce 100644 --- a/packages/messaging/package.json +++ b/packages/messaging/package.json @@ -60,7 +60,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/performance-compat/package.json b/packages/performance-compat/package.json index 94050c1ed3..4099db0992 100644 --- a/packages/performance-compat/package.json +++ b/packages/performance-compat/package.json @@ -51,7 +51,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.5" + "@firebase/app-compat": "0.5.6" }, "repository": { "directory": "packages/performance-compat", diff --git a/packages/performance/package.json b/packages/performance/package.json index 125d3f084f..eaebecb664 100644 --- a/packages/performance/package.json +++ b/packages/performance/package.json @@ -47,7 +47,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/remote-config-compat/package.json b/packages/remote-config-compat/package.json index dbf19c1830..d7a28f82db 100644 --- a/packages/remote-config-compat/package.json +++ b/packages/remote-config-compat/package.json @@ -50,7 +50,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.5" + "@firebase/app-compat": "0.5.6" }, "repository": { "directory": "packages/remote-config-compat", diff --git a/packages/remote-config/package.json b/packages/remote-config/package.json index d02f746ed2..83d9886b89 100644 --- a/packages/remote-config/package.json +++ b/packages/remote-config/package.json @@ -48,7 +48,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/storage-compat/package.json b/packages/storage-compat/package.json index 19a5f352b7..c20456e6f9 100644 --- a/packages/storage-compat/package.json +++ b/packages/storage-compat/package.json @@ -44,7 +44,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.5", + "@firebase/app-compat": "0.5.6", "@firebase/auth-compat": "0.6.1", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", diff --git a/packages/storage/package.json b/packages/storage/package.json index 2b0df30704..6e7a4db769 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -54,7 +54,7 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "@firebase/auth": "1.11.1", "rollup": "2.79.2", "@rollup/plugin-alias": "5.1.1", diff --git a/packages/template/package.json b/packages/template/package.json index 635f4f451c..54395dfd17 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -48,7 +48,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index 78a2f87e21..8653103c7f 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -40,7 +40,7 @@ "yargs": "17.7.2" }, "devDependencies": { - "@firebase/app": "0.14.5", + "@firebase/app": "0.14.6", "@firebase/logger": "0.5.0", "@types/webpack": "5.28.5" }, From d1d898f555d4da1c24941f93e47a75d660311650 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Fri, 14 Nov 2025 11:07:01 -0800 Subject: [PATCH 018/174] Disable flaky totp tests (#9371) --- packages/auth/test/integration/flows/totp.test.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/auth/test/integration/flows/totp.test.ts b/packages/auth/test/integration/flows/totp.test.ts index 9d8e8893de..a62c475ce7 100644 --- a/packages/auth/test/integration/flows/totp.test.ts +++ b/packages/auth/test/integration/flows/totp.test.ts @@ -52,7 +52,13 @@ let totpTimestamp: Date; let emulatorUrl: string | null; let mfaUser: MultiFactorUser | null; -describe(' Integration tests: Mfa enrollment using totp', () => { +/** + * TOTP tests disabled until they can be rewritten without requiring a + * permanent account. + */ + +// eslint-disable-next-line no-restricted-properties +describe.skip(' Integration tests: Mfa enrollment using totp', () => { beforeEach(async () => { emulatorUrl = getEmulatorUrl(); if (!emulatorUrl) { @@ -122,7 +128,8 @@ describe(' Integration tests: Mfa enrollment using totp', () => { }); }); -describe('Integration tests: sign-in for mfa-enrolled users', () => { +// eslint-disable-next-line no-restricted-properties +describe.skip('Integration tests: sign-in for mfa-enrolled users', () => { beforeEach(async () => { emulatorUrl = getEmulatorUrl(); mfaUser = null; From 60d1b18bdd8e6ae618005e021dc5d1f16db1937c Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 20 Nov 2025 09:37:28 -0800 Subject: [PATCH 019/174] Update PR template (#9391) --- .github/PULL_REQUEST_TEMPLATE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3d81fd0c9f..826f24be71 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -14,6 +14,6 @@ Before you file this pull request, please read these guidelines: ### API Changes - * At this time we cannot accept changes that affect the public API. If you'd like to help - us make Firebase APIs better, please propose your change in an issue so that we - can discuss it together. + * Changes that affect the public API will require internal review. Before making a + PR that changes the public API, we would suggest first proposing your change in an + issue so that we can discuss it together. From 59407948daf848fea069b776a55bef62bbcd602f Mon Sep 17 00:00:00 2001 From: cherylEnkidu <96084918+cherylEnkidu@users.noreply.github.com> Date: Mon, 24 Nov 2025 14:56:01 -0500 Subject: [PATCH 020/174] fix(firestore): Corrected misleading error message when doc() is called with undefined. (#9386) * Corrected misleading error message when doc() is called with undefined. * add changeset * Update packages/firestore/test/lite/integration.test.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * remove any * add ts-ignore * fix error message * improve code --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .changeset/thin-sheep-smoke.md | 5 +++++ packages/firestore/src/lite-api/reference.ts | 2 +- packages/firestore/test/lite/integration.test.ts | 6 ++++++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 .changeset/thin-sheep-smoke.md diff --git a/.changeset/thin-sheep-smoke.md b/.changeset/thin-sheep-smoke.md new file mode 100644 index 0000000000..83af71b0d0 --- /dev/null +++ b/.changeset/thin-sheep-smoke.md @@ -0,0 +1,5 @@ +--- +'@firebase/firestore': patch +--- + +Fix: Corrected misleading error message when doc() is called with undefined. diff --git a/packages/firestore/src/lite-api/reference.ts b/packages/firestore/src/lite-api/reference.ts index f38dad9a07..e6c5fd7b05 100644 --- a/packages/firestore/src/lite-api/reference.ts +++ b/packages/firestore/src/lite-api/reference.ts @@ -651,7 +651,7 @@ export function doc( ) { throw new FirestoreError( Code.INVALID_ARGUMENT, - 'Expected first argument to collection() to be a CollectionReference, ' + + 'Expected first argument to doc() to be a CollectionReference, ' + 'a DocumentReference or FirebaseFirestore' ); } diff --git a/packages/firestore/test/lite/integration.test.ts b/packages/firestore/test/lite/integration.test.ts index 7fb7eafcb1..54595ade4d 100644 --- a/packages/firestore/test/lite/integration.test.ts +++ b/packages/firestore/test/lite/integration.test.ts @@ -285,6 +285,12 @@ describe('doc', () => { it('validates path', () => { return withTestDb(db => { + expect(() => + // @ts-expect-error + doc({}, 'coll/doc') + ).to.throw( + 'Expected first argument to doc() to be a CollectionReference, a DocumentReference or FirebaseFirestore' + ); expect(() => doc(db, 'coll')).to.throw( 'Invalid document reference. Document references must have an even ' + 'number of segments, but coll has 1.' From e6415ddee915e5c4dc6ef323fd717ce254f63c51 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 25 Nov 2025 14:33:30 -0500 Subject: [PATCH 021/174] test(ai): run prompt templates integration tests against prod endpoint (#9387) The integration tests were originally written to run against staging. Now that this feature is in prod, we should test against the prod endpoint. --- packages/ai/integration/constants.ts | 16 ++++++++++++++++ packages/ai/integration/prompt-templates.test.ts | 15 +++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/packages/ai/integration/constants.ts b/packages/ai/integration/constants.ts index 3e84f360a0..c1bf74770c 100644 --- a/packages/ai/integration/constants.ts +++ b/packages/ai/integration/constants.ts @@ -94,6 +94,22 @@ export const liveTestConfigs: readonly TestConfig[] = backends.flatMap( } ); +/** + * Test configurations used for server prompt templates integration tests. + * Server prompt templates don't define the model name from the client, so these test configs + * do not define a model string. + * These tests should only run once per backend, rather than once per backend *per model*. + */ +export const promptTemplatesTestConfigs: readonly TestConfig[] = + backends.flatMap(backend => { + const ai = getAI(app, { backend }); + return { + ai, + model: '', // Unused by prompt templates tests + toString: () => formatConfigAsString({ ai, model: '' }).trim() + }; + }); + export const TINY_IMG_BASE64 = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII='; export const IMAGE_MIME_TYPE = 'image/png'; diff --git a/packages/ai/integration/prompt-templates.test.ts b/packages/ai/integration/prompt-templates.test.ts index 3a7f903856..a73f17eee2 100644 --- a/packages/ai/integration/prompt-templates.test.ts +++ b/packages/ai/integration/prompt-templates.test.ts @@ -21,8 +21,7 @@ import { getTemplateGenerativeModel, getTemplateImagenModel } from '../src'; -import { testConfigs } from './constants'; -import { STAGING_URL } from '../src/constants'; +import { promptTemplatesTestConfigs } from './constants'; const templateBackendSuffix = ( backendType: BackendType @@ -31,13 +30,11 @@ const templateBackendSuffix = ( describe('Prompt templates', function () { this.timeout(20_000); - testConfigs.forEach(testConfig => { + promptTemplatesTestConfigs.forEach(testConfig => { describe(`${testConfig.toString()}`, () => { describe('Generative Model', () => { it('successfully generates content', async () => { - const model = getTemplateGenerativeModel(testConfig.ai, { - baseUrl: STAGING_URL - }); + const model = getTemplateGenerativeModel(testConfig.ai); const { response } = await model.generateContent( `sassy-greeting-${templateBackendSuffix( testConfig.ai.backend.backendType @@ -49,16 +46,14 @@ describe('Prompt templates', function () { }); describe('Imagen model', async () => { it('successfully generates images', async () => { - const model = getTemplateImagenModel(testConfig.ai, { - baseUrl: STAGING_URL - }); + const model = getTemplateImagenModel(testConfig.ai); const { images } = await model.generateImages( `portrait-${templateBackendSuffix( testConfig.ai.backend.backendType )}`, { animal: 'Rhino' } ); - expect(images.length).to.equal(2); // We ask for two images in the prompt template + expect(images.length).to.equal(1); // The template is configured to generate one image. }); }); }); From 9101b4611aa1e0fa1a913d4ebdcda43f0ceef72d Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Mon, 1 Dec 2025 15:28:45 -0500 Subject: [PATCH 022/174] test(ai): prompt for grep string in debug script (#9400) * test(ai): prompt for grep string in debug script Mocha lets us filter tests using the `--grep` command-line option. This is useful when debugging the AI integration tests, which run against a grid of backend x model. With this grid there may me multiple redundant test runs, and the tests may take >20 minutes. With this new config, we can isolate the test we want to debug. Before running, VSCode will prompt us for a regex to use for grepping tests by name. An example grep string would be `Google AI gemini-2.0-flash generateContent: google search grounding`. Without this, I've been manually editing the input test files to be the file with the test I'm running, then manually editing `integration/constants.ts` to remove the additional backends and model names. * update default and example --- .vscode/launch.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 8f132cbe5c..97e3c8c0e3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -37,7 +37,8 @@ "src/index.node.ts", "--timeout", "5000", - "integration/**/*.test.ts" + "integration/**/*.test.ts", + "--grep", "${input:grepString}", ], "env": { "TS_NODE_COMPILER_OPTIONS": "{\"module\":\"commonjs\"}" @@ -184,5 +185,13 @@ "cwd": "${workspaceRoot}/packages/firestore", "args": ["start", "--auto-watch", "--integration", "--browsers", "Chrome"] } + ], + "inputs": [ + { + "id": "grepString", + "type": "promptString", + "description": "Enter grep pattern (e.g., 'Google AI gemini-2.0-flash generateContent')", + "default": "" + } ] } From f5fc6bf76a4b9b9318549185438b9975351d1739 Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Mon, 1 Dec 2025 15:35:33 -0500 Subject: [PATCH 023/174] test(ai): Remove flaky token count integration expect directives (#9401) We had some "ballpark" checks for the number of tokens returned in responses. However, the number of tokens returned had a high variance based on general AI chaos and the model that was used. This PR replaces somewhat exacting token count checks with simple non-zero checks in order to reduce flake. Additionally, the change removes `toolUsePromptTokenCount` checks for the `gemini-2.0-flash` model, which doesn't support this field. --- packages/ai/integration/chat.test.ts | 67 ++++--------------- .../ai/integration/generate-content.test.ts | 50 +++++--------- 2 files changed, 29 insertions(+), 88 deletions(-) diff --git a/packages/ai/integration/chat.test.ts b/packages/ai/integration/chat.test.ts index b6772a38fb..4d76652920 100644 --- a/packages/ai/integration/chat.test.ts +++ b/packages/ai/integration/chat.test.ts @@ -24,7 +24,7 @@ import { SafetySetting, getGenerativeModel } from '../src'; -import { testConfigs, TOKEN_COUNT_DELTA } from './constants'; +import { testConfigs } from './constants'; describe('Chat Session', () => { testConfigs.forEach(testConfig => { @@ -98,62 +98,21 @@ describe('Chat Session', () => { if (model.model.includes('gemini-2.5-flash')) { // Token counts can vary slightly in chat context - expect(response1.usageMetadata!.promptTokenCount).to.be.closeTo( - 17, // "What is the capital of France?" + system instruction - TOKEN_COUNT_DELTA + 2 // More variance for chat context - ); - expect(response1.usageMetadata!.candidatesTokenCount).to.be.closeTo( - 8, // "Paris" - TOKEN_COUNT_DELTA - ); - expect(response1.usageMetadata!.totalTokenCount).to.be.closeTo( - 49, // "What is the capital of France?" + system instruction + "Paris" - TOKEN_COUNT_DELTA + 3 // More variance for chat context - ); - expect(response1.usageMetadata!.totalTokenCount).to.be.closeTo( - 49, // "What is the capital of France?" + system instruction + "Paris" - TOKEN_COUNT_DELTA + 3 // More variance for chat context - ); - - expect(response2.usageMetadata!.promptTokenCount).to.be.closeTo( - 32, // History + "And what about Italy?" + system instruction - TOKEN_COUNT_DELTA + 5 // More variance for chat context with history - ); - expect(response2.usageMetadata!.candidatesTokenCount).to.be.closeTo( - 8, - TOKEN_COUNT_DELTA - ); - expect(response2.usageMetadata!.totalTokenCount).to.be.closeTo( - 68, - TOKEN_COUNT_DELTA + 2 - ); + expect(response1.usageMetadata!.promptTokenCount).to.not.equal(0); + expect(response1.usageMetadata!.candidatesTokenCount).to.not.equal(0); + expect(response1.usageMetadata!.totalTokenCount).to.not.equal(0); + expect(response2.usageMetadata!.promptTokenCount).to.not.equal(0); + expect(response2.usageMetadata!.candidatesTokenCount).to.not.equal(0); + expect(response2.usageMetadata!.totalTokenCount).to.not.equal(0); } else if (model.model.includes('gemini-2.0-flash')) { expect(response1.usageMetadata).to.not.be.null; // Token counts can vary slightly in chat context - expect(response1.usageMetadata!.promptTokenCount).to.be.closeTo( - 15, // "What is the capital of France?" + system instruction - TOKEN_COUNT_DELTA + 2 // More variance for chat context - ); - expect(response1.usageMetadata!.candidatesTokenCount).to.be.closeTo( - 8, // "Paris" - TOKEN_COUNT_DELTA - ); - expect(response1.usageMetadata!.totalTokenCount).to.be.closeTo( - 23, // "What is the capital of France?" + system instruction + "Paris" - TOKEN_COUNT_DELTA + 3 // More variance for chat context - ); - expect(response2.usageMetadata!.promptTokenCount).to.be.closeTo( - 28, // History + "And what about Italy?" + system instruction - TOKEN_COUNT_DELTA + 5 // More variance for chat context with history - ); - expect(response2.usageMetadata!.candidatesTokenCount).to.be.closeTo( - 8, - TOKEN_COUNT_DELTA - ); - expect(response2.usageMetadata!.totalTokenCount).to.be.closeTo( - 36, - TOKEN_COUNT_DELTA - ); + expect(response1.usageMetadata!.promptTokenCount).to.not.equal(0); + expect(response1.usageMetadata!.candidatesTokenCount).to.not.equal(0); + expect(response1.usageMetadata!.totalTokenCount).to.not.equal(0); + expect(response2.usageMetadata!.promptTokenCount).to.not.equal(0); + expect(response2.usageMetadata!.candidatesTokenCount).to.not.equal(0); + expect(response2.usageMetadata!.totalTokenCount).to.not.equal(0); } }); }); diff --git a/packages/ai/integration/generate-content.test.ts b/packages/ai/integration/generate-content.test.ts index ffb1ecca69..e56203c1f9 100644 --- a/packages/ai/integration/generate-content.test.ts +++ b/packages/ai/integration/generate-content.test.ts @@ -29,7 +29,7 @@ import { URLRetrievalStatus, getGenerativeModel } from '../src'; -import { testConfigs, TOKEN_COUNT_DELTA } from './constants'; +import { testConfigs } from './constants'; describe('Generate Content', function () { this.timeout(20_000); @@ -88,22 +88,10 @@ describe('Generate Content', function () { expect(response.usageMetadata).to.not.be.null; if (model.model.includes('gemini-2.5-flash')) { - expect(response.usageMetadata!.promptTokenCount).to.be.closeTo( - 22, - TOKEN_COUNT_DELTA - ); - expect(response.usageMetadata!.candidatesTokenCount).to.be.closeTo( - 2, - TOKEN_COUNT_DELTA - ); - expect(response.usageMetadata!.thoughtsTokenCount).to.be.closeTo( - 30, - TOKEN_COUNT_DELTA * 2 - ); - expect(response.usageMetadata!.totalTokenCount).to.be.closeTo( - 55, - TOKEN_COUNT_DELTA * 2 - ); + expect(response.usageMetadata!.promptTokenCount).to.not.equal(0); + expect(response.usageMetadata!.candidatesTokenCount).to.not.equal(0); + expect(response.usageMetadata!.thoughtsTokenCount).to.not.equal(0); + expect(response.usageMetadata!.totalTokenCount).to.not.equal(0); expect(response.usageMetadata!.promptTokensDetails).to.not.be.null; expect(response.usageMetadata!.promptTokensDetails!.length).to.equal( 1 @@ -113,22 +101,13 @@ describe('Generate Content', function () { ).to.equal(Modality.TEXT); expect( response.usageMetadata!.promptTokensDetails![0].tokenCount - ).to.closeTo(22, TOKEN_COUNT_DELTA); + ).to.not.equal(0); // candidatesTokenDetails comes back about half the time, so let's just not test it. } else if (model.model.includes('gemini-2.0-flash')) { - expect(response.usageMetadata!.promptTokenCount).to.be.closeTo( - 21, - TOKEN_COUNT_DELTA - ); - expect(response.usageMetadata!.candidatesTokenCount).to.be.closeTo( - 4, - TOKEN_COUNT_DELTA - ); - expect(response.usageMetadata!.totalTokenCount).to.be.closeTo( - 25, - TOKEN_COUNT_DELTA * 2 - ); + expect(response.usageMetadata!.promptTokenCount).to.not.equal(0); + expect(response.usageMetadata!.candidatesTokenCount).to.not.equal(0); + expect(response.usageMetadata!.totalTokenCount).to.not.equal(0); expect(response.usageMetadata!.promptTokensDetails).to.not.be.null; expect(response.usageMetadata!.promptTokensDetails!.length).to.equal( 1 @@ -149,7 +128,7 @@ describe('Generate Content', function () { ).to.equal(Modality.TEXT); expect( response.usageMetadata!.candidatesTokensDetails![0].tokenCount - ).to.be.closeTo(4, TOKEN_COUNT_DELTA); + ).to.not.equal(0); } }); @@ -230,8 +209,11 @@ describe('Generate Content', function () { const usageMetadata = response.usageMetadata; expect(usageMetadata).to.exist; - expect(usageMetadata?.toolUsePromptTokenCount).to.exist; - expect(usageMetadata?.toolUsePromptTokenCount).to.be.greaterThan(0); + // usageMetaData.toolUsePromptTokenCount does not exist in Gemini 2.0 flash responses. + if (!model.model.includes('gemini-2.0-flash')) { + expect(usageMetadata?.toolUsePromptTokenCount).to.exist; + expect(usageMetadata?.toolUsePromptTokenCount).to.be.greaterThan(0); + } }); it('generateContent: url context and google search grounding', async () => { @@ -288,7 +270,7 @@ describe('Generate Content', function () { }); const result = await model.generateContent( - 'Recommend 3 books for beginners to read to learn more about the latest advancements in Quantum Computing.' + 'Recommend 3 books for beginners to read to learn more about the latest advancements in Quantum Computing' ); const response = result.response; const urlContextMetadata = From 5c7430deabb20ddce2a26ea9a565323d2a0f612e Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 3 Dec 2025 13:11:23 -0800 Subject: [PATCH 024/174] fix(ai): Fix `generateContentStream` returning wrong inferenceSource. (#9381) --- .changeset/gorgeous-rice-carry.md | 5 +++ .../ai/src/methods/generate-content.test.ts | 31 +++++++++++++++++-- packages/ai/src/methods/generate-content.ts | 6 +++- 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 .changeset/gorgeous-rice-carry.md diff --git a/.changeset/gorgeous-rice-carry.md b/.changeset/gorgeous-rice-carry.md new file mode 100644 index 0000000000..80d58cede5 --- /dev/null +++ b/.changeset/gorgeous-rice-carry.md @@ -0,0 +1,5 @@ +--- +'@firebase/ai': patch +--- + +Fix `generateContentStream` returning wrong `inferenceSource`. diff --git a/packages/ai/src/methods/generate-content.test.ts b/packages/ai/src/methods/generate-content.test.ts index 8a274c2441..be94a7b29a 100644 --- a/packages/ai/src/methods/generate-content.test.ts +++ b/packages/ai/src/methods/generate-content.test.ts @@ -26,6 +26,7 @@ import { import * as request from '../requests/request'; import { generateContent, + generateContentStream, templateGenerateContent, templateGenerateContentStream } from './generate-content'; @@ -35,6 +36,7 @@ import { HarmBlockMethod, HarmBlockThreshold, HarmCategory, + InferenceSource, Language, Outcome } from '../types'; @@ -548,8 +550,7 @@ describe('generateContent()', () => { ); }); }); - // TODO: define a similar test for generateContentStream - it('on-device', async () => { + it('generateContent on-device', async () => { const chromeAdapter = fakeChromeAdapter; const isAvailableStub = stub(chromeAdapter, 'isAvailable').resolves(true); const mockResponse = getMockResponse( @@ -566,9 +567,35 @@ describe('generateContent()', () => { chromeAdapter ); expect(result.response.text()).to.include('Mountain View, California'); + expect(result.response.inferenceSource).to.equal(InferenceSource.ON_DEVICE); expect(isAvailableStub).to.be.called; expect(generateContentStub).to.be.calledWith(fakeRequestParams); }); + it('generateContentStream on-device', async () => { + const chromeAdapter = fakeChromeAdapter; + const isAvailableStub = stub(chromeAdapter, 'isAvailable').resolves(true); + const mockResponse = getMockResponseStreaming( + 'vertexAI', + 'streaming-success-basic-reply-short.txt' + ); + const generateContentStreamStub = stub( + chromeAdapter, + 'generateContentStream' + ).resolves(mockResponse as Response); + const result = await generateContentStream( + fakeApiSettings, + 'model', + fakeRequestParams, + chromeAdapter + ); + const aggregatedResponse = await result.response; + expect(aggregatedResponse.text()).to.include('Cheyenne'); + expect(aggregatedResponse.inferenceSource).to.equal( + InferenceSource.ON_DEVICE + ); + expect(isAvailableStub).to.be.called; + expect(generateContentStreamStub).to.be.calledWith(fakeRequestParams); + }); }); describe('templateGenerateContent', () => { diff --git a/packages/ai/src/methods/generate-content.ts b/packages/ai/src/methods/generate-content.ts index fc6eac15c7..56f55f1b02 100644 --- a/packages/ai/src/methods/generate-content.ts +++ b/packages/ai/src/methods/generate-content.ts @@ -70,7 +70,11 @@ export async function generateContentStream( () => generateContentStreamOnCloud(apiSettings, model, params, requestOptions) ); - return processStream(callResult.response, apiSettings); // TODO: Map streaming responses + return processStream( + callResult.response, + apiSettings, + callResult.inferenceSource + ); } async function generateContentOnCloud( From a09ef786f35beca082b32a3194cc368b0050ea2c Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Thu, 4 Dec 2025 13:45:21 -0500 Subject: [PATCH 025/174] build(deps): update optional react-native-async-storage peerDependency to v2+ (#9385) v1 does not work with modern react-native, and projects that rely on firebase-js-sdk have difficulty overriding this peer dependency to the v2 series that works, because of unrelated issues with the npm package manager --- packages/auth/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/auth/package.json b/packages/auth/package.json index 2d9ed76a1e..d4f1ce69c0 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -116,7 +116,7 @@ }, "peerDependencies": { "@firebase/app": "0.x", - "@react-native-async-storage/async-storage": "^1.18.1" + "@react-native-async-storage/async-storage": "^2.2.0" }, "peerDependenciesMeta": { "@react-native-async-storage/async-storage": { From 1e406a2b7140b014edac26f0e5179878bb3d821f Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 4 Dec 2025 11:36:46 -0800 Subject: [PATCH 026/174] add changeset for #9385 (#9410) --- .changeset/four-vans-mix.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/four-vans-mix.md diff --git a/.changeset/four-vans-mix.md b/.changeset/four-vans-mix.md new file mode 100644 index 0000000000..e763d0c310 --- /dev/null +++ b/.changeset/four-vans-mix.md @@ -0,0 +1,5 @@ +--- +'@firebase/auth': minor +--- + +Upgraded react-native-async-storage peerDependency to v2+. From 5511b4fa7de0e98f3a3b933645584ba758de4405 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 9 Dec 2025 09:45:50 -0500 Subject: [PATCH 027/174] test(ai): Add all general use models to integration tests (#9413) --- packages/ai/integration/chat.test.ts | 3 +- packages/ai/integration/constants.ts | 9 +++- packages/ai/integration/count-tokens.test.ts | 41 +++++++++++++++---- .../ai/integration/generate-content.test.ts | 15 ++++--- 4 files changed, 51 insertions(+), 17 deletions(-) diff --git a/packages/ai/integration/chat.test.ts b/packages/ai/integration/chat.test.ts index 4d76652920..4a867b364a 100644 --- a/packages/ai/integration/chat.test.ts +++ b/packages/ai/integration/chat.test.ts @@ -26,7 +26,8 @@ import { } from '../src'; import { testConfigs } from './constants'; -describe('Chat Session', () => { +describe('Chat Session', function () { + this.timeout(20_000); testConfigs.forEach(testConfig => { describe(`${testConfig.toString()}`, () => { const commonGenerationConfig: GenerationConfig = { diff --git a/packages/ai/integration/constants.ts b/packages/ai/integration/constants.ts index c1bf74770c..64c20f8b2e 100644 --- a/packages/ai/integration/constants.ts +++ b/packages/ai/integration/constants.ts @@ -52,7 +52,14 @@ const backendNames: Map = new Map([ [BackendType.VERTEX_AI, 'Vertex AI'] ]); -const modelNames: readonly string[] = ['gemini-2.0-flash', 'gemini-2.5-flash']; +const modelNames: readonly string[] = [ + 'gemini-2.0-flash-001', + 'gemini-2.0-flash-lite-001', + 'gemini-2.5-flash', + 'gemini-2.5-flash-lite', + 'gemini-2.5-pro', + 'gemini-3-pro-preview' +]; // The Live API requires a different set of models, and they're different for each backend. const liveModelNames: Map = new Map([ diff --git a/packages/ai/integration/count-tokens.test.ts b/packages/ai/integration/count-tokens.test.ts index 3256a9ed9d..e2e3a5e304 100644 --- a/packages/ai/integration/count-tokens.test.ts +++ b/packages/ai/integration/count-tokens.test.ts @@ -118,9 +118,18 @@ describe('Count Tokens', () => { }; const response = await model.countTokens([imagePart]); + let expectedImageTokens: number; + if (testConfig.model === 'gemini-3-pro-preview') { + expectedImageTokens = + testConfig.ai.backend.backendType === BackendType.GOOGLE_AI + ? 1089 + : 1120; + } else { + expectedImageTokens = 258; + } + if (testConfig.ai.backend.backendType === BackendType.GOOGLE_AI) { - const expectedImageTokens = 259; - expect(response.totalTokens).to.equal(expectedImageTokens); + expect(response.totalTokens).to.equal(expectedImageTokens + 1); // There will be 1 unexpected text token expect(response.totalBillableCharacters).to.be.undefined; // Incorrect behavior expect(response.promptTokensDetails!.length).to.equal(2); expect(response.promptTokensDetails![0]).to.deep.equal({ @@ -129,19 +138,18 @@ describe('Count Tokens', () => { }); expect(response.promptTokensDetails![1]).to.deep.equal({ modality: Modality.IMAGE, - tokenCount: 258 + tokenCount: expectedImageTokens }); } else if ( testConfig.ai.backend.backendType === BackendType.VERTEX_AI ) { - const expectedImageTokens = 258; expect(response.totalTokens).to.equal(expectedImageTokens); expect(response.totalBillableCharacters).to.be.undefined; // Incorrect behavior expect(response.promptTokensDetails!.length).to.equal(1); // Note: No text tokens are present for Vertex AI with image-only input. expect(response.promptTokensDetails![0]).to.deep.equal({ modality: Modality.IMAGE, - tokenCount: 258 + tokenCount: expectedImageTokens }); expect(response.promptTokensDetails![0].tokenCount).to.equal( expectedImageTokens @@ -220,13 +228,23 @@ describe('Count Tokens', () => { expect(response.promptTokensDetails).to.exist; expect(response.promptTokensDetails!.length).to.equal(3); + let expectedImageTokenCount; + if (testConfig.model === 'gemini-3-pro-preview') { + expectedImageTokenCount = + testConfig.ai.backend.backendType === BackendType.GOOGLE_AI + ? 1089 + : 1120; + } else { + expectedImageTokenCount = 258; + } + expect(imageDetails).to.deep.equal({ modality: Modality.IMAGE, - tokenCount: 258 + tokenCount: expectedImageTokenCount }); if (testConfig.ai.backend.backendType === BackendType.GOOGLE_AI) { - expect(response.totalTokens).to.equal(267); + expect(response.totalTokens).to.equal(expectedImageTokenCount + 9); expect(response.totalBillableCharacters).to.be.undefined; expect(textDetails).to.deep.equal({ modality: Modality.TEXT, @@ -239,7 +257,7 @@ describe('Count Tokens', () => { } else if ( testConfig.ai.backend.backendType === BackendType.VERTEX_AI ) { - expect(response.totalTokens).to.equal(261); + expect(response.totalTokens).to.equal(expectedImageTokenCount + 3); expect(textDetails).to.deep.equal({ modality: Modality.TEXT, tokenCount: 3 @@ -269,7 +287,12 @@ describe('Count Tokens', () => { const response = await model.countTokens([filePart]); - const expectedFileTokens = 258; + let expectedFileTokens: number; + if (testConfig.model === 'gemini-3-pro-preview') { + expectedFileTokens = 1120; + } else { + expectedFileTokens = 258; + } expect(response.totalTokens).to.equal(expectedFileTokens); expect(response.totalBillableCharacters).to.be.undefined; expect(response.promptTokensDetails).to.exist; diff --git a/packages/ai/integration/generate-content.test.ts b/packages/ai/integration/generate-content.test.ts index e56203c1f9..ce52a1f68f 100644 --- a/packages/ai/integration/generate-content.test.ts +++ b/packages/ai/integration/generate-content.test.ts @@ -32,7 +32,7 @@ import { import { testConfigs } from './constants'; describe('Generate Content', function () { - this.timeout(20_000); + this.timeout(90_000); // gemini 3 requests take a long time, especially when using google search and url context. testConfigs.forEach(testConfig => { describe(`${testConfig.toString()}`, () => { const commonGenerationConfig: GenerationConfig = { @@ -175,8 +175,9 @@ describe('Generate Content', function () { describe('URL Context', async () => { // URL Context is not supported in Google AI for gemini-2.0-flash if ( - testConfig.ai.backend.backendType === BackendType.GOOGLE_AI && - testConfig.model === 'gemini-2.0-flash' + ['gemini-2.0-flash-001', 'gemini-2.0-flash-lite-001'].includes( + testConfig.model + ) // Models that don't support URL Context ) { return; } @@ -232,9 +233,7 @@ describe('Generate Content', function () { const urlContextMetadata = response.candidates?.[0].urlContextMetadata; const groundingMetadata = response.candidates?.[0].groundingMetadata; - expect(trimmedText).to.contain( - 'hypermedia information retrieval initiative' - ); + expect(trimmedText.length).to.be.greaterThan(0); expect(urlContextMetadata?.urlMetadata).to.exist; expect( urlContextMetadata?.urlMetadata.length @@ -302,6 +301,10 @@ describe('Generate Content', function () { }); it('generateContent: code execution', async () => { + if (testConfig.model === 'gemini-2.0-flash-lite-001') { + // This model does not support code execution + return; + } const model = getGenerativeModel(testConfig.ai, { model: testConfig.model, generationConfig: commonGenerationConfig, From bc2b2cdeae920ff22aca3414c2a1b79d4a3b1351 Mon Sep 17 00:00:00 2001 From: aalej Date: Sat, 13 Dec 2025 03:16:11 +0800 Subject: [PATCH 028/174] update link to /ailogic (#9399) --- .changeset/gentle-queens-argue.md | 5 +++++ packages/ai/src/requests/request.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/gentle-queens-argue.md diff --git a/.changeset/gentle-queens-argue.md b/.changeset/gentle-queens-argue.md new file mode 100644 index 0000000000..d14ec3d16a --- /dev/null +++ b/.changeset/gentle-queens-argue.md @@ -0,0 +1,5 @@ +--- +'@firebase/ai': patch +--- + +update the link /genai to /ailogic diff --git a/packages/ai/src/requests/request.ts b/packages/ai/src/requests/request.ts index 7664765ab0..cfd5a180ca 100644 --- a/packages/ai/src/requests/request.ts +++ b/packages/ai/src/requests/request.ts @@ -226,7 +226,7 @@ export async function makeRequest( `The Firebase AI SDK requires the Firebase AI ` + `API ('firebasevertexai.googleapis.com') to be enabled in your ` + `Firebase project. Enable this API by visiting the Firebase Console ` + - `at https://console.firebase.google.com/project/${url.params.apiSettings.project}/genai/ ` + + `at https://console.firebase.google.com/project/${url.params.apiSettings.project}/ailogic/ ` + `and clicking "Get started". If you enabled this API recently, ` + `wait a few minutes for the action to propagate to our systems and ` + `then retry.`, From 8e26a5590ca1dfb809720f8697429e3894123406 Mon Sep 17 00:00:00 2001 From: Google Open Source Bot Date: Tue, 16 Dec 2025 05:43:50 -0800 Subject: [PATCH 029/174] Version Packages (#9428) Version Packages for v12.6.1 release. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/four-vans-mix.md | 5 ----- .changeset/gentle-queens-argue.md | 5 ----- .changeset/gorgeous-rice-carry.md | 5 ----- .changeset/thin-sheep-smoke.md | 5 ----- integration/compat-interop/package.json | 4 ++-- integration/firestore/package.json | 2 +- integration/messaging/package.json | 2 +- packages/ai/CHANGELOG.md | 8 ++++++++ packages/ai/package.json | 2 +- packages/auth-compat/CHANGELOG.md | 7 +++++++ packages/auth-compat/package.json | 4 ++-- packages/auth/CHANGELOG.md | 6 ++++++ packages/auth/package.json | 2 +- packages/firebase/CHANGELOG.md | 16 ++++++++++++++++ packages/firebase/package.json | 12 ++++++------ packages/firestore-compat/CHANGELOG.md | 7 +++++++ packages/firestore-compat/package.json | 4 ++-- packages/firestore/CHANGELOG.md | 6 ++++++ packages/firestore/package.json | 4 ++-- packages/storage-compat/package.json | 2 +- packages/storage/package.json | 2 +- 21 files changed, 70 insertions(+), 40 deletions(-) delete mode 100644 .changeset/four-vans-mix.md delete mode 100644 .changeset/gentle-queens-argue.md delete mode 100644 .changeset/gorgeous-rice-carry.md delete mode 100644 .changeset/thin-sheep-smoke.md diff --git a/.changeset/four-vans-mix.md b/.changeset/four-vans-mix.md deleted file mode 100644 index e763d0c310..0000000000 --- a/.changeset/four-vans-mix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/auth': minor ---- - -Upgraded react-native-async-storage peerDependency to v2+. diff --git a/.changeset/gentle-queens-argue.md b/.changeset/gentle-queens-argue.md deleted file mode 100644 index d14ec3d16a..0000000000 --- a/.changeset/gentle-queens-argue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/ai': patch ---- - -update the link /genai to /ailogic diff --git a/.changeset/gorgeous-rice-carry.md b/.changeset/gorgeous-rice-carry.md deleted file mode 100644 index 80d58cede5..0000000000 --- a/.changeset/gorgeous-rice-carry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/ai': patch ---- - -Fix `generateContentStream` returning wrong `inferenceSource`. diff --git a/.changeset/thin-sheep-smoke.md b/.changeset/thin-sheep-smoke.md deleted file mode 100644 index 83af71b0d0..0000000000 --- a/.changeset/thin-sheep-smoke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/firestore': patch ---- - -Fix: Corrected misleading error message when doc() is called with undefined. diff --git a/integration/compat-interop/package.json b/integration/compat-interop/package.json index 0703401f09..070857d141 100644 --- a/integration/compat-interop/package.json +++ b/integration/compat-interop/package.json @@ -12,8 +12,8 @@ "@firebase/app-compat": "0.5.6", "@firebase/analytics": "0.10.19", "@firebase/analytics-compat": "0.2.25", - "@firebase/auth": "1.11.1", - "@firebase/auth-compat": "0.6.1", + "@firebase/auth": "1.12.0", + "@firebase/auth-compat": "0.6.2", "@firebase/functions": "0.13.1", "@firebase/functions-compat": "0.4.1", "@firebase/messaging": "0.12.23", diff --git a/integration/firestore/package.json b/integration/firestore/package.json index b65148c5f5..97fd26e548 100644 --- a/integration/firestore/package.json +++ b/integration/firestore/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@firebase/app": "0.14.6", - "@firebase/firestore": "4.9.2" + "@firebase/firestore": "4.9.3" }, "devDependencies": { "@types/mocha": "9.1.1", diff --git a/integration/messaging/package.json b/integration/messaging/package.json index 0e4b008ee8..e1dec05ea2 100644 --- a/integration/messaging/package.json +++ b/integration/messaging/package.json @@ -9,7 +9,7 @@ "test:manual": "mocha --exit" }, "devDependencies": { - "firebase": "12.6.0", + "firebase": "12.7.0", "chai": "4.5.0", "chromedriver": "119.0.1", "express": "4.21.2", diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 08dd565f62..f70be3e194 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,5 +1,13 @@ # @firebase/ai +## 2.6.1 + +### Patch Changes + +- [`bc2b2cd`](https://github.com/firebase/firebase-js-sdk/commit/bc2b2cdeae920ff22aca3414c2a1b79d4a3b1351) [#9399](https://github.com/firebase/firebase-js-sdk/pull/9399) - update the link /genai to /ailogic + +- [`5c7430d`](https://github.com/firebase/firebase-js-sdk/commit/5c7430deabb20ddce2a26ea9a565323d2a0f612e) [#9381](https://github.com/firebase/firebase-js-sdk/pull/9381) - Fix `generateContentStream` returning wrong `inferenceSource`. + ## 2.6.0 ### Minor Changes diff --git a/packages/ai/package.json b/packages/ai/package.json index b7b690ea59..d75b9fe721 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/ai", - "version": "2.6.0", + "version": "2.6.1", "description": "The Firebase AI SDK", "author": "Firebase (https://firebase.google.com/)", "engines": { diff --git a/packages/auth-compat/CHANGELOG.md b/packages/auth-compat/CHANGELOG.md index c8024cbe85..775c77b9af 100644 --- a/packages/auth-compat/CHANGELOG.md +++ b/packages/auth-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/auth-compat +## 0.6.2 + +### Patch Changes + +- Updated dependencies [[`1e406a2`](https://github.com/firebase/firebase-js-sdk/commit/1e406a2b7140b014edac26f0e5179878bb3d821f)]: + - @firebase/auth@1.12.0 + ## 0.6.1 ### Patch Changes diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index 507676b0b1..6af8c73273 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth-compat", - "version": "0.6.1", + "version": "0.6.2", "description": "FirebaseAuth compatibility package that uses API style compatible with Firebase@8 and prior versions", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -49,7 +49,7 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/auth": "1.11.1", + "@firebase/auth": "1.12.0", "@firebase/auth-types": "0.13.0", "@firebase/component": "0.7.0", "@firebase/util": "1.13.0", diff --git a/packages/auth/CHANGELOG.md b/packages/auth/CHANGELOG.md index 298371600d..b19ebe3154 100644 --- a/packages/auth/CHANGELOG.md +++ b/packages/auth/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/auth +## 1.12.0 + +### Minor Changes + +- [`1e406a2`](https://github.com/firebase/firebase-js-sdk/commit/1e406a2b7140b014edac26f0e5179878bb3d821f) [#9410](https://github.com/firebase/firebase-js-sdk/pull/9410) - Upgraded react-native-async-storage peerDependency to v2+. + ## 1.11.1 ### Patch Changes diff --git a/packages/auth/package.json b/packages/auth/package.json index d4f1ce69c0..03a6426070 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth", - "version": "1.11.1", + "version": "1.12.0", "description": "The Firebase Authenticaton component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/node/index.js", diff --git a/packages/firebase/CHANGELOG.md b/packages/firebase/CHANGELOG.md index 42b95f095d..f1374cf1e9 100644 --- a/packages/firebase/CHANGELOG.md +++ b/packages/firebase/CHANGELOG.md @@ -1,5 +1,21 @@ # firebase +## 12.7.0 + +### Minor Changes + +- Update root "firebase" package as a "minor" release due to bumps in: + @firebase/auth. + +### Patch Changes + +- Updated dependencies [[`1e406a2`](https://github.com/firebase/firebase-js-sdk/commit/1e406a2b7140b014edac26f0e5179878bb3d821f), [`bc2b2cd`](https://github.com/firebase/firebase-js-sdk/commit/bc2b2cdeae920ff22aca3414c2a1b79d4a3b1351), [`5c7430d`](https://github.com/firebase/firebase-js-sdk/commit/5c7430deabb20ddce2a26ea9a565323d2a0f612e), [`5940794`](https://github.com/firebase/firebase-js-sdk/commit/59407948daf848fea069b776a55bef62bbcd602f)]: + - @firebase/auth@1.12.0 + - @firebase/ai@2.6.1 + - @firebase/firestore@4.9.3 + - @firebase/auth-compat@0.6.2 + - @firebase/firestore-compat@0.4.3 + ## 12.6.0 ### Minor Changes diff --git a/packages/firebase/package.json b/packages/firebase/package.json index 69ca37b633..c71928a0ef 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -1,6 +1,6 @@ { "name": "firebase", - "version": "12.6.0", + "version": "12.7.0", "description": "Firebase JavaScript library for web and Node.js", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -399,17 +399,17 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/ai": "2.6.0", + "@firebase/ai": "2.6.1", "@firebase/app": "0.14.6", "@firebase/app-compat": "0.5.6", "@firebase/app-types": "0.9.3", - "@firebase/auth": "1.11.1", - "@firebase/auth-compat": "0.6.1", + "@firebase/auth": "1.12.0", + "@firebase/auth-compat": "0.6.2", "@firebase/data-connect": "0.3.12", "@firebase/database": "1.1.0", "@firebase/database-compat": "2.1.0", - "@firebase/firestore": "4.9.2", - "@firebase/firestore-compat": "0.4.2", + "@firebase/firestore": "4.9.3", + "@firebase/firestore-compat": "0.4.3", "@firebase/functions": "0.13.1", "@firebase/functions-compat": "0.4.1", "@firebase/installations": "0.6.19", diff --git a/packages/firestore-compat/CHANGELOG.md b/packages/firestore-compat/CHANGELOG.md index e5a1aa19d6..90a42aeb7f 100644 --- a/packages/firestore-compat/CHANGELOG.md +++ b/packages/firestore-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/firestore-compat +## 0.4.3 + +### Patch Changes + +- Updated dependencies [[`5940794`](https://github.com/firebase/firebase-js-sdk/commit/59407948daf848fea069b776a55bef62bbcd602f)]: + - @firebase/firestore@4.9.3 + ## 0.4.2 ### Patch Changes diff --git a/packages/firestore-compat/package.json b/packages/firestore-compat/package.json index 26c64617b9..492998f200 100644 --- a/packages/firestore-compat/package.json +++ b/packages/firestore-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore-compat", - "version": "0.4.2", + "version": "0.4.3", "description": "The Cloud Firestore component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -47,7 +47,7 @@ }, "dependencies": { "@firebase/component": "0.7.0", - "@firebase/firestore": "4.9.2", + "@firebase/firestore": "4.9.3", "@firebase/util": "1.13.0", "@firebase/firestore-types": "3.0.3", "tslib": "^2.1.0" diff --git a/packages/firestore/CHANGELOG.md b/packages/firestore/CHANGELOG.md index b3d1f6d462..8330a62eef 100644 --- a/packages/firestore/CHANGELOG.md +++ b/packages/firestore/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/firestore +## 4.9.3 + +### Patch Changes + +- [`5940794`](https://github.com/firebase/firebase-js-sdk/commit/59407948daf848fea069b776a55bef62bbcd602f) [#9386](https://github.com/firebase/firebase-js-sdk/pull/9386) (fixes [#9378](https://github.com/firebase/firebase-js-sdk/issues/9378)) - Fix: Corrected misleading error message when doc() is called with undefined. + ## 4.9.2 ### Patch Changes diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 6c3a2eefaa..a421f06687 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore", - "version": "4.9.2", + "version": "4.9.3", "engines": { "node": ">=20.0.0" }, @@ -114,7 +114,7 @@ "devDependencies": { "@firebase/app": "0.14.6", "@firebase/app-compat": "0.5.6", - "@firebase/auth": "1.11.1", + "@firebase/auth": "1.12.0", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", "@types/eslint": "7.29.0", diff --git a/packages/storage-compat/package.json b/packages/storage-compat/package.json index c20456e6f9..762c193638 100644 --- a/packages/storage-compat/package.json +++ b/packages/storage-compat/package.json @@ -45,7 +45,7 @@ }, "devDependencies": { "@firebase/app-compat": "0.5.6", - "@firebase/auth-compat": "0.6.1", + "@firebase/auth-compat": "0.6.2", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/storage/package.json b/packages/storage/package.json index 6e7a4db769..f8061e76e1 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -55,7 +55,7 @@ }, "devDependencies": { "@firebase/app": "0.14.6", - "@firebase/auth": "1.11.1", + "@firebase/auth": "1.12.0", "rollup": "2.79.2", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", From 9cf4b7e35d73c5ae03bbee3e016970af0982ccdf Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 5 Jan 2026 12:18:52 -0800 Subject: [PATCH 030/174] test(ai): Update LiveAPI model names in integration tests (#9420) --- packages/ai/integration/constants.ts | 17 ++++- packages/ai/integration/live.test.ts | 100 ++++++++++++++++++--------- 2 files changed, 80 insertions(+), 37 deletions(-) diff --git a/packages/ai/integration/constants.ts b/packages/ai/integration/constants.ts index 64c20f8b2e..2c942e44f8 100644 --- a/packages/ai/integration/constants.ts +++ b/packages/ai/integration/constants.ts @@ -47,6 +47,14 @@ const backends: readonly Backend[] = [ new VertexAIBackend('global') ]; +/** + * Vertex Live API only works on us-central1 at the moment. + */ +const liveBackends: readonly Backend[] = [ + new GoogleAIBackend(), + new VertexAIBackend('us-central1') +]; + const backendNames: Map = new Map([ [BackendType.GOOGLE_AI, 'Google AI'], [BackendType.VERTEX_AI, 'Vertex AI'] @@ -63,8 +71,11 @@ const modelNames: readonly string[] = [ // The Live API requires a different set of models, and they're different for each backend. const liveModelNames: Map = new Map([ - [BackendType.GOOGLE_AI, ['gemini-live-2.5-flash-preview']], - [BackendType.VERTEX_AI, ['gemini-2.0-flash-live-preview-04-09']] + [BackendType.GOOGLE_AI, ['gemini-2.5-flash-native-audio-preview-09-2025']], + [ + BackendType.VERTEX_AI, + ['gemini-live-2.5-flash-preview-native-audio-09-2025'] + ] ]); /** @@ -85,7 +96,7 @@ export const testConfigs: readonly TestConfig[] = backends.flatMap(backend => { /** * Test configurations used for the Live API integration tests. */ -export const liveTestConfigs: readonly TestConfig[] = backends.flatMap( +export const liveTestConfigs: readonly TestConfig[] = liveBackends.flatMap( backend => { const testConfigs: TestConfig[] = []; liveModelNames.get(backend.backendType)!.forEach(modelName => { diff --git a/packages/ai/integration/live.test.ts b/packages/ai/integration/live.test.ts index 2a35795164..f8237658ee 100644 --- a/packages/ai/integration/live.test.ts +++ b/packages/ai/integration/live.test.ts @@ -28,12 +28,18 @@ import { liveTestConfigs } from './constants'; import { HELLO_AUDIO_PCM_BASE64 } from './sample-data/hello-audio'; // A helper function to consume the generator and collect text parts from one turn. -async function nextTurnText( +async function nextTurnData( stream: AsyncGenerator< LiveServerContent | LiveServerToolCall | LiveServerToolCallCancellation > -): Promise { +): Promise<{ + text: string; + hasAudioData: boolean; + hasThinking: boolean; +}> { let text = ''; + let hasAudioData = false; + let hasThinking = false; // We don't use `for await...of` on the generator, because that would automatically close the generator. // We want to keep the generator open so that we can pass it to this function again to get the // next turn's text. @@ -46,16 +52,31 @@ async function nextTurnText( switch (chunk.type) { case 'serverContent': if (chunk.turnComplete) { - return text; + return { + text, + hasAudioData, + hasThinking + }; } const parts = chunk.modelTurn?.parts; if (parts) { parts.forEach(part => { if (part.text) { + if (part.thought) { + hasThinking = true; + } text += part.text; + } else if (part.inlineData) { + if (part.inlineData.mimeType.startsWith('audio')) { + hasAudioData = true; + } } else { - throw Error(`Expected TextPart but got ${JSON.stringify(part)}`); + throw Error( + `Expected TextPart or InlineDataPart but got ${JSON.stringify( + part + )}` + ); } }); } @@ -67,14 +88,18 @@ async function nextTurnText( result = await stream.next(); } - return text; + return { + text, + hasAudioData, + hasThinking + }; } describe('Live', function () { this.timeout(20000); const textLiveGenerationConfig: LiveGenerationConfig = { - responseModalities: [ResponseModality.TEXT], + responseModalities: [ResponseModality.AUDIO], temperature: 0, topP: 0 }; @@ -89,13 +114,13 @@ describe('Live', function () { }); const session = await model.connect(); - const responsePromise = nextTurnText(session.receive()); + const responsePromise = nextTurnData(session.receive()); await session.send( 'Where is Google headquarters located? Answer with the city name only.' ); - const responseText = await responsePromise; - expect(responseText).to.exist; - expect(responseText).to.include('Mountain View'); + const responseData = await responsePromise; + expect(responseData).to.exist; + expect(responseData.hasAudioData).to.be.true; await session.close(); }); it('should handle multiple messages in a session', async () => { @@ -110,24 +135,25 @@ describe('Live', function () { 'Where is Google headquarters located? Answer with the city name only.' ); - const responsePromise1 = nextTurnText(generator); - const responseText1 = await responsePromise1; // Wait for the turn to complete - expect(responseText1).to.include('Mountain View'); + const responsePromise1 = nextTurnData(generator); + const responseData1 = await responsePromise1; // Wait for the turn to complete + expect(responseData1.hasAudioData).to.be.true; await session.send( 'What state is that in? Answer with the state name only.' ); - const responsePromise2 = nextTurnText(generator); - const responseText2 = await responsePromise2; // Wait for the second turn to complete - expect(responseText2).to.include('California'); + const responsePromise2 = nextTurnData(generator); + const responseData2 = await responsePromise2; // Wait for the second turn to complete + expect(responseData2.hasAudioData).to.be.true; await session.close(); }); it('close() should be idempotent and terminate the stream', async () => { const model = getLiveGenerativeModel(testConfig.ai, { - model: testConfig.model + model: testConfig.model, + generationConfig: textLiveGenerationConfig }); const session = await model.connect(); const generator = session.receive(); @@ -157,12 +183,12 @@ describe('Live', function () { generationConfig: textLiveGenerationConfig }); const session = await model.connect(); - const responsePromise = nextTurnText(session.receive()); + const responsePromise = nextTurnData(session.receive()); await session.sendTextRealtime('Are you an AI? Yes or No.'); - const responseText = await responsePromise; - expect(responseText).to.include('Yes'); + const responseData = await responsePromise; + expect(responseData.hasAudioData).to.be.true; await session.close(); }); @@ -175,15 +201,15 @@ describe('Live', function () { generationConfig: textLiveGenerationConfig }); const session = await model.connect(); - const responsePromise = nextTurnText(session.receive()); + const responsePromise = nextTurnData(session.receive()); await session.sendAudioRealtime({ data: HELLO_AUDIO_PCM_BASE64, // "Hey, can you hear me?" mimeType: 'audio/pcm' }); - const responseText = await responsePromise; - expect(responseText).to.include('Yes'); + const responseData = await responsePromise; + expect(responseData.hasAudioData).to.be.true; await session.close(); }); @@ -196,7 +222,7 @@ describe('Live', function () { generationConfig: textLiveGenerationConfig }); const session = await model.connect(); - const responsePromise = nextTurnText(session.receive()); + const responsePromise = nextTurnData(session.receive()); await session.sendMediaChunks([ { @@ -205,8 +231,8 @@ describe('Live', function () { } ]); - const responseText = await responsePromise; - expect(responseText).to.include('Yes'); + const responseData = await responsePromise; + expect(responseData.hasAudioData).to.be.true; await session.close(); }); @@ -217,7 +243,7 @@ describe('Live', function () { generationConfig: textLiveGenerationConfig }); const session = await model.connect(); - const responsePromise = nextTurnText(session.receive()); + const responsePromise = nextTurnData(session.receive()); // TODO (dlarocque): Pass two PCM files with different audio, and validate that the model // heard both. @@ -226,8 +252,11 @@ describe('Live', function () { { data: HELLO_AUDIO_PCM_BASE64, mimeType: 'audio/pcm' } ]); - const responseText = await responsePromise; - expect(responseText).to.include('Yes'); + const responseData = await responsePromise; + // Sometimes it responds with only thinking. Developer API may + // have trouble handling the double audio? + expect(responseData.hasAudioData || responseData.hasThinking).to.be + .true; await session.close(); }); @@ -240,7 +269,7 @@ describe('Live', function () { generationConfig: textLiveGenerationConfig }); const session = await model.connect(); - const responsePromise = nextTurnText(session.receive()); + const responsePromise = nextTurnData(session.receive()); // TODO (dlarocque): Pass two PCM files with different audio, and validate that the model // heard both. @@ -259,8 +288,11 @@ describe('Live', function () { }); await session.sendMediaStream(testStream); - const responseText = await responsePromise; - expect(responseText).to.include('Yes'); + const responseData = await responsePromise; + // Sometimes it responds with only thinking. Developer API may + // have trouble handling the double audio? + expect(responseData.hasAudioData || responseData.hasThinking).to.be + .true; await session.close(); }); @@ -400,8 +432,8 @@ describe('Live', function () { // Send a message that should trigger a function call to fetchWeather await session.send('Whats the weather on June 15, 2025 in Toronto?'); - const finalResponseText = await streamPromise; - expect(finalResponseText).to.include('22'); // Should include the result of our function call + const finalResponseData = await streamPromise; + expect(finalResponseData).to.include('22'); // Should include the result of our function call await session.close(); }); From 8bac8f0b2861ca192f07d9f4e5826709a77a9c63 Mon Sep 17 00:00:00 2001 From: Aman Raj Date: Wed, 7 Jan 2026 23:41:13 +0530 Subject: [PATCH 031/174] fix(ai): correct typo 'seperate' to 'separate' in imagen internal types (#9438) Fixes #9437. - Fixed spelling error in comment at line 79 - Changed 'seperate' to 'separate' in packages/ai/src/types/imagen/internal.ts --- packages/ai/src/types/imagen/internal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ai/src/types/imagen/internal.ts b/packages/ai/src/types/imagen/internal.ts index 1a34eb18f5..24f0553ebf 100644 --- a/packages/ai/src/types/imagen/internal.ts +++ b/packages/ai/src/types/imagen/internal.ts @@ -76,7 +76,7 @@ export interface ImagenResponseInternal { * The parameters to be sent in the request body of the HTTP call * to the Vertex AI backend. * - * We need a seperate internal-only interface for this because the REST + * We need a separate internal-only interface for this because the REST * API expects different parameter names than what we show to our users. * * Sample request body JSON: From 83e686478cea10c707909369dcf590cb09c59ef7 Mon Sep 17 00:00:00 2001 From: Mark Duckworth <1124037+MarkDuckworth@users.noreply.github.com> Date: Thu, 8 Jan 2026 02:05:34 +0000 Subject: [PATCH 032/174] feat/pipelines to main (#9356) --- .changeset/big-pipeline-release.md | 6 + .../firestore-lite-pipelines.api.md | 1316 +++ common/api-review/firestore-pipelines.api.md | 1353 +++ docs-devsite/_toc.yaml | 124 + docs-devsite/firestore.md | 2 + ...estore_lite_pipelines.aggregatefunction.md | 109 + ...restore_lite_pipelines.aliasedaggregate.md | 78 + ...estore_lite_pipelines.aliasedexpression.md | 102 + ...estore_lite_pipelines.booleanexpression.md | 274 + .../firestore_lite_pipelines.bytes.md | 177 + ...tore_lite_pipelines.collectionreference.md | 121 + .../firestore_lite_pipelines.documentdata.md | 19 + ...estore_lite_pipelines.documentreference.md | 207 + ...restore_lite_pipelines.documentsnapshot.md | 125 + .../firestore_lite_pipelines.expression.md | 4173 +++++++ .../firestore_lite_pipelines.field.md | 103 + .../firestore_lite_pipelines.fieldpath.md | 72 + .../firestore_lite_pipelines.fieldvalue.md | 46 + .../firestore_lite_pipelines.firestore.md | 68 + ...e_lite_pipelines.firestoredataconverter.md | 261 + ...store_lite_pipelines.functionexpression.md | 90 + .../firestore_lite_pipelines.geopoint.md | 143 + docs-devsite/firestore_lite_pipelines.md | 9839 ++++++++++++++++ .../firestore_lite_pipelines.ordering.md | 80 + .../firestore_lite_pipelines.pipeline.md | 1560 +++ ...firestore_lite_pipelines.pipelineresult.md | 168 + ...restore_lite_pipelines.pipelinesnapshot.md | 103 + ...firestore_lite_pipelines.pipelinesource.md | 251 + .../firestore_lite_pipelines.query.md | 125 + ...re_lite_pipelines.querydocumentsnapshot.md | 45 + .../firestore_lite_pipelines.selectable.md | 39 + .../firestore_lite_pipelines.stageoptions.md | 51 + .../firestore_lite_pipelines.timestamp.md | 265 + .../firestore_lite_pipelines.vectorvalue.md | 101 + .../firestore_pipelines.aggregatefunction.md | 109 + .../firestore_pipelines.aliasedaggregate.md | 78 + .../firestore_pipelines.aliasedexpression.md | 102 + .../firestore_pipelines.booleanexpression.md | 274 + docs-devsite/firestore_pipelines.bytes.md | 177 + ...firestore_pipelines.collectionreference.md | 121 + .../firestore_pipelines.documentdata.md | 19 + .../firestore_pipelines.documentreference.md | 207 + .../firestore_pipelines.documentsnapshot.md | 162 + .../firestore_pipelines.expression.md | 4173 +++++++ docs-devsite/firestore_pipelines.field.md | 103 + docs-devsite/firestore_pipelines.fieldpath.md | 72 + .../firestore_pipelines.fieldvalue.md | 46 + docs-devsite/firestore_pipelines.firestore.md | 68 + ...estore_pipelines.firestoredataconverter.md | 264 + .../firestore_pipelines.functionexpression.md | 90 + docs-devsite/firestore_pipelines.geopoint.md | 143 + docs-devsite/firestore_pipelines.md | 9899 +++++++++++++++++ docs-devsite/firestore_pipelines.ordering.md | 80 + docs-devsite/firestore_pipelines.pipeline.md | 674 ++ ...estore_pipelines.pipelineexecuteoptions.md | 132 + .../firestore_pipelines.pipelineresult.md | 168 + .../firestore_pipelines.pipelinesnapshot.md | 103 + .../firestore_pipelines.pipelinesource.md | 251 + docs-devsite/firestore_pipelines.query.md | 125 + ...restore_pipelines.querydocumentsnapshot.md | 54 + .../firestore_pipelines.selectable.md | 39 + .../firestore_pipelines.snapshotmetadata.md | 75 + .../firestore_pipelines.snapshotoptions.md | 41 + .../firestore_pipelines.stageoptions.md | 51 + docs-devsite/firestore_pipelines.timestamp.md | 265 + .../firestore_pipelines.vectorvalue.md | 101 + integration/firestore/gulpfile.js | 13 +- integration/firestore/package.json | 7 +- integration/firestore/pipeline_export.ts | 21 + package.json | 1 + .../firestore/lite/pipelines/index.ts | 18 + .../firestore/lite/pipelines/package.json | 7 + packages/firebase/firestore/package.json | 2 +- .../firebase/firestore/pipelines/index.cdn.ts | 21 + .../firebase/firestore/pipelines/index.ts | 18 + .../firebase/firestore/pipelines/package.json | 7 + packages/firebase/gulpfile.js | 2 +- packages/firebase/package.json | 26 + packages/firebase/rollup.config.js | 7 +- packages/firestore/.eslintrc.js | 2 +- packages/firestore/api-extractor.json | 20 +- packages/firestore/externs.json | 2 + .../firestore/lite/pipelines/package.json | 14 + .../firestore/lite/pipelines/pipelines.d.ts | 28 + .../firestore/lite/pipelines/pipelines.ts | 194 + packages/firestore/package.json | 39 +- packages/firestore/pipelines/package.json | 14 + packages/firestore/pipelines/pipelines.d.ts | 28 + .../firestore/pipelines/pipelines.node.ts | 18 + packages/firestore/pipelines/pipelines.rn.ts | 18 + packages/firestore/pipelines/pipelines.ts | 51 + packages/firestore/rollup.config.js | 63 +- packages/firestore/rollup.config.lite.js | 54 +- packages/firestore/src/api/aggregate.ts | 10 +- packages/firestore/src/api/database.ts | 1 + packages/firestore/src/api/parse_context.ts | 45 + packages/firestore/src/api/pipeline.ts | 47 + packages/firestore/src/api/pipeline_impl.ts | 216 + packages/firestore/src/api/reference_impl.ts | 19 +- packages/firestore/src/api/snapshot.ts | 6 +- packages/firestore/src/api/transaction.ts | 2 +- .../firestore/src/api/user_data_writer.ts | 38 + packages/firestore/src/api_pipelines.ts | 165 + packages/firestore/src/core/database_info.ts | 3 +- .../firestore/src/core/firestore_client.ts | 32 +- packages/firestore/src/core/options_util.ts | 95 + packages/firestore/src/core/pipeline-util.ts | 271 + .../firestore/src/core/structured_pipeline.ts | 67 + packages/firestore/src/global.ts | 29 + .../firestore/src/lite-api/aggregate_types.ts | 25 +- packages/firestore/src/lite-api/components.ts | 5 +- .../src/lite-api/database_augmentation.ts | 16 + .../firestore/src/lite-api/expressions.ts | 8183 ++++++++++++++ .../firestore/src/lite-api/pipeline-result.ts | 278 + .../firestore/src/lite-api/pipeline-source.ts | 278 + packages/firestore/src/lite-api/pipeline.ts | 1478 +++ .../firestore/src/lite-api/pipeline_impl.ts | 152 + .../src/lite-api/pipeline_options.ts | 83 + packages/firestore/src/lite-api/query.ts | 3 +- packages/firestore/src/lite-api/reference.ts | 6 + packages/firestore/src/lite-api/snapshot.ts | 39 +- packages/firestore/src/lite-api/stage.ts | 764 ++ .../firestore/src/lite-api/stage_options.ts | 345 + .../src/lite-api/user_data_reader.ts | 70 +- .../src/model/pipeline_stream_element.ts | 30 + .../platform/browser/webchannel_connection.ts | 115 +- .../src/platform/node/grpc_connection.ts | 18 +- .../src/platform/rn_lite/snapshot_to_json.ts | 7 + packages/firestore/src/protos/compile.sh | 15 +- .../src/protos/firestore_proto_api.ts | 92 +- .../protos/google/firestore/v1/document.proto | 112 + .../google/firestore/v1/firestore.proto | 88 +- .../protos/google/firestore/v1/pipeline.proto | 41 + .../google/firestore/v1/query_profile.proto | 92 + packages/firestore/src/protos/protos.json | 854 +- packages/firestore/src/remote/datastore.ts | 44 +- .../src/remote/internal_serializer.ts | 48 +- .../firestore/src/remote/rest_connection.ts | 11 +- packages/firestore/src/remote/serializer.ts | 137 +- .../firestore/src/util/input_validation.ts | 3 +- packages/firestore/src/util/misc.ts | 20 + packages/firestore/src/util/obj.ts | 2 +- packages/firestore/src/util/pipeline_util.ts | 156 + packages/firestore/src/util/proto.ts | 155 + packages/firestore/src/util/types.ts | 24 + .../test/integration/api/aggregation.test.ts | 132 +- .../integration/api/array_transforms.test.ts | 4 +- .../test/integration/api/bundle.test.ts | 1 + .../api/composite_index_query.test.ts | 183 +- .../test/integration/api/database.test.ts | 180 +- .../test/integration/api/pipeline.test.ts | 4346 ++++++++ .../test/integration/api/provider.test.ts | 23 +- .../test/integration/api/query.test.ts | 437 +- .../integration/api/query_to_pipeline.test.ts | 817 ++ .../integration/api_internal/console.test.ts | 69 + .../integration/api_internal/pipeline.test.ts | 200 + .../integration/api_internal/query.test.ts | 467 + .../util/composite_index_test_helper.ts | 2 + .../test/integration/util/helpers.ts | 20 +- .../test/integration/util/internal_helpers.ts | 3 +- .../test/integration/util/pipeline_export.ts | 23 + .../integration/util/testing_hooks_util.ts | 2 + .../firestore/test/lite/integration.test.ts | 81 +- packages/firestore/test/lite/pipeline.test.ts | 4140 +++++++ .../firestore/test/lite/pipeline_export.ts | 24 + .../test/unit/api/document_change.test.ts | 2 +- .../test/unit/api/pipeline_impl.test.ts | 202 + .../test/unit/core/options_util.test.ts | 224 + .../unit/core/structured_pipeline.test.ts | 187 + .../test/unit/remote/fetch_connection.test.ts | 1 + .../unit/remote/grpc_connection.node.test.ts | 81 + .../test/unit/remote/rest_connection.test.ts | 5 +- .../test/unit/remote/serializer.helper.ts | 2 +- .../web_channel_connection.browser.test.ts | 70 + .../firestore/test/unit/specs/spec_builder.ts | 2 +- .../test/unit/specs/spec_test_runner.ts | 3 +- packages/firestore/test/util/api_helpers.ts | 2 +- .../firestore/test/util/mocha_extensions.ts | 98 + repo-scripts/prune-dts/extract-public-api.ts | 19 +- repo-scripts/prune-dts/prune-dts.ts | 157 +- .../bundle-definitions/firestore.json | 128 + .../build/rollup_replace_declare_module.js | 141 + scripts/size_report/report_binary_size.ts | 2 +- yarn.lock | 251 +- 184 files changed, 66938 insertions(+), 1185 deletions(-) create mode 100644 .changeset/big-pipeline-release.md create mode 100644 common/api-review/firestore-lite-pipelines.api.md create mode 100644 common/api-review/firestore-pipelines.api.md create mode 100644 docs-devsite/firestore_lite_pipelines.aggregatefunction.md create mode 100644 docs-devsite/firestore_lite_pipelines.aliasedaggregate.md create mode 100644 docs-devsite/firestore_lite_pipelines.aliasedexpression.md create mode 100644 docs-devsite/firestore_lite_pipelines.booleanexpression.md create mode 100644 docs-devsite/firestore_lite_pipelines.bytes.md create mode 100644 docs-devsite/firestore_lite_pipelines.collectionreference.md create mode 100644 docs-devsite/firestore_lite_pipelines.documentdata.md create mode 100644 docs-devsite/firestore_lite_pipelines.documentreference.md create mode 100644 docs-devsite/firestore_lite_pipelines.documentsnapshot.md create mode 100644 docs-devsite/firestore_lite_pipelines.expression.md create mode 100644 docs-devsite/firestore_lite_pipelines.field.md create mode 100644 docs-devsite/firestore_lite_pipelines.fieldpath.md create mode 100644 docs-devsite/firestore_lite_pipelines.fieldvalue.md create mode 100644 docs-devsite/firestore_lite_pipelines.firestore.md create mode 100644 docs-devsite/firestore_lite_pipelines.firestoredataconverter.md create mode 100644 docs-devsite/firestore_lite_pipelines.functionexpression.md create mode 100644 docs-devsite/firestore_lite_pipelines.geopoint.md create mode 100644 docs-devsite/firestore_lite_pipelines.md create mode 100644 docs-devsite/firestore_lite_pipelines.ordering.md create mode 100644 docs-devsite/firestore_lite_pipelines.pipeline.md create mode 100644 docs-devsite/firestore_lite_pipelines.pipelineresult.md create mode 100644 docs-devsite/firestore_lite_pipelines.pipelinesnapshot.md create mode 100644 docs-devsite/firestore_lite_pipelines.pipelinesource.md create mode 100644 docs-devsite/firestore_lite_pipelines.query.md create mode 100644 docs-devsite/firestore_lite_pipelines.querydocumentsnapshot.md create mode 100644 docs-devsite/firestore_lite_pipelines.selectable.md create mode 100644 docs-devsite/firestore_lite_pipelines.stageoptions.md create mode 100644 docs-devsite/firestore_lite_pipelines.timestamp.md create mode 100644 docs-devsite/firestore_lite_pipelines.vectorvalue.md create mode 100644 docs-devsite/firestore_pipelines.aggregatefunction.md create mode 100644 docs-devsite/firestore_pipelines.aliasedaggregate.md create mode 100644 docs-devsite/firestore_pipelines.aliasedexpression.md create mode 100644 docs-devsite/firestore_pipelines.booleanexpression.md create mode 100644 docs-devsite/firestore_pipelines.bytes.md create mode 100644 docs-devsite/firestore_pipelines.collectionreference.md create mode 100644 docs-devsite/firestore_pipelines.documentdata.md create mode 100644 docs-devsite/firestore_pipelines.documentreference.md create mode 100644 docs-devsite/firestore_pipelines.documentsnapshot.md create mode 100644 docs-devsite/firestore_pipelines.expression.md create mode 100644 docs-devsite/firestore_pipelines.field.md create mode 100644 docs-devsite/firestore_pipelines.fieldpath.md create mode 100644 docs-devsite/firestore_pipelines.fieldvalue.md create mode 100644 docs-devsite/firestore_pipelines.firestore.md create mode 100644 docs-devsite/firestore_pipelines.firestoredataconverter.md create mode 100644 docs-devsite/firestore_pipelines.functionexpression.md create mode 100644 docs-devsite/firestore_pipelines.geopoint.md create mode 100644 docs-devsite/firestore_pipelines.md create mode 100644 docs-devsite/firestore_pipelines.ordering.md create mode 100644 docs-devsite/firestore_pipelines.pipeline.md create mode 100644 docs-devsite/firestore_pipelines.pipelineexecuteoptions.md create mode 100644 docs-devsite/firestore_pipelines.pipelineresult.md create mode 100644 docs-devsite/firestore_pipelines.pipelinesnapshot.md create mode 100644 docs-devsite/firestore_pipelines.pipelinesource.md create mode 100644 docs-devsite/firestore_pipelines.query.md create mode 100644 docs-devsite/firestore_pipelines.querydocumentsnapshot.md create mode 100644 docs-devsite/firestore_pipelines.selectable.md create mode 100644 docs-devsite/firestore_pipelines.snapshotmetadata.md create mode 100644 docs-devsite/firestore_pipelines.snapshotoptions.md create mode 100644 docs-devsite/firestore_pipelines.stageoptions.md create mode 100644 docs-devsite/firestore_pipelines.timestamp.md create mode 100644 docs-devsite/firestore_pipelines.vectorvalue.md create mode 100644 integration/firestore/pipeline_export.ts create mode 100644 packages/firebase/firestore/lite/pipelines/index.ts create mode 100644 packages/firebase/firestore/lite/pipelines/package.json create mode 100644 packages/firebase/firestore/pipelines/index.cdn.ts create mode 100644 packages/firebase/firestore/pipelines/index.ts create mode 100644 packages/firebase/firestore/pipelines/package.json create mode 100644 packages/firestore/lite/pipelines/package.json create mode 100644 packages/firestore/lite/pipelines/pipelines.d.ts create mode 100644 packages/firestore/lite/pipelines/pipelines.ts create mode 100644 packages/firestore/pipelines/package.json create mode 100644 packages/firestore/pipelines/pipelines.d.ts create mode 100644 packages/firestore/pipelines/pipelines.node.ts create mode 100644 packages/firestore/pipelines/pipelines.rn.ts create mode 100644 packages/firestore/pipelines/pipelines.ts create mode 100644 packages/firestore/src/api/pipeline.ts create mode 100644 packages/firestore/src/api/pipeline_impl.ts create mode 100644 packages/firestore/src/api/user_data_writer.ts create mode 100644 packages/firestore/src/api_pipelines.ts create mode 100644 packages/firestore/src/core/options_util.ts create mode 100644 packages/firestore/src/core/pipeline-util.ts create mode 100644 packages/firestore/src/core/structured_pipeline.ts create mode 100644 packages/firestore/src/global.ts create mode 100644 packages/firestore/src/lite-api/database_augmentation.ts create mode 100644 packages/firestore/src/lite-api/expressions.ts create mode 100644 packages/firestore/src/lite-api/pipeline-result.ts create mode 100644 packages/firestore/src/lite-api/pipeline-source.ts create mode 100644 packages/firestore/src/lite-api/pipeline.ts create mode 100644 packages/firestore/src/lite-api/pipeline_impl.ts create mode 100644 packages/firestore/src/lite-api/pipeline_options.ts create mode 100644 packages/firestore/src/lite-api/stage.ts create mode 100644 packages/firestore/src/lite-api/stage_options.ts create mode 100644 packages/firestore/src/model/pipeline_stream_element.ts create mode 100644 packages/firestore/src/protos/google/firestore/v1/pipeline.proto create mode 100644 packages/firestore/src/protos/google/firestore/v1/query_profile.proto create mode 100644 packages/firestore/src/util/pipeline_util.ts create mode 100644 packages/firestore/src/util/proto.ts create mode 100644 packages/firestore/test/integration/api/pipeline.test.ts create mode 100644 packages/firestore/test/integration/api/query_to_pipeline.test.ts create mode 100644 packages/firestore/test/integration/api_internal/console.test.ts create mode 100644 packages/firestore/test/integration/api_internal/pipeline.test.ts create mode 100644 packages/firestore/test/integration/api_internal/query.test.ts create mode 100644 packages/firestore/test/integration/util/pipeline_export.ts create mode 100644 packages/firestore/test/lite/pipeline.test.ts create mode 100644 packages/firestore/test/lite/pipeline_export.ts create mode 100644 packages/firestore/test/unit/api/pipeline_impl.test.ts create mode 100644 packages/firestore/test/unit/core/options_util.test.ts create mode 100644 packages/firestore/test/unit/core/structured_pipeline.test.ts create mode 100644 packages/firestore/test/unit/remote/grpc_connection.node.test.ts create mode 100644 packages/firestore/test/unit/remote/web_channel_connection.browser.test.ts create mode 100644 packages/firestore/test/util/mocha_extensions.ts create mode 100644 scripts/build/rollup_replace_declare_module.js diff --git a/.changeset/big-pipeline-release.md b/.changeset/big-pipeline-release.md new file mode 100644 index 0000000000..de771854a3 --- /dev/null +++ b/.changeset/big-pipeline-release.md @@ -0,0 +1,6 @@ +--- +'@firebase/firestore': minor +'firebase': minor +--- + +Release Firestore Pipelines for Enterprise edition in public preview. diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md new file mode 100644 index 0000000000..b19de978f9 --- /dev/null +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -0,0 +1,1316 @@ +## API Report File for "@firebase/firestore-lite-pipelines" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { FirebaseApp } from '@firebase/app'; + +// @beta +export function abs(expr: Expression): FunctionExpression; + +// @beta +export function abs(fieldName: string): FunctionExpression; + +// @beta +export function add(first: Expression, second: Expression | unknown): FunctionExpression; + +// @beta +export function add(fieldName: string, second: Expression | unknown): FunctionExpression; + +// @beta +export type AddFieldsStageOptions = StageOptions & { + fields: Selectable[]; +}; + +// @beta +export class AggregateFunction { + constructor(name: string, params: Expression[]); + as(name: string): AliasedAggregate; + // (undocumented) + exprType: ExpressionType; + } + +// @beta +export type AggregateStageOptions = StageOptions & { + accumulators: AliasedAggregate[]; + groups?: Array; +}; + +// @beta +export class AliasedAggregate { + constructor(aggregate: AggregateFunction, alias: string, _methodName: string | undefined); + // (undocumented) + readonly aggregate: AggregateFunction; + // (undocumented) + readonly alias: string; +} + +// @beta (undocumented) +export class AliasedExpression implements Selectable { + constructor(expr: Expression, alias: string, _methodName: string | undefined); + // (undocumented) + readonly alias: string; + // (undocumented) + readonly expr: Expression; + // (undocumented) + exprType: ExpressionType; + // (undocumented) + selectable: true; +} + +// @beta +export function and(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; + +// @beta +export function array(elements: unknown[]): FunctionExpression; + +// @beta +export function arrayConcat(firstArray: Expression, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; + +// @beta +export function arrayConcat(firstArrayField: string, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; + +// @beta +export function arrayContains(array: Expression, element: Expression): BooleanExpression; + +// @beta +export function arrayContains(array: Expression, element: unknown): BooleanExpression; + +// @beta +export function arrayContains(fieldName: string, element: Expression): BooleanExpression; + +// @beta +export function arrayContains(fieldName: string, element: unknown): BooleanExpression; + +// @beta +export function arrayContainsAll(array: Expression, values: Array): BooleanExpression; + +// @beta +export function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; + +// @beta +export function arrayContainsAll(array: Expression, arrayExpression: Expression): BooleanExpression; + +// @beta +export function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; + +// @beta +export function arrayContainsAny(array: Expression, values: Array): BooleanExpression; + +// @beta +export function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; + +// @beta +export function arrayContainsAny(array: Expression, values: Expression): BooleanExpression; + +// @beta +export function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; + +// @beta +export function arrayGet(arrayField: string, offset: number): FunctionExpression; + +// @beta +export function arrayGet(arrayField: string, offsetExpr: Expression): FunctionExpression; + +// @beta +export function arrayGet(arrayExpression: Expression, offset: number): FunctionExpression; + +// @beta +export function arrayGet(arrayExpression: Expression, offsetExpr: Expression): FunctionExpression; + +// @beta +export function arrayLength(fieldName: string): FunctionExpression; + +// @beta +export function arrayLength(array: Expression): FunctionExpression; + +// @beta +export function arraySum(fieldName: string): FunctionExpression; + +// @beta +export function arraySum(expression: Expression): FunctionExpression; + +// @beta +export function ascending(expr: Expression): Ordering; + +// @beta +export function ascending(fieldName: string): Ordering; + +// @beta +export function average(expression: Expression): AggregateFunction; + +// @beta +export function average(fieldName: string): AggregateFunction; + +// @beta +export abstract class BooleanExpression extends Expression { + conditional(thenExpr: Expression, elseExpr: Expression): FunctionExpression; + countIf(): AggregateFunction; + ifError(catchValue: BooleanExpression): BooleanExpression; + ifError(catchValue: boolean): BooleanExpression; + ifError(catchValue: Expression): FunctionExpression; + ifError(catchValue: unknown): FunctionExpression; + not(): BooleanExpression; +} + +// @beta +export function byteLength(expr: Expression): FunctionExpression; + +// @beta +export function byteLength(fieldName: string): FunctionExpression; + +// @beta +export function ceil(fieldName: string): FunctionExpression; + +// @beta +export function ceil(expression: Expression): FunctionExpression; + +// @beta +export function charLength(fieldName: string): FunctionExpression; + +// @beta +export function charLength(stringExpression: Expression): FunctionExpression; + +// @beta +export type CollectionGroupStageOptions = StageOptions & { + collectionId: string; + forceIndex?: string; +}; + +// @beta +export function collectionId(fieldName: string): FunctionExpression; + +// @beta +export function collectionId(expression: Expression): FunctionExpression; + +// @beta +export type CollectionStageOptions = StageOptions & { + collection: string | Query; + forceIndex?: string; +}; + +// @beta +export function concat(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function concat(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function conditional(condition: BooleanExpression, thenExpr: Expression, elseExpr: Expression): FunctionExpression; + +// @beta +export function constant(value: number): Expression; + +// @beta +export function constant(value: string): Expression; + +// @beta +export function constant(value: boolean): BooleanExpression; + +// @beta +export function constant(value: null): Expression; + +// Warning: (ae-forgotten-export) The symbol "GeoPoint" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export function constant(value: GeoPoint): Expression; + +// Warning: (ae-forgotten-export) The symbol "Timestamp" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export function constant(value: Timestamp): Expression; + +// @beta +export function constant(value: Date): Expression; + +// Warning: (ae-forgotten-export) The symbol "Bytes" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export function constant(value: Bytes): Expression; + +// Warning: (ae-forgotten-export) The symbol "DocumentReference" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export function constant(value: DocumentReference): Expression; + +// Warning: (ae-forgotten-export) The symbol "VectorValue" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export function constant(value: VectorValue): Expression; + +// @beta +export function cosineDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; + +// @beta +export function cosineDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; + +// @beta +export function cosineDistance(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; + +// @beta +export function cosineDistance(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; + +// @beta +export function count(expression: Expression): AggregateFunction; + +// @beta +export function count(fieldName: string): AggregateFunction; + +// @beta +export function countAll(): AggregateFunction; + +// @beta +export function countDistinct(expr: Expression | string): AggregateFunction; + +// @beta +export function countIf(booleanExpr: BooleanExpression): AggregateFunction; + +// @beta +export function currentTimestamp(): FunctionExpression; + +// @beta +export type DatabaseStageOptions = StageOptions & {}; + +// @beta +export function descending(expr: Expression): Ordering; + +// @beta +export function descending(fieldName: string): Ordering; + +// @beta +export type DistinctStageOptions = StageOptions & { + groups: Array; +}; + +// @beta +export function divide(left: Expression, right: Expression): FunctionExpression; + +// @beta +export function divide(expression: Expression, value: unknown): FunctionExpression; + +// @beta +export function divide(fieldName: string, expressions: Expression): FunctionExpression; + +// @beta +export function divide(fieldName: string, value: unknown): FunctionExpression; + +// @beta +export function documentId(documentPath: string | DocumentReference): FunctionExpression; + +// @beta +export function documentId(documentPathExpr: Expression): FunctionExpression; + +// @beta +export type DocumentsStageOptions = StageOptions & { + docs: Array; +}; + +// @beta +export function dotProduct(fieldName: string, vector: number[] | VectorValue): FunctionExpression; + +// @beta +export function dotProduct(fieldName: string, vectorExpression: Expression): FunctionExpression; + +// @beta +export function dotProduct(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; + +// @beta +export function dotProduct(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; + +// @beta +export function endsWith(fieldName: string, suffix: string): BooleanExpression; + +// @beta +export function endsWith(fieldName: string, suffix: Expression): BooleanExpression; + +// @beta +export function endsWith(stringExpression: Expression, suffix: string): BooleanExpression; + +// @beta +export function endsWith(stringExpression: Expression, suffix: Expression): BooleanExpression; + +// @beta +export function equal(left: Expression, right: Expression): BooleanExpression; + +// @beta +export function equal(expression: Expression, value: unknown): BooleanExpression; + +// @beta +export function equal(fieldName: string, expression: Expression): BooleanExpression; + +// @beta +export function equal(fieldName: string, value: unknown): BooleanExpression; + +// @beta +export function equalAny(expression: Expression, values: Array): BooleanExpression; + +// @beta +export function equalAny(expression: Expression, arrayExpression: Expression): BooleanExpression; + +// @beta +export function equalAny(fieldName: string, values: Array): BooleanExpression; + +// @beta +export function equalAny(fieldName: string, arrayExpression: Expression): BooleanExpression; + +// @beta +export function euclideanDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; + +// @beta +export function euclideanDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; + +// @beta +export function euclideanDistance(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; + +// @beta +export function euclideanDistance(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; + +// @beta +export function execute(pipeline: Pipeline): Promise; + +// @beta +export function exists(value: Expression): BooleanExpression; + +// @beta +export function exists(fieldName: string): BooleanExpression; + +// @beta +export function exp(expression: Expression): FunctionExpression; + +// @beta +export function exp(fieldName: string): FunctionExpression; + +// @beta +export abstract class Expression { + abs(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + add(second: Expression | unknown): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayConcat(secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayContains(expression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + arrayContains(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + arrayContainsAll(values: Array): BooleanExpression; + /* Excluded from this release type: _readUserData */ + arrayContainsAll(arrayExpression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + arrayContainsAny(values: Array): BooleanExpression; + /* Excluded from this release type: _readUserData */ + arrayContainsAny(arrayExpression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + arrayGet(offset: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayGet(offsetExpr: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayLength(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayReverse(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arraySum(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + as(name: string): AliasedExpression; + /* Excluded from this release type: _readUserData */ + asBoolean(): BooleanExpression; + /* Excluded from this release type: _readUserData */ + ascending(): Ordering; + /* Excluded from this release type: _readUserData */ + average(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + byteLength(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + ceil(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + charLength(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + collectionId(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + concat(second: Expression | unknown, ...others: Array): FunctionExpression; + /* Excluded from this release type: _readUserData */ + cosineDistance(vectorExpression: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + cosineDistance(vector: VectorValue | number[]): FunctionExpression; + /* Excluded from this release type: _readUserData */ + count(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + countDistinct(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + descending(): Ordering; + /* Excluded from this release type: _readUserData */ + divide(divisor: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + divide(divisor: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + documentId(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + dotProduct(vectorExpression: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + dotProduct(vector: VectorValue | number[]): FunctionExpression; + /* Excluded from this release type: _readUserData */ + endsWith(suffix: string): BooleanExpression; + /* Excluded from this release type: _readUserData */ + endsWith(suffix: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + equal(expression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + equal(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + equalAny(values: Array): BooleanExpression; + /* Excluded from this release type: _readUserData */ + equalAny(arrayExpression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + euclideanDistance(vectorExpression: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + euclideanDistance(vector: VectorValue | number[]): FunctionExpression; + /* Excluded from this release type: _readUserData */ + exists(): BooleanExpression; + /* Excluded from this release type: _readUserData */ + exp(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + // (undocumented) + abstract readonly expressionType: ExpressionType; + /* Excluded from this release type: _readUserData */ + floor(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + greaterThan(expression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + greaterThan(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + greaterThanOrEqual(expression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + greaterThanOrEqual(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + ifAbsent(elseValue: unknown): Expression; + /* Excluded from this release type: _readUserData */ + ifAbsent(elseExpression: unknown): Expression; + /* Excluded from this release type: _readUserData */ + ifError(catchExpr: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + ifError(catchValue: unknown): FunctionExpression; + /* Excluded from this release type: _readUserData */ + isAbsent(): BooleanExpression; + /* Excluded from this release type: _readUserData */ + isError(): BooleanExpression; + /* Excluded from this release type: _readUserData */ + join(delimiterExpression: Expression): Expression; + /* Excluded from this release type: _readUserData */ + join(delimiter: string): Expression; + /* Excluded from this release type: _readUserData */ + length(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + lessThan(experession: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + lessThan(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + lessThanOrEqual(expression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + lessThanOrEqual(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + like(pattern: string): BooleanExpression; + /* Excluded from this release type: _readUserData */ + like(pattern: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + ln(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + log10(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + logicalMaximum(second: Expression | unknown, ...others: Array): FunctionExpression; + /* Excluded from this release type: _readUserData */ + logicalMinimum(second: Expression | unknown, ...others: Array): FunctionExpression; + /* Excluded from this release type: _readUserData */ + mapGet(subfield: string): FunctionExpression; + /* Excluded from this release type: _readUserData */ + mapMerge(secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; + /* Excluded from this release type: _readUserData */ + mapRemove(key: string): FunctionExpression; + /* Excluded from this release type: _readUserData */ + mapRemove(keyExpr: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + maximum(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + minimum(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + mod(expression: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + mod(value: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + multiply(second: Expression | number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + notEqual(expression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + notEqual(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + notEqualAny(values: Array): BooleanExpression; + /* Excluded from this release type: _readUserData */ + notEqualAny(arrayExpression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + pow(exponent: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + pow(exponent: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + regexContains(pattern: string): BooleanExpression; + /* Excluded from this release type: _readUserData */ + regexContains(pattern: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + regexMatch(pattern: string): BooleanExpression; + /* Excluded from this release type: _readUserData */ + regexMatch(pattern: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + reverse(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + round(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + round(decimalPlaces: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + round(decimalPlaces: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + split(delimiter: string): FunctionExpression; + /* Excluded from this release type: _readUserData */ + split(delimiter: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + sqrt(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + startsWith(prefix: string): BooleanExpression; + /* Excluded from this release type: _readUserData */ + startsWith(prefix: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + stringConcat(secondString: Expression | string, ...otherStrings: Array): FunctionExpression; + /* Excluded from this release type: _readUserData */ + stringContains(substring: string): BooleanExpression; + /* Excluded from this release type: _readUserData */ + stringContains(expr: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + stringReverse(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + substring(position: number, length?: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + substring(position: Expression, length?: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + subtract(subtrahend: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + subtract(subtrahend: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + sum(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + timestampAdd(unit: Expression, amount: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampAdd(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampSubtract(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampToUnixMicros(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampToUnixMillis(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampToUnixSeconds(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampTruncate(granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampTruncate(granularity: Expression, timezone?: string | Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + toLower(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + toUpper(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + trim(valueToTrim?: string | Expression | Bytes): FunctionExpression; + /* Excluded from this release type: _readUserData */ + type(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + unixMicrosToTimestamp(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + unixMillisToTimestamp(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + unixSecondsToTimestamp(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + vectorLength(): FunctionExpression; +} + +// @beta +export type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression'; + +// @beta +export class Field extends Expression implements Selectable { + // (undocumented) + get alias(): string; + // (undocumented) + get expr(): Expression; + // (undocumented) + readonly expressionType: ExpressionType; + // (undocumented) + get fieldName(): string; + // (undocumented) + selectable: true; +} + +// @beta +export function field(name: string): Field; + +// Warning: (ae-forgotten-export) The symbol "FieldPath" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export function field(path: FieldPath): Field; + +// @beta +export type FindNearestStageOptions = StageOptions & { + field: Field | string; + vectorValue: VectorValue | number[]; + distanceMeasure: 'euclidean' | 'cosine' | 'dot_product'; + limit?: number; + distanceField?: string; +}; + +// @beta +export function floor(expr: Expression): FunctionExpression; + +// @beta +export function floor(fieldName: string): FunctionExpression; + +// @beta +export class FunctionExpression extends Expression { + constructor(name: string, params: Expression[]); + constructor(name: string, params: Expression[], _methodName: string | undefined); + // (undocumented) + readonly expressionType: ExpressionType; + } + +// @beta +export function greaterThan(left: Expression, right: Expression): BooleanExpression; + +// @beta +export function greaterThan(expression: Expression, value: unknown): BooleanExpression; + +// @beta +export function greaterThan(fieldName: string, expression: Expression): BooleanExpression; + +// @beta +export function greaterThan(fieldName: string, value: unknown): BooleanExpression; + +// @beta +export function greaterThanOrEqual(left: Expression, right: Expression): BooleanExpression; + +// @beta +export function greaterThanOrEqual(expression: Expression, value: unknown): BooleanExpression; + +// @beta +export function greaterThanOrEqual(fieldName: string, value: Expression): BooleanExpression; + +// @beta +export function greaterThanOrEqual(fieldName: string, value: unknown): BooleanExpression; + +// @beta +export function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expression; + +// @beta +export function ifAbsent(ifExpr: Expression, elseValue: unknown): Expression; + +// @beta +export function ifAbsent(ifFieldName: string, elseExpr: Expression): Expression; + +// @beta +export function ifAbsent(ifFieldName: string | Expression, elseValue: Expression | unknown): Expression; + +// @beta +export function ifError(tryExpr: BooleanExpression, catchExpr: BooleanExpression): BooleanExpression; + +// @beta +export function ifError(tryExpr: Expression, catchExpr: Expression): FunctionExpression; + +// @beta +export function ifError(tryExpr: Expression, catchValue: unknown): FunctionExpression; + +// @beta +export function isAbsent(value: Expression): BooleanExpression; + +// @beta +export function isAbsent(field: string): BooleanExpression; + +// @beta +export function isError(value: Expression): BooleanExpression; + +// @beta +export function join(arrayFieldName: string, delimiter: string): Expression; + +// @beta +export function join(arrayExpression: Expression, delimiterExpression: Expression): Expression; + +// @beta +export function join(arrayExpression: Expression, delimiter: string): Expression; + +// @beta +export function join(arrayFieldName: string, delimiterExpression: Expression): Expression; + +// @beta +function length_2(fieldName: string): FunctionExpression; + +// @beta +function length_2(expression: Expression): FunctionExpression; + +export { length_2 as length } + +// @beta +export function lessThan(left: Expression, right: Expression): BooleanExpression; + +// @beta +export function lessThan(expression: Expression, value: unknown): BooleanExpression; + +// @beta +export function lessThan(fieldName: string, expression: Expression): BooleanExpression; + +// @beta +export function lessThan(fieldName: string, value: unknown): BooleanExpression; + +// @beta +export function lessThanOrEqual(left: Expression, right: Expression): BooleanExpression; + +// @beta +export function lessThanOrEqual(expression: Expression, value: unknown): BooleanExpression; + +// @beta +export function lessThanOrEqual(fieldName: string, expression: Expression): BooleanExpression; + +// @beta +export function lessThanOrEqual(fieldName: string, value: unknown): BooleanExpression; + +// @beta +export function like(fieldName: string, pattern: string): BooleanExpression; + +// @beta +export function like(fieldName: string, pattern: Expression): BooleanExpression; + +// @beta +export function like(stringExpression: Expression, pattern: string): BooleanExpression; + +// @beta +export function like(stringExpression: Expression, pattern: Expression): BooleanExpression; + +// @beta +export type LimitStageOptions = StageOptions & { + limit: number; +}; + +// @beta +export function ln(fieldName: string): FunctionExpression; + +// @beta +export function ln(expression: Expression): FunctionExpression; + +// @beta +export function log(expression: Expression, base: number): FunctionExpression; + +// @beta +export function log(expression: Expression, base: Expression): FunctionExpression; + +// @beta +export function log(fieldName: string, base: number): FunctionExpression; + +// @beta +export function log(fieldName: string, base: Expression): FunctionExpression; + +// @beta +export function log10(fieldName: string): FunctionExpression; + +// @beta +export function log10(expression: Expression): FunctionExpression; + +// @beta +export function logicalMaximum(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function logicalMaximum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function logicalMinimum(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function logicalMinimum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function map(elements: Record): FunctionExpression; + +// @beta +export function mapGet(fieldName: string, subField: string): FunctionExpression; + +// @beta +export function mapGet(mapExpression: Expression, subField: string): FunctionExpression; + +// @beta +export function mapMerge(mapField: string, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; + +// @beta +export function mapMerge(firstMap: Record | Expression, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; + +// @beta +export function mapRemove(mapField: string, key: string): FunctionExpression; + +// @beta +export function mapRemove(mapExpr: Expression, key: string): FunctionExpression; + +// @beta +export function mapRemove(mapField: string, keyExpr: Expression): FunctionExpression; + +// @beta +export function mapRemove(mapExpr: Expression, keyExpr: Expression): FunctionExpression; + +// @beta +export function maximum(expression: Expression): AggregateFunction; + +// @beta +export function maximum(fieldName: string): AggregateFunction; + +// @beta +export function minimum(expression: Expression): AggregateFunction; + +// @beta +export function minimum(fieldName: string): AggregateFunction; + +// @beta +export function mod(left: Expression, right: Expression): FunctionExpression; + +// @beta +export function mod(expression: Expression, value: unknown): FunctionExpression; + +// @beta +export function mod(fieldName: string, expression: Expression): FunctionExpression; + +// @beta +export function mod(fieldName: string, value: unknown): FunctionExpression; + +// @beta +export function multiply(first: Expression, second: Expression | unknown): FunctionExpression; + +// @beta +export function multiply(fieldName: string, second: Expression | unknown): FunctionExpression; + +// @beta +export function not(booleanExpr: BooleanExpression): BooleanExpression; + +// @beta +export function notEqual(left: Expression, right: Expression): BooleanExpression; + +// @beta +export function notEqual(expression: Expression, value: unknown): BooleanExpression; + +// @beta +export function notEqual(fieldName: string, expression: Expression): BooleanExpression; + +// @beta +export function notEqual(fieldName: string, value: unknown): BooleanExpression; + +// @beta +export function notEqualAny(element: Expression, values: Array): BooleanExpression; + +// @beta +export function notEqualAny(fieldName: string, values: Array): BooleanExpression; + +// @beta +export function notEqualAny(element: Expression, arrayExpression: Expression): BooleanExpression; + +// @beta +export function notEqualAny(fieldName: string, arrayExpression: Expression): BooleanExpression; + +// @beta +export type OffsetStageOptions = StageOptions & { + offset: number; +}; + +// @beta +export type OneOf = { + [K in keyof T]: Pick & { + [P in Exclude]?: undefined; + }; +}[keyof T]; + +// @beta +export function or(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; + +// @beta +export class Ordering { + constructor(expr: Expression, direction: 'ascending' | 'descending', _methodName: string | undefined); + // (undocumented) + readonly direction: 'ascending' | 'descending'; + // (undocumented) + readonly expr: Expression; +} + +// @beta +export class Pipeline { + /* Excluded from this release type: _db */ + /* Excluded from this release type: userDataReader */ + /* Excluded from this release type: _userDataWriter */ + /* Excluded from this release type: stages */ + /* Excluded from this release type: __constructor */ + addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; + addFields(options: AddFieldsStageOptions): Pipeline; + aggregate(accumulator: AliasedAggregate, ...additionalAccumulators: AliasedAggregate[]): Pipeline; + aggregate(options: AggregateStageOptions): Pipeline; + distinct(group: string | Selectable, ...additionalGroups: Array): Pipeline; + distinct(options: DistinctStageOptions): Pipeline; + findNearest(options: FindNearestStageOptions): Pipeline; + limit(limit: number): Pipeline; + limit(options: LimitStageOptions): Pipeline; + offset(offset: number): Pipeline; + offset(options: OffsetStageOptions): Pipeline; + rawStage(name: string, params: unknown[], options?: { + [key: string]: Expression | unknown; + }): Pipeline; + removeFields(fieldValue: Field | string, ...additionalFields: Array): Pipeline; + removeFields(options: RemoveFieldsStageOptions): Pipeline; + replaceWith(fieldName: string): Pipeline; + replaceWith(expr: Expression): Pipeline; + replaceWith(options: ReplaceWithStageOptions): Pipeline; + sample(documents: number): Pipeline; + sample(options: SampleStageOptions): Pipeline; + select(selection: Selectable | string, ...additionalSelections: Array): Pipeline; + select(options: SelectStageOptions): Pipeline; + sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; + sort(options: SortStageOptions): Pipeline; + union(other: Pipeline): Pipeline; + union(options: UnionStageOptions): Pipeline; + unnest(selectable: Selectable, indexField?: string): Pipeline; + unnest(options: UnnestStageOptions): Pipeline; + where(condition: BooleanExpression): Pipeline; + where(options: WhereStageOptions): Pipeline; +} + +// Warning: (ae-forgotten-export) The symbol "DocumentData" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export class PipelineResult { + /* Excluded from this release type: _ref */ + /* Excluded from this release type: _fields */ + /* Excluded from this release type: __constructor */ + get createTime(): Timestamp | undefined; + data(): AppModelType; + get(fieldPath: string | FieldPath | Field): any; + get id(): string | undefined; + get ref(): DocumentReference | undefined; + get updateTime(): Timestamp | undefined; +} + +// @beta +export class PipelineSnapshot { + constructor(pipeline: Pipeline, results: PipelineResult[], executionTime?: Timestamp); + get executionTime(): Timestamp; + get results(): PipelineResult[]; +} + +// @beta +export class PipelineSource { + collection(collection: string | Query): PipelineType; + collection(options: CollectionStageOptions): PipelineType; + collectionGroup(collectionId: string): PipelineType; + collectionGroup(options: CollectionGroupStageOptions): PipelineType; + createFrom(query: Query): Pipeline; + database(): PipelineType; + database(options: DatabaseStageOptions): PipelineType; + documents(docs: Array): PipelineType; + documents(options: DocumentsStageOptions): PipelineType; + } + +// @beta +export function pow(base: Expression, exponent: Expression): FunctionExpression; + +// @beta +export function pow(base: Expression, exponent: number): FunctionExpression; + +// @beta +export function pow(base: string, exponent: Expression): FunctionExpression; + +// @beta +export function pow(base: string, exponent: number): FunctionExpression; + +// @beta +export function regexContains(fieldName: string, pattern: string): BooleanExpression; + +// @beta +export function regexContains(fieldName: string, pattern: Expression): BooleanExpression; + +// @beta +export function regexContains(stringExpression: Expression, pattern: string): BooleanExpression; + +// @beta +export function regexContains(stringExpression: Expression, pattern: Expression): BooleanExpression; + +// @beta +export function regexMatch(fieldName: string, pattern: string): BooleanExpression; + +// @beta +export function regexMatch(fieldName: string, pattern: Expression): BooleanExpression; + +// @beta +export function regexMatch(stringExpression: Expression, pattern: string): BooleanExpression; + +// @beta +export function regexMatch(stringExpression: Expression, pattern: Expression): BooleanExpression; + +// @beta +export type RemoveFieldsStageOptions = StageOptions & { + fields: Array; +}; + +// @beta +export type ReplaceWithStageOptions = StageOptions & { + map: Expression | string; +}; + +// @beta +export function reverse(stringExpression: Expression): FunctionExpression; + +// @beta +export function reverse(field: string): FunctionExpression; + +// @beta +export function round(fieldName: string): FunctionExpression; + +// @beta +export function round(expression: Expression): FunctionExpression; + +// @beta +export function round(fieldName: string, decimalPlaces: number | Expression): FunctionExpression; + +// @beta +export function round(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; + +// @beta +export type SampleStageOptions = StageOptions & OneOf<{ + percentage: number; + documents: number; +}>; + +// @beta +export interface Selectable { + // (undocumented) + selectable: true; +} + +// @beta +export type SelectStageOptions = StageOptions & { + selections: Array; +}; + +// @beta +export type SortStageOptions = StageOptions & { + orderings: Ordering[]; +}; + +// @beta +export function split(fieldName: string, delimiter: string): FunctionExpression; + +// @beta +export function split(fieldName: string, delimiter: Expression): FunctionExpression; + +// @beta +export function split(expression: Expression, delimiter: string): FunctionExpression; + +// @beta +export function split(expression: Expression, delimiter: Expression): FunctionExpression; + +// @beta +export function sqrt(expression: Expression): FunctionExpression; + +// @beta +export function sqrt(fieldName: string): FunctionExpression; + +// @beta +export interface StageOptions { + rawOptions?: { + [name: string]: unknown; + }; +} + +// @beta +export function startsWith(fieldName: string, prefix: string): BooleanExpression; + +// @beta +export function startsWith(fieldName: string, prefix: Expression): BooleanExpression; + +// @beta +export function startsWith(stringExpression: Expression, prefix: string): BooleanExpression; + +// @beta +export function startsWith(stringExpression: Expression, prefix: Expression): BooleanExpression; + +// @beta +export function stringConcat(fieldName: string, secondString: Expression | string, ...otherStrings: Array): FunctionExpression; + +// @beta +export function stringConcat(firstString: Expression, secondString: Expression | string, ...otherStrings: Array): FunctionExpression; + +// @beta +export function stringContains(fieldName: string, substring: string): BooleanExpression; + +// @beta +export function stringContains(fieldName: string, substring: Expression): BooleanExpression; + +// @beta +export function stringContains(stringExpression: Expression, substring: string): BooleanExpression; + +// @beta +export function stringContains(stringExpression: Expression, substring: Expression): BooleanExpression; + +// @beta +export function stringReverse(stringExpression: Expression): FunctionExpression; + +// @beta +export function stringReverse(field: string): FunctionExpression; + +// @beta +export function substring(field: string, position: number, length?: number): FunctionExpression; + +// @beta +export function substring(input: Expression, position: number, length?: number): FunctionExpression; + +// @beta +export function substring(field: string, position: Expression, length?: Expression): FunctionExpression; + +// @beta +export function substring(input: Expression, position: Expression, length?: Expression): FunctionExpression; + +// @beta +export function subtract(left: Expression, right: Expression): FunctionExpression; + +// @beta +export function subtract(expression: Expression, value: unknown): FunctionExpression; + +// @beta +export function subtract(fieldName: string, expression: Expression): FunctionExpression; + +// @beta +export function subtract(fieldName: string, value: unknown): FunctionExpression; + +// @beta +export function sum(expression: Expression): AggregateFunction; + +// @beta +export function sum(fieldName: string): AggregateFunction; + +// @beta +export type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; + +// @beta +export function timestampAdd(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; + +// @beta +export function timestampAdd(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + +// @beta +export function timestampAdd(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + +// @beta +export function timestampSubtract(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; + +// @beta +export function timestampSubtract(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + +// @beta +export function timestampSubtract(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + +// @beta +export function timestampToUnixMicros(expr: Expression): FunctionExpression; + +// @beta +export function timestampToUnixMicros(fieldName: string): FunctionExpression; + +// @beta +export function timestampToUnixMillis(expr: Expression): FunctionExpression; + +// @beta +export function timestampToUnixMillis(fieldName: string): FunctionExpression; + +// @beta +export function timestampToUnixSeconds(expr: Expression): FunctionExpression; + +// @beta +export function timestampToUnixSeconds(fieldName: string): FunctionExpression; + +// @beta +export function timestampTruncate(fieldName: string, granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; + +// @beta +export function timestampTruncate(fieldName: string, granularity: Expression, timezone?: string | Expression): FunctionExpression; + +// @beta +export function timestampTruncate(timestampExpression: Expression, granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; + +// @beta +export function timestampTruncate(timestampExpression: Expression, granularity: Expression, timezone?: string | Expression): FunctionExpression; + +// @beta +export function toLower(fieldName: string): FunctionExpression; + +// @beta +export function toLower(stringExpression: Expression): FunctionExpression; + +// @beta +export function toUpper(fieldName: string): FunctionExpression; + +// @beta +export function toUpper(stringExpression: Expression): FunctionExpression; + +// @beta +export function trim(fieldName: string, valueToTrim?: string | Expression): FunctionExpression; + +// @beta +export function trim(stringExpression: Expression, valueToTrim?: string | Expression): FunctionExpression; + +// @beta +export function type(fieldName: string): FunctionExpression; + +// @beta +export function type(expression: Expression): FunctionExpression; + +// @beta +export type UnionStageOptions = StageOptions & { + other: Pipeline; +}; + +// @beta +export function unixMicrosToTimestamp(expr: Expression): FunctionExpression; + +// @beta +export function unixMicrosToTimestamp(fieldName: string): FunctionExpression; + +// @beta +export function unixMillisToTimestamp(expr: Expression): FunctionExpression; + +// @beta +export function unixMillisToTimestamp(fieldName: string): FunctionExpression; + +// @beta +export function unixSecondsToTimestamp(expr: Expression): FunctionExpression; + +// @beta +export function unixSecondsToTimestamp(fieldName: string): FunctionExpression; + +// @beta +export type UnnestStageOptions = StageOptions & { + selectable: Selectable; + indexField?: string; +}; + +// @beta +export function vectorLength(vectorExpression: Expression): FunctionExpression; + +// @beta +export function vectorLength(fieldName: string): FunctionExpression; + +// @beta +export type WhereStageOptions = StageOptions & { + condition: BooleanExpression; +}; + +// @beta +export function xor(first: BooleanExpression, second: BooleanExpression, ...additionalConditions: BooleanExpression[]): BooleanExpression; + + +// Warnings were encountered during analysis: +// +// /Users/markduckworth/projects/firebase-js-sdk/packages/firestore/dist/lite/pipelines.d.ts:830:5 - (ae-forgotten-export) The symbol "Query" needs to be exported by the entry point pipelines.d.ts + +// (No @packageDocumentation comment for this package) + +``` diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md new file mode 100644 index 0000000000..2d701d9058 --- /dev/null +++ b/common/api-review/firestore-pipelines.api.md @@ -0,0 +1,1353 @@ +## API Report File for "@firebase/firestore-pipelines" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { FirebaseApp } from '@firebase/app'; + +// @beta +export function abs(expr: Expression): FunctionExpression; + +// @beta +export function abs(fieldName: string): FunctionExpression; + +// @beta +export function add(first: Expression, second: Expression | unknown): FunctionExpression; + +// @beta +export function add(fieldName: string, second: Expression | unknown): FunctionExpression; + +// @beta +export type AddFieldsStageOptions = StageOptions & { + fields: Selectable[]; +}; + +// @beta +export class AggregateFunction { + constructor(name: string, params: Expression[]); + as(name: string): AliasedAggregate; + // (undocumented) + exprType: ExpressionType; + } + +// @beta +export type AggregateStageOptions = StageOptions & { + accumulators: AliasedAggregate[]; + groups?: Array; +}; + +// @beta +export class AliasedAggregate { + constructor(aggregate: AggregateFunction, alias: string, _methodName: string | undefined); + // (undocumented) + readonly aggregate: AggregateFunction; + // (undocumented) + readonly alias: string; +} + +// @beta (undocumented) +export class AliasedExpression implements Selectable { + constructor(expr: Expression, alias: string, _methodName: string | undefined); + // (undocumented) + readonly alias: string; + // (undocumented) + readonly expr: Expression; + // (undocumented) + exprType: ExpressionType; + // (undocumented) + selectable: true; +} + +// @beta +export function and(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; + +// @beta +export function array(elements: unknown[]): FunctionExpression; + +// @beta +export function arrayConcat(firstArray: Expression, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; + +// @beta +export function arrayConcat(firstArrayField: string, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; + +// @beta +export function arrayContains(array: Expression, element: Expression): BooleanExpression; + +// @beta +export function arrayContains(array: Expression, element: unknown): BooleanExpression; + +// @beta +export function arrayContains(fieldName: string, element: Expression): BooleanExpression; + +// @beta +export function arrayContains(fieldName: string, element: unknown): BooleanExpression; + +// @beta +export function arrayContainsAll(array: Expression, values: Array): BooleanExpression; + +// @beta +export function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; + +// @beta +export function arrayContainsAll(array: Expression, arrayExpression: Expression): BooleanExpression; + +// @beta +export function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; + +// @beta +export function arrayContainsAny(array: Expression, values: Array): BooleanExpression; + +// @beta +export function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; + +// @beta +export function arrayContainsAny(array: Expression, values: Expression): BooleanExpression; + +// @beta +export function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; + +// @beta +export function arrayGet(arrayField: string, offset: number): FunctionExpression; + +// @beta +export function arrayGet(arrayField: string, offsetExpr: Expression): FunctionExpression; + +// @beta +export function arrayGet(arrayExpression: Expression, offset: number): FunctionExpression; + +// @beta +export function arrayGet(arrayExpression: Expression, offsetExpr: Expression): FunctionExpression; + +// @beta +export function arrayLength(fieldName: string): FunctionExpression; + +// @beta +export function arrayLength(array: Expression): FunctionExpression; + +// @beta +export function arraySum(fieldName: string): FunctionExpression; + +// @beta +export function arraySum(expression: Expression): FunctionExpression; + +// @beta +export function ascending(expr: Expression): Ordering; + +// @beta +export function ascending(fieldName: string): Ordering; + +// @beta +export function average(expression: Expression): AggregateFunction; + +// @beta +export function average(fieldName: string): AggregateFunction; + +// @beta +export abstract class BooleanExpression extends Expression { + conditional(thenExpr: Expression, elseExpr: Expression): FunctionExpression; + countIf(): AggregateFunction; + ifError(catchValue: BooleanExpression): BooleanExpression; + ifError(catchValue: boolean): BooleanExpression; + ifError(catchValue: Expression): FunctionExpression; + ifError(catchValue: unknown): FunctionExpression; + not(): BooleanExpression; +} + +// @beta +export function byteLength(expr: Expression): FunctionExpression; + +// @beta +export function byteLength(fieldName: string): FunctionExpression; + +// @beta +export function ceil(fieldName: string): FunctionExpression; + +// @beta +export function ceil(expression: Expression): FunctionExpression; + +// @beta +export function charLength(fieldName: string): FunctionExpression; + +// @beta +export function charLength(stringExpression: Expression): FunctionExpression; + +// @beta +export type CollectionGroupStageOptions = StageOptions & { + collectionId: string; + forceIndex?: string; +}; + +// @beta +export function collectionId(fieldName: string): FunctionExpression; + +// @beta +export function collectionId(expression: Expression): FunctionExpression; + +// @beta +export type CollectionStageOptions = StageOptions & { + collection: string | Query; + forceIndex?: string; +}; + +// @beta +export function concat(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function concat(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function conditional(condition: BooleanExpression, thenExpr: Expression, elseExpr: Expression): FunctionExpression; + +// @beta +export function constant(value: number): Expression; + +// @beta +export function constant(value: string): Expression; + +// @beta +export function constant(value: boolean): BooleanExpression; + +// @beta +export function constant(value: null): Expression; + +// Warning: (ae-forgotten-export) The symbol "GeoPoint" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export function constant(value: GeoPoint): Expression; + +// Warning: (ae-forgotten-export) The symbol "Timestamp" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export function constant(value: Timestamp): Expression; + +// @beta +export function constant(value: Date): Expression; + +// Warning: (ae-forgotten-export) The symbol "Bytes" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export function constant(value: Bytes): Expression; + +// Warning: (ae-forgotten-export) The symbol "DocumentReference" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export function constant(value: DocumentReference): Expression; + +// Warning: (ae-forgotten-export) The symbol "VectorValue" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export function constant(value: VectorValue): Expression; + +// @beta +export function cosineDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; + +// @beta +export function cosineDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; + +// @beta +export function cosineDistance(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; + +// @beta +export function cosineDistance(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; + +// @beta +export function count(expression: Expression): AggregateFunction; + +// @beta +export function count(fieldName: string): AggregateFunction; + +// @beta +export function countAll(): AggregateFunction; + +// @beta +export function countDistinct(expr: Expression | string): AggregateFunction; + +// @beta +export function countIf(booleanExpr: BooleanExpression): AggregateFunction; + +// @beta +export function currentTimestamp(): FunctionExpression; + +// @beta +export type DatabaseStageOptions = StageOptions & {}; + +// @beta +export function descending(expr: Expression): Ordering; + +// @beta +export function descending(fieldName: string): Ordering; + +// @beta +export type DistinctStageOptions = StageOptions & { + groups: Array; +}; + +// @beta +export function divide(left: Expression, right: Expression): FunctionExpression; + +// @beta +export function divide(expression: Expression, value: unknown): FunctionExpression; + +// @beta +export function divide(fieldName: string, expressions: Expression): FunctionExpression; + +// @beta +export function divide(fieldName: string, value: unknown): FunctionExpression; + +// @beta +export function documentId(documentPath: string | DocumentReference): FunctionExpression; + +// @beta +export function documentId(documentPathExpr: Expression): FunctionExpression; + +// @beta +export type DocumentsStageOptions = StageOptions & { + docs: Array; +}; + +// @beta +export function dotProduct(fieldName: string, vector: number[] | VectorValue): FunctionExpression; + +// @beta +export function dotProduct(fieldName: string, vectorExpression: Expression): FunctionExpression; + +// @beta +export function dotProduct(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; + +// @beta +export function dotProduct(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; + +// @beta +export function endsWith(fieldName: string, suffix: string): BooleanExpression; + +// @beta +export function endsWith(fieldName: string, suffix: Expression): BooleanExpression; + +// @beta +export function endsWith(stringExpression: Expression, suffix: string): BooleanExpression; + +// @beta +export function endsWith(stringExpression: Expression, suffix: Expression): BooleanExpression; + +// @beta +export function equal(left: Expression, right: Expression): BooleanExpression; + +// @beta +export function equal(expression: Expression, value: unknown): BooleanExpression; + +// @beta +export function equal(fieldName: string, expression: Expression): BooleanExpression; + +// @beta +export function equal(fieldName: string, value: unknown): BooleanExpression; + +// @beta +export function equalAny(expression: Expression, values: Array): BooleanExpression; + +// @beta +export function equalAny(expression: Expression, arrayExpression: Expression): BooleanExpression; + +// @beta +export function equalAny(fieldName: string, values: Array): BooleanExpression; + +// @beta +export function equalAny(fieldName: string, arrayExpression: Expression): BooleanExpression; + +// @beta +export function euclideanDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; + +// @beta +export function euclideanDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; + +// @beta +export function euclideanDistance(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; + +// @beta +export function euclideanDistance(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; + +// @beta +export function execute(pipeline: Pipeline): Promise; + +// @beta +export function execute(options: PipelineExecuteOptions): Promise; + +// @beta +export function exists(value: Expression): BooleanExpression; + +// @beta +export function exists(fieldName: string): BooleanExpression; + +// @beta +export function exp(expression: Expression): FunctionExpression; + +// @beta +export function exp(fieldName: string): FunctionExpression; + +// @beta +export abstract class Expression { + abs(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + add(second: Expression | unknown): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayConcat(secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayContains(expression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + arrayContains(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + arrayContainsAll(values: Array): BooleanExpression; + /* Excluded from this release type: _readUserData */ + arrayContainsAll(arrayExpression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + arrayContainsAny(values: Array): BooleanExpression; + /* Excluded from this release type: _readUserData */ + arrayContainsAny(arrayExpression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + arrayGet(offset: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayGet(offsetExpr: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayLength(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayReverse(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arraySum(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + as(name: string): AliasedExpression; + /* Excluded from this release type: _readUserData */ + asBoolean(): BooleanExpression; + /* Excluded from this release type: _readUserData */ + ascending(): Ordering; + /* Excluded from this release type: _readUserData */ + average(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + byteLength(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + ceil(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + charLength(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + collectionId(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + concat(second: Expression | unknown, ...others: Array): FunctionExpression; + /* Excluded from this release type: _readUserData */ + cosineDistance(vectorExpression: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + cosineDistance(vector: VectorValue | number[]): FunctionExpression; + /* Excluded from this release type: _readUserData */ + count(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + countDistinct(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + descending(): Ordering; + /* Excluded from this release type: _readUserData */ + divide(divisor: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + divide(divisor: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + documentId(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + dotProduct(vectorExpression: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + dotProduct(vector: VectorValue | number[]): FunctionExpression; + /* Excluded from this release type: _readUserData */ + endsWith(suffix: string): BooleanExpression; + /* Excluded from this release type: _readUserData */ + endsWith(suffix: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + equal(expression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + equal(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + equalAny(values: Array): BooleanExpression; + /* Excluded from this release type: _readUserData */ + equalAny(arrayExpression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + euclideanDistance(vectorExpression: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + euclideanDistance(vector: VectorValue | number[]): FunctionExpression; + /* Excluded from this release type: _readUserData */ + exists(): BooleanExpression; + /* Excluded from this release type: _readUserData */ + exp(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + // (undocumented) + abstract readonly expressionType: ExpressionType; + /* Excluded from this release type: _readUserData */ + floor(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + greaterThan(expression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + greaterThan(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + greaterThanOrEqual(expression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + greaterThanOrEqual(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + ifAbsent(elseValue: unknown): Expression; + /* Excluded from this release type: _readUserData */ + ifAbsent(elseExpression: unknown): Expression; + /* Excluded from this release type: _readUserData */ + ifError(catchExpr: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + ifError(catchValue: unknown): FunctionExpression; + /* Excluded from this release type: _readUserData */ + isAbsent(): BooleanExpression; + /* Excluded from this release type: _readUserData */ + isError(): BooleanExpression; + /* Excluded from this release type: _readUserData */ + join(delimiterExpression: Expression): Expression; + /* Excluded from this release type: _readUserData */ + join(delimiter: string): Expression; + /* Excluded from this release type: _readUserData */ + length(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + lessThan(experession: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + lessThan(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + lessThanOrEqual(expression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + lessThanOrEqual(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + like(pattern: string): BooleanExpression; + /* Excluded from this release type: _readUserData */ + like(pattern: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + ln(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + log10(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + logicalMaximum(second: Expression | unknown, ...others: Array): FunctionExpression; + /* Excluded from this release type: _readUserData */ + logicalMinimum(second: Expression | unknown, ...others: Array): FunctionExpression; + /* Excluded from this release type: _readUserData */ + mapGet(subfield: string): FunctionExpression; + /* Excluded from this release type: _readUserData */ + mapMerge(secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; + /* Excluded from this release type: _readUserData */ + mapRemove(key: string): FunctionExpression; + /* Excluded from this release type: _readUserData */ + mapRemove(keyExpr: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + maximum(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + minimum(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + mod(expression: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + mod(value: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + multiply(second: Expression | number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + notEqual(expression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + notEqual(value: unknown): BooleanExpression; + /* Excluded from this release type: _readUserData */ + notEqualAny(values: Array): BooleanExpression; + /* Excluded from this release type: _readUserData */ + notEqualAny(arrayExpression: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + pow(exponent: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + pow(exponent: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + regexContains(pattern: string): BooleanExpression; + /* Excluded from this release type: _readUserData */ + regexContains(pattern: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + regexMatch(pattern: string): BooleanExpression; + /* Excluded from this release type: _readUserData */ + regexMatch(pattern: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + reverse(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + round(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + round(decimalPlaces: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + round(decimalPlaces: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + split(delimiter: string): FunctionExpression; + /* Excluded from this release type: _readUserData */ + split(delimiter: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + sqrt(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + startsWith(prefix: string): BooleanExpression; + /* Excluded from this release type: _readUserData */ + startsWith(prefix: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + stringConcat(secondString: Expression | string, ...otherStrings: Array): FunctionExpression; + /* Excluded from this release type: _readUserData */ + stringContains(substring: string): BooleanExpression; + /* Excluded from this release type: _readUserData */ + stringContains(expr: Expression): BooleanExpression; + /* Excluded from this release type: _readUserData */ + stringReverse(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + substring(position: number, length?: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + substring(position: Expression, length?: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + subtract(subtrahend: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + subtract(subtrahend: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + sum(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + timestampAdd(unit: Expression, amount: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampAdd(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampSubtract(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampToUnixMicros(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampToUnixMillis(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampToUnixSeconds(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampTruncate(granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampTruncate(granularity: Expression, timezone?: string | Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + toLower(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + toUpper(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + trim(valueToTrim?: string | Expression | Bytes): FunctionExpression; + /* Excluded from this release type: _readUserData */ + type(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + unixMicrosToTimestamp(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + unixMillisToTimestamp(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + unixSecondsToTimestamp(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + vectorLength(): FunctionExpression; +} + +// @beta +export type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression'; + +// @beta +export class Field extends Expression implements Selectable { + // (undocumented) + get alias(): string; + // (undocumented) + get expr(): Expression; + // (undocumented) + readonly expressionType: ExpressionType; + // (undocumented) + get fieldName(): string; + // (undocumented) + selectable: true; +} + +// @beta +export function field(name: string): Field; + +// Warning: (ae-forgotten-export) The symbol "FieldPath" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export function field(path: FieldPath): Field; + +// @beta +export type FindNearestStageOptions = StageOptions & { + field: Field | string; + vectorValue: VectorValue | number[]; + distanceMeasure: 'euclidean' | 'cosine' | 'dot_product'; + limit?: number; + distanceField?: string; +}; + +// @beta +export function floor(expr: Expression): FunctionExpression; + +// @beta +export function floor(fieldName: string): FunctionExpression; + +// @beta +export class FunctionExpression extends Expression { + constructor(name: string, params: Expression[]); + constructor(name: string, params: Expression[], _methodName: string | undefined); + // (undocumented) + readonly expressionType: ExpressionType; + } + +// @beta +export function greaterThan(left: Expression, right: Expression): BooleanExpression; + +// @beta +export function greaterThan(expression: Expression, value: unknown): BooleanExpression; + +// @beta +export function greaterThan(fieldName: string, expression: Expression): BooleanExpression; + +// @beta +export function greaterThan(fieldName: string, value: unknown): BooleanExpression; + +// @beta +export function greaterThanOrEqual(left: Expression, right: Expression): BooleanExpression; + +// @beta +export function greaterThanOrEqual(expression: Expression, value: unknown): BooleanExpression; + +// @beta +export function greaterThanOrEqual(fieldName: string, value: Expression): BooleanExpression; + +// @beta +export function greaterThanOrEqual(fieldName: string, value: unknown): BooleanExpression; + +// @beta +export function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expression; + +// @beta +export function ifAbsent(ifExpr: Expression, elseValue: unknown): Expression; + +// @beta +export function ifAbsent(ifFieldName: string, elseExpr: Expression): Expression; + +// @beta +export function ifAbsent(ifFieldName: string | Expression, elseValue: Expression | unknown): Expression; + +// @beta +export function ifError(tryExpr: BooleanExpression, catchExpr: BooleanExpression): BooleanExpression; + +// @beta +export function ifError(tryExpr: Expression, catchExpr: Expression): FunctionExpression; + +// @beta +export function ifError(tryExpr: Expression, catchValue: unknown): FunctionExpression; + +// @beta +export function isAbsent(value: Expression): BooleanExpression; + +// @beta +export function isAbsent(field: string): BooleanExpression; + +// @beta +export function isError(value: Expression): BooleanExpression; + +// @beta +export function join(arrayFieldName: string, delimiter: string): Expression; + +// @beta +export function join(arrayExpression: Expression, delimiterExpression: Expression): Expression; + +// @beta +export function join(arrayExpression: Expression, delimiter: string): Expression; + +// @beta +export function join(arrayFieldName: string, delimiterExpression: Expression): Expression; + +// @beta +function length_2(fieldName: string): FunctionExpression; + +// @beta +function length_2(expression: Expression): FunctionExpression; + +export { length_2 as length } + +// @beta +export function lessThan(left: Expression, right: Expression): BooleanExpression; + +// @beta +export function lessThan(expression: Expression, value: unknown): BooleanExpression; + +// @beta +export function lessThan(fieldName: string, expression: Expression): BooleanExpression; + +// @beta +export function lessThan(fieldName: string, value: unknown): BooleanExpression; + +// @beta +export function lessThanOrEqual(left: Expression, right: Expression): BooleanExpression; + +// @beta +export function lessThanOrEqual(expression: Expression, value: unknown): BooleanExpression; + +// @beta +export function lessThanOrEqual(fieldName: string, expression: Expression): BooleanExpression; + +// @beta +export function lessThanOrEqual(fieldName: string, value: unknown): BooleanExpression; + +// @beta +export function like(fieldName: string, pattern: string): BooleanExpression; + +// @beta +export function like(fieldName: string, pattern: Expression): BooleanExpression; + +// @beta +export function like(stringExpression: Expression, pattern: string): BooleanExpression; + +// @beta +export function like(stringExpression: Expression, pattern: Expression): BooleanExpression; + +// @beta +export type LimitStageOptions = StageOptions & { + limit: number; +}; + +// @beta +export function ln(fieldName: string): FunctionExpression; + +// @beta +export function ln(expression: Expression): FunctionExpression; + +// @beta +export function log(expression: Expression, base: number): FunctionExpression; + +// @beta +export function log(expression: Expression, base: Expression): FunctionExpression; + +// @beta +export function log(fieldName: string, base: number): FunctionExpression; + +// @beta +export function log(fieldName: string, base: Expression): FunctionExpression; + +// @beta +export function log10(fieldName: string): FunctionExpression; + +// @beta +export function log10(expression: Expression): FunctionExpression; + +// @beta +export function logicalMaximum(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function logicalMaximum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function logicalMinimum(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function logicalMinimum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function map(elements: Record): FunctionExpression; + +// @beta +export function mapGet(fieldName: string, subField: string): FunctionExpression; + +// @beta +export function mapGet(mapExpression: Expression, subField: string): FunctionExpression; + +// @beta +export function mapMerge(mapField: string, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; + +// @beta +export function mapMerge(firstMap: Record | Expression, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; + +// @beta +export function mapRemove(mapField: string, key: string): FunctionExpression; + +// @beta +export function mapRemove(mapExpr: Expression, key: string): FunctionExpression; + +// @beta +export function mapRemove(mapField: string, keyExpr: Expression): FunctionExpression; + +// @beta +export function mapRemove(mapExpr: Expression, keyExpr: Expression): FunctionExpression; + +// @beta +export function maximum(expression: Expression): AggregateFunction; + +// @beta +export function maximum(fieldName: string): AggregateFunction; + +// @beta +export function minimum(expression: Expression): AggregateFunction; + +// @beta +export function minimum(fieldName: string): AggregateFunction; + +// @beta +export function mod(left: Expression, right: Expression): FunctionExpression; + +// @beta +export function mod(expression: Expression, value: unknown): FunctionExpression; + +// @beta +export function mod(fieldName: string, expression: Expression): FunctionExpression; + +// @beta +export function mod(fieldName: string, value: unknown): FunctionExpression; + +// @beta +export function multiply(first: Expression, second: Expression | unknown): FunctionExpression; + +// @beta +export function multiply(fieldName: string, second: Expression | unknown): FunctionExpression; + +// @beta +export function not(booleanExpr: BooleanExpression): BooleanExpression; + +// @beta +export function notEqual(left: Expression, right: Expression): BooleanExpression; + +// @beta +export function notEqual(expression: Expression, value: unknown): BooleanExpression; + +// @beta +export function notEqual(fieldName: string, expression: Expression): BooleanExpression; + +// @beta +export function notEqual(fieldName: string, value: unknown): BooleanExpression; + +// @beta +export function notEqualAny(element: Expression, values: Array): BooleanExpression; + +// @beta +export function notEqualAny(fieldName: string, values: Array): BooleanExpression; + +// @beta +export function notEqualAny(element: Expression, arrayExpression: Expression): BooleanExpression; + +// @beta +export function notEqualAny(fieldName: string, arrayExpression: Expression): BooleanExpression; + +// @beta +export type OffsetStageOptions = StageOptions & { + offset: number; +}; + +// @beta +export type OneOf = { + [K in keyof T]: Pick & { + [P in Exclude]?: undefined; + }; +}[keyof T]; + +// @beta +export function or(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; + +// @beta +export class Ordering { + constructor(expr: Expression, direction: 'ascending' | 'descending', _methodName: string | undefined); + // (undocumented) + readonly direction: 'ascending' | 'descending'; + // (undocumented) + readonly expr: Expression; +} + +// @beta (undocumented) +export class Pipeline { + // (undocumented) + addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; + // (undocumented) + addFields(options: AddFieldsStageOptions): Pipeline; + // (undocumented) + aggregate(accumulator: AliasedAggregate, ...additionalAccumulators: AliasedAggregate[]): Pipeline; + // (undocumented) + aggregate(options: AggregateStageOptions): Pipeline; + // (undocumented) + distinct(group: string | Selectable, ...additionalGroups: Array): Pipeline; + // (undocumented) + distinct(options: DistinctStageOptions): Pipeline; + // (undocumented) + findNearest(options: FindNearestStageOptions): Pipeline; + // (undocumented) + limit(limit: number): Pipeline; + // (undocumented) + limit(options: LimitStageOptions): Pipeline; + // (undocumented) + offset(offset: number): Pipeline; + // (undocumented) + offset(options: OffsetStageOptions): Pipeline; + // (undocumented) + rawStage(name: string, params: unknown[], options?: { [key: string]: Expression | unknown; }): Pipeline; + // (undocumented) + removeFields(fieldValue: Field | string, ...additionalFields: Array): Pipeline; + // (undocumented) + removeFields(options: RemoveFieldsStageOptions): Pipeline; + // (undocumented) + replaceWith(fieldName: string): Pipeline; + // (undocumented) + replaceWith(expr: Expression): Pipeline; + // (undocumented) + replaceWith(options: ReplaceWithStageOptions): Pipeline; + // (undocumented) + sample(documents: number): Pipeline; + // (undocumented) + sample(options: SampleStageOptions): Pipeline; + // (undocumented) + select(selection: Selectable | string, ...additionalSelections: Array): Pipeline; + // (undocumented) + select(options: SelectStageOptions): Pipeline; + // (undocumented) + sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; + // (undocumented) + sort(options: SortStageOptions): Pipeline; + // (undocumented) + union(other: Pipeline): Pipeline; + // (undocumented) + union(options: UnionStageOptions): Pipeline; + // (undocumented) + unnest(selectable: Selectable, indexField?: string): Pipeline; + // (undocumented) + unnest(options: UnnestStageOptions): Pipeline; + // (undocumented) + where(condition: BooleanExpression): Pipeline; + // (undocumented) + where(options: WhereStageOptions): Pipeline; +} + +// @beta +export interface PipelineExecuteOptions { + indexMode?: 'recommended'; + pipeline: Pipeline; + rawOptions?: { + [name: string]: unknown; + }; +} + +// Warning: (ae-forgotten-export) The symbol "DocumentData" needs to be exported by the entry point pipelines.d.ts +// +// @beta +export class PipelineResult { + /* Excluded from this release type: _ref */ + /* Excluded from this release type: _fields */ + /* Excluded from this release type: __constructor */ + get createTime(): Timestamp | undefined; + data(): AppModelType; + get(fieldPath: string | FieldPath | Field): any; + get id(): string | undefined; + get ref(): DocumentReference | undefined; + get updateTime(): Timestamp | undefined; +} + +// @beta +export function pipelineResultEqual(left: PipelineResult, right: PipelineResult): boolean; + +// @beta +export class PipelineSnapshot { + constructor(pipeline: Pipeline, results: PipelineResult[], executionTime?: Timestamp); + get executionTime(): Timestamp; + get results(): PipelineResult[]; +} + +// @beta +export class PipelineSource { + collection(collection: string | Query): PipelineType; + collection(options: CollectionStageOptions): PipelineType; + collectionGroup(collectionId: string): PipelineType; + collectionGroup(options: CollectionGroupStageOptions): PipelineType; + createFrom(query: Query): Pipeline; + database(): PipelineType; + database(options: DatabaseStageOptions): PipelineType; + documents(docs: Array): PipelineType; + documents(options: DocumentsStageOptions): PipelineType; + } + +// @beta +export function pow(base: Expression, exponent: Expression): FunctionExpression; + +// @beta +export function pow(base: Expression, exponent: number): FunctionExpression; + +// @beta +export function pow(base: string, exponent: Expression): FunctionExpression; + +// @beta +export function pow(base: string, exponent: number): FunctionExpression; + +// @beta +export function regexContains(fieldName: string, pattern: string): BooleanExpression; + +// @beta +export function regexContains(fieldName: string, pattern: Expression): BooleanExpression; + +// @beta +export function regexContains(stringExpression: Expression, pattern: string): BooleanExpression; + +// @beta +export function regexContains(stringExpression: Expression, pattern: Expression): BooleanExpression; + +// @beta +export function regexMatch(fieldName: string, pattern: string): BooleanExpression; + +// @beta +export function regexMatch(fieldName: string, pattern: Expression): BooleanExpression; + +// @beta +export function regexMatch(stringExpression: Expression, pattern: string): BooleanExpression; + +// @beta +export function regexMatch(stringExpression: Expression, pattern: Expression): BooleanExpression; + +// @beta +export type RemoveFieldsStageOptions = StageOptions & { + fields: Array; +}; + +// @beta +export type ReplaceWithStageOptions = StageOptions & { + map: Expression | string; +}; + +// @beta +export function reverse(stringExpression: Expression): FunctionExpression; + +// @beta +export function reverse(field: string): FunctionExpression; + +// @beta +export function round(fieldName: string): FunctionExpression; + +// @beta +export function round(expression: Expression): FunctionExpression; + +// @beta +export function round(fieldName: string, decimalPlaces: number | Expression): FunctionExpression; + +// @beta +export function round(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; + +// @beta +export type SampleStageOptions = StageOptions & OneOf<{ + percentage: number; + documents: number; +}>; + +// @beta +export interface Selectable { + // (undocumented) + selectable: true; +} + +// @beta +export type SelectStageOptions = StageOptions & { + selections: Array; +}; + +// @beta +export type SortStageOptions = StageOptions & { + orderings: Ordering[]; +}; + +// @beta +export function split(fieldName: string, delimiter: string): FunctionExpression; + +// @beta +export function split(fieldName: string, delimiter: Expression): FunctionExpression; + +// @beta +export function split(expression: Expression, delimiter: string): FunctionExpression; + +// @beta +export function split(expression: Expression, delimiter: Expression): FunctionExpression; + +// @beta +export function sqrt(expression: Expression): FunctionExpression; + +// @beta +export function sqrt(fieldName: string): FunctionExpression; + +// @beta +export interface StageOptions { + rawOptions?: { + [name: string]: unknown; + }; +} + +// @beta +export function startsWith(fieldName: string, prefix: string): BooleanExpression; + +// @beta +export function startsWith(fieldName: string, prefix: Expression): BooleanExpression; + +// @beta +export function startsWith(stringExpression: Expression, prefix: string): BooleanExpression; + +// @beta +export function startsWith(stringExpression: Expression, prefix: Expression): BooleanExpression; + +// @beta +export function stringConcat(fieldName: string, secondString: Expression | string, ...otherStrings: Array): FunctionExpression; + +// @beta +export function stringConcat(firstString: Expression, secondString: Expression | string, ...otherStrings: Array): FunctionExpression; + +// @beta +export function stringContains(fieldName: string, substring: string): BooleanExpression; + +// @beta +export function stringContains(fieldName: string, substring: Expression): BooleanExpression; + +// @beta +export function stringContains(stringExpression: Expression, substring: string): BooleanExpression; + +// @beta +export function stringContains(stringExpression: Expression, substring: Expression): BooleanExpression; + +// @beta +export function stringReverse(stringExpression: Expression): FunctionExpression; + +// @beta +export function stringReverse(field: string): FunctionExpression; + +// @beta +export function substring(field: string, position: number, length?: number): FunctionExpression; + +// @beta +export function substring(input: Expression, position: number, length?: number): FunctionExpression; + +// @beta +export function substring(field: string, position: Expression, length?: Expression): FunctionExpression; + +// @beta +export function substring(input: Expression, position: Expression, length?: Expression): FunctionExpression; + +// @beta +export function subtract(left: Expression, right: Expression): FunctionExpression; + +// @beta +export function subtract(expression: Expression, value: unknown): FunctionExpression; + +// @beta +export function subtract(fieldName: string, expression: Expression): FunctionExpression; + +// @beta +export function subtract(fieldName: string, value: unknown): FunctionExpression; + +// @beta +export function sum(expression: Expression): AggregateFunction; + +// @beta +export function sum(fieldName: string): AggregateFunction; + +// @beta +export type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; + +// @beta +export function timestampAdd(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; + +// @beta +export function timestampAdd(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + +// @beta +export function timestampAdd(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + +// @beta +export function timestampSubtract(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; + +// @beta +export function timestampSubtract(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + +// @beta +export function timestampSubtract(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + +// @beta +export function timestampToUnixMicros(expr: Expression): FunctionExpression; + +// @beta +export function timestampToUnixMicros(fieldName: string): FunctionExpression; + +// @beta +export function timestampToUnixMillis(expr: Expression): FunctionExpression; + +// @beta +export function timestampToUnixMillis(fieldName: string): FunctionExpression; + +// @beta +export function timestampToUnixSeconds(expr: Expression): FunctionExpression; + +// @beta +export function timestampToUnixSeconds(fieldName: string): FunctionExpression; + +// @beta +export function timestampTruncate(fieldName: string, granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; + +// @beta +export function timestampTruncate(fieldName: string, granularity: Expression, timezone?: string | Expression): FunctionExpression; + +// @beta +export function timestampTruncate(timestampExpression: Expression, granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; + +// @beta +export function timestampTruncate(timestampExpression: Expression, granularity: Expression, timezone?: string | Expression): FunctionExpression; + +// @beta +export function toLower(fieldName: string): FunctionExpression; + +// @beta +export function toLower(stringExpression: Expression): FunctionExpression; + +// @beta +export function toUpper(fieldName: string): FunctionExpression; + +// @beta +export function toUpper(stringExpression: Expression): FunctionExpression; + +// @beta +export function trim(fieldName: string, valueToTrim?: string | Expression): FunctionExpression; + +// @beta +export function trim(stringExpression: Expression, valueToTrim?: string | Expression): FunctionExpression; + +// @beta +export function type(fieldName: string): FunctionExpression; + +// @beta +export function type(expression: Expression): FunctionExpression; + +// @beta +export type UnionStageOptions = StageOptions & { + other: Pipeline; +}; + +// @beta +export function unixMicrosToTimestamp(expr: Expression): FunctionExpression; + +// @beta +export function unixMicrosToTimestamp(fieldName: string): FunctionExpression; + +// @beta +export function unixMillisToTimestamp(expr: Expression): FunctionExpression; + +// @beta +export function unixMillisToTimestamp(fieldName: string): FunctionExpression; + +// @beta +export function unixSecondsToTimestamp(expr: Expression): FunctionExpression; + +// @beta +export function unixSecondsToTimestamp(fieldName: string): FunctionExpression; + +// @beta +export type UnnestStageOptions = StageOptions & { + selectable: Selectable; + indexField?: string; +}; + +// @beta +export function vectorLength(vectorExpression: Expression): FunctionExpression; + +// @beta +export function vectorLength(fieldName: string): FunctionExpression; + +// @beta +export type WhereStageOptions = StageOptions & { + condition: BooleanExpression; +}; + +// @beta +export function xor(first: BooleanExpression, second: BooleanExpression, ...additionalConditions: BooleanExpression[]): BooleanExpression; + + +// Warnings were encountered during analysis: +// +// /Users/markduckworth/projects/firebase-js-sdk/packages/firestore/dist/pipelines.d.ts:827:5 - (ae-forgotten-export) The symbol "Query" needs to be exported by the entry point pipelines.d.ts + +// (No @packageDocumentation comment for this package) + +``` diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index 92633c553a..401bcb3bc1 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -597,6 +597,130 @@ toc: path: /docs/reference/js/firestore_lite.vectorvalue.md - title: WriteBatch path: /docs/reference/js/firestore_lite.writebatch.md +- title: firestore/lite/pipelines + path: /docs/reference/js/firestore_lite_pipelines.md + section: + - title: AggregateFunction + path: /docs/reference/js/firestore_lite_pipelines.aggregatefunction.md + - title: AliasedAggregate + path: /docs/reference/js/firestore_lite_pipelines.aliasedaggregate.md + - title: AliasedExpression + path: /docs/reference/js/firestore_lite_pipelines.aliasedexpression.md + - title: BooleanExpression + path: /docs/reference/js/firestore_lite_pipelines.booleanexpression.md + - title: Bytes + path: /docs/reference/js/firestore_lite_pipelines.bytes.md + - title: CollectionReference + path: /docs/reference/js/firestore_lite_pipelines.collectionreference.md + - title: DocumentData + path: /docs/reference/js/firestore_lite_pipelines.documentdata.md + - title: DocumentReference + path: /docs/reference/js/firestore_lite_pipelines.documentreference.md + - title: DocumentSnapshot + path: /docs/reference/js/firestore_lite_pipelines.documentsnapshot.md + - title: Expression + path: /docs/reference/js/firestore_lite_pipelines.expression.md + - title: Field + path: /docs/reference/js/firestore_lite_pipelines.field.md + - title: FieldPath + path: /docs/reference/js/firestore_lite_pipelines.fieldpath.md + - title: FieldValue + path: /docs/reference/js/firestore_lite_pipelines.fieldvalue.md + - title: Firestore + path: /docs/reference/js/firestore_lite_pipelines.firestore.md + - title: FirestoreDataConverter + path: /docs/reference/js/firestore_lite_pipelines.firestoredataconverter.md + - title: FunctionExpression + path: /docs/reference/js/firestore_lite_pipelines.functionexpression.md + - title: GeoPoint + path: /docs/reference/js/firestore_lite_pipelines.geopoint.md + - title: Ordering + path: /docs/reference/js/firestore_lite_pipelines.ordering.md + - title: Pipeline + path: /docs/reference/js/firestore_lite_pipelines.pipeline.md + - title: PipelineResult + path: /docs/reference/js/firestore_lite_pipelines.pipelineresult.md + - title: PipelineSnapshot + path: /docs/reference/js/firestore_lite_pipelines.pipelinesnapshot.md + - title: PipelineSource + path: /docs/reference/js/firestore_lite_pipelines.pipelinesource.md + - title: Query + path: /docs/reference/js/firestore_lite_pipelines.query.md + - title: QueryDocumentSnapshot + path: /docs/reference/js/firestore_lite_pipelines.querydocumentsnapshot.md + - title: Selectable + path: /docs/reference/js/firestore_lite_pipelines.selectable.md + - title: StageOptions + path: /docs/reference/js/firestore_lite_pipelines.stageoptions.md + - title: Timestamp + path: /docs/reference/js/firestore_lite_pipelines.timestamp.md + - title: VectorValue + path: /docs/reference/js/firestore_lite_pipelines.vectorvalue.md +- title: firestore/pipelines + path: /docs/reference/js/firestore_pipelines.md + section: + - title: AggregateFunction + path: /docs/reference/js/firestore_pipelines.aggregatefunction.md + - title: AliasedAggregate + path: /docs/reference/js/firestore_pipelines.aliasedaggregate.md + - title: AliasedExpression + path: /docs/reference/js/firestore_pipelines.aliasedexpression.md + - title: BooleanExpression + path: /docs/reference/js/firestore_pipelines.booleanexpression.md + - title: Bytes + path: /docs/reference/js/firestore_pipelines.bytes.md + - title: CollectionReference + path: /docs/reference/js/firestore_pipelines.collectionreference.md + - title: DocumentData + path: /docs/reference/js/firestore_pipelines.documentdata.md + - title: DocumentReference + path: /docs/reference/js/firestore_pipelines.documentreference.md + - title: DocumentSnapshot + path: /docs/reference/js/firestore_pipelines.documentsnapshot.md + - title: Expression + path: /docs/reference/js/firestore_pipelines.expression.md + - title: Field + path: /docs/reference/js/firestore_pipelines.field.md + - title: FieldPath + path: /docs/reference/js/firestore_pipelines.fieldpath.md + - title: FieldValue + path: /docs/reference/js/firestore_pipelines.fieldvalue.md + - title: Firestore + path: /docs/reference/js/firestore_pipelines.firestore.md + - title: FirestoreDataConverter + path: /docs/reference/js/firestore_pipelines.firestoredataconverter.md + - title: FunctionExpression + path: /docs/reference/js/firestore_pipelines.functionexpression.md + - title: GeoPoint + path: /docs/reference/js/firestore_pipelines.geopoint.md + - title: Ordering + path: /docs/reference/js/firestore_pipelines.ordering.md + - title: Pipeline + path: /docs/reference/js/firestore_pipelines.pipeline.md + - title: PipelineExecuteOptions + path: /docs/reference/js/firestore_pipelines.pipelineexecuteoptions.md + - title: PipelineResult + path: /docs/reference/js/firestore_pipelines.pipelineresult.md + - title: PipelineSnapshot + path: /docs/reference/js/firestore_pipelines.pipelinesnapshot.md + - title: PipelineSource + path: /docs/reference/js/firestore_pipelines.pipelinesource.md + - title: Query + path: /docs/reference/js/firestore_pipelines.query.md + - title: QueryDocumentSnapshot + path: /docs/reference/js/firestore_pipelines.querydocumentsnapshot.md + - title: Selectable + path: /docs/reference/js/firestore_pipelines.selectable.md + - title: SnapshotMetadata + path: /docs/reference/js/firestore_pipelines.snapshotmetadata.md + - title: SnapshotOptions + path: /docs/reference/js/firestore_pipelines.snapshotoptions.md + - title: StageOptions + path: /docs/reference/js/firestore_pipelines.stageoptions.md + - title: Timestamp + path: /docs/reference/js/firestore_pipelines.timestamp.md + - title: VectorValue + path: /docs/reference/js/firestore_pipelines.vectorvalue.md - title: functions path: /docs/reference/js/functions.md section: diff --git a/docs-devsite/firestore.md b/docs-devsite/firestore.md index c8c647cf61..f44659816b 100644 --- a/docs-devsite/firestore.md +++ b/docs-devsite/firestore.md @@ -16,4 +16,6 @@ Cloud Firestore | --- | --- | | [/](./firestore_.md#@firebase/firestore) | | | [/lite](./firestore_lite.md#@firebase/firestore/lite) | | +| [/lite/pipelines](./firestore_lite_pipelines.md#@firebase/firestore/lite/pipelines) | | +| [/pipelines](./firestore_pipelines.md#@firebase/firestore/pipelines) | | diff --git a/docs-devsite/firestore_lite_pipelines.aggregatefunction.md b/docs-devsite/firestore_lite_pipelines.aggregatefunction.md new file mode 100644 index 0000000000..17925a6144 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.aggregatefunction.md @@ -0,0 +1,109 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# AggregateFunction class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +A class that represents an aggregate function. + +Signature: + +```typescript +export declare class AggregateFunction +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(name, params)](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunctionconstructor) | | (Public Preview) Constructs a new instance of the AggregateFunction class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [exprType](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunctionexprtype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [as(name)](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunctionas) | | (Public Preview) Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. +```typescript +// Calculate the average price of all items and assign it the alias "averagePrice". +firestore.pipeline().collection("items") + .aggregate(field("price").average().as("averagePrice")); + +``` + | + +## AggregateFunction.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `AggregateFunction` class + +Signature: + +```typescript +constructor(name: string, params: Expression[]); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | +| params | [Expression](./firestore_lite_pipelines.expression.md#expression_class)\[\] | | + +## AggregateFunction.exprType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +exprType: ExpressionType; +``` + +## AggregateFunction.as() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. + +```typescript +// Calculate the average price of all items and assign it the alias "averagePrice". +firestore.pipeline().collection("items") + .aggregate(field("price").average().as("averagePrice")); + +``` + +Signature: + +```typescript +as(name: string): AliasedAggregate; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | The alias to assign to this AggregateFunction. A new that wraps this AggregateFunction and associates it with the provided alias. | + +Returns: + +[AliasedAggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregate_class) + diff --git a/docs-devsite/firestore_lite_pipelines.aliasedaggregate.md b/docs-devsite/firestore_lite_pipelines.aliasedaggregate.md new file mode 100644 index 0000000000..47f02ca732 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.aliasedaggregate.md @@ -0,0 +1,78 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# AliasedAggregate class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An AggregateFunction with alias. + +Signature: + +```typescript +export declare class AliasedAggregate +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(aggregate, alias, \_methodName)](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregateconstructor) | | (Public Preview) Constructs a new instance of the AliasedAggregate class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [aggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregateaggregate) | | [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) | (Public Preview) | +| [alias](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregatealias) | | string | (Public Preview) | + +## AliasedAggregate.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `AliasedAggregate` class + +Signature: + +```typescript +constructor(aggregate: AggregateFunction, alias: string, _methodName: string | undefined); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| aggregate | [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) | | +| alias | string | | +| \_methodName | string \| undefined | | + +## AliasedAggregate.aggregate + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly aggregate: AggregateFunction; +``` + +## AliasedAggregate.alias + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly alias: string; +``` diff --git a/docs-devsite/firestore_lite_pipelines.aliasedexpression.md b/docs-devsite/firestore_lite_pipelines.aliasedexpression.md new file mode 100644 index 0000000000..9e65be574c --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.aliasedexpression.md @@ -0,0 +1,102 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# AliasedExpression class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + + +Signature: + +```typescript +export declare class AliasedExpression implements Selectable +``` +Implements: [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(expr, alias, \_methodName)](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionconstructor) | | (Public Preview) Constructs a new instance of the AliasedExpression class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [alias](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionalias) | | string | (Public Preview) | +| [expr](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionexpr) | | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | (Public Preview) | +| [exprType](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionexprtype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) | +| [selectable](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionselectable) | | true | (Public Preview) | + +## AliasedExpression.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `AliasedExpression` class + +Signature: + +```typescript +constructor(expr: Expression, alias: string, _methodName: string | undefined); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | +| alias | string | | +| \_methodName | string \| undefined | | + +## AliasedExpression.alias + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly alias: string; +``` + +## AliasedExpression.expr + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly expr: Expression; +``` + +## AliasedExpression.exprType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +exprType: ExpressionType; +``` + +## AliasedExpression.selectable + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +selectable: true; +``` diff --git a/docs-devsite/firestore_lite_pipelines.booleanexpression.md b/docs-devsite/firestore_lite_pipelines.booleanexpression.md new file mode 100644 index 0000000000..f77b0e503d --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.booleanexpression.md @@ -0,0 +1,274 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# BooleanExpression class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An interface that represents a filter condition. + +Signature: + +```typescript +export declare abstract class BooleanExpression extends Expression +``` +Extends: [Expression](./firestore_lite_pipelines.expression.md#expression_class) + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [conditional(thenExpr, elseExpr)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressionconditional) | | (Public Preview) Creates a conditional expression that evaluates to the 'then' expression if this expression evaluates to true, or evaluates to the 'else' expression if this expressions evaluates false. +```typescript +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor")); + +``` + | +| [countIf()](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioncountif) | | (Public Preview) Creates an aggregation that finds the count of input documents satisfying this boolean expression. +```typescript +// Find the count of documents with a score greater than 90 +field("score").greaterThan(90).countIf().as("highestScore"); + +``` + A new AggregateFunction representing the 'countIf' aggregation. | +| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. +```typescript +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +constant(50).divide('length').gt(1).ifError(constant(false)); + +``` + | +| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. +```typescript +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +constant(50).divide('length').gt(1).ifError(false); + +``` + | +| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. +```typescript +// Create an expression that protects against a divide by zero error. +constant(50).divide('length').gt(1).ifError(constant(0)); + +``` + | +| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. +```typescript +// Create an expression that protects against a divide by zero error. +constant(50).divide('length').gt(1).ifError(0); + +``` + | +| [not()](./firestore_lite_pipelines.booleanexpression.md#booleanexpressionnot) | | (Public Preview) Creates an expression that negates this boolean expression. +```typescript +// Find documents where the 'tags' field does not contain 'completed' +field("tags").arrayContains("completed").not(); + +``` + A new representing the negated filter condition. | + +## BooleanExpression.conditional() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a conditional expression that evaluates to the 'then' expression if `this` expression evaluates to `true`, or evaluates to the 'else' expression if `this` expressions evaluates `false`. + +```typescript +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor")); + +``` + +Signature: + +```typescript +conditional(thenExpr: Expression, elseExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| thenExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is true. | +| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. A new representing the conditional expression. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## BooleanExpression.countIf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the count of input documents satisfying this boolean expression. + +```typescript +// Find the count of documents with a score greater than 90 +field("score").greaterThan(90).countIf().as("highestScore"); + +``` + A new `AggregateFunction` representing the 'countIf' aggregation. + +Signature: + +```typescript +countIf(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + +```typescript +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +constant(50).divide('length').gt(1).ifError(constant(false)); + +``` + +Signature: + +```typescript +ifError(catchValue: BooleanExpression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| catchValue | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + +```typescript +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +constant(50).divide('length').gt(1).ifError(false); + +``` + +Signature: + +```typescript +ifError(catchValue: boolean): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| catchValue | boolean | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + +```typescript +// Create an expression that protects against a divide by zero error. +constant(50).divide('length').gt(1).ifError(constant(0)); + +``` + +Signature: + +```typescript +ifError(catchValue: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| catchValue | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + +```typescript +// Create an expression that protects against a divide by zero error. +constant(50).divide('length').gt(1).ifError(0); + +``` + +Signature: + +```typescript +ifError(catchValue: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| catchValue | unknown | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## BooleanExpression.not() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that negates this boolean expression. + +```typescript +// Find documents where the 'tags' field does not contain 'completed' +field("tags").arrayContains("completed").not(); + +``` + A new representing the negated filter condition. + +Signature: + +```typescript +not(): BooleanExpression; +``` +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + diff --git a/docs-devsite/firestore_lite_pipelines.bytes.md b/docs-devsite/firestore_lite_pipelines.bytes.md new file mode 100644 index 0000000000..472e606423 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.bytes.md @@ -0,0 +1,177 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Bytes class +An immutable object representing an array of bytes. + +Signature: + +```typescript +export declare class Bytes +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [fromBase64String(base64)](./firestore_lite_pipelines.bytes.md#bytesfrombase64string) | static | Creates a new Bytes object from the given Base64 string, converting it to bytes. | +| [fromJSON(json)](./firestore_lite_pipelines.bytes.md#bytesfromjson) | static | Builds a Bytes instance from a JSON object created by [Bytes.toJSON()](./firestore_.bytes.md#bytestojson). | +| [fromUint8Array(array)](./firestore_lite_pipelines.bytes.md#bytesfromuint8array) | static | Creates a new Bytes object from the given Uint8Array. | +| [isEqual(other)](./firestore_lite_pipelines.bytes.md#bytesisequal) | | Returns true if this Bytes object is equal to the provided one. | +| [toBase64()](./firestore_lite_pipelines.bytes.md#bytestobase64) | | Returns the underlying bytes as a Base64-encoded string. | +| [toJSON()](./firestore_lite_pipelines.bytes.md#bytestojson) | | Returns a JSON-serializable representation of this Bytes instance. | +| [toString()](./firestore_lite_pipelines.bytes.md#bytestostring) | | Returns a string representation of the Bytes object. | +| [toUint8Array()](./firestore_lite_pipelines.bytes.md#bytestouint8array) | | Returns the underlying bytes in a new Uint8Array. | + +## Bytes.fromBase64String() + +Creates a new `Bytes` object from the given Base64 string, converting it to bytes. + +Signature: + +```typescript +static fromBase64String(base64: string): Bytes; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| base64 | string | The Base64 string used to create the Bytes object. | + +Returns: + +[Bytes](./firestore_lite.bytes.md#bytes_class) + +## Bytes.fromJSON() + +Builds a `Bytes` instance from a JSON object created by [Bytes.toJSON()](./firestore_.bytes.md#bytestojson). + +Signature: + +```typescript +static fromJSON(json: object): Bytes; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| json | object | a JSON object represention of a Bytes instance | + +Returns: + +[Bytes](./firestore_lite.bytes.md#bytes_class) + +an instance of [Bytes](./firestore_.bytes.md#bytes_class) if the JSON object could be parsed. Throws a [FirestoreError](./firestore_.firestoreerror.md#firestoreerror_class) if an error occurs. + +## Bytes.fromUint8Array() + +Creates a new `Bytes` object from the given Uint8Array. + +Signature: + +```typescript +static fromUint8Array(array: Uint8Array): Bytes; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | Uint8Array | The Uint8Array used to create the Bytes object. | + +Returns: + +[Bytes](./firestore_lite.bytes.md#bytes_class) + +## Bytes.isEqual() + +Returns true if this `Bytes` object is equal to the provided one. + +Signature: + +```typescript +isEqual(other: Bytes): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [Bytes](./firestore_lite.bytes.md#bytes_class) | The Bytes object to compare against. | + +Returns: + +boolean + +true if this `Bytes` object is equal to the provided one. + +## Bytes.toBase64() + +Returns the underlying bytes as a Base64-encoded string. + +Signature: + +```typescript +toBase64(): string; +``` +Returns: + +string + +The Base64-encoded string created from the `Bytes` object. + +## Bytes.toJSON() + +Returns a JSON-serializable representation of this `Bytes` instance. + +Signature: + +```typescript +toJSON(): object; +``` +Returns: + +object + +a JSON representation of this object. + +## Bytes.toString() + +Returns a string representation of the `Bytes` object. + +Signature: + +```typescript +toString(): string; +``` +Returns: + +string + +A string representation of the `Bytes` object. + +## Bytes.toUint8Array() + +Returns the underlying bytes in a new `Uint8Array`. + +Signature: + +```typescript +toUint8Array(): Uint8Array; +``` +Returns: + +Uint8Array + +The Uint8Array created from the `Bytes` object. + diff --git a/docs-devsite/firestore_lite_pipelines.collectionreference.md b/docs-devsite/firestore_lite_pipelines.collectionreference.md new file mode 100644 index 0000000000..3107761b62 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.collectionreference.md @@ -0,0 +1,121 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# CollectionReference class +A `CollectionReference` object can be used for adding documents, getting document references, and querying for documents (using [query()](./firestore_.md#query_9f7b0f4)). + +Signature: + +```typescript +export declare class CollectionReference extends Query +``` +Extends: [Query](./firestore_lite.query.md#query_class)<AppModelType, DbModelType> + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [id](./firestore_lite_pipelines.collectionreference.md#collectionreferenceid) | | string | The collection's identifier. | +| [parent](./firestore_lite_pipelines.collectionreference.md#collectionreferenceparent) | | [DocumentReference](./firestore_lite.documentreference.md#documentreference_class)<[DocumentData](./firestore_lite.documentdata.md#documentdata_interface), [DocumentData](./firestore_lite.documentdata.md#documentdata_interface)> \| null | A reference to the containing DocumentReference if this is a subcollection. If this isn't a subcollection, the reference is null. | +| [path](./firestore_lite_pipelines.collectionreference.md#collectionreferencepath) | | string | A string representing the path of the referenced collection (relative to the root of the database). | +| [type](./firestore_lite_pipelines.collectionreference.md#collectionreferencetype) | | (not declared) | The type of this Firestore reference. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [withConverter(converter)](./firestore_lite_pipelines.collectionreference.md#collectionreferencewithconverter) | | Applies a custom data converter to this CollectionReference, allowing you to use your own custom model objects with Firestore. When you call [addDoc()](./firestore_.md#adddoc_6e783ff) with the returned CollectionReference instance, the provided converter will convert between Firestore data of type NewDbModelType and your custom type NewAppModelType. | +| [withConverter(converter)](./firestore_lite_pipelines.collectionreference.md#collectionreferencewithconverter) | | Removes the current converter. | + +## CollectionReference.id + +The collection's identifier. + +Signature: + +```typescript +get id(): string; +``` + +## CollectionReference.parent + +A reference to the containing `DocumentReference` if this is a subcollection. If this isn't a subcollection, the reference is null. + +Signature: + +```typescript +get parent(): DocumentReference | null; +``` + +## CollectionReference.path + +A string representing the path of the referenced collection (relative to the root of the database). + +Signature: + +```typescript +get path(): string; +``` + +## CollectionReference.type + +The type of this Firestore reference. + +Signature: + +```typescript +readonly type = "collection"; +``` + +## CollectionReference.withConverter() + +Applies a custom data converter to this `CollectionReference`, allowing you to use your own custom model objects with Firestore. When you call [addDoc()](./firestore_.md#adddoc_6e783ff) with the returned `CollectionReference` instance, the provided converter will convert between Firestore data of type `NewDbModelType` and your custom type `NewAppModelType`. + +Signature: + +```typescript +withConverter(converter: FirestoreDataConverter): CollectionReference; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| converter | [FirestoreDataConverter](./firestore_lite.firestoredataconverter.md#firestoredataconverter_interface)<NewAppModelType, NewDbModelType> | Converts objects to and from Firestore. | + +Returns: + +[CollectionReference](./firestore_lite.collectionreference.md#collectionreference_class)<NewAppModelType, NewDbModelType> + +A `CollectionReference` that uses the provided converter. + +## CollectionReference.withConverter() + +Removes the current converter. + +Signature: + +```typescript +withConverter(converter: null): CollectionReference; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| converter | null | null removes the current converter. | + +Returns: + +[CollectionReference](./firestore_lite.collectionreference.md#collectionreference_class)<[DocumentData](./firestore_lite.documentdata.md#documentdata_interface), [DocumentData](./firestore_lite.documentdata.md#documentdata_interface)> + +A `CollectionReference` that does not use a converter. + diff --git a/docs-devsite/firestore_lite_pipelines.documentdata.md b/docs-devsite/firestore_lite_pipelines.documentdata.md new file mode 100644 index 0000000000..c93565207a --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.documentdata.md @@ -0,0 +1,19 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# DocumentData interface +Document data (for use with [setDoc()](./firestore_lite.md#setdoc_ee215ad)) consists of fields mapped to values. + +Signature: + +```typescript +export declare interface DocumentData +``` diff --git a/docs-devsite/firestore_lite_pipelines.documentreference.md b/docs-devsite/firestore_lite_pipelines.documentreference.md new file mode 100644 index 0000000000..d5f35c6483 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.documentreference.md @@ -0,0 +1,207 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# DocumentReference class +A `DocumentReference` refers to a document location in a Firestore database and can be used to write, read, or listen to the location. The document at the referenced location may or may not exist. + +Signature: + +```typescript +export declare class DocumentReference +``` + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [converter](./firestore_lite_pipelines.documentreference.md#documentreferenceconverter) | | [FirestoreDataConverter](./firestore_lite.firestoredataconverter.md#firestoredataconverter_interface)<AppModelType, DbModelType> \| null | If provided, the FirestoreDataConverter associated with this instance. | +| [firestore](./firestore_lite_pipelines.documentreference.md#documentreferencefirestore) | | [Firestore](./firestore_lite.firestore.md#firestore_class) | The [Firestore](./firestore_.firestore.md#firestore_class) instance the document is in. This is useful for performing transactions, for example. | +| [id](./firestore_lite_pipelines.documentreference.md#documentreferenceid) | | string | The document's identifier within its collection. | +| [parent](./firestore_lite_pipelines.documentreference.md#documentreferenceparent) | | [CollectionReference](./firestore_lite.collectionreference.md#collectionreference_class)<AppModelType, DbModelType> | The collection this DocumentReference belongs to. | +| [path](./firestore_lite_pipelines.documentreference.md#documentreferencepath) | | string | A string representing the path of the referenced document (relative to the root of the database). | +| [type](./firestore_lite_pipelines.documentreference.md#documentreferencetype) | | (not declared) | The type of this Firestore reference. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [fromJSON(firestore, json)](./firestore_lite_pipelines.documentreference.md#documentreferencefromjson) | static | Builds a DocumentReference instance from a JSON object created by [DocumentReference.toJSON()](./firestore_.documentreference.md#documentreferencetojson). | +| [fromJSON(firestore, json, converter)](./firestore_lite_pipelines.documentreference.md#documentreferencefromjson) | static | Builds a DocumentReference instance from a JSON object created by [DocumentReference.toJSON()](./firestore_.documentreference.md#documentreferencetojson). | +| [toJSON()](./firestore_lite_pipelines.documentreference.md#documentreferencetojson) | | Returns a JSON-serializable representation of this DocumentReference instance. | +| [withConverter(converter)](./firestore_lite_pipelines.documentreference.md#documentreferencewithconverter) | | Applies a custom data converter to this DocumentReference, allowing you to use your own custom model objects with Firestore. When you call [setDoc()](./firestore_lite.md#setdoc_ee215ad), [getDoc()](./firestore_lite.md#getdoc_4569087), etc. with the returned DocumentReference instance, the provided converter will convert between Firestore data of type NewDbModelType and your custom type NewAppModelType. | +| [withConverter(converter)](./firestore_lite_pipelines.documentreference.md#documentreferencewithconverter) | | Removes the current converter. | + +## DocumentReference.converter + +If provided, the `FirestoreDataConverter` associated with this instance. + +Signature: + +```typescript +readonly converter: FirestoreDataConverter | null; +``` + +## DocumentReference.firestore + +The [Firestore](./firestore_.firestore.md#firestore_class) instance the document is in. This is useful for performing transactions, for example. + +Signature: + +```typescript +readonly firestore: Firestore; +``` + +## DocumentReference.id + +The document's identifier within its collection. + +Signature: + +```typescript +get id(): string; +``` + +## DocumentReference.parent + +The collection this `DocumentReference` belongs to. + +Signature: + +```typescript +get parent(): CollectionReference; +``` + +## DocumentReference.path + +A string representing the path of the referenced document (relative to the root of the database). + +Signature: + +```typescript +get path(): string; +``` + +## DocumentReference.type + +The type of this Firestore reference. + +Signature: + +```typescript +readonly type = "document"; +``` + +## DocumentReference.fromJSON() + +Builds a `DocumentReference` instance from a JSON object created by [DocumentReference.toJSON()](./firestore_.documentreference.md#documentreferencetojson). + +Signature: + +```typescript +static fromJSON(firestore: Firestore, json: object): DocumentReference; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| firestore | [Firestore](./firestore_lite.firestore.md#firestore_class) | The [Firestore](./firestore_.firestore.md#firestore_class) instance the snapshot should be loaded for. | +| json | object | a JSON object represention of a DocumentReference instance | + +Returns: + +[DocumentReference](./firestore_lite.documentreference.md#documentreference_class) + +an instance of [DocumentReference](./firestore_.documentreference.md#documentreference_class) if the JSON object could be parsed. Throws a [FirestoreError](./firestore_.firestoreerror.md#firestoreerror_class) if an error occurs. + +## DocumentReference.fromJSON() + +Builds a `DocumentReference` instance from a JSON object created by [DocumentReference.toJSON()](./firestore_.documentreference.md#documentreferencetojson). + +Signature: + +```typescript +static fromJSON(firestore: Firestore, json: object, converter: FirestoreDataConverter): DocumentReference; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| firestore | [Firestore](./firestore_lite.firestore.md#firestore_class) | The [Firestore](./firestore_.firestore.md#firestore_class) instance the snapshot should be loaded for. | +| json | object | a JSON object represention of a DocumentReference instance | +| converter | [FirestoreDataConverter](./firestore_lite.firestoredataconverter.md#firestoredataconverter_interface)<NewAppModelType, NewDbModelType> | Converts objects to and from Firestore. | + +Returns: + +[DocumentReference](./firestore_lite.documentreference.md#documentreference_class)<NewAppModelType, NewDbModelType> + +an instance of [DocumentReference](./firestore_.documentreference.md#documentreference_class) if the JSON object could be parsed. Throws a [FirestoreError](./firestore_.firestoreerror.md#firestoreerror_class) if an error occurs. + +## DocumentReference.toJSON() + +Returns a JSON-serializable representation of this `DocumentReference` instance. + +Signature: + +```typescript +toJSON(): object; +``` +Returns: + +object + +a JSON representation of this object. + +## DocumentReference.withConverter() + +Applies a custom data converter to this `DocumentReference`, allowing you to use your own custom model objects with Firestore. When you call [setDoc()](./firestore_lite.md#setdoc_ee215ad), [getDoc()](./firestore_lite.md#getdoc_4569087), etc. with the returned `DocumentReference` instance, the provided converter will convert between Firestore data of type `NewDbModelType` and your custom type `NewAppModelType`. + +Signature: + +```typescript +withConverter(converter: FirestoreDataConverter): DocumentReference; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| converter | [FirestoreDataConverter](./firestore_lite.firestoredataconverter.md#firestoredataconverter_interface)<NewAppModelType, NewDbModelType> | Converts objects to and from Firestore. | + +Returns: + +[DocumentReference](./firestore_lite.documentreference.md#documentreference_class)<NewAppModelType, NewDbModelType> + +A `DocumentReference` that uses the provided converter. + +## DocumentReference.withConverter() + +Removes the current converter. + +Signature: + +```typescript +withConverter(converter: null): DocumentReference; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| converter | null | null removes the current converter. | + +Returns: + +[DocumentReference](./firestore_lite.documentreference.md#documentreference_class)<[DocumentData](./firestore_lite.documentdata.md#documentdata_interface), [DocumentData](./firestore_lite.documentdata.md#documentdata_interface)> + +A `DocumentReference` that does not use a converter. + diff --git a/docs-devsite/firestore_lite_pipelines.documentsnapshot.md b/docs-devsite/firestore_lite_pipelines.documentsnapshot.md new file mode 100644 index 0000000000..2c8849818d --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.documentsnapshot.md @@ -0,0 +1,125 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# DocumentSnapshot class +A `DocumentSnapshot` contains data read from a document in your Firestore database. The data can be extracted with `.data()` or `.get()` to get a specific field. + +For a `DocumentSnapshot` that points to a non-existing document, any data access will return 'undefined'. You can use the `exists()` method to explicitly verify a document's existence. + +Signature: + +```typescript +export declare class DocumentSnapshot +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)()](./firestore_lite_pipelines.documentsnapshot.md#documentsnapshotconstructor) | | Constructs a new instance of the DocumentSnapshot class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [id](./firestore_lite_pipelines.documentsnapshot.md#documentsnapshotid) | | string | Property of the DocumentSnapshot that provides the document's ID. | +| [ref](./firestore_lite_pipelines.documentsnapshot.md#documentsnapshotref) | | [DocumentReference](./firestore_lite.documentreference.md#documentreference_class)<AppModelType, DbModelType> | The DocumentReference for the document included in the DocumentSnapshot. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [data()](./firestore_lite_pipelines.documentsnapshot.md#documentsnapshotdata) | | Retrieves all fields in the document as an Object. Returns undefined if the document doesn't exist. | +| [exists()](./firestore_lite_pipelines.documentsnapshot.md#documentsnapshotexists) | | Signals whether or not the document at the snapshot's location exists. | +| [get(fieldPath)](./firestore_lite_pipelines.documentsnapshot.md#documentsnapshotget) | | Retrieves the field specified by fieldPath. Returns undefined if the document or field doesn't exist. | + +## DocumentSnapshot.(constructor) + +Constructs a new instance of the `DocumentSnapshot` class + +Signature: + +```typescript +protected constructor(); +``` + +## DocumentSnapshot.id + +Property of the `DocumentSnapshot` that provides the document's ID. + +Signature: + +```typescript +get id(): string; +``` + +## DocumentSnapshot.ref + +The `DocumentReference` for the document included in the `DocumentSnapshot`. + +Signature: + +```typescript +get ref(): DocumentReference; +``` + +## DocumentSnapshot.data() + +Retrieves all fields in the document as an `Object`. Returns `undefined` if the document doesn't exist. + +Signature: + +```typescript +data(): AppModelType | undefined; +``` +Returns: + +AppModelType \| undefined + +An `Object` containing all fields in the document or `undefined` if the document doesn't exist. + +## DocumentSnapshot.exists() + +Signals whether or not the document at the snapshot's location exists. + +Signature: + +```typescript +exists(): this is QueryDocumentSnapshot; +``` +Returns: + +this is [QueryDocumentSnapshot](./firestore_lite.querydocumentsnapshot.md#querydocumentsnapshot_class)<AppModelType, DbModelType> + +true if the document exists. + +## DocumentSnapshot.get() + +Retrieves the field specified by `fieldPath`. Returns `undefined` if the document or field doesn't exist. + +Signature: + +```typescript +get(fieldPath: string | FieldPath): any; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldPath | string \| [FieldPath](./firestore_lite.fieldpath.md#fieldpath_class) | The path (for example 'foo' or 'foo.bar') to a specific field. | + +Returns: + +any + +The data at the specified field location or undefined if no such field exists in the document. + diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md new file mode 100644 index 0000000000..fbaba7d825 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -0,0 +1,4173 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Expression class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Represents an expression that can be evaluated to a value within the execution of a . + +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 `Expr` class provides a fluent API for building expressions. You can chain together method calls to create complex expressions. + +Signature: + +```typescript +export declare abstract class Expression +``` + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [expressionType](./firestore_lite_pipelines.expression.md#expressionexpressiontype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [abs()](./firestore_lite_pipelines.expression.md#expressionabs) | | (Public Preview) Creates an expression that computes the absolute value of a numeric value. +```typescript +// Compute the absolute value of the 'price' field. +field("price").abs(); + +``` + A new representing the absolute value of the numeric value. | +| [add(second)](./firestore_lite_pipelines.expression.md#expressionadd) | | (Public Preview) Creates an expression that adds this expression to another expression. +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +field("quantity").add(field("reserve")); + +``` + | +| [arrayConcat(secondArray, otherArrays)](./firestore_lite_pipelines.expression.md#expressionarrayconcat) | | (Public Preview) Creates an expression that concatenates an array expression with one or more other arrays. +```typescript +// Combine the 'items' array with another array field. +field("items").arrayConcat(field("otherItems")); + +``` + | +| [arrayContains(expression)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific element. +```typescript +// Check if the 'sizes' array contains the value from the 'selectedSize' field +field("sizes").arrayContains(field("selectedSize")); + +``` + | +| [arrayContains(value)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific value. +```typescript +// Check if the 'colors' array contains "red" +field("colors").arrayContains("red"); + +``` + | +| [arrayContainsAll(values)](./firestore_lite_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. +```typescript +// Check if the 'tags' array contains both the value in field "tag1" and the literal value "tag2" +field("tags").arrayContainsAll([field("tag1"), "tag2"]); + +``` + | +| [arrayContainsAll(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. +```typescript +// Check if the 'tags' array contains both of the values from field "tag1" and the literal value "tag2" +field("tags").arrayContainsAll(array([field("tag1"), "tag2"])); + +``` + | +| [arrayContainsAny(values)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. +```typescript +// Check if the 'categories' array contains either values from field "cate1" or "cate2" +field("categories").arrayContainsAny([field("cate1"), field("cate2")]); + +``` + | +| [arrayContainsAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. +```typescript +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); + +``` + | +| [arrayGet(offset)](./firestore_lite_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +```typescript +// Return the value in the 'tags' field array at index `1`. +field('tags').arrayGet(1); + +``` + | +| [arrayGet(offsetExpr)](./firestore_lite_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +field('tags').arrayGet(field('favoriteTag')); + +``` + | +| [arrayLength()](./firestore_lite_pipelines.expression.md#expressionarraylength) | | (Public Preview) Creates an expression that calculates the length of an array. +```typescript +// Get the number of items in the 'cart' array +field("cart").arrayLength(); + +``` + A new Expr representing the length of the array. | +| [arrayReverse()](./firestore_lite_pipelines.expression.md#expressionarrayreverse) | | (Public Preview) Creates an expression that reverses an array. +```typescript +// Reverse the value of the 'myArray' field. +field("myArray").arrayReverse(); + +``` + A new representing the reversed array. | +| [arraySum()](./firestore_lite_pipelines.expression.md#expressionarraysum) | | (Public Preview) Creates an expression that computes the sum of the elements in an array. +```typescript +// Compute the sum of the elements in the 'scores' field. +field("scores").arraySum(); + +``` + A new representing the sum of the elements in the array. | +| [as(name)](./firestore_lite_pipelines.expression.md#expressionas) | | (Public Preview) 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. +```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")); + +``` + | +| [asBoolean()](./firestore_lite_pipelines.expression.md#expressionasboolean) | | (Public Preview) Wraps the expression in a \[BooleanExpression\]. A \[BooleanExpression\] representing the same expression. | +| [ascending()](./firestore_lite_pipelines.expression.md#expressionascending) | | (Public Preview) Creates an that sorts documents in ascending order based on this expression. +```typescript +// Sort documents by the 'name' field in ascending order +pipeline().collection("users") + .sort(field("name").ascending()); + +``` + A new Ordering for ascending sorting. | +| [average()](./firestore_lite_pipelines.expression.md#expressionaverage) | | (Public Preview) Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. +```typescript +// Calculate the average age of users +field("age").average().as("averageAge"); + +``` + A new AggregateFunction representing the 'average' aggregation. | +| [byteLength()](./firestore_lite_pipelines.expression.md#expressionbytelength) | | (Public Preview) Creates an expression that calculates the length of this string expression in bytes. +```typescript +// Calculate the length of the 'myString' field in bytes. +field("myString").byteLength(); + +``` + A new representing the length of the string in bytes. | +| [ceil()](./firestore_lite_pipelines.expression.md#expressionceil) | | (Public Preview) Creates an expression that computes the ceiling of a numeric value. +```typescript +// Compute the ceiling of the 'price' field. +field("price").ceil(); + +``` + A new representing the ceiling of the numeric value. | +| [charLength()](./firestore_lite_pipelines.expression.md#expressioncharlength) | | (Public Preview) Creates an expression that calculates the character length of a string in UTF-8. +```typescript +// Get the character length of the 'name' field in its UTF-8 form. +field("name").charLength(); + +``` + A new Expr representing the length of the string. | +| [collectionId()](./firestore_lite_pipelines.expression.md#expressioncollectionid) | | (Public Preview) Creates an expression that returns the collection ID from a path. +```typescript +// Get the collection ID from a path. +field("__path__").collectionId(); + +``` + A new representing the collectionId operation. | +| [concat(second, others)](./firestore_lite_pipelines.expression.md#expressionconcat) | | (Public Preview) Creates an expression that concatenates expression results together. +```typescript +// Combine the 'firstName', ' ', and 'lastName' fields into a single value. +field("firstName").concat(constant(" "), field("lastName")); + +``` + | +| [cosineDistance(vectorExpression)](./firestore_lite_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the cosine distance between two vectors. +```typescript +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +field("userVector").cosineDistance(field("itemVector")); + +``` + | +| [cosineDistance(vector)](./firestore_lite_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the Cosine distance between two vectors. +```typescript +// Calculate the Cosine distance between the 'location' field and a target location +field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); + +``` + | +| [count()](./firestore_lite_pipelines.expression.md#expressioncount) | | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. +```typescript +// Count the total number of products +field("productId").count().as("totalProducts"); + +``` + A new AggregateFunction representing the 'count' aggregation. | +| [countDistinct()](./firestore_lite_pipelines.expression.md#expressioncountdistinct) | | (Public Preview) Creates an aggregation that counts the number of distinct values of the expression or field. +```typescript +// Count the distinct number of products +field("productId").countDistinct().as("distinctProducts"); + +``` + A new AggregateFunction representing the 'count\_distinct' aggregation. | +| [descending()](./firestore_lite_pipelines.expression.md#expressiondescending) | | (Public Preview) Creates an that sorts documents in descending order based on this expression. +```typescript +// Sort documents by the 'createdAt' field in descending order +firestore.pipeline().collection("users") + .sort(field("createdAt").descending()); + +``` + A new Ordering for descending sorting. | +| [divide(divisor)](./firestore_lite_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by another expression. +```typescript +// Divide the 'total' field by the 'count' field +field("total").divide(field("count")); + +``` + | +| [divide(divisor)](./firestore_lite_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by a constant value. +```typescript +// Divide the 'value' field by 10 +field("value").divide(10); + +``` + | +| [documentId()](./firestore_lite_pipelines.expression.md#expressiondocumentid) | | (Public Preview) Creates an expression that returns the document ID from a path. +```typescript +// Get the document ID from a path. +field("__path__").documentId(); + +``` + A new representing the documentId operation. | +| [dotProduct(vectorExpression)](./firestore_lite_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. +```typescript +// Calculate the dot product between a feature vector and a target vector +field("features").dotProduct([0.5, 0.8, 0.2]); + +``` + | +| [dotProduct(vector)](./firestore_lite_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. +```typescript +// Calculate the dot product between a feature vector and a target vector +field("features").dotProduct(new VectorValue([0.5, 0.8, 0.2])); + +``` + | +| [endsWith(suffix)](./firestore_lite_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix. +```typescript +// Check if the 'filename' field ends with ".txt" +field("filename").endsWith(".txt"); + +``` + | +| [endsWith(suffix)](./firestore_lite_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix (represented as an expression). +```typescript +// Check if the 'url' field ends with the value of the 'extension' field +field("url").endsWith(field("extension")); + +``` + | +| [equal(expression)](./firestore_lite_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to another expression. +```typescript +// Check if the 'age' field is equal to 21 +field("age").equal(21); + +``` + | +| [equal(value)](./firestore_lite_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to a constant value. +```typescript +// Check if the 'city' field is equal to "London" +field("city").equal("London"); + +``` + | +| [equalAny(values)](./firestore_lite_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +field("category").equalAny("Electronics", field("primaryType")); + +``` + | +| [equalAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +field("category").equalAny(array(["Electronics", field("primaryType")])); + +``` + | +| [euclideanDistance(vectorExpression)](./firestore_lite_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location +field("location").euclideanDistance([37.7749, -122.4194]); + +``` + | +| [euclideanDistance(vector)](./firestore_lite_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location +field("location").euclideanDistance(new VectorValue([37.7749, -122.4194])); + +``` + | +| [exists()](./firestore_lite_pipelines.expression.md#expressionexists) | | (Public Preview) Creates an expression that checks if a field exists in the document. +```typescript +// Check if the document has a field named "phoneNumber" +field("phoneNumber").exists(); + +``` + A new Expr representing the 'exists' check. | +| [exp()](./firestore_lite_pipelines.expression.md#expressionexp) | | (Public Preview) Creates an expression that computes e to the power of this expression. +```typescript +// Compute e to the power of the 'value' field. +field("value").exp(); + +``` + A new representing the exp of the numeric value. | +| [floor()](./firestore_lite_pipelines.expression.md#expressionfloor) | | (Public Preview) Creates an expression that computes the floor of a numeric value. +```typescript +// Compute the floor of the 'price' field. +field("price").floor(); + +``` + A new representing the floor of the numeric value. | +| [greaterThan(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than another expression. +```typescript +// Check if the 'age' field is greater than the 'limit' field +field("age").greaterThan(field("limit")); + +``` + | +| [greaterThan(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than a constant value. +```typescript +// Check if the 'price' field is greater than 100 +field("price").greaterThan(100); + +``` + | +| [greaterThanOrEqual(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to another expression. +```typescript +// Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1 +field("quantity").greaterThanOrEqual(field('requirement').add(1)); + +``` + | +| [greaterThanOrEqual(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to a constant value. +```typescript +// Check if the 'score' field is greater than or equal to 80 +field("score").greaterThanOrEqual(80); + +``` + | +| [ifAbsent(elseValue)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of the this expression evaluation. +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +field("optional_field").ifAbsent("default_value") + +``` + | +| [ifAbsent(elseExpression)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. +```typescript +// Returns the value of the optional field 'optional_field', or if that is +// absent, then returns the value of the field ` +field("optional_field").ifAbsent(field('default_field')) + +``` + | +| [ifError(catchExpr)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. +```typescript +// Returns the first item in the title field arrays, or returns +// the entire title field if the array is empty or the field is another type. +field("title").arrayGet(0).ifError(field("title")); + +``` + | +| [ifError(catchValue)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. +```typescript +// Returns the first item in the title field arrays, or returns +// "Default Title" +field("title").arrayGet(0).ifError("Default Title"); + +``` + | +| [isAbsent()](./firestore_lite_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. +```typescript +// Check if the field `value` is absent. +field("value").isAbsent(); + +``` + A new representing the 'isAbsent' check. | +| [isError()](./firestore_lite_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. +```typescript +// Check if the result of a calculation is an error +field("title").arrayContains(1).isError(); + +``` + A new representing the 'isError' check. | +| [join(delimiterExpression)](./firestore_lite_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array into a string. +```typescript +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +field("tags").join(field("separator")) + +``` + | +| [join(delimiter)](./firestore_lite_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array field into a string. +```typescript +// Join the elements of the 'tags' field with a comma and space. +field("tags").join(", ") + +``` + | +| [length()](./firestore_lite_pipelines.expression.md#expressionlength) | | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. +```typescript +// Get the length of the 'name' field. +field("name").length(); + +// Get the number of items in the 'cart' array. +field("cart").length(); + +``` + A new Expr representing the length of the string, array, map, vector, or bytes. | +| [lessThan(experession)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than another expression. +```typescript +// Check if the 'age' field is less than 'limit' +field("age").lessThan(field('limit')); + +``` + | +| [lessThan(value)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than a constant value. +```typescript +// Check if the 'price' field is less than 50 +field("price").lessThan(50); + +``` + | +| [lessThanOrEqual(expression)](./firestore_lite_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to another expression. +```typescript +// Check if the 'quantity' field is less than or equal to 20 +field("quantity").lessThan(constant(20)); + +``` + | +| [lessThanOrEqual(value)](./firestore_lite_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to a constant value. +```typescript +// Check if the 'score' field is less than or equal to 70 +field("score").lessThan(70); + +``` + | +| [like(pattern)](./firestore_lite_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. +```typescript +// Check if the 'title' field contains the word "guide" (case-sensitive) +field("title").like("%guide%"); + +``` + | +| [like(pattern)](./firestore_lite_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. +```typescript +// Check if the 'title' field contains the word "guide" (case-sensitive) +field("title").like("%guide%"); + +``` + | +| [ln()](./firestore_lite_pipelines.expression.md#expressionln) | | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. +```typescript +// Compute the natural logarithm of the 'value' field. +field("value").ln(); + +``` + A new representing the natural logarithm of the numeric value. | +| [log10()](./firestore_lite_pipelines.expression.md#expressionlog10) | | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. +```typescript +// Compute the base-10 logarithm of the 'value' field. +field("value").log10(); + +``` + A new representing the base-10 logarithm of the numeric value. | +| [logicalMaximum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalmaximum) | | (Public Preview) Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. +```typescript +// Returns the larger value between the 'timestamp' field and the current timestamp. +field("timestamp").logicalMaximum(Function.currentTimestamp()); + +``` + | +| [logicalMinimum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalminimum) | | (Public Preview) Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. +```typescript +// Returns the smaller value between the 'timestamp' field and the current timestamp. +field("timestamp").logicalMinimum(Function.currentTimestamp()); + +``` + | +| [mapGet(subfield)](./firestore_lite_pipelines.expression.md#expressionmapget) | | (Public Preview) Accesses a value from a map (object) field using the provided key. +```typescript +// Get the 'city' value from the 'address' map field +field("address").mapGet("city"); + +``` + | +| [mapMerge(secondMap, otherMaps)](./firestore_lite_pipelines.expression.md#expressionmapmerge) | | (Public Preview) Creates an expression that merges multiple map values. +``` +// 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}, {}) + +``` + | +| [mapRemove(key)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. +``` +// Removes the key 'baz' from the input map. +map({foo: 'bar', baz: true}).mapRemove('baz'); + +``` + | +| [mapRemove(keyExpr)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. +``` +// Removes the key 'baz' from the input map. +map({foo: 'bar', baz: true}).mapRemove(constant('baz')); + +``` + | +| [maximum()](./firestore_lite_pipelines.expression.md#expressionmaximum) | | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. +```typescript +// Find the highest score in a leaderboard +field("score").maximum().as("highestScore"); + +``` + A new AggregateFunction representing the 'maximum' aggregation. | +| [minimum()](./firestore_lite_pipelines.expression.md#expressionminimum) | | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. +```typescript +// Find the lowest price of all products +field("price").minimum().as("lowestPrice"); + +``` + A new AggregateFunction representing the 'minimum' aggregation. | +| [mod(expression)](./firestore_lite_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. +```typescript +// Calculate the remainder of dividing the 'value' field by the 'divisor' field +field("value").mod(field("divisor")); + +``` + | +| [mod(value)](./firestore_lite_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. +```typescript +// Calculate the remainder of dividing the 'value' field by 10 +field("value").mod(10); + +``` + | +| [multiply(second)](./firestore_lite_pipelines.expression.md#expressionmultiply) | | (Public Preview) Creates an expression that multiplies this expression by another expression. +```typescript +// Multiply the 'quantity' field by the 'price' field +field("quantity").multiply(field("price")); + +``` + | +| [notEqual(expression)](./firestore_lite_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to another expression. +```typescript +// Check if the 'status' field is not equal to "completed" +field("status").notEqual("completed"); + +``` + | +| [notEqual(value)](./firestore_lite_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to a constant value. +```typescript +// Check if the 'country' field is not equal to "USA" +field("country").notEqual("USA"); + +``` + | +| [notEqualAny(values)](./firestore_lite_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the provided values or expressions. +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +field("status").notEqualAny(["pending", field("rejectedStatus")]); + +``` + | +| [notEqualAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. +```typescript +// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' +field("status").notEqualAny(field('rejectedStatuses')); + +``` + | +| [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of another expression. +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +field("base").pow(field("exponent")); + +``` + | +| [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of a constant value. +```typescript +// Raise the value of the 'base' field to the power of 2. +field("base").pow(2); + +``` + | +| [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +field("description").regexContains("(?i)example"); + +``` + | +| [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. +```typescript +// Check if the 'description' field contains the regular expression stored in field 'regex' +field("description").regexContains(field("regex")); + +``` + | +| [regexMatch(pattern)](./firestore_lite_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. +```typescript +// Check if the 'email' field matches a valid email pattern +field("email").regexMatch("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + +``` + | +| [regexMatch(pattern)](./firestore_lite_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. +```typescript +// Check if the 'email' field matches a regular expression stored in field 'regex' +field("email").regexMatch(field("regex")); + +``` + | +| [reverse()](./firestore_lite_pipelines.expression.md#expressionreverse) | | (Public Preview) Creates an expression that reverses this string expression. +```typescript +// Reverse the value of the 'myString' field. +field("myString").reverse(); + +``` + A new representing the reversed string. | +| [round()](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. +```typescript +// Round the value of the 'price' field. +field("price").round(); + +``` + A new Expr representing the rounded value. | +| [round(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. +```typescript +// Round the value of the 'price' field to two decimal places. +field("price").round(2); + +``` + | +| [round(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. +```typescript +// Round the value of the 'price' field to two decimal places. +field("price").round(constant(2)); + +``` + | +| [split(delimiter)](./firestore_lite_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | +| [split(delimiter)](./firestore_lite_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | +| [sqrt()](./firestore_lite_pipelines.expression.md#expressionsqrt) | | (Public Preview) Creates an expression that computes the square root of a numeric value. +```typescript +// Compute the square root of the 'value' field. +field("value").sqrt(); + +``` + A new representing the square root of the numeric value. | +| [startsWith(prefix)](./firestore_lite_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix. +```typescript +// Check if the 'name' field starts with "Mr." +field("name").startsWith("Mr."); + +``` + | +| [startsWith(prefix)](./firestore_lite_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix (represented as an expression). +```typescript +// Check if the 'fullName' field starts with the value of the 'firstName' field +field("fullName").startsWith(field("firstName")); + +``` + | +| [stringConcat(secondString, otherStrings)](./firestore_lite_pipelines.expression.md#expressionstringconcat) | | (Public Preview) Creates an expression that concatenates string expressions together. +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +field("firstName").stringConcat(constant(" "), field("lastName")); + +``` + | +| [stringContains(substring)](./firestore_lite_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified substring. +```typescript +// Check if the 'description' field contains "example". +field("description").stringContains("example"); + +``` + | +| [stringContains(expr)](./firestore_lite_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains the string represented by another expression. +```typescript +// Check if the 'description' field contains the value of the 'keyword' field. +field("description").stringContains(field("keyword")); + +``` + | +| [stringReverse()](./firestore_lite_pipelines.expression.md#expressionstringreverse) | | (Public Preview) Creates an expression that reverses a string. +```typescript +// Reverse the value of the 'myString' field. +field("myString").stringReverse(); + +``` + A new representing the reversed string. | +| [substring(position, length)](./firestore_lite_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | +| [substring(position, length)](./firestore_lite_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | +| [subtract(subtrahend)](./firestore_lite_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts another expression from this expression. +```typescript +// Subtract the 'discount' field from the 'price' field +field("price").subtract(field("discount")); + +``` + | +| [subtract(subtrahend)](./firestore_lite_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts a constant value from this expression. +```typescript +// Subtract 20 from the value of the 'total' field +field("total").subtract(20); + +``` + | +| [sum()](./firestore_lite_pipelines.expression.md#expressionsum) | | (Public Preview) Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. +```typescript +// Calculate the total revenue from a set of orders +field("orderAmount").sum().as("totalRevenue"); + +``` + A new AggregateFunction representing the 'sum' aggregation. | +| [timestampAdd(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. +```typescript +// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. +field("timestamp").timestampAdd(field("unit"), field("amount")); + +``` + | +| [timestampAdd(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. +```typescript +// Add 1 day to the 'timestamp' field. +field("timestamp").timestampAdd("day", 1); + +``` + | +| [timestampSubtract(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. +```typescript +// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. +field("timestamp").timestampSubtract(field("unit"), field("amount")); + +``` + | +| [timestampSubtract(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. +```typescript +// Subtract 1 day from the 'timestamp' field. +field("timestamp").timestampSubtract("day", 1); + +``` + | +| [timestampToUnixMicros()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixmicros) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +field("timestamp").timestampToUnixMicros(); + +``` + A new representing the number of microseconds since epoch. | +| [timestampToUnixMillis()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixmillis) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +field("timestamp").timestampToUnixMillis(); + +``` + A new representing the number of milliseconds since epoch. | +| [timestampToUnixSeconds()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixseconds) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to seconds since epoch. +field("timestamp").timestampToUnixSeconds(); + +``` + A new representing the number of seconds since epoch. | +| [timestampTruncate(granularity, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestamptruncate) | | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(granularity, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestamptruncate) | | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [toLower()](./firestore_lite_pipelines.expression.md#expressiontolower) | | (Public Preview) Creates an expression that converts a string to lowercase. +```typescript +// Convert the 'name' field to lowercase +field("name").toLower(); + +``` + A new Expr representing the lowercase string. | +| [toUpper()](./firestore_lite_pipelines.expression.md#expressiontoupper) | | (Public Preview) Creates an expression that converts a string to uppercase. +```typescript +// Convert the 'title' field to uppercase +field("title").toUpper(); + +``` + A new Expr representing the uppercase string. | +| [trim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressiontrim) | | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array. +```typescript +// Trim whitespace from the 'userInput' field +field("userInput").trim(); + +// Trim quotes from the 'userInput' field +field("userInput").trim('"'); + +``` + | +| [type()](./firestore_lite_pipelines.expression.md#expressiontype) | | (Public Preview) Creates an expression that returns the data type of this expression's result, as a string. | +| [unixMicrosToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixmicrostotimestamp) | | (Public Preview) 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. +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +field("microseconds").unixMicrosToTimestamp(); + +``` + A new representing the timestamp. | +| [unixMillisToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixmillistotimestamp) | | (Public Preview) 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. +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +field("milliseconds").unixMillisToTimestamp(); + +``` + A new representing the timestamp. | +| [unixSecondsToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixsecondstotimestamp) | | (Public Preview) 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. +```typescript +// Interpret the 'seconds' field as seconds since epoch. +field("seconds").unixSecondsToTimestamp(); + +``` + A new representing the timestamp. | +| [vectorLength()](./firestore_lite_pipelines.expression.md#expressionvectorlength) | | (Public Preview) Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. +```typescript +// Get the vector length (dimension) of the field 'embedding'. +field("embedding").vectorLength(); + +``` + A new representing the length of the vector. | + +## Expression.expressionType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +abstract readonly expressionType: ExpressionType; +``` + +## Expression.abs() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the absolute value of a numeric value. + +```typescript +// Compute the absolute value of the 'price' field. +field("price").abs(); + +``` + A new representing the absolute value of the numeric value. + +Signature: + +```typescript +abs(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.add() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds this expression to another expression. + +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +field("quantity").add(field("reserve")); + +``` + +Signature: + +```typescript +add(second: Expression | unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The expression or literal to add to this expression. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.arrayConcat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates an array expression with one or more other arrays. + +```typescript +// Combine the 'items' array with another array field. +field("items").arrayConcat(field("otherItems")); + +``` + +Signature: + +```typescript +arrayConcat(secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| secondArray | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\] | Second array expression or array literal to concatenate. | +| otherArrays | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. A new Expr representing the concatenated array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.arrayContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains a specific element. + +```typescript +// Check if the 'sizes' array contains the value from the 'selectedSize' field +field("sizes").arrayContains(field("selectedSize")); + +``` + +Signature: + +```typescript +arrayContains(expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The element to search for in the array. A new Expr representing the 'array\_contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.arrayContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains a specific value. + +```typescript +// Check if the 'colors' array contains "red" +field("colors").arrayContains("red"); + +``` + +Signature: + +```typescript +arrayContains(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The element to search for in the array. A new Expr representing the 'array\_contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.arrayContainsAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains all the specified elements. + +```typescript +// Check if the 'tags' array contains both the value in field "tag1" and the literal value "tag2" +field("tags").arrayContainsAll([field("tag1"), "tag2"]); + +``` + +Signature: + +```typescript +arrayContainsAll(values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new Expr representing the 'array\_contains\_all' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.arrayContainsAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains all the specified elements. + +```typescript +// Check if the 'tags' array contains both of the values from field "tag1" and the literal value "tag2" +field("tags").arrayContainsAll(array([field("tag1"), "tag2"])); + +``` + +Signature: + +```typescript +arrayContainsAll(arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. A new Expr representing the 'array\_contains\_all' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.arrayContainsAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains any of the specified elements. + +```typescript +// Check if the 'categories' array contains either values from field "cate1" or "cate2" +field("categories").arrayContainsAny([field("cate1"), field("cate2")]); + +``` + +Signature: + +```typescript +arrayContainsAny(values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new Expr representing the 'array\_contains\_any' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.arrayContainsAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains any of the specified elements. + +```typescript +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); + +``` + +Signature: + +```typescript +arrayContainsAny(arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. A new Expr representing the 'array\_contains\_any' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.arrayGet() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + +```typescript +// Return the value in the 'tags' field array at index `1`. +field('tags').arrayGet(1); + +``` + +Signature: + +```typescript +arrayGet(offset: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| offset | number | The index of the element to return. A new Expr representing the 'arrayGet' operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.arrayGet() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +field('tags').arrayGet(field('favoriteTag')); + +``` + +Signature: + +```typescript +arrayGet(offsetExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expr evaluating to the index of the element to return. A new Expr representing the 'arrayGet' operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.arrayLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of an array. + +```typescript +// Get the number of items in the 'cart' array +field("cart").arrayLength(); + +``` + A new `Expr` representing the length of the array. + +Signature: + +```typescript +arrayLength(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.arrayReverse() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses an array. + +```typescript +// Reverse the value of the 'myArray' field. +field("myArray").arrayReverse(); + +``` + A new representing the reversed array. + +Signature: + +```typescript +arrayReverse(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.arraySum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. + +```typescript +// Compute the sum of the elements in the 'scores' field. +field("scores").arraySum(); + +``` + A new representing the sum of the elements in the array. + +Signature: + +```typescript +arraySum(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.as() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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. + +```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")); + +``` + +Signature: + +```typescript +as(name: string): AliasedExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | The alias to assign to this expression. A new that wraps this expression and associates it with the provided alias. | + +Returns: + +[AliasedExpression](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpression_class) + +## Expression.asBoolean() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Wraps the expression in a \[BooleanExpression\]. + + A \[BooleanExpression\] representing the same expression. + +Signature: + +```typescript +asBoolean(): BooleanExpression; +``` +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.ascending() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an that sorts documents in ascending order based on this expression. + +```typescript +// Sort documents by the 'name' field in ascending order +pipeline().collection("users") + .sort(field("name").ascending()); + +``` + A new `Ordering` for ascending sorting. + +Signature: + +```typescript +ascending(): Ordering; +``` +Returns: + +[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) + +## Expression.average() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. + +```typescript +// Calculate the average age of users +field("age").average().as("averageAge"); + +``` + A new `AggregateFunction` representing the 'average' aggregation. + +Signature: + +```typescript +average(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +## Expression.byteLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of this string expression in bytes. + +```typescript +// Calculate the length of the 'myString' field in bytes. +field("myString").byteLength(); + +``` + A new representing the length of the string in bytes. + +Signature: + +```typescript +byteLength(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.ceil() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. + +```typescript +// Compute the ceiling of the 'price' field. +field("price").ceil(); + +``` + A new representing the ceiling of the numeric value. + +Signature: + +```typescript +ceil(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.charLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the character length of a string in UTF-8. + +```typescript +// Get the character length of the 'name' field in its UTF-8 form. +field("name").charLength(); + +``` + A new `Expr` representing the length of the string. + +Signature: + +```typescript +charLength(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.collectionId() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. + +```typescript +// Get the collection ID from a path. +field("__path__").collectionId(); + +``` + A new representing the collectionId operation. + +Signature: + +```typescript +collectionId(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.concat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates expression results together. + +```typescript +// Combine the 'firstName', ' ', and 'lastName' fields into a single value. +field("firstName").concat(constant(" "), field("lastName")); + +``` + +Signature: + +```typescript +concat(second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The additional expression or literal to concatenate. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals to concatenate. A new Expr representing the concatenated value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.cosineDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the cosine distance between two vectors. + +```typescript +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +field("userVector").cosineDistance(field("itemVector")); + +``` + +Signature: + +```typescript +cosineDistance(vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new Expr representing the cosine distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.cosineDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between two vectors. + +```typescript +// Calculate the Cosine distance between the 'location' field and a target location +field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); + +``` + +Signature: + +```typescript +cosineDistance(vector: VectorValue | number[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vector | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as a VectorValue) to compare against. A new Expr representing the Cosine\* distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.count() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. + +```typescript +// Count the total number of products +field("productId").count().as("totalProducts"); + +``` + A new `AggregateFunction` representing the 'count' aggregation. + +Signature: + +```typescript +count(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +## Expression.countDistinct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of distinct values of the expression or field. + +```typescript +// Count the distinct number of products +field("productId").countDistinct().as("distinctProducts"); + +``` + A new `AggregateFunction` representing the 'count\_distinct' aggregation. + +Signature: + +```typescript +countDistinct(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +## Expression.descending() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an that sorts documents in descending order based on this expression. + +```typescript +// Sort documents by the 'createdAt' field in descending order +firestore.pipeline().collection("users") + .sort(field("createdAt").descending()); + +``` + A new `Ordering` for descending sorting. + +Signature: + +```typescript +descending(): Ordering; +``` +Returns: + +[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) + +## Expression.divide() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides this expression by another expression. + +```typescript +// Divide the 'total' field by the 'count' field +field("total").divide(field("count")); + +``` + +Signature: + +```typescript +divide(divisor: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| divisor | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to divide by. A new Expr representing the division operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.divide() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides this expression by a constant value. + +```typescript +// Divide the 'value' field by 10 +field("value").divide(10); + +``` + +Signature: + +```typescript +divide(divisor: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| divisor | number | The constant value to divide by. A new Expr representing the division operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.documentId() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the document ID from a path. + +```typescript +// Get the document ID from a path. +field("__path__").documentId(); + +``` + A new representing the documentId operation. + +Signature: + +```typescript +documentId(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.dotProduct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between two vectors. + +```typescript +// Calculate the dot product between a feature vector and a target vector +field("features").dotProduct([0.5, 0.8, 0.2]); + +``` + +Signature: + +```typescript +dotProduct(vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (as an array of numbers) to calculate with. A new Expr representing the dot product between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.dotProduct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between two vectors. + +```typescript +// Calculate the dot product between a feature vector and a target vector +field("features").dotProduct(new VectorValue([0.5, 0.8, 0.2])); + +``` + +Signature: + +```typescript +dotProduct(vector: VectorValue | number[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vector | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as an array of numbers) to calculate with. A new Expr representing the dot product between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.endsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string ends with a given postfix. + +```typescript +// Check if the 'filename' field ends with ".txt" +field("filename").endsWith(".txt"); + +``` + +Signature: + +```typescript +endsWith(suffix: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| suffix | string | The postfix to check for. A new Expr representing the 'ends with' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.endsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string ends with a given postfix (represented as an expression). + +```typescript +// Check if the 'url' field ends with the value of the 'extension' field +field("url").endsWith(field("extension")); + +``` + +Signature: + +```typescript +endsWith(suffix: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| suffix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The postfix expression to check for. A new Expr representing the 'ends with' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.equal() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to another expression. + +```typescript +// Check if the 'age' field is equal to 21 +field("age").equal(21); + +``` + +Signature: + +```typescript +equal(expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for equality. A new Expr representing the equality comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.equal() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to a constant value. + +```typescript +// Check if the 'city' field is equal to "London" +field("city").equal("London"); + +``` + +Signature: + +```typescript +equal(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The constant value to compare for equality. A new Expr representing the equality comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.equalAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to any of the provided values or expressions. + +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +field("category").equalAny("Electronics", field("primaryType")); + +``` + +Signature: + +```typescript +equalAny(values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values or expressions to check against. A new Expr representing the 'IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.equalAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to any of the provided values or expressions. + +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +field("category").equalAny(array(["Electronics", field("primaryType")])); + +``` + +Signature: + +```typescript +equalAny(arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array of values to check against. A new Expr representing the 'IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.euclideanDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between two vectors. + +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location +field("location").euclideanDistance([37.7749, -122.4194]); + +``` + +Signature: + +```typescript +euclideanDistance(vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (as an array of numbers) to calculate with. A new Expr representing the Euclidean distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.euclideanDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between two vectors. + +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location +field("location").euclideanDistance(new VectorValue([37.7749, -122.4194])); + +``` + +Signature: + +```typescript +euclideanDistance(vector: VectorValue | number[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vector | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as a VectorValue) to compare against. A new Expr representing the Euclidean distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.exists() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field exists in the document. + +```typescript +// Check if the document has a field named "phoneNumber" +field("phoneNumber").exists(); + +``` + A new `Expr` representing the 'exists' check. + +Signature: + +```typescript +exists(): BooleanExpression; +``` +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.exp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes e to the power of this expression. + +```typescript +// Compute e to the power of the 'value' field. +field("value").exp(); + +``` + A new representing the exp of the numeric value. + +Signature: + +```typescript +exp(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.floor() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the floor of a numeric value. + +```typescript +// Compute the floor of the 'price' field. +field("price").floor(); + +``` + A new representing the floor of the numeric value. + +Signature: + +```typescript +floor(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.greaterThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than another expression. + +```typescript +// Check if the 'age' field is greater than the 'limit' field +field("age").greaterThan(field("limit")); + +``` + +Signature: + +```typescript +greaterThan(expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for greater than. A new Expr representing the greater than comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.greaterThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than a constant value. + +```typescript +// Check if the 'price' field is greater than 100 +field("price").greaterThan(100); + +``` + +Signature: + +```typescript +greaterThan(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The constant value to compare for greater than. A new Expr representing the greater than comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.greaterThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than or equal to another expression. + +```typescript +// Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1 +field("quantity").greaterThanOrEqual(field('requirement').add(1)); + +``` + +Signature: + +```typescript +greaterThanOrEqual(expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for greater than or equal to. A new Expr representing the greater than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.greaterThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than or equal to a constant value. + +```typescript +// Check if the 'score' field is greater than or equal to 80 +field("score").greaterThanOrEqual(80); + +``` + +Signature: + +```typescript +greaterThanOrEqual(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The constant value to compare for greater than or equal to. A new Expr representing the greater than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.ifAbsent() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of the this expression evaluation. + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +field("optional_field").ifAbsent("default_value") + +``` + +Signature: + +```typescript +ifAbsent(elseValue: unknown): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elseValue | unknown | The value that will be returned if this Expression evaluates to an absent value. A new \[Expression\] representing the ifAbsent operation. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +## Expression.ifAbsent() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of this expression evaluation. + +```typescript +// Returns the value of the optional field 'optional_field', or if that is +// absent, then returns the value of the field ` +field("optional_field").ifAbsent(field('default_field')) + +``` + +Signature: + +```typescript +ifAbsent(elseExpression: unknown): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elseExpression | unknown | The Expression that will be evaluated if this Expression evaluates to an absent value. A new \[Expression\] representing the ifAbsent operation. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +## Expression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the result of the `catchExpr` argument if there is an error, else return the result of this expression. + +```typescript +// Returns the first item in the title field arrays, or returns +// the entire title field if the array is empty or the field is another type. +field("title").arrayGet(0).ifError(field("title")); + +``` + +Signature: + +```typescript +ifError(catchExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| catchExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The catch expression that will be evaluated and returned if this expression produces an error. A new representing the 'ifError' operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + +```typescript +// Returns the first item in the title field arrays, or returns +// "Default Title" +field("title").arrayGet(0).ifError("Default Title"); + +``` + +Signature: + +```typescript +ifError(catchValue: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| catchValue | unknown | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.isAbsent() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns `true` if the result of this expression is absent. Otherwise, returns `false` even if the value is `null`. + +```typescript +// Check if the field `value` is absent. +field("value").isAbsent(); + +``` + A new representing the 'isAbsent' check. + +Signature: + +```typescript +isAbsent(): BooleanExpression; +``` +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.isError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a given expression produces an error. + +```typescript +// Check if the result of a calculation is an error +field("title").arrayContains(1).isError(); + +``` + A new representing the 'isError' check. + +Signature: + +```typescript +isError(): BooleanExpression; +``` +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.join() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + +```typescript +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +field("tags").join(field("separator")) + +``` + +Signature: + +```typescript +join(delimiterExpression: Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. A new Expression representing the join operation. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +## Expression.join() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array field into a string. + +```typescript +// Join the elements of the 'tags' field with a comma and space. +field("tags").join(", ") + +``` + +Signature: + +```typescript +join(delimiter: string): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| delimiter | string | The string to use as a delimiter. A new Expression representing the join operation. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +## Expression.length() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string, array, map, vector, or bytes. + +```typescript +// Get the length of the 'name' field. +field("name").length(); + +// Get the number of items in the 'cart' array. +field("cart").length(); + +``` + A new `Expr` representing the length of the string, array, map, vector, or bytes. + +Signature: + +```typescript +length(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.lessThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than another expression. + +```typescript +// Check if the 'age' field is less than 'limit' +field("age").lessThan(field('limit')); + +``` + +Signature: + +```typescript +lessThan(experession: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| experession | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for less than. A new Expr representing the less than comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.lessThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than a constant value. + +```typescript +// Check if the 'price' field is less than 50 +field("price").lessThan(50); + +``` + +Signature: + +```typescript +lessThan(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The constant value to compare for less than. A new Expr representing the less than comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.lessThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than or equal to another expression. + +```typescript +// Check if the 'quantity' field is less than or equal to 20 +field("quantity").lessThan(constant(20)); + +``` + +Signature: + +```typescript +lessThanOrEqual(expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for less than or equal to. A new Expr representing the less than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.lessThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than or equal to a constant value. + +```typescript +// Check if the 'score' field is less than or equal to 70 +field("score").lessThan(70); + +``` + +Signature: + +```typescript +lessThanOrEqual(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The constant value to compare for less than or equal to. A new Expr representing the less than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.like() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive string comparison. + +```typescript +// Check if the 'title' field contains the word "guide" (case-sensitive) +field("title").like("%guide%"); + +``` + +Signature: + +```typescript +like(pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | string | The pattern to search for. You can use "%" as a wildcard character. A new Expr representing the 'like' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.like() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive string comparison. + +```typescript +// Check if the 'title' field contains the word "guide" (case-sensitive) +field("title").like("%guide%"); + +``` + +Signature: + +```typescript +like(pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. A new Expr representing the 'like' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.ln() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the natural logarithm of a numeric value. + +```typescript +// Compute the natural logarithm of the 'value' field. +field("value").ln(); + +``` + A new representing the natural logarithm of the numeric value. + +Signature: + +```typescript +ln(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.log10() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the base-10 logarithm of a numeric value. + +```typescript +// Compute the base-10 logarithm of the 'value' field. +field("value").log10(); + +``` + A new representing the base-10 logarithm of the numeric value. + +Signature: + +```typescript +log10(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.logicalMaximum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. + +```typescript +// Returns the larger value between the 'timestamp' field and the current timestamp. +field("timestamp").logicalMaximum(Function.currentTimestamp()); + +``` + +Signature: + +```typescript +logicalMaximum(second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to compare with. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals to compare with. A new representing the logical maximum operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.logicalMinimum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. + +```typescript +// Returns the smaller value between the 'timestamp' field and the current timestamp. +field("timestamp").logicalMinimum(Function.currentTimestamp()); + +``` + +Signature: + +```typescript +logicalMinimum(second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to compare with. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals to compare with. A new representing the logical minimum operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.mapGet() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Accesses a value from a map (object) field using the provided key. + +```typescript +// Get the 'city' value from the 'address' map field +field("address").mapGet("city"); + +``` + +Signature: + +```typescript +mapGet(subfield: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| subfield | string | The key to access in the map. A new Expr representing the value associated with the given key in the map. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.mapMerge() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that merges multiple map values. + +``` +// 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}, {}) + +``` + +Signature: + +```typescript +mapMerge(secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| secondMap | Record<string, unknown> \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A required second map to merge. Represented as a literal or an expression that returns a map. | +| otherMaps | Array<Record<string, unknown> \| [Expression](./firestore_lite_pipelines.expression.md#expression_class)> | Optional additional maps to merge. Each map is represented as a literal or an expression that returns a map. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new representing the 'mapMerge' operation. + +## Expression.mapRemove() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map produced by evaluating this expression. + +``` +// Removes the key 'baz' from the input map. +map({foo: 'bar', baz: true}).mapRemove('baz'); + +``` + +Signature: + +```typescript +mapRemove(key: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| key | string | The name of the key to remove from the input map. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new representing the 'mapRemove' operation. + +## Expression.mapRemove() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map produced by evaluating this expression. + +``` +// Removes the key 'baz' from the input map. +map({foo: 'bar', baz: true}).mapRemove(constant('baz')); + +``` + +Signature: + +```typescript +mapRemove(keyExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| keyExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that produces the name of the key to remove from the input map. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new representing the 'mapRemove' operation. + +## Expression.maximum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the maximum value of a field across multiple stage inputs. + +```typescript +// Find the highest score in a leaderboard +field("score").maximum().as("highestScore"); + +``` + A new `AggregateFunction` representing the 'maximum' aggregation. + +Signature: + +```typescript +maximum(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +## Expression.minimum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the minimum value of a field across multiple stage inputs. + +```typescript +// Find the lowest price of all products +field("price").minimum().as("lowestPrice"); + +``` + A new `AggregateFunction` representing the 'minimum' aggregation. + +Signature: + +```typescript +minimum(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +## Expression.mod() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. + +```typescript +// Calculate the remainder of dividing the 'value' field by the 'divisor' field +field("value").mod(field("divisor")); + +``` + +Signature: + +```typescript +mod(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to divide by. A new Expr representing the modulo operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.mod() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. + +```typescript +// Calculate the remainder of dividing the 'value' field by 10 +field("value").mod(10); + +``` + +Signature: + +```typescript +mod(value: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | number | The constant value to divide by. A new Expr representing the modulo operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.multiply() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that multiplies this expression by another expression. + +```typescript +// Multiply the 'quantity' field by the 'price' field +field("quantity").multiply(field("price")); + +``` + +Signature: + +```typescript +multiply(second: Expression | number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| number | The second expression or literal to multiply by. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.notEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to another expression. + +```typescript +// Check if the 'status' field is not equal to "completed" +field("status").notEqual("completed"); + +``` + +Signature: + +```typescript +notEqual(expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for inequality. A new Expr representing the inequality comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.notEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to a constant value. + +```typescript +// Check if the 'country' field is not equal to "USA" +field("country").notEqual("USA"); + +``` + +Signature: + +```typescript +notEqual(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The constant value to compare for inequality. A new Expr representing the inequality comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.notEqualAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to any of the provided values or expressions. + +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +field("status").notEqualAny(["pending", field("rejectedStatus")]); + +``` + +Signature: + +```typescript +notEqualAny(values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values or expressions to check against. A new Expr representing the 'notEqualAny' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.notEqualAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. + +```typescript +// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' +field("status").notEqualAny(field('rejectedStatuses')); + +``` + +Signature: + +```typescript +notEqualAny(arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The values or expressions to check against. A new Expr representing the 'notEqualAny' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.pow() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of this expression raised to the power of another expression. + +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +field("base").pow(field("exponent")); + +``` + +Signature: + +```typescript +pow(exponent: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise this expression to the power of. A new Expr representing the power operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.pow() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of this expression raised to the power of a constant value. + +```typescript +// Raise the value of the 'base' field to the power of 2. +field("base").pow(2); + +``` + +Signature: + +```typescript +pow(exponent: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| exponent | number | The constant value to raise this expression to the power of. A new Expr representing the power operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.regexContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains a specified regular expression as a substring. + +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +field("description").regexContains("(?i)example"); + +``` + +Signature: + +```typescript +regexContains(pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | string | The regular expression to use for the search. A new Expr representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.regexContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains a specified regular expression as a substring. + +```typescript +// Check if the 'description' field contains the regular expression stored in field 'regex' +field("description").regexContains(field("regex")); + +``` + +Signature: + +```typescript +regexContains(pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the search. A new Expr representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.regexMatch() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string matches a specified regular expression. + +```typescript +// Check if the 'email' field matches a valid email pattern +field("email").regexMatch("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + +``` + +Signature: + +```typescript +regexMatch(pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | string | The regular expression to use for the match. A new Expr representing the regular expression match. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.regexMatch() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string matches a specified regular expression. + +```typescript +// Check if the 'email' field matches a regular expression stored in field 'regex' +field("email").regexMatch(field("regex")); + +``` + +Signature: + +```typescript +regexMatch(pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the match. A new Expr representing the regular expression match. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.reverse() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses this string expression. + +```typescript +// Reverse the value of the 'myString' field. +field("myString").reverse(); + +``` + A new representing the reversed string. + +Signature: + +```typescript +reverse(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.round() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the nearest whole number. + +```typescript +// Round the value of the 'price' field. +field("price").round(); + +``` + A new `Expr` representing the rounded value. + +Signature: + +```typescript +round(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.round() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + +```typescript +// Round the value of the 'price' field to two decimal places. +field("price").round(2); + +``` + +Signature: + +```typescript +round(decimalPlaces: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| decimalPlaces | number | A constant specifying the rounding precision in decimal places. A new Expr representing the rounded value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.round() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + +```typescript +// Round the value of the 'price' field to two decimal places. +field("price").round(constant(2)); + +``` + +Signature: + +```typescript +round(decimalPlaces: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| decimalPlaces | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression specifying the rounding precision in decimal places. A new Expr representing the rounded value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.split() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. + +Signature: + +```typescript +split(delimiter: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| delimiter | string | | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Split the 'scoresCsv' field on delimiter ',' +field('scoresCsv').split(',') + +``` + A new representing the split function. + +## Expression.split() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. + +Signature: + +```typescript +split(delimiter: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| delimiter | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Split the 'scores' field on delimiter ',' or ':' depending on the stored format +field('scores').split(conditional(field('format').equal('csv'), constant(','), constant(':')) + +``` + A new representing the split function. + +## Expression.sqrt() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the square root of a numeric value. + +```typescript +// Compute the square root of the 'value' field. +field("value").sqrt(); + +``` + A new representing the square root of the numeric value. + +Signature: + +```typescript +sqrt(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.startsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string starts with a given prefix. + +```typescript +// Check if the 'name' field starts with "Mr." +field("name").startsWith("Mr."); + +``` + +Signature: + +```typescript +startsWith(prefix: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| prefix | string | The prefix to check for. A new Expr representing the 'starts with' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.startsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string starts with a given prefix (represented as an expression). + +```typescript +// Check if the 'fullName' field starts with the value of the 'firstName' field +field("fullName").startsWith(field("firstName")); + +``` + +Signature: + +```typescript +startsWith(prefix: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| prefix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The prefix expression to check for. A new Expr representing the 'starts with' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.stringConcat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates string expressions together. + +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +field("firstName").stringConcat(constant(" "), field("lastName")); + +``` + +Signature: + +```typescript +stringConcat(secondString: Expression | string, ...otherStrings: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| secondString | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string | The additional expression or string literal to concatenate. | +| otherStrings | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or string literals to concatenate. A new Expr representing the concatenated string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.stringContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains a specified substring. + +```typescript +// Check if the 'description' field contains "example". +field("description").stringContains("example"); + +``` + +Signature: + +```typescript +stringContains(substring: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| substring | string | The substring to search for. A new Expr representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.stringContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains the string represented by another expression. + +```typescript +// Check if the 'description' field contains the value of the 'keyword' field. +field("description").stringContains(field("keyword")); + +``` + +Signature: + +```typescript +stringContains(expr: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the substring to search for. A new Expr representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.stringReverse() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string. + +```typescript +// Reverse the value of the 'myString' field. +field("myString").stringReverse(); + +``` + A new representing the reversed string. + +Signature: + +```typescript +stringReverse(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.substring() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a substring of the results of this expression. + +Signature: + +```typescript +substring(position: number, length?: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| position | number | Index of the first character of the substring. | +| length | number | Length of the substring. If not provided, the substring will end at the end of the input. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.substring() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a substring of the results of this expression. + +Signature: + +```typescript +substring(position: Expression, length?: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| position | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression returning the index of the first character of the substring. | +| length | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression returning the length of the substring. If not provided the substring will end at the end of the input. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.subtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts another expression from this expression. + +```typescript +// Subtract the 'discount' field from the 'price' field +field("price").subtract(field("discount")); + +``` + +Signature: + +```typescript +subtract(subtrahend: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| subtrahend | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract from this expression. A new Expr representing the subtraction operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.subtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a constant value from this expression. + +```typescript +// Subtract 20 from the value of the 'total' field +field("total").subtract(20); + +``` + +Signature: + +```typescript +subtract(subtrahend: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| subtrahend | number | The constant value to subtract. A new Expr representing the subtraction operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.sum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. + +```typescript +// Calculate the total revenue from a set of orders +field("orderAmount").sum().as("totalRevenue"); + +``` + A new `AggregateFunction` representing the 'sum' aggregation. + +Signature: + +```typescript +sum(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +## Expression.timestampAdd() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to this timestamp expression. + +```typescript +// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. +field("timestamp").timestampAdd(field("unit"), field("amount")); + +``` + +Signature: + +```typescript +timestampAdd(unit: Expression, amount: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| unit | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | +| amount | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampAdd() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to this timestamp expression. + +```typescript +// Add 1 day to the 'timestamp' field. +field("timestamp").timestampAdd("day", 1); + +``` + +Signature: + +```typescript +timestampAdd(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | +| amount | number | The amount of time to add. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampSubtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from this timestamp expression. + +```typescript +// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. +field("timestamp").timestampSubtract(field("unit"), field("amount")); + +``` + +Signature: + +```typescript +timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| unit | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | +| amount | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampSubtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from this timestamp expression. + +```typescript +// Subtract 1 day from the 'timestamp' field. +field("timestamp").timestampSubtract("day", 1); + +``` + +Signature: + +```typescript +timestampSubtract(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | +| amount | number | The amount of time to subtract. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampToUnixMicros() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +field("timestamp").timestampToUnixMicros(); + +``` + A new representing the number of microseconds since epoch. + +Signature: + +```typescript +timestampToUnixMicros(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampToUnixMillis() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +field("timestamp").timestampToUnixMillis(); + +``` + A new representing the number of milliseconds since epoch. + +Signature: + +```typescript +timestampToUnixMillis(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampToUnixSeconds() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to seconds since epoch. +field("timestamp").timestampToUnixSeconds(); + +``` + A new representing the number of seconds since epoch. + +Signature: + +```typescript +timestampToUnixSeconds(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampTruncate() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a timestamp to a specified granularity. + +Signature: + +```typescript +timestampTruncate(granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| granularity | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | The granularity to truncate to. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Truncate the 'createdAt' timestamp to the beginning of the day. +field('createdAt').timestampTruncate('day') + +``` + +## Expression.timestampTruncate() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a timestamp to a specified granularity. + +Signature: + +```typescript +timestampTruncate(granularity: Expression, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| granularity | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The granularity to truncate to. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. +field('createdAt').timestampTruncate(field('granularity')) + +``` + +## Expression.toLower() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string to lowercase. + +```typescript +// Convert the 'name' field to lowercase +field("name").toLower(); + +``` + A new `Expr` representing the lowercase string. + +Signature: + +```typescript +toLower(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.toUpper() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string to uppercase. + +```typescript +// Convert the 'title' field to uppercase +field("title").toUpper(); + +``` + A new `Expr` representing the uppercase string. + +Signature: + +```typescript +toUpper(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.trim() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes leading and trailing characters from a string or byte array. + +```typescript +// Trim whitespace from the 'userInput' field +field("userInput").trim(); + +// Trim quotes from the 'userInput' field +field("userInput").trim('"'); + +``` + +Signature: + +```typescript +trim(valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | 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. A new Expr representing the trimmed string or byte array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.type() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the data type of this expression's result, as a string. + +Signature: + +```typescript +type(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Get the data type of the value in field 'title' +field('title').type() + +``` + A new {Expression} representing the data type. + +## Expression.unixMicrosToTimestamp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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. + +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +field("microseconds").unixMicrosToTimestamp(); + +``` + A new representing the timestamp. + +Signature: + +```typescript +unixMicrosToTimestamp(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.unixMillisToTimestamp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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. + +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +field("milliseconds").unixMillisToTimestamp(); + +``` + A new representing the timestamp. + +Signature: + +```typescript +unixMillisToTimestamp(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.unixSecondsToTimestamp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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. + +```typescript +// Interpret the 'seconds' field as seconds since epoch. +field("seconds").unixSecondsToTimestamp(); + +``` + A new representing the timestamp. + +Signature: + +```typescript +unixSecondsToTimestamp(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## Expression.vectorLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. + +```typescript +// Get the vector length (dimension) of the field 'embedding'. +field("embedding").vectorLength(); + +``` + A new representing the length of the vector. + +Signature: + +```typescript +vectorLength(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + diff --git a/docs-devsite/firestore_lite_pipelines.field.md b/docs-devsite/firestore_lite_pipelines.field.md new file mode 100644 index 0000000000..37ec1ea479 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.field.md @@ -0,0 +1,103 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Field class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Represents a reference to a field in a Firestore document, or outputs of a stage. + +

Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines. + +

You can create a `Field` instance using the static method: + +```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"); + +``` + +Signature: + +```typescript +export declare class Field extends Expression implements Selectable +``` +Extends: [Expression](./firestore_lite_pipelines.expression.md#expression_class) + +Implements: [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [alias](./firestore_lite_pipelines.field.md#fieldalias) | | string | (Public Preview) | +| [expr](./firestore_lite_pipelines.field.md#fieldexpr) | | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | (Public Preview) | +| [expressionType](./firestore_lite_pipelines.field.md#fieldexpressiontype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) | +| [fieldName](./firestore_lite_pipelines.field.md#fieldfieldname) | | string | (Public Preview) | +| [selectable](./firestore_lite_pipelines.field.md#fieldselectable) | | true | (Public Preview) | + +## Field.alias + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +get alias(): string; +``` + +## Field.expr + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +get expr(): Expression; +``` + +## Field.expressionType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly expressionType: ExpressionType; +``` + +## Field.fieldName + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +get fieldName(): string; +``` + +## Field.selectable + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +selectable: true; +``` diff --git a/docs-devsite/firestore_lite_pipelines.fieldpath.md b/docs-devsite/firestore_lite_pipelines.fieldpath.md new file mode 100644 index 0000000000..f2c97ebcaa --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.fieldpath.md @@ -0,0 +1,72 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FieldPath class +A `FieldPath` refers to a field in a document. The path may consist of a single field name (referring to a top-level field in the document), or a list of field names (referring to a nested field in the document). + +Create a `FieldPath` by providing field names. If more than one field name is provided, the path will point to a nested field in a document. + +Signature: + +```typescript +export declare class FieldPath +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(fieldNames)](./firestore_lite_pipelines.fieldpath.md#fieldpathconstructor) | | Creates a FieldPath from the provided field names. If more than one field name is provided, the path will point to a nested field in a document. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [isEqual(other)](./firestore_lite_pipelines.fieldpath.md#fieldpathisequal) | | Returns true if this FieldPath is equal to the provided one. | + +## FieldPath.(constructor) + +Creates a `FieldPath` from the provided field names. If more than one field name is provided, the path will point to a nested field in a document. + +Signature: + +```typescript +constructor(...fieldNames: string[]); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldNames | string\[\] | A list of field names. | + +## FieldPath.isEqual() + +Returns true if this `FieldPath` is equal to the provided one. + +Signature: + +```typescript +isEqual(other: FieldPath): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [FieldPath](./firestore_lite.fieldpath.md#fieldpath_class) | The FieldPath to compare against. | + +Returns: + +boolean + +true if this `FieldPath` is equal to the provided one. + diff --git a/docs-devsite/firestore_lite_pipelines.fieldvalue.md b/docs-devsite/firestore_lite_pipelines.fieldvalue.md new file mode 100644 index 0000000000..5bd2451357 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.fieldvalue.md @@ -0,0 +1,46 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FieldValue class +Sentinel values that can be used when writing document fields with `set()` or `update()`. + +Signature: + +```typescript +export declare abstract class FieldValue +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [isEqual(other)](./firestore_lite_pipelines.fieldvalue.md#fieldvalueisequal) | | Compares FieldValues for equality. | + +## FieldValue.isEqual() + +Compares `FieldValue`s for equality. + +Signature: + +```typescript +abstract isEqual(other: FieldValue): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [FieldValue](./firestore_lite.fieldvalue.md#fieldvalue_class) | | + +Returns: + +boolean + diff --git a/docs-devsite/firestore_lite_pipelines.firestore.md b/docs-devsite/firestore_lite_pipelines.firestore.md new file mode 100644 index 0000000000..0cb6b7a13d --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.firestore.md @@ -0,0 +1,68 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Firestore class +The Cloud Firestore service interface. + +Do not call this constructor directly. Instead, use [getFirestore()](./firestore_.md#getfirestore). + +Signature: + +```typescript +export declare class Firestore +``` + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [app](./firestore_lite_pipelines.firestore.md#firestoreapp) | | [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) | The [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) associated with this Firestore service instance. | +| [type](./firestore_lite_pipelines.firestore.md#firestoretype) | | 'firestore-lite' \| 'firestore' | Whether it's a Firestore or Firestore Lite instance. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [toJSON()](./firestore_lite_pipelines.firestore.md#firestoretojson) | | Returns a JSON-serializable representation of this Firestore instance. | + +## Firestore.app + +The [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) associated with this `Firestore` service instance. + +Signature: + +```typescript +get app(): FirebaseApp; +``` + +## Firestore.type + +Whether it's a Firestore or Firestore Lite instance. + +Signature: + +```typescript +type: 'firestore-lite' | 'firestore'; +``` + +## Firestore.toJSON() + +Returns a JSON-serializable representation of this `Firestore` instance. + +Signature: + +```typescript +toJSON(): object; +``` +Returns: + +object + diff --git a/docs-devsite/firestore_lite_pipelines.firestoredataconverter.md b/docs-devsite/firestore_lite_pipelines.firestoredataconverter.md new file mode 100644 index 0000000000..fed5547848 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.firestoredataconverter.md @@ -0,0 +1,261 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FirestoreDataConverter interface +Converter used by `withConverter()` to transform user objects of type `AppModelType` into Firestore data of type `DbModelType`. + +Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore. + +In this context, an "AppModel" is a class that is used in an application to package together related information and functionality. Such a class could, for example, have properties with complex, nested data types, properties used for memoization, properties of types not supported by Firestore (such as `symbol` and `bigint`), and helper functions that perform compound operations. Such classes are not suitable and/or possible to store into a Firestore database. Instead, instances of such classes need to be converted to "plain old JavaScript objects" (POJOs) with exclusively primitive properties, potentially nested inside other POJOs or arrays of POJOs. In this context, this type is referred to as the "DbModel" and would be an object suitable for persisting into Firestore. For convenience, applications can implement `FirestoreDataConverter` and register the converter with Firestore objects, such as `DocumentReference` or `Query`, to automatically convert `AppModel` to `DbModel` when storing into Firestore, and convert `DbModel` to `AppModel` when retrieving from Firestore. + +Signature: + +```typescript +export declare interface FirestoreDataConverter +``` + +## Methods + +| Method | Description | +| --- | --- | +| [fromFirestore(snapshot)](./firestore_lite_pipelines.firestoredataconverter.md#firestoredataconverterfromfirestore) | Called by the Firestore SDK to convert Firestore data into an object of type AppModelType. You can access your data by calling: snapshot.data().Generally, the data returned from snapshot.data() can be cast to DbModelType; however, this is not guaranteed because Firestore does not enforce a schema on the database. For example, writes from a previous version of the application or writes from another client that did not use a type converter could have written data with different properties and/or property types. The implementation will need to choose whether to gracefully recover from non-conforming data or throw an error. | +| [toFirestore(modelObject)](./firestore_lite_pipelines.firestoredataconverter.md#firestoredataconvertertofirestore) | Called by the Firestore SDK to convert a custom model object of type AppModelType into a plain JavaScript object (suitable for writing directly to the Firestore database) of type DbModelType. Used with [setDoc()](./firestore_lite.md#setdoc_ee215ad), and .The WithFieldValue<T> type extends T to also allow FieldValues such as [deleteField()](./firestore_.md#deletefield) to be used as property values. | +| [toFirestore(modelObject, options)](./firestore_lite_pipelines.firestoredataconverter.md#firestoredataconvertertofirestore) | Called by the Firestore SDK to convert a custom model object of type AppModelType into a plain JavaScript object (suitable for writing directly to the Firestore database) of type DbModelType. Used with [setDoc()](./firestore_lite.md#setdoc_ee215ad), and with merge:true or mergeFields.The PartialWithFieldValue<T> type extends Partial<T> to allow FieldValues such as [arrayUnion()](./firestore_.md#arrayunion_7d853aa) to be used as property values. It also supports nested Partial by allowing nested fields to be omitted. | + +## FirestoreDataConverter.fromFirestore() + +Called by the Firestore SDK to convert Firestore data into an object of type `AppModelType`. You can access your data by calling: `snapshot.data()`. + +Generally, the data returned from `snapshot.data()` can be cast to `DbModelType`; however, this is not guaranteed because Firestore does not enforce a schema on the database. For example, writes from a previous version of the application or writes from another client that did not use a type converter could have written data with different properties and/or property types. The implementation will need to choose whether to gracefully recover from non-conforming data or throw an error. + +Signature: + +```typescript +fromFirestore(snapshot: QueryDocumentSnapshot): AppModelType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| snapshot | [QueryDocumentSnapshot](./firestore_lite.querydocumentsnapshot.md#querydocumentsnapshot_class)<[DocumentData](./firestore_lite.documentdata.md#documentdata_interface), [DocumentData](./firestore_lite.documentdata.md#documentdata_interface)> | A QueryDocumentSnapshot containing your data and metadata. | + +Returns: + +AppModelType + +## FirestoreDataConverter.toFirestore() + +Called by the Firestore SDK to convert a custom model object of type `AppModelType` into a plain JavaScript object (suitable for writing directly to the Firestore database) of type `DbModelType`. Used with [setDoc()](./firestore_lite.md#setdoc_ee215ad), and . + +The `WithFieldValue` type extends `T` to also allow FieldValues such as [deleteField()](./firestore_.md#deletefield) to be used as property values. + +Signature: + +```typescript +toFirestore(modelObject: WithFieldValue): WithFieldValue; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| modelObject | [WithFieldValue](./firestore_lite.md#withfieldvalue)<AppModelType> | | + +Returns: + +[WithFieldValue](./firestore_lite.md#withfieldvalue)<DbModelType> + +## FirestoreDataConverter.toFirestore() + +Called by the Firestore SDK to convert a custom model object of type `AppModelType` into a plain JavaScript object (suitable for writing directly to the Firestore database) of type `DbModelType`. Used with [setDoc()](./firestore_lite.md#setdoc_ee215ad), and with `merge:true` or `mergeFields`. + +The `PartialWithFieldValue` type extends `Partial` to allow FieldValues such as [arrayUnion()](./firestore_.md#arrayunion_7d853aa) to be used as property values. It also supports nested `Partial` by allowing nested fields to be omitted. + +Signature: + +```typescript +toFirestore(modelObject: PartialWithFieldValue, options: SetOptions): PartialWithFieldValue; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| modelObject | [PartialWithFieldValue](./firestore_lite.md#partialwithfieldvalue)<AppModelType> | | +| options | [SetOptions](./firestore_lite.md#setoptions) | | + +Returns: + +[PartialWithFieldValue](./firestore_lite.md#partialwithfieldvalue)<DbModelType> + +### Example + +Simple Example + +```typescript +const numberConverter = { + toFirestore(value: WithFieldValue) { + return { value }; + }, + fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions) { + return snapshot.data(options).value as number; + } +}; + +async function simpleDemo(db: Firestore): Promise { + const documentRef = doc(db, 'values/value123').withConverter(numberConverter); + + // converters are used with `setDoc`, `addDoc`, and `getDoc` + await setDoc(documentRef, 42); + const snapshot1 = await getDoc(documentRef); + assertEqual(snapshot1.data(), 42); + + // converters are not used when writing data with `updateDoc` + await updateDoc(documentRef, { value: 999 }); + const snapshot2 = await getDoc(documentRef); + assertEqual(snapshot2.data(), 999); +} + +``` +Advanced Example + +```typescript +// The Post class is a model that is used by our application. +// This class may have properties and methods that are specific +// to our application execution, which do not need to be persisted +// to Firestore. +class Post { + constructor( + readonly title: string, + readonly author: string, + readonly lastUpdatedMillis: number + ) {} + toString(): string { + return `${this.title} by ${this.author}`; + } +} + +// The PostDbModel represents how we want our posts to be stored +// in Firestore. This DbModel has different properties (`ttl`, +// `aut`, and `lut`) from the Post class we use in our application. +interface PostDbModel { + ttl: string; + aut: { firstName: string; lastName: string }; + lut: Timestamp; +} + +// The `PostConverter` implements `FirestoreDataConverter` and specifies +// how the Firestore SDK can convert `Post` objects to `PostDbModel` +// objects and vice versa. +class PostConverter implements FirestoreDataConverter { + toFirestore(post: WithFieldValue): WithFieldValue { + return { + ttl: post.title, + aut: this._autFromAuthor(post.author), + lut: this._lutFromLastUpdatedMillis(post.lastUpdatedMillis) + }; + } + + fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions): Post { + const data = snapshot.data(options) as PostDbModel; + const author = `${data.aut.firstName} ${data.aut.lastName}`; + return new Post(data.ttl, author, data.lut.toMillis()); + } + + _autFromAuthor( + author: string | FieldValue + ): { firstName: string; lastName: string } | FieldValue { + if (typeof author !== 'string') { + // `author` is a FieldValue, so just return it. + return author; + } + const [firstName, lastName] = author.split(' '); + return {firstName, lastName}; + } + + _lutFromLastUpdatedMillis( + lastUpdatedMillis: number | FieldValue + ): Timestamp | FieldValue { + if (typeof lastUpdatedMillis !== 'number') { + // `lastUpdatedMillis` must be a FieldValue, so just return it. + return lastUpdatedMillis; + } + return Timestamp.fromMillis(lastUpdatedMillis); + } +} + +async function advancedDemo(db: Firestore): Promise { + // Create a `DocumentReference` with a `FirestoreDataConverter`. + const documentRef = doc(db, 'posts/post123').withConverter(new PostConverter()); + + // The `data` argument specified to `setDoc()` is type checked by the + // TypeScript compiler to be compatible with `Post`. Since the `data` + // argument is typed as `WithFieldValue` rather than just `Post`, + // this allows properties of the `data` argument to also be special + // Firestore values that perform server-side mutations, such as + // `arrayRemove()`, `deleteField()`, and `serverTimestamp()`. + await setDoc(documentRef, { + title: 'My Life', + author: 'Foo Bar', + lastUpdatedMillis: serverTimestamp() + }); + + // The TypeScript compiler will fail to compile if the `data` argument to + // `setDoc()` is _not_ compatible with `WithFieldValue`. This + // type checking prevents the caller from specifying objects with incorrect + // properties or property values. + // @ts-expect-error "Argument of type { ttl: string; } is not assignable + // to parameter of type WithFieldValue" + await setDoc(documentRef, { ttl: 'The Title' }); + + // When retrieving a document with `getDoc()` the `DocumentSnapshot` + // object's `data()` method returns a `Post`, rather than a generic object, + // which would have been returned if the `DocumentReference` did _not_ have a + // `FirestoreDataConverter` attached to it. + const snapshot1: DocumentSnapshot = await getDoc(documentRef); + const post1: Post = snapshot1.data()!; + if (post1) { + assertEqual(post1.title, 'My Life'); + assertEqual(post1.author, 'Foo Bar'); + } + + // The `data` argument specified to `updateDoc()` is type checked by the + // TypeScript compiler to be compatible with `PostDbModel`. Note that + // unlike `setDoc()`, whose `data` argument must be compatible with `Post`, + // the `data` argument to `updateDoc()` must be compatible with + // `PostDbModel`. Similar to `setDoc()`, since the `data` argument is typed + // as `WithFieldValue` rather than just `PostDbModel`, this + // allows properties of the `data` argument to also be those special + // Firestore values, like `arrayRemove()`, `deleteField()`, and + // `serverTimestamp()`. + await updateDoc(documentRef, { + 'aut.firstName': 'NewFirstName', + lut: serverTimestamp() + }); + + // The TypeScript compiler will fail to compile if the `data` argument to + // `updateDoc()` is _not_ compatible with `WithFieldValue`. + // This type checking prevents the caller from specifying objects with + // incorrect properties or property values. + // @ts-expect-error "Argument of type { title: string; } is not assignable + // to parameter of type WithFieldValue" + await updateDoc(documentRef, { title: 'New Title' }); + const snapshot2: DocumentSnapshot = await getDoc(documentRef); + const post2: Post = snapshot2.data()!; + if (post2) { + assertEqual(post2.title, 'My Life'); + assertEqual(post2.author, 'NewFirstName Bar'); + } +} + +``` + diff --git a/docs-devsite/firestore_lite_pipelines.functionexpression.md b/docs-devsite/firestore_lite_pipelines.functionexpression.md new file mode 100644 index 0000000000..ef3a422c16 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.functionexpression.md @@ -0,0 +1,90 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FunctionExpression class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +This class defines the base class for Firestore functions, which can be evaluated within pipeline execution. + +Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_.md#and_e72c712), , or the methods on (, , etc.) to construct new Function instances. + +Signature: + +```typescript +export declare class FunctionExpression extends Expression +``` +Extends: [Expression](./firestore_lite_pipelines.expression.md#expression_class) + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(name, params)](./firestore_lite_pipelines.functionexpression.md#functionexpressionconstructor) | | (Public Preview) Constructs a new instance of the FunctionExpression class | +| [(constructor)(name, params, \_methodName)](./firestore_lite_pipelines.functionexpression.md#functionexpressionconstructor) | | (Public Preview) Constructs a new instance of the FunctionExpression class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [expressionType](./firestore_lite_pipelines.functionexpression.md#functionexpressionexpressiontype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) | + +## FunctionExpression.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `FunctionExpression` class + +Signature: + +```typescript +constructor(name: string, params: Expression[]); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | +| params | [Expression](./firestore_lite_pipelines.expression.md#expression_class)\[\] | | + +## FunctionExpression.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `FunctionExpression` class + +Signature: + +```typescript +constructor(name: string, params: Expression[], _methodName: string | undefined); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | +| params | [Expression](./firestore_lite_pipelines.expression.md#expression_class)\[\] | | +| \_methodName | string \| undefined | | + +## FunctionExpression.expressionType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly expressionType: ExpressionType; +``` diff --git a/docs-devsite/firestore_lite_pipelines.geopoint.md b/docs-devsite/firestore_lite_pipelines.geopoint.md new file mode 100644 index 0000000000..2c4eb68deb --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.geopoint.md @@ -0,0 +1,143 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GeoPoint class +An immutable object representing a geographic location in Firestore. The location is represented as latitude/longitude pair. + +Latitude values are in the range of \[-90, 90\]. Longitude values are in the range of \[-180, 180\]. + +Signature: + +```typescript +export declare class GeoPoint +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(latitude, longitude)](./firestore_lite_pipelines.geopoint.md#geopointconstructor) | | Creates a new immutable GeoPoint object with the provided latitude and longitude values. | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [latitude](./firestore_lite_pipelines.geopoint.md#geopointlatitude) | | number | The latitude of this GeoPoint instance. | +| [longitude](./firestore_lite_pipelines.geopoint.md#geopointlongitude) | | number | The longitude of this GeoPoint instance. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [fromJSON(json)](./firestore_lite_pipelines.geopoint.md#geopointfromjson) | static | Builds a GeoPoint instance from a JSON object created by [GeoPoint.toJSON()](./firestore_.geopoint.md#geopointtojson). | +| [isEqual(other)](./firestore_lite_pipelines.geopoint.md#geopointisequal) | | Returns true if this GeoPoint is equal to the provided one. | +| [toJSON()](./firestore_lite_pipelines.geopoint.md#geopointtojson) | | Returns a JSON-serializable representation of this GeoPoint instance. | + +## GeoPoint.(constructor) + +Creates a new immutable `GeoPoint` object with the provided latitude and longitude values. + +Signature: + +```typescript +constructor(latitude: number, longitude: number); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| latitude | number | The latitude as number between -90 and 90. | +| longitude | number | The longitude as number between -180 and 180. | + +## GeoPoint.latitude + +The latitude of this `GeoPoint` instance. + +Signature: + +```typescript +get latitude(): number; +``` + +## GeoPoint.longitude + +The longitude of this `GeoPoint` instance. + +Signature: + +```typescript +get longitude(): number; +``` + +## GeoPoint.fromJSON() + +Builds a `GeoPoint` instance from a JSON object created by [GeoPoint.toJSON()](./firestore_.geopoint.md#geopointtojson). + +Signature: + +```typescript +static fromJSON(json: object): GeoPoint; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| json | object | a JSON object represention of a GeoPoint instance | + +Returns: + +[GeoPoint](./firestore_lite.geopoint.md#geopoint_class) + +an instance of [GeoPoint](./firestore_.geopoint.md#geopoint_class) if the JSON object could be parsed. Throws a [FirestoreError](./firestore_.firestoreerror.md#firestoreerror_class) if an error occurs. + +## GeoPoint.isEqual() + +Returns true if this `GeoPoint` is equal to the provided one. + +Signature: + +```typescript +isEqual(other: GeoPoint): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [GeoPoint](./firestore_lite.geopoint.md#geopoint_class) | The GeoPoint to compare against. | + +Returns: + +boolean + +true if this `GeoPoint` is equal to the provided one. + +## GeoPoint.toJSON() + +Returns a JSON-serializable representation of this `GeoPoint` instance. + +Signature: + +```typescript +toJSON(): { + latitude: number; + longitude: number; + type: string; + }; +``` +Returns: + +{ latitude: number; longitude: number; type: string; } + +a JSON representation of this object. + diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md new file mode 100644 index 0000000000..8173c81da6 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.md @@ -0,0 +1,9839 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# @firebase/firestore/lite/pipelines + +## Functions + +| Function | Description | +| --- | --- | +| function() | +| [countAll()](./firestore_lite_pipelines.md#countall) | (Public Preview) Creates an aggregation that counts the total number of stage inputs. +```typescript +// Count the total number of input documents +countAll().as("totalDocument"); + +``` + A new representing the 'countAll' aggregation. | +| [currentTimestamp()](./firestore_lite_pipelines.md#currenttimestamp) | (Public Preview) Creates an expression that evaluates to the current server timestamp. +```typescript +// Get the current server timestamp +currentTimestamp() + +``` + A new Expression representing the current server timestamp. | +| function(array, ...) | +| [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_a00ea48) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. +```typescript +// Check if the 'colors' array contains the value of field 'selectedColor' +arrayContains(field("colors"), field("selectedColor")); + +``` + | +| [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_7328608) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. +```typescript +// Check if the 'colors' array contains "red" +arrayContains(field("colors"), "red"); + +``` + | +| [arrayContainsAll(array, values)](./firestore_lite_pipelines.md#arraycontainsall_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. +```typescript +// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" +arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); + +``` + | +| [arrayContainsAll(array, arrayExpression)](./firestore_lite_pipelines.md#arraycontainsall_7b535db) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. +```typescript +// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" +arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); + +``` + | +| [arrayContainsAny(array, values)](./firestore_lite_pipelines.md#arraycontainsany_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. +```typescript +// Check if the 'categories' array contains either values from field "cate1" or "Science" +arrayContainsAny(field("categories"), [field("cate1"), "Science"]); + +``` + | +| [arrayContainsAny(array, values)](./firestore_lite_pipelines.md#arraycontainsany_c381a96) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. +```typescript +// Check if the 'categories' array contains either values from field "cate1" or "Science" +arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); + +``` + | +| [arrayLength(array)](./firestore_lite_pipelines.md#arraylength_195e339) | (Public Preview) Creates an expression that calculates the length of an array expression. +```typescript +// Get the number of items in the 'cart' array +arrayLength(field("cart")); + +``` + | +| function(arrayExpression, ...) | +| [arrayGet(arrayExpression, offset)](./firestore_lite_pipelines.md#arrayget_f2e27cc) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +```typescript +// Return the value in the tags field array at index 1. +arrayGet(field('tags'), 1); + +``` + | +| [arrayGet(arrayExpression, offsetExpr)](./firestore_lite_pipelines.md#arrayget_484550d) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet(field('tags'), field('favoriteTag')); + +``` + | +| [join(arrayExpression, delimiterExpression)](./firestore_lite_pipelines.md#join_313e6aa) | (Public Preview) Creates an expression that joins the elements of an array into a string. +```typescript +// Join an array of string using the delimiter from the 'separator' field. +join(array(['foo', 'bar']), field("separator")) + +``` + | +| [join(arrayExpression, delimiter)](./firestore_lite_pipelines.md#join_d088d29) | (Public Preview) Creates an expression that joins the elements of an array into a string. +```typescript +// Join the elements of the 'tags' field with a comma and space. +join(field("tags"), ", ") + +``` + | +| function(arrayField, ...) | +| [arrayGet(arrayField, offset)](./firestore_lite_pipelines.md#arrayget_3f58471) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +```typescript +// Return the value in the tags field array at index 1. +arrayGet('tags', 1); + +``` + | +| [arrayGet(arrayField, offsetExpr)](./firestore_lite_pipelines.md#arrayget_1904c9a) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet('tags', field('favoriteTag')); + +``` + | +| function(arrayFieldName, ...) | +| [join(arrayFieldName, delimiter)](./firestore_lite_pipelines.md#join_478ef36) | (Public Preview) Creates an expression that joins the elements of an array into a string. +```typescript +// Join the elements of the 'tags' field with a comma and space. +join("tags", ", ") + +``` + | +| [join(arrayFieldName, delimiterExpression)](./firestore_lite_pipelines.md#join_829294c) | (Public Preview) Creates an expression that joins the elements of an array into a string. +```typescript +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +join('tags', field("separator")) + +``` + | +| function(base, ...) | +| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_e4a9e64) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent expression. +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow(field("base"), field("exponent")); + +``` + | +| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_93eae7f) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent. +```typescript +// Raise the value of the 'base' field to the power of 2. +pow(field("base"), 2); + +``` + | +| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_a237721) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent expression. +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow("base", field("exponent")); + +``` + | +| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_f4d7908) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent. +```typescript +// Raise the value of the 'base' field to the power of 2. +pow("base", 2); + +``` + | +| function(booleanExpr, ...) | +| [countIf(booleanExpr)](./firestore_lite_pipelines.md#countif_c5b8fb1) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. +```typescript +// Count the number of documents where 'is_active' field equals true +countIf(field("is_active").equal(true)).as("numActiveDocuments"); + +``` + | +| [not(booleanExpr)](./firestore_lite_pipelines.md#not_c5b8fb1) | (Public Preview) Creates an expression that negates a filter condition. +```typescript +// Find documents where the 'completed' field is NOT true +not(equal("completed", true)); + +``` + | +| function(condition, ...) | +| [conditional(condition, thenExpr, elseExpr)](./firestore_lite_pipelines.md#conditional_07a206d) | (Public Preview) Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. +```typescript +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +conditional( + greaterThan("age", 18), constant("Adult"), constant("Minor")); + +``` + | +| function(documentPath, ...) | +| [documentId(documentPath)](./firestore_lite_pipelines.md#documentid_cef293c) | (Public Preview) Creates an expression that returns the document ID from a path. +```typescript +// Get the document ID from a path. +documentId(myDocumentReference); + +``` + A new representing the documentId operation. | +| function(documentPathExpr, ...) | +| [documentId(documentPathExpr)](./firestore_lite_pipelines.md#documentid_9a69021) | (Public Preview) Creates an expression that returns the document ID from a path. +```typescript +// Get the document ID from a path. +documentId(field("__path__")); + +``` + A new representing the documentId operation. | +| function(element, ...) | +| [notEqualAny(element, values)](./firestore_lite_pipelines.md#notequalany_c2c5bcb) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + | +| [notEqualAny(element, arrayExpression)](./firestore_lite_pipelines.md#notequalany_16b2851) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. +```typescript +// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + | +| function(elements, ...) | +| [array(elements)](./firestore_lite_pipelines.md#array_7d853aa) | (Public Preview) Creates an expression that creates a Firestore array value from an input array. +```typescript +// Create an array value from the input array and reference the 'baz' field value from the input document. +array(['bar', Field.of('baz')]).as('foo'); + +``` + | +| [map(elements)](./firestore_lite_pipelines.md#map_ce5dee1) | (Public Preview) Creates an expression that creates a Firestore map value from an input object. +```typescript +// Create a map from the input object and reference the 'baz' field value from the input document. +map({foo: 'bar', baz: Field.of('baz')}).as('data'); + +``` + | +| function(expr, ...) | +| [abs(expr)](./firestore_lite_pipelines.md#abs_005f3d4) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | +| [ascending(expr)](./firestore_lite_pipelines.md#ascending_005f3d4) | (Public Preview) Creates an that sorts documents in ascending order based on an expression. +```typescript +// Sort documents by the 'name' field in lowercase in ascending order +firestore.pipeline().collection("users") + .sort(ascending(field("name").toLower())); + +``` + | +| [byteLength(expr)](./firestore_lite_pipelines.md#bytelength_005f3d4) | (Public Preview) Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. +```typescript +// Calculate the length of the 'myString' field in bytes. +byteLength(field("myString")); + +``` + | +| [countDistinct(expr)](./firestore_lite_pipelines.md#countdistinct_3c28b08) | (Public Preview) Creates an aggregation that counts the number of distinct values of a field. | +| [descending(expr)](./firestore_lite_pipelines.md#descending_005f3d4) | (Public Preview) Creates an that sorts documents in descending order based on an expression. +```typescript +// Sort documents by the 'name' field in lowercase in descending order +firestore.pipeline().collection("users") + .sort(descending(field("name").toLower())); + +``` + | +| [floor(expr)](./firestore_lite_pipelines.md#floor_005f3d4) | (Public Preview) Creates an expression that computes the floor of a numeric value. | +| [timestampToUnixMicros(expr)](./firestore_lite_pipelines.md#timestamptounixmicros_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros(field("timestamp")); + +``` + | +| [timestampToUnixMillis(expr)](./firestore_lite_pipelines.md#timestamptounixmillis_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis(field("timestamp")); + +``` + | +| [timestampToUnixSeconds(expr)](./firestore_lite_pipelines.md#timestamptounixseconds_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds(field("timestamp")); + +``` + | +| [unixMicrosToTimestamp(expr)](./firestore_lite_pipelines.md#unixmicrostotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp(field("microseconds")); + +``` + | +| [unixMillisToTimestamp(expr)](./firestore_lite_pipelines.md#unixmillistotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp(field("milliseconds")); + +``` + | +| [unixSecondsToTimestamp(expr)](./firestore_lite_pipelines.md#unixsecondstotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +```typescript +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp(field("seconds")); + +``` + | +| function(expression, ...) | +| [arraySum(expression)](./firestore_lite_pipelines.md#arraysum_1138a27) | (Public Preview) Creates an expression that computes the sum of the elements in an array. +```typescript +// Compute the sum of the elements in the 'scores' field. +arraySum(field("scores")); + +``` + | +| [average(expression)](./firestore_lite_pipelines.md#average_1138a27) | (Public Preview) Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. +```typescript +// Calculate the average age of users +average(field("age")).as("averageAge"); + +``` + | +| [ceil(expression)](./firestore_lite_pipelines.md#ceil_1138a27) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. +```typescript +// Compute the ceiling of the 'price' field. +ceil(field("price")); + +``` + | +| [collectionId(expression)](./firestore_lite_pipelines.md#collectionid_1138a27) | (Public Preview) Creates an expression that returns the collection ID from a path. +```typescript +// Get the collection ID from a path. +collectionId(field("__name__")); + +``` + | +| [count(expression)](./firestore_lite_pipelines.md#count_1138a27) | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. +```typescript +// Count the number of items where the price is greater than 10 +count(field("price").greaterThan(10)).as("expensiveItemCount"); + +``` + | +| [divide(expression, value)](./firestore_lite_pipelines.md#divide_01df3cf) | (Public Preview) Creates an expression that divides an expression by a constant value. +```typescript +// Divide the 'value' field by 10 +divide(field("value"), 10); + +``` + | +| [equal(expression, value)](./firestore_lite_pipelines.md#equal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is equal to a constant value. +```typescript +// Check if the 'age' field is equal to 21 +equal(field("age"), 21); + +``` + | +| [equalAny(expression, values)](./firestore_lite_pipelines.md#equalany_7e759b5) | (Public Preview) Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny(field("category"), [constant("Electronics"), field("primaryType")]); + +``` + | +| [equalAny(expression, arrayExpression)](./firestore_lite_pipelines.md#equalany_214ce68) | (Public Preview) Creates an expression that checks if an expression is equal to any of the provided values. +```typescript +// Check if the 'category' field is set to a value in the disabledCategories field +equalAny(field("category"), field('disabledCategories')); + +``` + | +| [exp(expression)](./firestore_lite_pipelines.md#exp_1138a27) | (Public Preview) Creates an expression that computes e to the power of the expression's result. +```typescript +// Compute e to the power of 2. +exp(constant(2)); + +``` + A new representing the exp of the numeric value. | +| [greaterThan(expression, value)](./firestore_lite_pipelines.md#greaterthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than a constant value. +```typescript +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), 18); + +``` + | +| [greaterThanOrEqual(expression, value)](./firestore_lite_pipelines.md#greaterthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than or equal to a constant value. +```typescript +// Check if the 'quantity' field is greater than or equal to 10 +greaterThanOrEqual(field("quantity"), 10); + +``` + | +| [length\_2(expression)](./firestore_lite_pipelines.md#length_2_1138a27) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. +```typescript +// Get the length of the 'name' field. +length(field("name")); + +// Get the number of items in the 'cart' array. +length(field("cart")); + +``` + | +| [lessThan(expression, value)](./firestore_lite_pipelines.md#lessthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than a constant value. +```typescript +// Check if the 'age' field is less than 30 +lessThan(field("age"), 30); + +``` + | +| [lessThanOrEqual(expression, value)](./firestore_lite_pipelines.md#lessthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than or equal to a constant value. +```typescript +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), 20); + +``` + | +| [ln(expression)](./firestore_lite_pipelines.md#ln_1138a27) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. +```typescript +// Compute the natural logarithm of the 'value' field. +ln(field("value")); + +``` + | +| [log(expression, base)](./firestore_lite_pipelines.md#log_ac183e2) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. +```typescript +// Compute the logarithm of the 'value' field with base 10. +log(field("value"), 10); + +``` + | +| [log(expression, base)](./firestore_lite_pipelines.md#log_1894737) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. +```typescript +// Compute the logarithm of the 'value' field with the base in the 'base' field. +log(field("value"), field("base")); + +``` + | +| [log10(expression)](./firestore_lite_pipelines.md#log10_1138a27) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. +```typescript +// Compute the base-10 logarithm of the 'value' field. +log10(field("value")); + +``` + | +| [maximum(expression)](./firestore_lite_pipelines.md#maximum_1138a27) | (Public Preview) Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. +```typescript +// Find the highest score in a leaderboard +maximum(field("score")).as("highestScore"); + +``` + | +| [minimum(expression)](./firestore_lite_pipelines.md#minimum_1138a27) | (Public Preview) Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. +```typescript +// Find the lowest price of all products +minimum(field("price")).as("lowestPrice"); + +``` + | +| [mod(expression, value)](./firestore_lite_pipelines.md#mod_01df3cf) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. +```typescript +// Calculate the remainder of dividing 'field1' by 5. +mod(field("field1"), 5); + +``` + | +| [notEqual(expression, value)](./firestore_lite_pipelines.md#notequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is not equal to a constant value. +```typescript +// Check if the 'status' field is not equal to "completed" +notEqual(field("status"), "completed"); + +``` + | +| [round(expression)](./firestore_lite_pipelines.md#round_1138a27) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. +```typescript +// Round the value of the 'price' field. +round(field("price")); + +``` + | +| [round(expression, decimalPlaces)](./firestore_lite_pipelines.md#round_a3a92d0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. +```typescript +// Round the value of the 'price' field to two decimal places. +round(field("price"), constant(2)); + +``` + | +| [split(expression, delimiter)](./firestore_lite_pipelines.md#split_5b5612b) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | +| [split(expression, delimiter)](./firestore_lite_pipelines.md#split_5a171ed) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | +| [sqrt(expression)](./firestore_lite_pipelines.md#sqrt_1138a27) | (Public Preview) Creates an expression that computes the square root of a numeric value. +```typescript +// Compute the square root of the 'value' field. +sqrt(field("value")); + +``` + | +| [subtract(expression, value)](./firestore_lite_pipelines.md#subtract_01df3cf) | (Public Preview) Creates an expression that subtracts a constant value from an expression. +```typescript +// Subtract the constant value 2 from the 'value' field +subtract(field("value"), 2); + +``` + | +| [sum(expression)](./firestore_lite_pipelines.md#sum_1138a27) | (Public Preview) Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. +```typescript +// Calculate the total revenue from a set of orders +sum(field("orderAmount")).as("totalRevenue"); + +``` + | +| [type(expression)](./firestore_lite_pipelines.md#type_1138a27) | (Public Preview) Creates an expression that returns the data type of an expression's result. | +| function(field, ...) | +| [isAbsent(field)](./firestore_lite_pipelines.md#isabsent_0fb8cd4) | (Public Preview) Creates an expression that returns true if a field is absent. Otherwise, returns false even if the field value is null. +```typescript +// Check if the field `value` is absent. +isAbsent("value"); + +``` + | +| [reverse(field)](./firestore_lite_pipelines.md#reverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. +```typescript +// Reverse the value of the 'myString' field. +reverse("myString"); + +``` + | +| [stringReverse(field)](./firestore_lite_pipelines.md#stringreverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. +```typescript +// Reverse the value of the 'myString' field. +strReverse("myString"); + +``` + | +| [substring(field, position, length)](./firestore_lite_pipelines.md#substring_0d9573a) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| [substring(field, position, length)](./firestore_lite_pipelines.md#substring_05cb14e) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| function(fieldName, ...) | +| [abs(fieldName)](./firestore_lite_pipelines.md#abs_e5b0480) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | +| [add(fieldName, second)](./firestore_lite_pipelines.md#add_b75bb8b) | (Public Preview) Creates an expression that adds a field's value to an expression. +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +add("quantity", field("reserve")); + +``` + | +| [arrayContains(fieldName, element)](./firestore_lite_pipelines.md#arraycontains_aaace4a) | (Public Preview) Creates an expression that checks if a field's array value contains a specific element. +```typescript +// Check if the 'colors' array contains the value of field 'selectedColor' +arrayContains("colors", field("selectedColor")); + +``` + | +| [arrayContains(fieldName, element)](./firestore_lite_pipelines.md#arraycontains_999590f) | (Public Preview) Creates an expression that checks if a field's array value contains a specific value. +```typescript +// Check if the 'colors' array contains "red" +arrayContains("colors", "red"); + +``` + | +| [arrayContainsAll(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsall_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. +```typescript +// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" +arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); + +``` + | +| [arrayContainsAll(fieldName, arrayExpression)](./firestore_lite_pipelines.md#arraycontainsall_48da8d9) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. +```typescript +// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" +arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); + +``` + | +| [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. +```typescript +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +arrayContainsAny("categories", [field("cate1"), "Science"]); + +``` + | +| [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_1b4f7cd) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. +```typescript +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +arrayContainsAny("categories", array([field("cate1"), "Science"])); + +``` + | +| [arrayLength(fieldName)](./firestore_lite_pipelines.md#arraylength_e5b0480) | (Public Preview) Creates an expression that calculates the length of an array in a specified field. +```typescript +// Get the number of items in field 'cart' +arrayLength('cart'); + +``` + | +| [arraySum(fieldName)](./firestore_lite_pipelines.md#arraysum_e5b0480) | (Public Preview) Creates an expression that computes the sum of the elements in an array. +```typescript +// Compute the sum of the elements in the 'scores' field. +arraySum("scores"); + +``` + | +| [ascending(fieldName)](./firestore_lite_pipelines.md#ascending_e5b0480) | (Public Preview) Creates an that sorts documents in ascending order based on a field. +```typescript +// Sort documents by the 'name' field in ascending order +firestore.pipeline().collection("users") + .sort(ascending("name")); + +``` + | +| [average(fieldName)](./firestore_lite_pipelines.md#average_e5b0480) | (Public Preview) Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. +```typescript +// Calculate the average age of users +average("age").as("averageAge"); + +``` + | +| [byteLength(fieldName)](./firestore_lite_pipelines.md#bytelength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. +```typescript +// Calculate the length of the 'myString' field in bytes. +byteLength("myString"); + +``` + | +| [ceil(fieldName)](./firestore_lite_pipelines.md#ceil_e5b0480) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. +```typescript +// Compute the ceiling of the 'price' field. +ceil("price"); + +``` + | +| [charLength(fieldName)](./firestore_lite_pipelines.md#charlength_e5b0480) | (Public Preview) Creates an expression that calculates the character length of a string field in UTF8. +```typescript +// Get the character length of the 'name' field in UTF-8. +strLength("name"); + +``` + | +| [collectionId(fieldName)](./firestore_lite_pipelines.md#collectionid_e5b0480) | (Public Preview) Creates an expression that returns the collection ID from a path. +```typescript +// Get the collection ID from a path. +collectionId("__name__"); + +``` + | +| [concat(fieldName, second, others)](./firestore_lite_pipelines.md#concat_828272e) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. +```typescript +// Concatenate a field with a literal string. +concat(field("firstName"), "Doe") + +``` + | +| [cosineDistance(fieldName, vector)](./firestore_lite_pipelines.md#cosinedistance_463a23e) | (Public Preview) Calculates the Cosine distance between a field's vector value and a literal vector value. +```typescript +// Calculate the Cosine distance between the 'location' field and a target location +cosineDistance("location", [37.7749, -122.4194]); + +``` + | +| [cosineDistance(fieldName, vectorExpression)](./firestore_lite_pipelines.md#cosinedistance_ed766a1) | (Public Preview) Calculates the Cosine distance between a field's vector value and a vector expression. +```typescript +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +cosineDistance("userVector", field("itemVector")); + +``` + | +| [count(fieldName)](./firestore_lite_pipelines.md#count_e5b0480) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the input field exists. +```typescript +// Count the total number of products +count("productId").as("totalProducts"); + +``` + | +| [descending(fieldName)](./firestore_lite_pipelines.md#descending_e5b0480) | (Public Preview) Creates an that sorts documents in descending order based on a field. +```typescript +// Sort documents by the 'name' field in descending order +firestore.pipeline().collection("users") + .sort(descending("name")); + +``` + | +| [divide(fieldName, expressions)](./firestore_lite_pipelines.md#divide_cf36e43) | (Public Preview) Creates an expression that divides a field's value by an expression. +```typescript +// Divide the 'total' field by the 'count' field +divide("total", field("count")); + +``` + | +| [divide(fieldName, value)](./firestore_lite_pipelines.md#divide_65e2f32) | (Public Preview) Creates an expression that divides a field's value by a constant value. +```typescript +// Divide the 'value' field by 10 +divide("value", 10); + +``` + | +| [dotProduct(fieldName, vector)](./firestore_lite_pipelines.md#dotproduct_463a23e) | (Public Preview) Calculates the dot product between a field's vector value and a double array. +```typescript +// Calculate the dot product distance between a feature vector and a target vector +dotProduct("features", [0.5, 0.8, 0.2]); + +``` + | +| [dotProduct(fieldName, vectorExpression)](./firestore_lite_pipelines.md#dotproduct_ed766a1) | (Public Preview) Calculates the dot product between a field's vector value and a vector expression. +```typescript +// Calculate the dot product distance between two document vectors: 'docVector1' and 'docVector2' +dotProduct("docVector1", field("docVector2")); + +``` + | +| [endsWith(fieldName, suffix)](./firestore_lite_pipelines.md#endswith_05ca3b0) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. +```typescript +// Check if the 'filename' field ends with ".txt" +endsWith("filename", ".txt"); + +``` + | +| [endsWith(fieldName, suffix)](./firestore_lite_pipelines.md#endswith_8fc0ebc) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. +```typescript +// Check if the 'url' field ends with the value of the 'extension' field +endsWith("url", field("extension")); + +``` + | +| [equal(fieldName, expression)](./firestore_lite_pipelines.md#equal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is equal to an expression. +```typescript +// Check if the 'age' field is equal to the 'limit' field +equal("age", field("limit")); + +``` + | +| [equal(fieldName, value)](./firestore_lite_pipelines.md#equal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is equal to a constant value. +```typescript +// Check if the 'city' field is equal to string constant "London" +equal("city", "London"); + +``` + | +| [equalAny(fieldName, values)](./firestore_lite_pipelines.md#equalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny("category", [constant("Electronics"), field("primaryType")]); + +``` + | +| [equalAny(fieldName, arrayExpression)](./firestore_lite_pipelines.md#equalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny("category", ["Electronics", field("primaryType")]); + +``` + | +| [euclideanDistance(fieldName, vector)](./firestore_lite_pipelines.md#euclideandistance_463a23e) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a double array. +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location +euclideanDistance("location", [37.7749, -122.4194]); + +``` + | +| [euclideanDistance(fieldName, vectorExpression)](./firestore_lite_pipelines.md#euclideandistance_ed766a1) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a vector expression. +```typescript +// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' +euclideanDistance("pointA", field("pointB")); + +``` + | +| [exists(fieldName)](./firestore_lite_pipelines.md#exists_e5b0480) | (Public Preview) Creates an expression that checks if a field exists. +```typescript +// Check if the document has a field named "phoneNumber" +exists("phoneNumber"); + +``` + | +| [exp(fieldName)](./firestore_lite_pipelines.md#exp_e5b0480) | (Public Preview) Creates an expression that computes e to the power of the expression's result. +```typescript +// Compute e to the power of the 'value' field. +exp('value'); + +``` + A new representing the exp of the numeric value. | +| [floor(fieldName)](./firestore_lite_pipelines.md#floor_e5b0480) | (Public Preview) Creates an expression that computes the floor of a numeric value. | +| [greaterThan(fieldName, expression)](./firestore_lite_pipelines.md#greaterthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is greater than an expression. +```typescript +// Check if the value of field 'age' is greater than the value of field 'limit' +greaterThan("age", field("limit")); + +``` + | +| [greaterThan(fieldName, value)](./firestore_lite_pipelines.md#greaterthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than a constant value. +```typescript +// Check if the 'price' field is greater than 100 +greaterThan("price", 100); + +``` + | +| [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_2e16acb) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to an expression. +```typescript +// Check if the value of field 'age' is greater than or equal to the value of field 'limit' +greaterThanOrEqual("age", field("limit")); + +``` + | +| [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to a constant value. +```typescript +// Check if the 'score' field is greater than or equal to 80 +greaterThanOrEqual("score", 80); + +``` + | +| [length\_2(fieldName)](./firestore_lite_pipelines.md#length_2_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. +```typescript +// Get the length of the 'name' field. +length("name"); + +// Get the number of items in the 'cart' array. +length("cart"); + +``` + | +| [lessThan(fieldName, expression)](./firestore_lite_pipelines.md#lessthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than an expression. +```typescript +// Check if the 'age' field is less than the 'limit' field +lessThan("age", field("limit")); + +``` + | +| [lessThan(fieldName, value)](./firestore_lite_pipelines.md#lessthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than a constant value. +```typescript +// Check if the 'price' field is less than 50 +lessThan("price", 50); + +``` + | +| [lessThanOrEqual(fieldName, expression)](./firestore_lite_pipelines.md#lessthanorequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to an expression. +```typescript +// Check if the 'quantity' field is less than or equal to the 'limit' field +lessThan("quantity", field("limit")); + +``` + | +| [lessThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#lessthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to a constant value. +```typescript +// Check if the 'score' field is less than or equal to 70 +lessThan("score", 70); + +``` + | +| [like(fieldName, pattern)](./firestore_lite_pipelines.md#like_67f7432) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. +```typescript +// Check if the 'title' field contains the string "guide" +like("title", "%guide%"); + +``` + | +| [like(fieldName, pattern)](./firestore_lite_pipelines.md#like_cb1318d) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. +```typescript +// Check if the 'title' field contains the string "guide" +like("title", field("pattern")); + +``` + | +| [ln(fieldName)](./firestore_lite_pipelines.md#ln_e5b0480) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. +```typescript +// Compute the natural logarithm of the 'value' field. +ln("value"); + +``` + | +| [log(fieldName, base)](./firestore_lite_pipelines.md#log_a89e21b) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. +```typescript +// Compute the logarithm of the 'value' field with base 10. +log("value", 10); + +``` + | +| [log(fieldName, base)](./firestore_lite_pipelines.md#log_805b11f) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. +```typescript +// Compute the logarithm of the 'value' field with the base in the 'base' field. +log("value", field("base")); + +``` + | +| [log10(fieldName)](./firestore_lite_pipelines.md#log10_e5b0480) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. +```typescript +// Compute the base-10 logarithm of the 'value' field. +log10("value"); + +``` + | +| [logicalMaximum(fieldName, second, others)](./firestore_lite_pipelines.md#logicalmaximum_828272e) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. +```typescript +// Returns the largest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMaximum("field1", field("field2"), 1000); + +``` + | +| [logicalMinimum(fieldName, second, others)](./firestore_lite_pipelines.md#logicalminimum_828272e) | (Public Preview) Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. +```typescript +// Returns the smallest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMinimum("field1", field("field2"), 1000); + +``` + | +| [mapGet(fieldName, subField)](./firestore_lite_pipelines.md#mapget_06663cf) | (Public Preview) Accesses a value from a map (object) field using the provided key. +```typescript +// Get the 'city' value from the 'address' map field +mapGet("address", "city"); + +``` + | +| [maximum(fieldName)](./firestore_lite_pipelines.md#maximum_e5b0480) | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. +```typescript +// Find the highest score in a leaderboard +maximum("score").as("highestScore"); + +``` + | +| [minimum(fieldName)](./firestore_lite_pipelines.md#minimum_e5b0480) | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. +```typescript +// Find the lowest price of all products +minimum("price").as("lowestPrice"); + +``` + | +| [mod(fieldName, expression)](./firestore_lite_pipelines.md#mod_1e91657) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. +```typescript +// Calculate the remainder of dividing 'field1' by 'field2'. +mod("field1", field("field2")); + +``` + | +| [mod(fieldName, value)](./firestore_lite_pipelines.md#mod_65e2f32) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. +```typescript +// Calculate the remainder of dividing 'field1' by 5. +mod("field1", 5); + +``` + | +| [multiply(fieldName, second)](./firestore_lite_pipelines.md#multiply_b75bb8b) | (Public Preview) Creates an expression that multiplies a field's value by an expression. +```typescript +// Multiply the 'quantity' field by the 'price' field +multiply("quantity", field("price")); + +``` + | +| [notEqual(fieldName, expression)](./firestore_lite_pipelines.md#notequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is not equal to an expression. +```typescript +// Check if the 'status' field is not equal to the value of 'expectedStatus' +notEqual("status", field("expectedStatus")); + +``` + | +| [notEqual(fieldName, value)](./firestore_lite_pipelines.md#notequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is not equal to a constant value. +```typescript +// Check if the 'country' field is not equal to "USA" +notEqual("country", "USA"); + +``` + | +| [notEqualAny(fieldName, values)](./firestore_lite_pipelines.md#notequalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +notEqualAny("status", [constant("pending"), field("rejectedStatus")]); + +``` + | +| [notEqualAny(fieldName, arrayExpression)](./firestore_lite_pipelines.md#notequalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. +```typescript +// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' +notEqualAny("status", field("rejectedStatuses")); + +``` + | +| [regexContains(fieldName, pattern)](./firestore_lite_pipelines.md#regexcontains_67f7432) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains("description", "(?i)example"); + +``` + | +| [regexContains(fieldName, pattern)](./firestore_lite_pipelines.md#regexcontains_cb1318d) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains("description", field("pattern")); + +``` + | +| [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_67f7432) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + +``` + | +| [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_cb1318d) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch("email", field("pattern")); + +``` + | +| [round(fieldName)](./firestore_lite_pipelines.md#round_e5b0480) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. +```typescript +// Round the value of the 'price' field. +round("price"); + +``` + | +| [round(fieldName, decimalPlaces)](./firestore_lite_pipelines.md#round_07d0cf0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. +```typescript +// Round the value of the 'price' field to two decimal places. +round("price", 2); + +``` + | +| [split(fieldName, delimiter)](./firestore_lite_pipelines.md#split_2cfdd37) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | +| [split(fieldName, delimiter)](./firestore_lite_pipelines.md#split_f4fe06a) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | +| [sqrt(fieldName)](./firestore_lite_pipelines.md#sqrt_e5b0480) | (Public Preview) Creates an expression that computes the square root of a numeric value. +```typescript +// Compute the square root of the 'value' field. +sqrt("value"); + +``` + | +| [startsWith(fieldName, prefix)](./firestore_lite_pipelines.md#startswith_89325cc) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. +```typescript +// Check if the 'name' field starts with "Mr." +startsWith("name", "Mr."); + +``` + | +| [startsWith(fieldName, prefix)](./firestore_lite_pipelines.md#startswith_266c338) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. +```typescript +// Check if the 'fullName' field starts with the value of the 'firstName' field +startsWith("fullName", field("firstName")); + +``` + | +| [stringConcat(fieldName, secondString, otherStrings)](./firestore_lite_pipelines.md#stringconcat_d80077e) | (Public Preview) Creates an expression that concatenates string functions, fields or constants together. +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +stringConcat("firstName", " ", field("lastName")); + +``` + | +| [stringContains(fieldName, substring)](./firestore_lite_pipelines.md#stringcontains_5b94cfe) | (Public Preview) Creates an expression that checks if a string field contains a specified substring. +```typescript +// Check if the 'description' field contains "example". +stringContains("description", "example"); + +``` + | +| [stringContains(fieldName, substring)](./firestore_lite_pipelines.md#stringcontains_ac3ba47) | (Public Preview) Creates an expression that checks if a string field contains a substring specified by an expression. +```typescript +// Check if the 'description' field contains the value of the 'keyword' field. +stringContains("description", field("keyword")); + +``` + | +| [subtract(fieldName, expression)](./firestore_lite_pipelines.md#subtract_1e91657) | (Public Preview) Creates an expression that subtracts an expression from a field's value. +```typescript +// Subtract the 'discount' field from the 'price' field +subtract("price", field("discount")); + +``` + | +| [subtract(fieldName, value)](./firestore_lite_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. +```typescript +// Subtract 20 from the value of the 'total' field +subtract("total", 20); + +``` + | +| [sum(fieldName)](./firestore_lite_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. +```typescript +// Calculate the total revenue from a set of orders +sum("orderAmount").as("totalRevenue"); + +``` + | +| [timestampAdd(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampadd_341fe7d) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. +```typescript +// Add 1 day to the 'timestamp' field. +timestampAdd("timestamp", "day", 1); + +``` + | +| [timestampSubtract(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_341fe7d) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. +```typescript +// Subtract 1 day from the 'timestamp' field. +timestampSubtract("timestamp", "day", 1); + +``` + | +| [timestampToUnixMicros(fieldName)](./firestore_lite_pipelines.md#timestamptounixmicros_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros("timestamp"); + +``` + | +| [timestampToUnixMillis(fieldName)](./firestore_lite_pipelines.md#timestamptounixmillis_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis("timestamp"); + +``` + | +| [timestampToUnixSeconds(fieldName)](./firestore_lite_pipelines.md#timestamptounixseconds_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds("timestamp"); + +``` + | +| [timestampTruncate(fieldName, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_b6c7512) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(fieldName, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_ed83d46) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [toLower(fieldName)](./firestore_lite_pipelines.md#tolower_e5b0480) | (Public Preview) Creates an expression that converts a string field to lowercase. +```typescript +// Convert the 'name' field to lowercase +toLower("name"); + +``` + | +| [toUpper(fieldName)](./firestore_lite_pipelines.md#toupper_e5b0480) | (Public Preview) Creates an expression that converts a string field to uppercase. +```typescript +// Convert the 'title' field to uppercase +toUpper("title"); + +``` + | +| [trim(fieldName, valueToTrim)](./firestore_lite_pipelines.md#trim_c9f90ee) | (Public Preview) Creates an expression that removes leading and trailing whitespace from a string or byte array. +```typescript +// Trim whitespace from the 'userInput' field +trim("userInput"); + +// Trim quotes from the 'userInput' field +trim("userInput", '"'); + +``` + | +| [type(fieldName)](./firestore_lite_pipelines.md#type_e5b0480) | (Public Preview) Creates an expression that returns the data type of the data in the specified field. | +| [unixMicrosToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixmicrostotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp("microseconds"); + +``` + | +| [unixMillisToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixmillistotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp("milliseconds"); + +``` + | +| [unixSecondsToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixsecondstotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +```typescript +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp("seconds"); + +``` + | +| [vectorLength(fieldName)](./firestore_lite_pipelines.md#vectorlength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector represented by a field. +```typescript +// Get the vector length (dimension) of the field 'embedding'. +vectorLength("embedding"); + +``` + | +| function(first, ...) | +| [add(first, second)](./firestore_lite_pipelines.md#add_846ca1b) | (Public Preview) Creates an expression that adds two expressions together. +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +add(field("quantity"), field("reserve")); + +``` + | +| [and(first, second, more)](./firestore_lite_pipelines.md#and_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'AND' operation on multiple filter conditions. +```typescript +// Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND +// the 'status' field is "active" +const condition = and(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); + +``` + | +| [concat(first, second, others)](./firestore_lite_pipelines.md#concat_83be015) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. +```typescript +// Concatenate the 'firstName' and 'lastName' fields with a space in between. +concat(field("firstName"), " ", field("lastName")) + +``` + | +| [logicalMaximum(first, second, others)](./firestore_lite_pipelines.md#logicalmaximum_83be015) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. +```typescript +// Returns the largest value between the 'field1' field, the 'field2' field, +// and 1000 +logicalMaximum(field("field1"), field("field2"), 1000); + +``` + | +| [logicalMinimum(first, second, others)](./firestore_lite_pipelines.md#logicalminimum_83be015) | (Public Preview) Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. +```typescript +// Returns the smallest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMinimum(field("field1"), field("field2"), 1000); + +``` + | +| [multiply(first, second)](./firestore_lite_pipelines.md#multiply_846ca1b) | (Public Preview) Creates an expression that multiplies two expressions together. +```typescript +// Multiply the 'quantity' field by the 'price' field +multiply(field("quantity"), field("price")); + +``` + | +| [or(first, second, more)](./firestore_lite_pipelines.md#or_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'OR' operation on multiple filter conditions. +```typescript +// Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR +// the 'status' field is "active" +const condition = or(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); + +``` + | +| [xor(first, second, additionalConditions)](./firestore_lite_pipelines.md#xor_8197113) | (Public Preview) Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. +```typescript +// Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London", +// or 'status' is "active". +const condition = xor( + greaterThan("age", 18), + equal("city", "London"), + equal("status", "active")); + +``` + | +| function(firstArray, ...) | +| [arrayConcat(firstArray, secondArray, otherArrays)](./firestore_lite_pipelines.md#arrayconcat_c00d5d7) | (Public Preview) Creates an expression that concatenates an array expression with other arrays. +```typescript +// Combine the 'items' array with two new item arrays +arrayConcat(field("items"), [field("newItems"), field("otherItems")]); + +``` + | +| function(firstArrayField, ...) | +| [arrayConcat(firstArrayField, secondArray, otherArrays)](./firestore_lite_pipelines.md#arrayconcat_f92063d) | (Public Preview) Creates an expression that concatenates a field's array value with other arrays. +```typescript +// Combine the 'items' array with two new item arrays +arrayConcat("items", [field("newItems"), field("otherItems")]); + +``` + | +| function(firstMap, ...) | +| [mapMerge(firstMap, secondMap, otherMaps)](./firestore_lite_pipelines.md#mapmerge_cfe77ce) | (Public Preview) Creates an expression that merges multiple map values. +``` +// Merges the map in the settings field with, a map literal, and a map in +// that is conditionally returned by another expression +mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) + +``` + | +| function(firstString, ...) | +| [stringConcat(firstString, secondString, otherStrings)](./firestore_lite_pipelines.md#stringconcat_8a8d1b6) | (Public Preview) Creates an expression that concatenates string expressions together. +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +stringConcat(field("firstName"), " ", field("lastName")); + +``` + | +| function(ifExpr, ...) | +| [ifAbsent(ifExpr, elseExpr)](./firestore_lite_pipelines.md#ifabsent_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent(field("optional_field"), constant("default_value")) + +``` + | +| [ifAbsent(ifExpr, elseValue)](./firestore_lite_pipelines.md#ifabsent_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent(field("optional_field"), "default_value") + +``` + | +| function(ifFieldName, ...) | +| [ifAbsent(ifFieldName, elseExpr)](./firestore_lite_pipelines.md#ifabsent_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName is absent, else return the value of the field. +```typescript +// Returns the value of the optional field 'optional_field', or returns the value of +// 'default_field' if 'optional_field' is absent. +ifAbsent("optional_field", field("default_field")) + +``` + | +| [ifAbsent(ifFieldName, elseValue)](./firestore_lite_pipelines.md#ifabsent_d8f2823) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName is absent, else return the value of the field. +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent("optional_field", "default_value") + +``` + | +| function(input, ...) | +| [substring(input, position, length)](./firestore_lite_pipelines.md#substring_e6e0aa3) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| [substring(input, position, length)](./firestore_lite_pipelines.md#substring_ab56dc6) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| function(left, ...) | +| [divide(left, right)](./firestore_lite_pipelines.md#divide_b3c3382) | (Public Preview) Creates an expression that divides two expressions. +```typescript +// Divide the 'total' field by the 'count' field +divide(field("total"), field("count")); + +``` + | +| [equal(left, right)](./firestore_lite_pipelines.md#equal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are equal. +```typescript +// Check if the 'age' field is equal to an expression +equal(field("age"), field("minAge").add(10)); + +``` + | +| [greaterThan(left, right)](./firestore_lite_pipelines.md#greaterthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than the second expression. +```typescript +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), Constant(9).add(9)); + +``` + | +| [greaterThanOrEqual(left, right)](./firestore_lite_pipelines.md#greaterthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than or equal to the second expression. +```typescript +// Check if the 'quantity' field is greater than or equal to the field "threshold" +greaterThanOrEqual(field("quantity"), field("threshold")); + +``` + | +| [lessThan(left, right)](./firestore_lite_pipelines.md#lessthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than the second expression. +```typescript +// Check if the 'age' field is less than 30 +lessThan(field("age"), field("limit")); + +``` + | +| [lessThanOrEqual(left, right)](./firestore_lite_pipelines.md#lessthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than or equal to the second expression. +```typescript +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), field("limit")); + +``` + | +| [mod(left, right)](./firestore_lite_pipelines.md#mod_b3c3382) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing two expressions. +```typescript +// Calculate the remainder of dividing 'field1' by 'field2'. +mod(field("field1"), field("field2")); + +``` + | +| [notEqual(left, right)](./firestore_lite_pipelines.md#notequal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are not equal. +```typescript +// Check if the 'status' field is not equal to field 'finalState' +notEqual(field("status"), field("finalState")); + +``` + | +| [subtract(left, right)](./firestore_lite_pipelines.md#subtract_b3c3382) | (Public Preview) Creates an expression that subtracts two expressions. +```typescript +// Subtract the 'discount' field from the 'price' field +subtract(field("price"), field("discount")); + +``` + | +| function(mapExpr, ...) | +| [mapRemove(mapExpr, key)](./firestore_lite_pipelines.md#mapremove_23c7d51) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. +``` +// Removes the key 'baz' from the input map. +mapRemove(map({foo: 'bar', baz: true}), 'baz'); + +``` + | +| [mapRemove(mapExpr, keyExpr)](./firestore_lite_pipelines.md#mapremove_9fbcaa3) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. +``` +// Removes the key 'baz' from the input map. +mapRemove(map({foo: 'bar', baz: true}), constant('baz')); + +``` + | +| function(mapExpression, ...) | +| [mapGet(mapExpression, subField)](./firestore_lite_pipelines.md#mapget_688c050) | (Public Preview) Accesses a value from a map (object) expression using the provided key. +```typescript +// Get the 'city' value from the 'address' map field +mapGet(field("address"), "city"); + +``` + | +| function(mapField, ...) | +| [mapMerge(mapField, secondMap, otherMaps)](./firestore_lite_pipelines.md#mapmerge_70a564b) | (Public Preview) Creates an expression that merges multiple map values. +``` +// Merges the map in the settings field with, a map literal, and a map in +// that is conditionally returned by another expression +mapMerge('settings', { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) + +``` + | +| [mapRemove(mapField, key)](./firestore_lite_pipelines.md#mapremove_bd5726e) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. +``` +// Removes the key 'city' field from the map in the address field of the input document. +mapRemove('address', 'city'); + +``` + | +| [mapRemove(mapField, keyExpr)](./firestore_lite_pipelines.md#mapremove_8406d13) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. +``` +// Removes the key 'city' field from the map in the address field of the input document. +mapRemove('address', constant('city')); + +``` + | +| function(name, ...) | +| [field(name)](./firestore_lite_pipelines.md#field_1eaaff4) | (Public Preview) Creates a instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). +```typescript +// Create a Field instance for the 'title' field +const titleField = field("title"); + +// Create a Field instance for a nested field 'author.firstName' +const authorFirstNameField = field("author.firstName"); + +``` + | +| function(path, ...) | +| [field(path)](./firestore_lite_pipelines.md#field_34ee07d) | (Public Preview) Creates a instance representing the field at the given path. | +| function(pipeline, ...) | +| [execute(pipeline)](./firestore_lite_pipelines.md#execute_01df620) | (Public Preview) Executes this pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a that contains a list of objects. Each typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:

  • If there are no stages or only transformation stages, each represents a single document.
  • If there is an aggregation, only a single is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each represents a distinct group and its associated aggregated values.

Example: +```typescript +const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") + .where(gt(field("rating"), 4.5)) + .select("title", "author", "rating")); + +const results: PipelineResults = snapshot.results; + +``` + | +| function(stringExpression, ...) | +| [charLength(stringExpression)](./firestore_lite_pipelines.md#charlength_c25a54a) | (Public Preview) Creates an expression that calculates the character length of a string expression in UTF-8. +```typescript +// Get the character length of the 'name' field in UTF-8. +strLength(field("name")); + +``` + | +| [endsWith(stringExpression, suffix)](./firestore_lite_pipelines.md#endswith_0a0b889) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." +endsWith(field("fullName"), "Jr."); + +``` + | +| [endsWith(stringExpression, suffix)](./firestore_lite_pipelines.md#endswith_13aee0d) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." +endsWith(field("fullName"), constant("Jr.")); + +``` + | +| [like(stringExpression, pattern)](./firestore_lite_pipelines.md#like_a84c581) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. +```typescript +// Check if the 'title' field contains the string "guide" +like(field("title"), "%guide%"); + +``` + | +| [like(stringExpression, pattern)](./firestore_lite_pipelines.md#like_b534848) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. +```typescript +// Check if the 'title' field contains the string "guide" +like(field("title"), field("pattern")); + +``` + | +| [regexContains(stringExpression, pattern)](./firestore_lite_pipelines.md#regexcontains_a84c581) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains(field("description"), "(?i)example"); + +``` + | +| [regexContains(stringExpression, pattern)](./firestore_lite_pipelines.md#regexcontains_b534848) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains(field("description"), field("pattern")); + +``` + | +| [regexMatch(stringExpression, pattern)](./firestore_lite_pipelines.md#regexmatch_a84c581) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch(field("email"), "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + +``` + | +| [regexMatch(stringExpression, pattern)](./firestore_lite_pipelines.md#regexmatch_b534848) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch(field("email"), field("pattern")); + +``` + | +| [reverse(stringExpression)](./firestore_lite_pipelines.md#reverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. +```typescript +// Reverse the value of the 'myString' field. +reverse(field("myString")); + +``` + | +| [startsWith(stringExpression, prefix)](./firestore_lite_pipelines.md#startswith_75c3dbb) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." +startsWith(field("fullName"), "Mr."); + +``` + | +| [startsWith(stringExpression, prefix)](./firestore_lite_pipelines.md#startswith_52f218a) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." +startsWith(field("fullName"), field("prefix")); + +``` + | +| [stringContains(stringExpression, substring)](./firestore_lite_pipelines.md#stringcontains_3e9ff32) | (Public Preview) Creates an expression that checks if a string expression contains a specified substring. +```typescript +// Check if the 'description' field contains "example". +stringContains(field("description"), "example"); + +``` + | +| [stringContains(stringExpression, substring)](./firestore_lite_pipelines.md#stringcontains_cc6ee02) | (Public Preview) Creates an expression that checks if a string expression contains a substring specified by another expression. +```typescript +// Check if the 'description' field contains the value of the 'keyword' field. +stringContains(field("description"), field("keyword")); + +``` + | +| [stringReverse(stringExpression)](./firestore_lite_pipelines.md#stringreverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. +```typescript +// Reverse the value of the 'myString' field. +strReverse(field("myString")); + +``` + | +| [toLower(stringExpression)](./firestore_lite_pipelines.md#tolower_c25a54a) | (Public Preview) Creates an expression that converts a string expression to lowercase. +```typescript +// Convert the 'name' field to lowercase +toLower(field("name")); + +``` + | +| [toUpper(stringExpression)](./firestore_lite_pipelines.md#toupper_c25a54a) | (Public Preview) Creates an expression that converts a string expression to uppercase. +```typescript +// Convert the 'title' field to uppercase +toUppercase(field("title")); + +``` + | +| [trim(stringExpression, valueToTrim)](./firestore_lite_pipelines.md#trim_dd54322) | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array expression. +```typescript +// Trim whitespace from the 'userInput' field +trim(field("userInput")); + +// Trim quotes from the 'userInput' field +trim(field("userInput"), '"'); + +``` + | +| function(timestamp, ...) | +| [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_98418f9) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. +```typescript +// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. +timestampAdd(field("timestamp"), field("unit"), field("amount")); + +``` + | +| [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_ffe8e57) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. +```typescript +// Add 1 day to the 'timestamp' field. +timestampAdd(field("timestamp"), "day", 1); + +``` + | +| [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_98418f9) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. +```typescript +// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. +timestampSubtract(field("timestamp"), field("unit"), field("amount")); + +``` + | +| [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_ffe8e57) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. +```typescript +// Subtract 1 day from the 'timestamp' field. +timestampSubtract(field("timestamp"), "day", 1); + +``` + | +| function(timestampExpression, ...) | +| [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_ad5d843) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_d6ab2a4) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| function(tryExpr, ...) | +| [ifError(tryExpr, catchExpr)](./firestore_lite_pipelines.md#iferror_a99a327) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation.This overload is useful when a BooleanExpression is required. +```typescript +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +ifError(constant(50).divide('length').gt(1), constant(false)); + +``` + | +| [ifError(tryExpr, catchExpr)](./firestore_lite_pipelines.md#iferror_756c12e) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. +```typescript +// Returns the first item in the title field arrays, or returns +// the entire title field if the array is empty or the field is another type. +ifError(field("title").arrayGet(0), field("title")); + +``` + | +| [ifError(tryExpr, catchValue)](./firestore_lite_pipelines.md#iferror_dc532f9) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. +```typescript +// Returns the first item in the title field arrays, or returns +// "Default Title" +ifError(field("title").arrayGet(0), "Default Title"); + +``` + | +| function(value, ...) | +| [constant(value)](./firestore_lite_pipelines.md#constant_0c00f91) | (Public Preview) Creates a Constant instance for a number value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_6dac335) | (Public Preview) Creates a Constant instance for a VectorValue value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_7c807cd) | (Public Preview) Creates a Constant instance for a string value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_b2e4f8d) | (Public Preview) Creates a BooleanExpression instance for a boolean value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_73ebd84) | (Public Preview) Creates a Constant instance for a null value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_72a76cb) | (Public Preview) Creates a Constant instance for a GeoPoint value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_000477d) | (Public Preview) Creates a Constant instance for a Timestamp value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_5131bf7) | (Public Preview) Creates a Constant instance for a Date value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_fdf565d) | (Public Preview) Creates a Constant instance for a Bytes value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_bcd2b0b) | (Public Preview) Creates a Constant instance for a DocumentReference value. | +| [exists(value)](./firestore_lite_pipelines.md#exists_f3daf14) | (Public Preview) Creates an expression that checks if a field exists. +```typescript +// Check if the document has a field named "phoneNumber" +exists(field("phoneNumber")); + +``` + | +| [isAbsent(value)](./firestore_lite_pipelines.md#isabsent_f3daf14) | (Public Preview) Creates an expression that returns true if a value is absent. Otherwise, returns false even if the value is null. +```typescript +// Check if the field `value` is absent. +isAbsent(field("value")); + +``` + | +| [isError(value)](./firestore_lite_pipelines.md#iserror_f3daf14) | (Public Preview) Creates an expression that checks if a given expression produces an error. +```typescript +// Check if the result of a calculation is an error +isError(field("title").arrayContains(1)); + +``` + | +| function(vectorExpression, ...) | +| [cosineDistance(vectorExpression, vector)](./firestore_lite_pipelines.md#cosinedistance_3a80317) | (Public Preview) Calculates the Cosine distance between a vector expression and a vector literal. +```typescript +// Calculate the cosine distance between the 'location' field and a target location +cosineDistance(field("location"), [37.7749, -122.4194]); + +``` + | +| [cosineDistance(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#cosinedistance_17b5bcc) | (Public Preview) Calculates the Cosine distance between two vector expressions. +```typescript +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +cosineDistance(field("userVector"), field("itemVector")); + +``` + | +| [dotProduct(vectorExpression, vector)](./firestore_lite_pipelines.md#dotproduct_3a80317) | (Public Preview) Calculates the dot product between a vector expression and a double array. +```typescript +// Calculate the dot product between a feature vector and a target vector +dotProduct(field("features"), [0.5, 0.8, 0.2]); + +``` + | +| [dotProduct(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#dotproduct_17b5bcc) | (Public Preview) Calculates the dot product between two vector expressions. +```typescript +// Calculate the dot product between two document vectors: 'docVector1' and 'docVector2' +dotProduct(field("docVector1"), field("docVector2")); + +``` + | +| [euclideanDistance(vectorExpression, vector)](./firestore_lite_pipelines.md#euclideandistance_3a80317) | (Public Preview) Calculates the Euclidean distance between a vector expression and a double array. +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location + +euclideanDistance(field("location"), [37.7749, -122.4194]); + +``` + | +| [euclideanDistance(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#euclideandistance_17b5bcc) | (Public Preview) Calculates the Euclidean distance between two vector expressions. +```typescript +// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' +euclideanDistance(field("pointA"), field("pointB")); + +``` + | +| [vectorLength(vectorExpression)](./firestore_lite_pipelines.md#vectorlength_58a039b) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector. +```typescript +// Get the vector length (dimension) of the field 'embedding'. +vectorLength(field("embedding")); + +``` + | + +## Classes + +| Class | Description | +| --- | --- | +| [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) | (Public Preview) A class that represents an aggregate function. | +| [AliasedAggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregate_class) | (Public Preview) An AggregateFunction with alias. | +| [AliasedExpression](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpression_class) | (Public Preview) | +| [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | (Public Preview) An interface that represents a filter condition. | +| [Bytes](./firestore_lite_pipelines.bytes.md#bytes_class) | An immutable object representing an array of bytes. | +| [CollectionReference](./firestore_lite_pipelines.collectionreference.md#collectionreference_class) | A CollectionReference object can be used for adding documents, getting document references, and querying for documents (using [query()](./firestore_.md#query_9f7b0f4)). | +| [DocumentReference](./firestore_lite_pipelines.documentreference.md#documentreference_class) | A DocumentReference refers to a document location in a Firestore database and can be used to write, read, or listen to the location. The document at the referenced location may or may not exist. | +| [DocumentSnapshot](./firestore_lite_pipelines.documentsnapshot.md#documentsnapshot_class) | A DocumentSnapshot contains data read from a document in your Firestore database. The data can be extracted with .data() or .get(<field>) to get a specific field.For a DocumentSnapshot that points to a non-existing document, any data access will return 'undefined'. You can use the exists() method to explicitly verify a document's existence. | +| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | (Public Preview) Represents an expression that can be evaluated to a value within the execution of a .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 Expr class provides a fluent API for building expressions. You can chain together method calls to create complex expressions. | +| [Field](./firestore_lite_pipelines.field.md#field_class) | (Public Preview) Represents a reference to a field in a Firestore document, or outputs of a stage.

Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines.

You can create a Field instance using the static method: +```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"); + +``` + | +| [FieldPath](./firestore_lite_pipelines.fieldpath.md#fieldpath_class) | A FieldPath refers to a field in a document. The path may consist of a single field name (referring to a top-level field in the document), or a list of field names (referring to a nested field in the document).Create a FieldPath by providing field names. If more than one field name is provided, the path will point to a nested field in a document. | +| [FieldValue](./firestore_lite_pipelines.fieldvalue.md#fieldvalue_class) | Sentinel values that can be used when writing document fields with set() or update(). | +| [Firestore](./firestore_lite_pipelines.firestore.md#firestore_class) | The Cloud Firestore service interface.Do not call this constructor directly. Instead, use [getFirestore()](./firestore_.md#getfirestore). | +| [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) | (Public Preview) This class defines the base class for Firestore functions, which can be evaluated within pipeline execution.Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_.md#and_e72c712), , or the methods on (, , etc.) to construct new Function instances. | +| [GeoPoint](./firestore_lite_pipelines.geopoint.md#geopoint_class) | An immutable object representing a geographic location in Firestore. The location is represented as latitude/longitude pair.Latitude values are in the range of \[-90, 90\]. Longitude values are in the range of \[-180, 180\]. | +| [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) | (Public Preview) Represents an ordering criterion for sorting documents in a Firestore pipeline.You create Ordering instances using the ascending and descending helper functions. | +| [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) | (Public Preview) The Pipeline class provides a flexible and expressive framework for building complex data transformation and query pipelines for Firestore.A pipeline takes data sources, such as Firestore collections or collection groups, and applies a series of stages that are chained together. Each stage takes the output from the previous stage (or the data source) and produces an output for the next stage (or as the final output of the pipeline).Expressions can be used within each stage to filter and transform data through the stage.NOTE: The chained stages do not prescribe exactly how Firestore will execute the pipeline. Instead, Firestore only guarantees that the result is the same as if the chained stages were executed in order.Usage Examples: +```typescript +const db: Firestore; // Assumes a valid firestore instance. + +// Example 1: Select specific fields and rename 'rating' to 'bookRating' +const results1 = await execute(db.pipeline() + .collection("books") + .select("title", "author", field("rating").as("bookRating"))); + +// Example 2: Filter documents where 'genre' is "Science Fiction" and 'published' is after 1950 +const results2 = await execute(db.pipeline() + .collection("books") + .where(and(field("genre").eq("Science Fiction"), field("published").gt(1950)))); + +// Example 3: Calculate the average rating of books published after 1980 +const results3 = await execute(db.pipeline() + .collection("books") + .where(field("published").gt(1980)) + .aggregate(avg(field("rating")).as("averageRating"))); + +``` + | +| [PipelineResult](./firestore_lite_pipelines.pipelineresult.md#pipelineresult_class) | (Public Preview) A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the or methods.

If the PipelineResult represents a non-document result, ref will return a undefined value. | +| [PipelineSnapshot](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) | (Public Preview) Represents the results of a Firestore pipeline execution.A PipelineSnapshot contains zero or more objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. | +| [PipelineSource](./firestore_lite_pipelines.pipelinesource.md#pipelinesource_class) | (Public Preview) Provides the entry point for defining the data source of a Firestore .Use the methods of this class (e.g., , , , or ) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. | +| [Query](./firestore_lite_pipelines.query.md#query_class) | A Query refers to a query which you can read or listen to. You can also construct refined Query objects by adding filters and ordering. | +| [QueryDocumentSnapshot](./firestore_lite_pipelines.querydocumentsnapshot.md#querydocumentsnapshot_class) | A QueryDocumentSnapshot contains data read from a document in your Firestore database as part of a query. The document is guaranteed to exist and its data can be extracted with .data() or .get(<field>) to get a specific field.A QueryDocumentSnapshot offers the same API surface as a DocumentSnapshot. Since query results contain only existing documents, the exists property will always be true and data() will never return 'undefined'. | +| [Timestamp](./firestore_lite_pipelines.timestamp.md#timestamp_class) | A Timestamp represents a point in time independent of any time zone or calendar, represented as seconds and fractions of seconds at nanosecond resolution in UTC Epoch time.It is encoded using the Proleptic Gregorian Calendar which extends the Gregorian calendar backwards to year one. It is encoded assuming all minutes are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.For examples and further specifications, refer to the [Timestamp definition](https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto). | +| [VectorValue](./firestore_lite_pipelines.vectorvalue.md#vectorvalue_class) | Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). VectorValue | + +## Interfaces + +| Interface | Description | +| --- | --- | +| [DocumentData](./firestore_lite_pipelines.documentdata.md#documentdata_interface) | Document data (for use with [setDoc()](./firestore_lite.md#setdoc_ee215ad)) consists of fields mapped to values. | +| [FirestoreDataConverter](./firestore_lite_pipelines.firestoredataconverter.md#firestoredataconverter_interface) | Converter used by withConverter() to transform user objects of type AppModelType into Firestore data of type DbModelType.Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore.In this context, an "AppModel" is a class that is used in an application to package together related information and functionality. Such a class could, for example, have properties with complex, nested data types, properties used for memoization, properties of types not supported by Firestore (such as symbol and bigint), and helper functions that perform compound operations. Such classes are not suitable and/or possible to store into a Firestore database. Instead, instances of such classes need to be converted to "plain old JavaScript objects" (POJOs) with exclusively primitive properties, potentially nested inside other POJOs or arrays of POJOs. In this context, this type is referred to as the "DbModel" and would be an object suitable for persisting into Firestore. For convenience, applications can implement FirestoreDataConverter and register the converter with Firestore objects, such as DocumentReference or Query, to automatically convert AppModel to DbModel when storing into Firestore, and convert DbModel to AppModel when retrieving from Firestore. | +| [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) | (Public Preview) An interface that represents a selectable expression. | +| [StageOptions](./firestore_lite_pipelines.stageoptions.md#stageoptions_interface) | (Public Preview) Options defining how a Stage is evaluated. | + +## Type Aliases + +| Type Alias | Description | +| --- | --- | +| [AddFieldsStageOptions](./firestore_lite_pipelines.md#addfieldsstageoptions) | (Public Preview) Options defining how an AddFieldsStage is evaluated. See . | +| [AggregateStageOptions](./firestore_lite_pipelines.md#aggregatestageoptions) | (Public Preview) Options defining how an AggregateStage is evaluated. See . | +| [CollectionGroupStageOptions](./firestore_lite_pipelines.md#collectiongroupstageoptions) | (Public Preview) Defines the configuration options for a within a pipeline. This type extends and provides specific settings for how a collection group is identified and processed during pipeline execution. | +| [CollectionStageOptions](./firestore_lite_pipelines.md#collectionstageoptions) | (Public Preview) Options defining how a CollectionStage is evaluated. See . | +| [DatabaseStageOptions](./firestore_lite_pipelines.md#databasestageoptions) | (Public Preview) Options defining how a DatabaseStage is evaluated. See . | +| [DistinctStageOptions](./firestore_lite_pipelines.md#distinctstageoptions) | (Public Preview) Options defining how a DistinctStage is evaluated. See . | +| [DocumentsStageOptions](./firestore_lite_pipelines.md#documentsstageoptions) | (Public Preview) Options defining how a DocumentsStage is evaluated. See . | +| [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) An enumeration of the different types of expressions. | +| [FindNearestStageOptions](./firestore_lite_pipelines.md#findneareststageoptions) | (Public Preview) Options defining how a FindNearestStage is evaluated. See . | +| [LimitStageOptions](./firestore_lite_pipelines.md#limitstageoptions) | (Public Preview) Options defining how a LimitStage is evaluated. See . | +| [OffsetStageOptions](./firestore_lite_pipelines.md#offsetstageoptions) | (Public Preview) Options defining how an OffsetStage is evaluated. See . | +| [OneOf](./firestore_lite_pipelines.md#oneof) | (Public Preview) Utility type to create an type that only allows one property of the Type param T to be set.type XorY = OneOf<{ x: unknown, y: unknown}> let a = { x: "foo" } // OK let b = { y: "foo" } // OK let c = { a: "foo", y: "foo" } // Not OK | +| [PartialWithFieldValue](./firestore_lite_pipelines.md#partialwithfieldvalue) | Similar to TypeScript's Partial<T>, but allows nested fields to be omitted and FieldValues to be passed in as property values. | +| [Primitive](./firestore_lite_pipelines.md#primitive) | Primitive types. | +| [RemoveFieldsStageOptions](./firestore_lite_pipelines.md#removefieldsstageoptions) | (Public Preview) Options defining how a RemoveFieldsStage is evaluated. See . | +| [ReplaceWithStageOptions](./firestore_lite_pipelines.md#replacewithstageoptions) | (Public Preview) Options defining how a ReplaceWithStage is evaluated. See . | +| [SampleStageOptions](./firestore_lite_pipelines.md#samplestageoptions) | (Public Preview) Defines the options for evaluating a sample stage within a pipeline. This type combines common with a specific configuration where only one of the defined sampling methods can be applied.See to create a sample stage.. | +| [SelectStageOptions](./firestore_lite_pipelines.md#selectstageoptions) | (Public Preview) Options defining how a SelectStage is evaluated. See . | +| [SetOptions](./firestore_lite_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | +| [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See . | +| [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | (Public Preview) Specify time granularity for expressions. | +| [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See . | +| [UnnestStageOptions](./firestore_lite_pipelines.md#unneststageoptions) | (Public Preview) Represents the specific options available for configuring an UnnestStage within a pipeline. | +| [WhereStageOptions](./firestore_lite_pipelines.md#wherestageoptions) | (Public Preview) Options defining how a WhereStage is evaluated. See . | +| [WithFieldValue](./firestore_lite_pipelines.md#withfieldvalue) | Allows FieldValues to be passed in as a property value while maintaining type safety. | + +## function() + +### countAll() {:#countall} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the total number of stage inputs. + +```typescript +// Count the total number of input documents +countAll().as("totalDocument"); + +``` + A new representing the 'countAll' aggregation. + +Signature: + +```typescript +export declare function countAll(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +### currentTimestamp() {:#currenttimestamp} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to the current server timestamp. + +```typescript +// Get the current server timestamp +currentTimestamp() + +``` + A new Expression representing the current server timestamp. + +Signature: + +```typescript +export declare function currentTimestamp(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(array, ...) + +### arrayContains(array, element) {:#arraycontains_a00ea48} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains a specific element. + +```typescript +// Check if the 'colors' array contains the value of field 'selectedColor' +arrayContains(field("colors"), field("selectedColor")); + +``` + +Signature: + +```typescript +export declare function arrayContains(array: Expression, element: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to check. | +| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The element to search for in the array. A new representing the 'array\_contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContains(array, element) {:#arraycontains_7328608} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains a specific element. + +```typescript +// Check if the 'colors' array contains "red" +arrayContains(field("colors"), "red"); + +``` + +Signature: + +```typescript +export declare function arrayContains(array: Expression, element: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to check. | +| element | unknown | The element to search for in the array. A new representing the 'array\_contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAll(array, values) {:#arraycontainsall_c658ad5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains all the specified elements. + +```typescript +// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" +arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); + +``` + +Signature: + +```typescript +export declare function arrayContainsAll(array: Expression, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to check. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new representing the 'array\_contains\_all' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAll(array, arrayExpression) {:#arraycontainsall_7b535db} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains all the specified elements. + +```typescript +// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" +arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); + +``` + +Signature: + +```typescript +export declare function arrayContainsAll(array: Expression, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to check. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. A new representing the 'array\_contains\_all' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAny(array, values) {:#arraycontainsany_c658ad5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains any of the specified elements. + +```typescript +// Check if the 'categories' array contains either values from field "cate1" or "Science" +arrayContainsAny(field("categories"), [field("cate1"), "Science"]); + +``` + +Signature: + +```typescript +export declare function arrayContainsAny(array: Expression, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to check. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new representing the 'array\_contains\_any' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAny(array, values) {:#arraycontainsany_c381a96} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains any of the specified elements. + +```typescript +// Check if the 'categories' array contains either values from field "cate1" or "Science" +arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); + +``` + +Signature: + +```typescript +export declare function arrayContainsAny(array: Expression, values: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to check. | +| values | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array. A new representing the 'array\_contains\_any' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayLength(array) {:#arraylength_195e339} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of an array expression. + +```typescript +// Get the number of items in the 'cart' array +arrayLength(field("cart")); + +``` + +Signature: + +```typescript +export declare function arrayLength(array: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to calculate the length of. A new representing the length of the array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(arrayExpression, ...) + +### arrayGet(arrayExpression, offset) {:#arrayget_f2e27cc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + +```typescript +// Return the value in the tags field array at index 1. +arrayGet(field('tags'), 1); + +``` + +Signature: + +```typescript +export declare function arrayGet(arrayExpression: Expression, offset: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expr evaluating to an array. | +| offset | number | The index of the element to return. A new Expr representing the 'arrayGet' operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### arrayGet(arrayExpression, offsetExpr) {:#arrayget_484550d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet(field('tags'), field('favoriteTag')); + +``` + +Signature: + +```typescript +export declare function arrayGet(arrayExpression: Expression, offsetExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expr evaluating to an array. | +| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expr evaluating to the index of the element to return. A new Expr representing the 'arrayGet' operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### join(arrayExpression, delimiterExpression) {:#join_313e6aa} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + +```typescript +// Join an array of string using the delimiter from the 'separator' field. +join(array(['foo', 'bar']), field("separator")) + +``` + +Signature: + +```typescript +export declare function join(arrayExpression: Expression, delimiterExpression: Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | +| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. A new Expression representing the join operation. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### join(arrayExpression, delimiter) {:#join_d088d29} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + +```typescript +// Join the elements of the 'tags' field with a comma and space. +join(field("tags"), ", ") + +``` + +Signature: + +```typescript +export declare function join(arrayExpression: Expression, delimiter: string): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | +| delimiter | string | The string to use as a delimiter. A new Expression representing the join operation. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +## function(arrayField, ...) + +### arrayGet(arrayField, offset) {:#arrayget_3f58471} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + +```typescript +// Return the value in the tags field array at index 1. +arrayGet('tags', 1); + +``` + +Signature: + +```typescript +export declare function arrayGet(arrayField: string, offset: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayField | string | The name of the array field. | +| offset | number | The index of the element to return. A new Expr representing the 'arrayGet' operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### arrayGet(arrayField, offsetExpr) {:#arrayget_1904c9a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet('tags', field('favoriteTag')); + +``` + +Signature: + +```typescript +export declare function arrayGet(arrayField: string, offsetExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayField | string | The name of the array field. | +| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expr evaluating to the index of the element to return. A new Expr representing the 'arrayGet' operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(arrayFieldName, ...) + +### join(arrayFieldName, delimiter) {:#join_478ef36} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + +```typescript +// Join the elements of the 'tags' field with a comma and space. +join("tags", ", ") + +``` + +Signature: + +```typescript +export declare function join(arrayFieldName: string, delimiter: string): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayFieldName | string | The name of the field containing the array. | +| delimiter | string | The string to use as a delimiter. A new Expression representing the join operation. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### join(arrayFieldName, delimiterExpression) {:#join_829294c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + +```typescript +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +join('tags', field("separator")) + +``` + +Signature: + +```typescript +export declare function join(arrayFieldName: string, delimiterExpression: Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayFieldName | string | The name of the field containing the array. | +| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. A new Expression representing the join operation. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +## function(base, ...) + +### pow(base, exponent) {:#pow_e4a9e64} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base expression raised to the power of the exponent expression. + +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow(field("base"), field("exponent")); + +``` + +Signature: + +```typescript +export declare function pow(base: Expression, exponent: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | +| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. A new Expr representing the power operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### pow(base, exponent) {:#pow_93eae7f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base expression raised to the power of the exponent. + +```typescript +// Raise the value of the 'base' field to the power of 2. +pow(field("base"), 2); + +``` + +Signature: + +```typescript +export declare function pow(base: Expression, exponent: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | +| exponent | number | The constant value to raise the base to the power of. A new Expr representing the power operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### pow(base, exponent) {:#pow_a237721} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base field raised to the power of the exponent expression. + +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow("base", field("exponent")); + +``` + +Signature: + +```typescript +export declare function pow(base: string, exponent: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| base | string | The name of the field to raise to the power of the exponent. | +| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. A new Expr representing the power operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### pow(base, exponent) {:#pow_f4d7908} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base field raised to the power of the exponent. + +```typescript +// Raise the value of the 'base' field to the power of 2. +pow("base", 2); + +``` + +Signature: + +```typescript +export declare function pow(base: string, exponent: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| base | string | The name of the field to raise to the power of the exponent. | +| exponent | number | The constant value to raise the base to the power of. A new Expr representing the power operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(booleanExpr, ...) + +### countIf(booleanExpr) {:#countif_c5b8fb1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. + +```typescript +// Count the number of documents where 'is_active' field equals true +countIf(field("is_active").equal(true)).as("numActiveDocuments"); + +``` + +Signature: + +```typescript +export declare function countIf(booleanExpr: BooleanExpression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| booleanExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The boolean expression to evaluate on each input. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'countIf' aggregation. + +### not(booleanExpr) {:#not_c5b8fb1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that negates a filter condition. + +```typescript +// Find documents where the 'completed' field is NOT true +not(equal("completed", true)); + +``` + +Signature: + +```typescript +export declare function not(booleanExpr: BooleanExpression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| booleanExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The filter condition to negate. A new representing the negated filter condition. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## function(condition, ...) + +### conditional(condition, thenExpr, elseExpr) {:#conditional_07a206d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. + +```typescript +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +conditional( + greaterThan("age", 18), constant("Adult"), constant("Minor")); + +``` + +Signature: + +```typescript +export declare function conditional(condition: BooleanExpression, thenExpr: Expression, elseExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| condition | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The condition to evaluate. | +| thenExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is true. | +| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. A new representing the conditional expression. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(documentPath, ...) + +### documentId(documentPath) {:#documentid_cef293c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the document ID from a path. + +```typescript +// Get the document ID from a path. +documentId(myDocumentReference); + +``` + A new representing the documentId operation. + +Signature: + +```typescript +export declare function documentId(documentPath: string | DocumentReference): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| documentPath | string \| [DocumentReference](./firestore_lite.documentreference.md#documentreference_class) | | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(documentPathExpr, ...) + +### documentId(documentPathExpr) {:#documentid_9a69021} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the document ID from a path. + +```typescript +// Get the document ID from a path. +documentId(field("__path__")); + +``` + A new representing the documentId operation. + +Signature: + +```typescript +export declare function documentId(documentPathExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| documentPathExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(element, ...) + +### notEqualAny(element, values) {:#notequalany_c2c5bcb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to any of the provided values or expressions. + +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + +Signature: + +```typescript +export declare function notEqualAny(element: Expression, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values to check against. A new representing the 'NOT IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### notEqualAny(element, arrayExpression) {:#notequalany_16b2851} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to any of the provided values or expressions. + +```typescript +// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + +Signature: + +```typescript +export declare function notEqualAny(element: Expression, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The values to check against. A new representing the 'NOT IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## function(elements, ...) + +### array(elements) {:#array_7d853aa} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that creates a Firestore array value from an input array. + +```typescript +// Create an array value from the input array and reference the 'baz' field value from the input document. +array(['bar', Field.of('baz')]).as('foo'); + +``` + +Signature: + +```typescript +export declare function array(elements: unknown[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elements | unknown\[\] | The input array to evaluate in the expression. A new representing the array function. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### map(elements) {:#map_ce5dee1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that creates a Firestore map value from an input object. + +```typescript +// Create a map from the input object and reference the 'baz' field value from the input document. +map({foo: 'bar', baz: Field.of('baz')}).as('data'); + +``` + +Signature: + +```typescript +export declare function map(elements: Record): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elements | Record<string, unknown> | The input map to evaluate in the expression. A new representing the map function. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(expr, ...) + +### abs(expr) {:#abs_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the absolute value of a numeric value. + +Signature: + +```typescript +export declare function abs(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compute the absolute value of. A new representing the absolute value of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### ascending(expr) {:#ascending_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an that sorts documents in ascending order based on an expression. + +```typescript +// Sort documents by the 'name' field in lowercase in ascending order +firestore.pipeline().collection("users") + .sort(ascending(field("name").toLower())); + +``` + +Signature: + +```typescript +export declare function ascending(expr: Expression): Ordering; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to create an ascending ordering for. A new Ordering for ascending sorting. | + +Returns: + +[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) + +### byteLength(expr) {:#bytelength_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. + +```typescript +// Calculate the length of the 'myString' field in bytes. +byteLength(field("myString")); + +``` + +Signature: + +```typescript +export declare function byteLength(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string. A new representing the length of the string in bytes. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### countDistinct(expr) {:#countdistinct_3c28b08} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of distinct values of a field. + +Signature: + +```typescript +export declare function countDistinct(expr: Expression | string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string | The expression or field to count distinct values of. A new AggregateFunction representing the 'count\_distinct' aggregation. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +### descending(expr) {:#descending_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an that sorts documents in descending order based on an expression. + +```typescript +// Sort documents by the 'name' field in lowercase in descending order +firestore.pipeline().collection("users") + .sort(descending(field("name").toLower())); + +``` + +Signature: + +```typescript +export declare function descending(expr: Expression): Ordering; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to create a descending ordering for. A new Ordering for descending sorting. | + +Returns: + +[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) + +### floor(expr) {:#floor_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the floor of a numeric value. + +Signature: + +```typescript +export declare function floor(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compute the floor of. A new representing the floor of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### timestampToUnixMicros(expr) {:#timestamptounixmicros_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros(field("timestamp")); + +``` + +Signature: + +```typescript +export declare function timestampToUnixMicros(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. A new representing the number of microseconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### timestampToUnixMillis(expr) {:#timestamptounixmillis_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis(field("timestamp")); + +``` + +Signature: + +```typescript +export declare function timestampToUnixMillis(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. A new representing the number of milliseconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### timestampToUnixSeconds(expr) {:#timestamptounixseconds_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds(field("timestamp")); + +``` + +Signature: + +```typescript +export declare function timestampToUnixSeconds(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. A new representing the number of seconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### unixMicrosToTimestamp(expr) {:#unixmicrostotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp(field("microseconds")); + +``` + +Signature: + +```typescript +export declare function unixMicrosToTimestamp(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of microseconds since epoch. A new representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### unixMillisToTimestamp(expr) {:#unixmillistotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp(field("milliseconds")); + +``` + +Signature: + +```typescript +export declare function unixMillisToTimestamp(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of milliseconds since epoch. A new representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### unixSecondsToTimestamp(expr) {:#unixsecondstotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +```typescript +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp(field("seconds")); + +``` + +Signature: + +```typescript +export declare function unixSecondsToTimestamp(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of seconds since epoch. A new representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(expression, ...) + +### arraySum(expression) {:#arraysum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. + +```typescript +// Compute the sum of the elements in the 'scores' field. +arraySum(field("scores")); + +``` + +Signature: + +```typescript +export declare function arraySum(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric array, which the sum will be computed for. A new Expr representing the sum of the elements in the array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### average(expression) {:#average_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. + +```typescript +// Calculate the average age of users +average(field("age")).as("averageAge"); + +``` + +Signature: + +```typescript +export declare function average(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the values to average. A new representing the 'average' aggregation. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +### ceil(expression) {:#ceil_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. + +```typescript +// Compute the ceiling of the 'price' field. +ceil(field("price")); + +``` + +Signature: + +```typescript +export declare function ceil(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the ceiling will be computed for. A new representing the ceiling of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### collectionId(expression) {:#collectionid_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. + +```typescript +// Get the collection ID from a path. +collectionId(field("__name__")); + +``` + +Signature: + +```typescript +export declare function collectionId(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a path, which the collection ID will be extracted from. A new representing the collectionId operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### count(expression) {:#count_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. + +```typescript +// Count the number of items where the price is greater than 10 +count(field("price").greaterThan(10)).as("expensiveItemCount"); + +``` + +Signature: + +```typescript +export declare function count(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to count. A new representing the 'count' aggregation. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +### divide(expression, value) {:#divide_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides an expression by a constant value. + +```typescript +// Divide the 'value' field by 10 +divide(field("value"), 10); + +``` + +Signature: + +```typescript +export declare function divide(expression: Expression, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to be divided. | +| value | unknown | The constant value to divide by. A new representing the division operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### equal(expression, value) {:#equal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is equal to a constant value. + +```typescript +// Check if the 'age' field is equal to 21 +equal(field("age"), 21); + +``` + +Signature: + +```typescript +export declare function equal(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the equality comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### equalAny(expression, values) {:#equalany_7e759b5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. + +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny(field("category"), [constant("Electronics"), field("primaryType")]); + +``` + +Signature: + +```typescript +export declare function equalAny(expression: Expression, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression whose results to compare. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values to check against. A new representing the 'IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### equalAny(expression, arrayExpression) {:#equalany_214ce68} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is equal to any of the provided values. + +```typescript +// Check if the 'category' field is set to a value in the disabledCategories field +equalAny(field("category"), field('disabledCategories')); + +``` + +Signature: + +```typescript +export declare function equalAny(expression: Expression, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression whose results to compare. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input. A new representing the 'IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### exp(expression) {:#exp_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes e to the power of the expression's result. + +```typescript +// Compute e to the power of 2. +exp(constant(2)); + +``` + A new representing the exp of the numeric value. + +Signature: + +```typescript +export declare function exp(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### greaterThan(expression, value) {:#greaterthan_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is greater than a constant value. + +```typescript +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), 18); + +``` + +Signature: + +```typescript +export declare function greaterThan(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the greater than comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### greaterThanOrEqual(expression, value) {:#greaterthanorequal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is greater than or equal to a constant value. + +```typescript +// Check if the 'quantity' field is greater than or equal to 10 +greaterThanOrEqual(field("quantity"), 10); + +``` + +Signature: + +```typescript +export declare function greaterThanOrEqual(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the greater than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### length\_2(expression) {:#length_2_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string, array, map, vector, or bytes. + +```typescript +// Get the length of the 'name' field. +length(field("name")); + +// Get the number of items in the 'cart' array. +length(field("cart")); + +``` + +Signature: + +```typescript +declare function length_2(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. A new Expr representing the length of the string, array, map, vector, or bytes. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### lessThan(expression, value) {:#lessthan_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is less than a constant value. + +```typescript +// Check if the 'age' field is less than 30 +lessThan(field("age"), 30); + +``` + +Signature: + +```typescript +export declare function lessThan(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the less than comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### lessThanOrEqual(expression, value) {:#lessthanorequal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is less than or equal to a constant value. + +```typescript +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), 20); + +``` + +Signature: + +```typescript +export declare function lessThanOrEqual(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the less than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### ln(expression) {:#ln_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the natural logarithm of a numeric value. + +```typescript +// Compute the natural logarithm of the 'value' field. +ln(field("value")); + +``` + +Signature: + +```typescript +export declare function ln(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the natural logarithm will be computed for. A new Expr representing the natural logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### log(expression, base) {:#log_ac183e2} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of an expression to a given base. + +```typescript +// Compute the logarithm of the 'value' field with base 10. +log(field("value"), 10); + +``` + +Signature: + +```typescript +export declare function log(expression: Expression, base: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | +| base | number | The base of the logarithm. A new representing the logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### log(expression, base) {:#log_1894737} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of an expression to a given base. + +```typescript +// Compute the logarithm of the 'value' field with the base in the 'base' field. +log(field("value"), field("base")); + +``` + +Signature: + +```typescript +export declare function log(expression: Expression, base: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | +| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The base of the logarithm. A new representing the logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### log10(expression) {:#log10_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the base-10 logarithm of a numeric value. + +```typescript +// Compute the base-10 logarithm of the 'value' field. +log10(field("value")); + +``` + +Signature: + +```typescript +export declare function log10(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. A new Expr representing the base-10 logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### maximum(expression) {:#maximum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. + +```typescript +// Find the highest score in a leaderboard +maximum(field("score")).as("highestScore"); + +``` + +Signature: + +```typescript +export declare function maximum(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the maximum value of. A new representing the 'maximum' aggregation. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +### minimum(expression) {:#minimum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. + +```typescript +// Find the lowest price of all products +minimum(field("price")).as("lowestPrice"); + +``` + +Signature: + +```typescript +export declare function minimum(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the minimum value of. A new representing the 'minimum' aggregation. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +### mod(expression, value) {:#mod_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. + +```typescript +// Calculate the remainder of dividing 'field1' by 5. +mod(field("field1"), 5); + +``` + +Signature: + +```typescript +export declare function mod(expression: Expression, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The dividend expression. | +| value | unknown | The divisor constant. A new representing the modulo operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### notEqual(expression, value) {:#notequal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to a constant value. + +```typescript +// Check if the 'status' field is not equal to "completed" +notEqual(field("status"), "completed"); + +``` + +Signature: + +```typescript +export declare function notEqual(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the inequality comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### round(expression) {:#round_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the nearest whole number. + +```typescript +// Round the value of the 'price' field. +round(field("price")); + +``` + +Signature: + +```typescript +export declare function round(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. A new Expr representing the rounded value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### round(expression, decimalPlaces) {:#round_a3a92d0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + +```typescript +// Round the value of the 'price' field to two decimal places. +round(field("price"), constant(2)); + +``` + +Signature: + +```typescript +export declare function round(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | +| decimalPlaces | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. A new Expr representing the rounded value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### split(expression, delimiter) {:#split_5b5612b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that splits a string into an array of substrings based on the provided delimiter. + +Signature: + +```typescript +export declare function split(expression: Expression, delimiter: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split the result of this expression. | +| delimiter | string | Split on this delimiter. A new representing the split function. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Split the 'scoresCsv' field on delimiter ',' +split(field('scoresCsv'), ',') + +``` + +### split(expression, delimiter) {:#split_5a171ed} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that splits a string into an array of substrings based on the provided delimiter. + +Signature: + +```typescript +export declare function split(expression: Expression, delimiter: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split the result of this expression. | +| delimiter | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. A new representing the split function. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Split the 'scores' field on delimiter ',' or ':' depending on the stored format +split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':')) + +``` + +### sqrt(expression) {:#sqrt_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the square root of a numeric value. + +```typescript +// Compute the square root of the 'value' field. +sqrt(field("value")); + +``` + +Signature: + +```typescript +export declare function sqrt(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the square root will be computed for. A new representing the square root of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### subtract(expression, value) {:#subtract_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a constant value from an expression. + +```typescript +// Subtract the constant value 2 from the 'value' field +subtract(field("value"), 2); + +``` + +Signature: + +```typescript +export declare function subtract(expression: Expression, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract from. | +| value | unknown | The constant value to subtract. A new representing the subtraction operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### sum(expression) {:#sum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. + +```typescript +// Calculate the total revenue from a set of orders +sum(field("orderAmount")).as("totalRevenue"); + +``` + +Signature: + +```typescript +export declare function sum(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to sum up. A new representing the 'sum' aggregation. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +### type(expression) {:#type_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the data type of an expression's result. + +Signature: + +```typescript +export declare function type(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Get the data type of a conditional expression +type(conditional(exists('foo'), constant(1), constant(true))) + +``` + A new {Expression} representing the data type. + +## function(field, ...) + +### isAbsent(field) {:#isabsent_0fb8cd4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns `true` if a field is absent. Otherwise, returns `false` even if the field value is `null`. + +```typescript +// Check if the field `value` is absent. +isAbsent("value"); + +``` + +Signature: + +```typescript +export declare function isAbsent(field: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | string | The field to check. A new representing the 'isAbsent' check. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### reverse(field) {:#reverse_0fb8cd4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string value in the specified field. + +```typescript +// Reverse the value of the 'myString' field. +reverse("myString"); + +``` + +Signature: + +```typescript +export declare function reverse(field: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | string | The name of the field representing the string to reverse. A new representing the reversed string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### stringReverse(field) {:#stringreverse_0fb8cd4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string value in the specified field. + +```typescript +// Reverse the value of the 'myString' field. +strReverse("myString"); + +``` + +Signature: + +```typescript +export declare function stringReverse(field: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | string | The name of the field representing the string to reverse. A new representing the reversed string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### substring(field, position, length) {:#substring_0d9573a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a substring of a string or byte array. + +Signature: + +```typescript +export declare function substring(field: string, position: number, length?: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | string | The name of a field containing a string or byte array to compute the substring from. | +| position | number | Index of the first character of the substring. | +| length | number | Length of the substring. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### substring(field, position, length) {:#substring_05cb14e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a substring of a string or byte array. + +Signature: + +```typescript +export declare function substring(field: string, position: Expression, length?: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | string | The name of a field containing a string or byte array to compute the substring from. | +| position | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that returns the index of the first character of the substring. | +| length | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that returns the length of the substring. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(fieldName, ...) + +### abs(fieldName) {:#abs_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the absolute value of a numeric value. + +Signature: + +```typescript +export declare function abs(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field to compute the absolute value of. A new representing the absolute value of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### add(fieldName, second) {:#add_b75bb8b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a field's value to an expression. + +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +add("quantity", field("reserve")); + +``` + +Signature: + +```typescript +export declare function add(fieldName: string, second: Expression | unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the value to add. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### arrayContains(fieldName, element) {:#arraycontains_aaace4a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains a specific element. + +```typescript +// Check if the 'colors' array contains the value of field 'selectedColor' +arrayContains("colors", field("selectedColor")); + +``` + +Signature: + +```typescript +export declare function arrayContains(fieldName: string, element: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The element to search for in the array. A new representing the 'array\_contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContains(fieldName, element) {:#arraycontains_999590f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains a specific value. + +```typescript +// Check if the 'colors' array contains "red" +arrayContains("colors", "red"); + +``` + +Signature: + +```typescript +export declare function arrayContains(fieldName: string, element: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| element | unknown | The element to search for in the array. A new representing the 'array\_contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAll(fieldName, values) {:#arraycontainsall_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains all the specified values or expressions. + +```typescript +// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" +arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); + +``` + +Signature: + +```typescript +export declare function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new representing the 'array\_contains\_all' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAll(fieldName, arrayExpression) {:#arraycontainsall_48da8d9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains all the specified values or expressions. + +```typescript +// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" +arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); + +``` + +Signature: + +```typescript +export declare function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. A new representing the 'array\_contains\_all' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAny(fieldName, values) {:#arraycontainsany_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains any of the specified elements. + +```typescript +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +arrayContainsAny("categories", [field("cate1"), "Science"]); + +``` + +Signature: + +```typescript +export declare function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new representing the 'array\_contains\_any' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAny(fieldName, values) {:#arraycontainsany_1b4f7cd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains any of the specified elements. + +```typescript +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +arrayContainsAny("categories", array([field("cate1"), "Science"])); + +``` + +Signature: + +```typescript +export declare function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| values | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array field. A new representing the 'array\_contains\_any' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayLength(fieldName) {:#arraylength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of an array in a specified field. + +```typescript +// Get the number of items in field 'cart' +arrayLength('cart'); + +``` + +Signature: + +```typescript +export declare function arrayLength(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing an array to calculate the length of. A new representing the length of the array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### arraySum(fieldName) {:#arraysum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. + +```typescript +// Compute the sum of the elements in the 'scores' field. +arraySum("scores"); + +``` + +Signature: + +```typescript +export declare function arraySum(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the sum of. A new Expr representing the sum of the elements in the array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### ascending(fieldName) {:#ascending_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an that sorts documents in ascending order based on a field. + +```typescript +// Sort documents by the 'name' field in ascending order +firestore.pipeline().collection("users") + .sort(ascending("name")); + +``` + +Signature: + +```typescript +export declare function ascending(fieldName: string): Ordering; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field to create an ascending ordering for. A new Ordering for ascending sorting. | + +Returns: + +[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) + +### average(fieldName) {:#average_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. + +```typescript +// Calculate the average age of users +average("age").as("averageAge"); + +``` + +Signature: + +```typescript +export declare function average(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing numeric values to average. A new representing the 'average' aggregation. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +### byteLength(fieldName) {:#bytelength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. + +```typescript +// Calculate the length of the 'myString' field in bytes. +byteLength("myString"); + +``` + +Signature: + +```typescript +export declare function byteLength(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. A new representing the length of the string in bytes. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### ceil(fieldName) {:#ceil_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. + +```typescript +// Compute the ceiling of the 'price' field. +ceil("price"); + +``` + +Signature: + +```typescript +export declare function ceil(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the ceiling of. A new representing the ceiling of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### charLength(fieldName) {:#charlength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the character length of a string field in UTF8. + +```typescript +// Get the character length of the 'name' field in UTF-8. +strLength("name"); + +``` + +Signature: + +```typescript +export declare function charLength(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. A new representing the length of the string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### collectionId(fieldName) {:#collectionid_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. + +```typescript +// Get the collection ID from a path. +collectionId("__name__"); + +``` + +Signature: + +```typescript +export declare function collectionId(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to get the collection ID from. A new representing the collectionId operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### concat(fieldName, second, others) {:#concat_828272e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. + +```typescript +// Concatenate a field with a literal string. +concat(field("firstName"), "Doe") + +``` + +Signature: + +```typescript +export declare function concat(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of a field to concatenate. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second literal or expression to concatenate. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Additional literal or expressions to concatenate. A new Expression representing the concatenation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### cosineDistance(fieldName, vector) {:#cosinedistance_463a23e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between a field's vector value and a literal vector value. + +```typescript +// Calculate the Cosine distance between the 'location' field and a target location +cosineDistance("location", [37.7749, -122.4194]); + +``` + +Signature: + +```typescript +export declare function cosineDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the first vector. | +| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles) or [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) to compare against. A new representing the Cosine distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### cosineDistance(fieldName, vectorExpression) {:#cosinedistance_ed766a1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between a field's vector value and a vector expression. + +```typescript +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +cosineDistance("userVector", field("itemVector")); + +``` + +Signature: + +```typescript +export declare function cosineDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the first vector. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the cosine distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### count(fieldName) {:#count_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs where the input field exists. + +```typescript +// Count the total number of products +count("productId").as("totalProducts"); + +``` + +Signature: + +```typescript +export declare function count(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to count. A new representing the 'count' aggregation. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +### descending(fieldName) {:#descending_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an that sorts documents in descending order based on a field. + +```typescript +// Sort documents by the 'name' field in descending order +firestore.pipeline().collection("users") + .sort(descending("name")); + +``` + +Signature: + +```typescript +export declare function descending(fieldName: string): Ordering; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field to create a descending ordering for. A new Ordering for descending sorting. | + +Returns: + +[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) + +### divide(fieldName, expressions) {:#divide_cf36e43} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides a field's value by an expression. + +```typescript +// Divide the 'total' field by the 'count' field +divide("total", field("count")); + +``` + +Signature: + +```typescript +export declare function divide(fieldName: string, expressions: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to be divided. | +| expressions | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to divide by. A new representing the division operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### divide(fieldName, value) {:#divide_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides a field's value by a constant value. + +```typescript +// Divide the 'value' field by 10 +divide("value", 10); + +``` + +Signature: + +```typescript +export declare function divide(fieldName: string, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to be divided. | +| value | unknown | The constant value to divide by. A new representing the division operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### dotProduct(fieldName, vector) {:#dotproduct_463a23e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between a field's vector value and a double array. + +```typescript +// Calculate the dot product distance between a feature vector and a target vector +dotProduct("features", [0.5, 0.8, 0.2]); + +``` + +Signature: + +```typescript +export declare function dotProduct(fieldName: string, vector: number[] | VectorValue): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the first vector. | +| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to calculate with. A new representing the dot product between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### dotProduct(fieldName, vectorExpression) {:#dotproduct_ed766a1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between a field's vector value and a vector expression. + +```typescript +// Calculate the dot product distance between two document vectors: 'docVector1' and 'docVector2' +dotProduct("docVector1", field("docVector2")); + +``` + +Signature: + +```typescript +export declare function dotProduct(fieldName: string, vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the first vector. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to calculate with. A new representing the dot product between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### endsWith(fieldName, suffix) {:#endswith_05ca3b0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value ends with a given postfix. + +```typescript +// Check if the 'filename' field ends with ".txt" +endsWith("filename", ".txt"); + +``` + +Signature: + +```typescript +export declare function endsWith(fieldName: string, suffix: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| suffix | string | The postfix to check for. A new representing the 'ends with' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### endsWith(fieldName, suffix) {:#endswith_8fc0ebc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value ends with a given postfix. + +```typescript +// Check if the 'url' field ends with the value of the 'extension' field +endsWith("url", field("extension")); + +``` + +Signature: + +```typescript +export declare function endsWith(fieldName: string, suffix: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| suffix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the postfix. A new representing the 'ends with' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### equal(fieldName, expression) {:#equal_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to an expression. + +```typescript +// Check if the 'age' field is equal to the 'limit' field +equal("age", field("limit")); + +``` + +Signature: + +```typescript +export declare function equal(fieldName: string, expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the equality comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### equal(fieldName, value) {:#equal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to a constant value. + +```typescript +// Check if the 'city' field is equal to string constant "London" +equal("city", "London"); + +``` + +Signature: + +```typescript +export declare function equal(fieldName: string, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the equality comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### equalAny(fieldName, values) {:#equalany_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to any of the provided values or expressions. + +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny("category", [constant("Electronics"), field("primaryType")]); + +``` + +Signature: + +```typescript +export declare function equalAny(fieldName: string, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field to compare. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values to check against. A new representing the 'IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### equalAny(fieldName, arrayExpression) {:#equalany_48da8d9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to any of the provided values or expressions. + +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny("category", ["Electronics", field("primaryType")]); + +``` + +Signature: + +```typescript +export declare function equalAny(fieldName: string, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field to compare. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input field. A new representing the 'IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### euclideanDistance(fieldName, vector) {:#euclideandistance_463a23e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between a field's vector value and a double array. + +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location +euclideanDistance("location", [37.7749, -122.4194]); + +``` + +Signature: + +```typescript +export declare function euclideanDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the first vector. | +| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. A new representing the Euclidean distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### euclideanDistance(fieldName, vectorExpression) {:#euclideandistance_ed766a1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between a field's vector value and a vector expression. + +```typescript +// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' +euclideanDistance("pointA", field("pointB")); + +``` + +Signature: + +```typescript +export declare function euclideanDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the first vector. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the Euclidean distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### exists(fieldName) {:#exists_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field exists. + +```typescript +// Check if the document has a field named "phoneNumber" +exists("phoneNumber"); + +``` + +Signature: + +```typescript +export declare function exists(fieldName: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. A new representing the 'exists' check. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### exp(fieldName) {:#exp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes e to the power of the expression's result. + +```typescript +// Compute e to the power of the 'value' field. +exp('value'); + +``` + A new representing the exp of the numeric value. + +Signature: + +```typescript +export declare function exp(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### floor(fieldName) {:#floor_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the floor of a numeric value. + +Signature: + +```typescript +export declare function floor(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the floor of. A new representing the floor of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### greaterThan(fieldName, expression) {:#greaterthan_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than an expression. + +```typescript +// Check if the value of field 'age' is greater than the value of field 'limit' +greaterThan("age", field("limit")); + +``` + +Signature: + +```typescript +export declare function greaterThan(fieldName: string, expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the greater than comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### greaterThan(fieldName, value) {:#greaterthan_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than a constant value. + +```typescript +// Check if the 'price' field is greater than 100 +greaterThan("price", 100); + +``` + +Signature: + +```typescript +export declare function greaterThan(fieldName: string, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the greater than comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_2e16acb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than or equal to an expression. + +```typescript +// Check if the value of field 'age' is greater than or equal to the value of field 'limit' +greaterThanOrEqual("age", field("limit")); + +``` + +Signature: + +```typescript +export declare function greaterThanOrEqual(fieldName: string, value: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the greater than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than or equal to a constant value. + +```typescript +// Check if the 'score' field is greater than or equal to 80 +greaterThanOrEqual("score", 80); + +``` + +Signature: + +```typescript +export declare function greaterThanOrEqual(fieldName: string, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the greater than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### length\_2(fieldName) {:#length_2_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string, array, map, vector, or bytes. + +```typescript +// Get the length of the 'name' field. +length("name"); + +// Get the number of items in the 'cart' array. +length("cart"); + +``` + +Signature: + +```typescript +declare function length_2(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to calculate the length of. A new Expr representing the length of the string, array, map, vector, or bytes. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### lessThan(fieldName, expression) {:#lessthan_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than an expression. + +```typescript +// Check if the 'age' field is less than the 'limit' field +lessThan("age", field("limit")); + +``` + +Signature: + +```typescript +export declare function lessThan(fieldName: string, expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the less than comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### lessThan(fieldName, value) {:#lessthan_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than a constant value. + +```typescript +// Check if the 'price' field is less than 50 +lessThan("price", 50); + +``` + +Signature: + +```typescript +export declare function lessThan(fieldName: string, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the less than comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### lessThanOrEqual(fieldName, expression) {:#lessthanorequal_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than or equal to an expression. + +```typescript +// Check if the 'quantity' field is less than or equal to the 'limit' field +lessThan("quantity", field("limit")); + +``` + +Signature: + +```typescript +export declare function lessThanOrEqual(fieldName: string, expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the less than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### lessThanOrEqual(fieldName, value) {:#lessthanorequal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than or equal to a constant value. + +```typescript +// Check if the 'score' field is less than or equal to 70 +lessThan("score", 70); + +``` + +Signature: + +```typescript +export declare function lessThanOrEqual(fieldName: string, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the less than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### like(fieldName, pattern) {:#like_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison against a field. + +```typescript +// Check if the 'title' field contains the string "guide" +like("title", "%guide%"); + +``` + +Signature: + +```typescript +export declare function like(fieldName: string, pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| pattern | string | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### like(fieldName, pattern) {:#like_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison against a field. + +```typescript +// Check if the 'title' field contains the string "guide" +like("title", field("pattern")); + +``` + +Signature: + +```typescript +export declare function like(fieldName: string, pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### ln(fieldName) {:#ln_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the natural logarithm of a numeric value. + +```typescript +// Compute the natural logarithm of the 'value' field. +ln("value"); + +``` + +Signature: + +```typescript +export declare function ln(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the natural logarithm of. A new Expr representing the natural logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### log(fieldName, base) {:#log_a89e21b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of a field to a given base. + +```typescript +// Compute the logarithm of the 'value' field with base 10. +log("value", 10); + +``` + +Signature: + +```typescript +export declare function log(fieldName: string, base: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the logarithm of. | +| base | number | The base of the logarithm. A new representing the logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### log(fieldName, base) {:#log_805b11f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of a field to a given base. + +```typescript +// Compute the logarithm of the 'value' field with the base in the 'base' field. +log("value", field("base")); + +``` + +Signature: + +```typescript +export declare function log(fieldName: string, base: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the logarithm of. | +| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The base of the logarithm. A new representing the logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### log10(fieldName) {:#log10_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the base-10 logarithm of a numeric value. + +```typescript +// Compute the base-10 logarithm of the 'value' field. +log10("value"); + +``` + +Signature: + +```typescript +export declare function log10(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the base-10 logarithm of. A new Expr representing the base-10 logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### logicalMaximum(fieldName, second, others) {:#logicalmaximum_828272e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. + +```typescript +// Returns the largest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMaximum("field1", field("field2"), 1000); + +``` + +Signature: + +```typescript +export declare function logicalMaximum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The first operand field name. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical maximum operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### logicalMinimum(fieldName, second, others) {:#logicalminimum_828272e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. + +```typescript +// Returns the smallest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMinimum("field1", field("field2"), 1000); + +``` + +Signature: + +```typescript +export declare function logicalMinimum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The first operand field name. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical minimum operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### mapGet(fieldName, subField) {:#mapget_06663cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Accesses a value from a map (object) field using the provided key. + +```typescript +// Get the 'city' value from the 'address' map field +mapGet("address", "city"); + +``` + +Signature: + +```typescript +export declare function mapGet(fieldName: string, subField: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name of the map field. | +| subField | string | The key to access in the map. A new representing the value associated with the given key in the map. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### maximum(fieldName) {:#maximum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the maximum value of a field across multiple stage inputs. + +```typescript +// Find the highest score in a leaderboard +maximum("score").as("highestScore"); + +``` + +Signature: + +```typescript +export declare function maximum(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to find the maximum value of. A new representing the 'maximum' aggregation. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +### minimum(fieldName) {:#minimum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the minimum value of a field across multiple stage inputs. + +```typescript +// Find the lowest price of all products +minimum("price").as("lowestPrice"); + +``` + +Signature: + +```typescript +export declare function minimum(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to find the minimum value of. A new representing the 'minimum' aggregation. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +### mod(fieldName, expression) {:#mod_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. + +```typescript +// Calculate the remainder of dividing 'field1' by 'field2'. +mod("field1", field("field2")); + +``` + +Signature: + +```typescript +export declare function mod(fieldName: string, expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The dividend field name. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The divisor expression. A new representing the modulo operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### mod(fieldName, value) {:#mod_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. + +```typescript +// Calculate the remainder of dividing 'field1' by 5. +mod("field1", 5); + +``` + +Signature: + +```typescript +export declare function mod(fieldName: string, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The dividend field name. | +| value | unknown | The divisor constant. A new representing the modulo operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### multiply(fieldName, second) {:#multiply_b75bb8b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that multiplies a field's value by an expression. + +```typescript +// Multiply the 'quantity' field by the 'price' field +multiply("quantity", field("price")); + +``` + +Signature: + +```typescript +export declare function multiply(fieldName: string, second: Expression | unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the value to add. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### notEqual(fieldName, expression) {:#notequal_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to an expression. + +```typescript +// Check if the 'status' field is not equal to the value of 'expectedStatus' +notEqual("status", field("expectedStatus")); + +``` + +Signature: + +```typescript +export declare function notEqual(fieldName: string, expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the inequality comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### notEqual(fieldName, value) {:#notequal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to a constant value. + +```typescript +// Check if the 'country' field is not equal to "USA" +notEqual("country", "USA"); + +``` + +Signature: + +```typescript +export declare function notEqual(fieldName: string, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the inequality comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### notEqualAny(fieldName, values) {:#notequalany_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. + +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +notEqualAny("status", [constant("pending"), field("rejectedStatus")]); + +``` + +Signature: + +```typescript +export declare function notEqualAny(fieldName: string, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values to check against. A new representing the 'NOT IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### notEqualAny(fieldName, arrayExpression) {:#notequalany_48da8d9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. + +```typescript +// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' +notEqualAny("status", field("rejectedStatuses")); + +``` + +Signature: + +```typescript +export declare function notEqualAny(fieldName: string, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The values to check against. A new representing the 'NOT IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### regexContains(fieldName, pattern) {:#regexcontains_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a specified regular expression as a substring. + +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains("description", "(?i)example"); + +``` + +Signature: + +```typescript +export declare function regexContains(fieldName: string, pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| pattern | string | The regular expression to use for the search. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### regexContains(fieldName, pattern) {:#regexcontains_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a specified regular expression as a substring. + +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains("description", field("pattern")); + +``` + +Signature: + +```typescript +export declare function regexContains(fieldName: string, pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the search. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### regexMatch(fieldName, pattern) {:#regexmatch_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field matches a specified regular expression. + +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + +``` + +Signature: + +```typescript +export declare function regexMatch(fieldName: string, pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| pattern | string | The regular expression to use for the match. A new representing the regular expression match. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### regexMatch(fieldName, pattern) {:#regexmatch_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field matches a specified regular expression. + +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch("email", field("pattern")); + +``` + +Signature: + +```typescript +export declare function regexMatch(fieldName: string, pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the match. A new representing the regular expression match. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### round(fieldName) {:#round_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the nearest whole number. + +```typescript +// Round the value of the 'price' field. +round("price"); + +``` + +Signature: + +```typescript +export declare function round(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to round. A new Expr representing the rounded value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### round(fieldName, decimalPlaces) {:#round_07d0cf0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + +```typescript +// Round the value of the 'price' field to two decimal places. +round("price", 2); + +``` + +Signature: + +```typescript +export declare function round(fieldName: string, decimalPlaces: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to round. | +| decimalPlaces | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. A new Expr representing the rounded value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### split(fieldName, delimiter) {:#split_2cfdd37} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that splits the value of a field on the provided delimiter. + +Signature: + +```typescript +export declare function split(fieldName: string, delimiter: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | Split the value in this field. | +| delimiter | string | Split on this delimiter. A new representing the split function. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Split the 'scoresCsv' field on delimiter ',' +split('scoresCsv', ',') + +``` + +### split(fieldName, delimiter) {:#split_f4fe06a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that splits the value of a field on the provided delimiter. + +Signature: + +```typescript +export declare function split(fieldName: string, delimiter: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | Split the value in this field. | +| delimiter | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. A new representing the split function. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Split the 'scores' field on delimiter ',' or ':' depending on the stored format +split('scores', conditional(field('format').equal('csv'), constant(','), constant(':')) + +``` + +### sqrt(fieldName) {:#sqrt_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the square root of a numeric value. + +```typescript +// Compute the square root of the 'value' field. +sqrt("value"); + +``` + +Signature: + +```typescript +export declare function sqrt(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the square root of. A new representing the square root of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### startsWith(fieldName, prefix) {:#startswith_89325cc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value starts with a given prefix. + +```typescript +// Check if the 'name' field starts with "Mr." +startsWith("name", "Mr."); + +``` + +Signature: + +```typescript +export declare function startsWith(fieldName: string, prefix: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| prefix | string | The prefix to check for. A new representing the 'starts with' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### startsWith(fieldName, prefix) {:#startswith_266c338} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value starts with a given prefix. + +```typescript +// Check if the 'fullName' field starts with the value of the 'firstName' field +startsWith("fullName", field("firstName")); + +``` + +Signature: + +```typescript +export declare function startsWith(fieldName: string, prefix: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| prefix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the prefix. A new representing the 'starts with' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### stringConcat(fieldName, secondString, otherStrings) {:#stringconcat_d80077e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates string functions, fields or constants together. + +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +stringConcat("firstName", " ", field("lastName")); + +``` + +Signature: + +```typescript +export declare function stringConcat(fieldName: string, secondString: Expression | string, ...otherStrings: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name containing the initial string value. | +| secondString | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string | An expression or string literal to concatenate. | +| otherStrings | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or literals (typically strings) to concatenate. A new representing the concatenated string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### stringContains(fieldName, substring) {:#stringcontains_5b94cfe} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a specified substring. + +```typescript +// Check if the 'description' field contains "example". +stringContains("description", "example"); + +``` + +Signature: + +```typescript +export declare function stringContains(fieldName: string, substring: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| substring | string | The substring to search for. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### stringContains(fieldName, substring) {:#stringcontains_ac3ba47} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a substring specified by an expression. + +```typescript +// Check if the 'description' field contains the value of the 'keyword' field. +stringContains("description", field("keyword")); + +``` + +Signature: + +```typescript +export declare function stringContains(fieldName: string, substring: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| substring | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the substring to search for. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### subtract(fieldName, expression) {:#subtract_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts an expression from a field's value. + +```typescript +// Subtract the 'discount' field from the 'price' field +subtract("price", field("discount")); + +``` + +Signature: + +```typescript +export declare function subtract(fieldName: string, expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to subtract from. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract. A new representing the subtraction operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### subtract(fieldName, value) {:#subtract_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a constant value from a field's value. + +```typescript +// Subtract 20 from the value of the 'total' field +subtract("total", 20); + +``` + +Signature: + +```typescript +export declare function subtract(fieldName: string, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to subtract from. | +| value | unknown | The constant value to subtract. A new representing the subtraction operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### sum(fieldName) {:#sum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. + +```typescript +// Calculate the total revenue from a set of orders +sum("orderAmount").as("totalRevenue"); + +``` + +Signature: + +```typescript +export declare function sum(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing numeric values to sum up. A new representing the 'sum' aggregation. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +### timestampAdd(fieldName, unit, amount) {:#timestampadd_341fe7d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to a timestamp represented by a field. + +```typescript +// Add 1 day to the 'timestamp' field. +timestampAdd("timestamp", "day", 1); + +``` + +Signature: + +```typescript +export declare function timestampAdd(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | +| amount | number | The amount of time to add. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_341fe7d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. + +```typescript +// Subtract 1 day from the 'timestamp' field. +timestampSubtract("timestamp", "day", 1); + +``` + +Signature: + +```typescript +export declare function timestampSubtract(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | +| amount | number | The amount of time to subtract. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### timestampToUnixMicros(fieldName) {:#timestamptounixmicros_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros("timestamp"); + +``` + +Signature: + +```typescript +export declare function timestampToUnixMicros(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. A new representing the number of microseconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### timestampToUnixMillis(fieldName) {:#timestamptounixmillis_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis("timestamp"); + +``` + +Signature: + +```typescript +export declare function timestampToUnixMillis(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. A new representing the number of milliseconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### timestampToUnixSeconds(fieldName) {:#timestamptounixseconds_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds("timestamp"); + +``` + +Signature: + +```typescript +export declare function timestampToUnixSeconds(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. A new representing the number of seconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### timestampTruncate(fieldName, granularity, timezone) {:#timestamptruncate_b6c7512} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a timestamp to a specified granularity. + +Signature: + +```typescript +export declare function timestampTruncate(fieldName: string, granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | Truncate the timestamp value contained in this field. | +| granularity | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | The granularity to truncate to. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Truncate the 'createdAt' timestamp to the beginning of the day. +field('createdAt').timestampTruncate('day') + +``` + +### timestampTruncate(fieldName, granularity, timezone) {:#timestamptruncate_ed83d46} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a timestamp to a specified granularity. + +Signature: + +```typescript +export declare function timestampTruncate(fieldName: string, granularity: Expression, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | Truncate the timestamp value contained in this field. | +| granularity | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The granularity to truncate to. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. +field('createdAt').timestampTruncate(field('granularity')) + +``` + +### toLower(fieldName) {:#tolower_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string field to lowercase. + +```typescript +// Convert the 'name' field to lowercase +toLower("name"); + +``` + +Signature: + +```typescript +export declare function toLower(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. A new representing the lowercase string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### toUpper(fieldName) {:#toupper_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string field to uppercase. + +```typescript +// Convert the 'title' field to uppercase +toUpper("title"); + +``` + +Signature: + +```typescript +export declare function toUpper(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. A new representing the uppercase string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### trim(fieldName, valueToTrim) {:#trim_c9f90ee} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes leading and trailing whitespace from a string or byte array. + +```typescript +// Trim whitespace from the 'userInput' field +trim("userInput"); + +// Trim quotes from the 'userInput' field +trim("userInput", '"'); + +``` + +Signature: + +```typescript +export declare function trim(fieldName: string, valueToTrim?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | 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. A new representing the trimmed string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### type(fieldName) {:#type_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the data type of the data in the specified field. + +Signature: + +```typescript +export declare function type(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Get the data type of the value in field 'title' +type('title') + +``` + A new {Expression} representing the data type. + +### unixMicrosToTimestamp(fieldName) {:#unixmicrostotimestamp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp("microseconds"); + +``` + +Signature: + +```typescript +export declare function unixMicrosToTimestamp(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the number of microseconds since epoch. A new representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### unixMillisToTimestamp(fieldName) {:#unixmillistotimestamp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp("milliseconds"); + +``` + +Signature: + +```typescript +export declare function unixMillisToTimestamp(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the number of milliseconds since epoch. A new representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### unixSecondsToTimestamp(fieldName) {:#unixsecondstotimestamp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +```typescript +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp("seconds"); + +``` + +Signature: + +```typescript +export declare function unixSecondsToTimestamp(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the number of seconds since epoch. A new representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### vectorLength(fieldName) {:#vectorlength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a Firestore Vector represented by a field. + +```typescript +// Get the vector length (dimension) of the field 'embedding'. +vectorLength("embedding"); + +``` + +Signature: + +```typescript +export declare function vectorLength(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the Firestore Vector. A new representing the length of the array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(first, ...) + +### add(first, second) {:#add_846ca1b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds two expressions together. + +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +add(field("quantity"), field("reserve")); + +``` + +Signature: + +```typescript +export declare function add(first: Expression, second: Expression | unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to add. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### and(first, second, more) {:#and_e0c48bd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'AND' operation on multiple filter conditions. + +```typescript +// Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND +// the 'status' field is "active" +const condition = and(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); + +``` + +Signature: + +```typescript +export declare function and(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The first filter condition. | +| second | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The second filter condition. | +| more | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'AND' together. A new representing the logical 'AND' operation. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### concat(first, second, others) {:#concat_83be015} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. + +```typescript +// Concatenate the 'firstName' and 'lastName' fields with a space in between. +concat(field("firstName"), " ", field("lastName")) + +``` + +Signature: + +```typescript +export declare function concat(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expressions to concatenate. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second literal or expression to concatenate. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Additional literals or expressions to concatenate. A new Expression representing the concatenation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### logicalMaximum(first, second, others) {:#logicalmaximum_83be015} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. + +```typescript +// Returns the largest value between the 'field1' field, the 'field2' field, +// and 1000 +logicalMaximum(field("field1"), field("field2"), 1000); + +``` + +Signature: + +```typescript +export declare function logicalMaximum(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first operand expression. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical maximum operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### logicalMinimum(first, second, others) {:#logicalminimum_83be015} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. + +```typescript +// Returns the smallest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMinimum(field("field1"), field("field2"), 1000); + +``` + +Signature: + +```typescript +export declare function logicalMinimum(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first operand expression. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical minimum operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### multiply(first, second) {:#multiply_846ca1b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that multiplies two expressions together. + +```typescript +// Multiply the 'quantity' field by the 'price' field +multiply(field("quantity"), field("price")); + +``` + +Signature: + +```typescript +export declare function multiply(first: Expression, second: Expression | unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to multiply. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to multiply. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### or(first, second, more) {:#or_e0c48bd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'OR' operation on multiple filter conditions. + +```typescript +// Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR +// the 'status' field is "active" +const condition = or(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); + +``` + +Signature: + +```typescript +export declare function or(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The first filter condition. | +| second | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The second filter condition. | +| more | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'OR' together. A new representing the logical 'OR' operation. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### xor(first, second, additionalConditions) {:#xor_8197113} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. + +```typescript +// Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London", +// or 'status' is "active". +const condition = xor( + greaterThan("age", 18), + equal("city", "London"), + equal("status", "active")); + +``` + +Signature: + +```typescript +export declare function xor(first: BooleanExpression, second: BooleanExpression, ...additionalConditions: BooleanExpression[]): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The first condition. | +| second | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The second condition. | +| additionalConditions | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional conditions to 'XOR' together. A new representing the logical 'XOR' operation. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## function(firstArray, ...) + +### arrayConcat(firstArray, secondArray, otherArrays) {:#arrayconcat_c00d5d7} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates an array expression with other arrays. + +```typescript +// Combine the 'items' array with two new item arrays +arrayConcat(field("items"), [field("newItems"), field("otherItems")]); + +``` + +Signature: + +```typescript +export declare function arrayConcat(firstArray: Expression, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| firstArray | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first array expression to concatenate to. | +| secondArray | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\] | The second array expression or array literal to concatenate to. | +| otherArrays | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. A new representing the concatenated array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(firstArrayField, ...) + +### arrayConcat(firstArrayField, secondArray, otherArrays) {:#arrayconcat_f92063d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates a field's array value with other arrays. + +```typescript +// Combine the 'items' array with two new item arrays +arrayConcat("items", [field("newItems"), field("otherItems")]); + +``` + +Signature: + +```typescript +export declare function arrayConcat(firstArrayField: string, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| firstArrayField | string | The first array to concatenate to. | +| secondArray | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\] | The second array expression or array literal to concatenate to. | +| otherArrays | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. A new representing the concatenated array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(firstMap, ...) + +### mapMerge(firstMap, secondMap, otherMaps) {:#mapmerge_cfe77ce} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that merges multiple map values. + +``` +// Merges the map in the settings field with, a map literal, and a map in +// that is conditionally returned by another expression +mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) + +``` + +Signature: + +```typescript +export declare function mapMerge(firstMap: Record | Expression, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| firstMap | Record<string, unknown> \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression or literal map value that will be merged. | +| secondMap | Record<string, unknown> \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A required second map to merge. Represented as a literal or an expression that returns a map. | +| otherMaps | Array<Record<string, unknown> \| [Expression](./firestore_lite_pipelines.expression.md#expression_class)> | Optional additional maps to merge. Each map is represented as a literal or an expression that returns a map. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(firstString, ...) + +### stringConcat(firstString, secondString, otherStrings) {:#stringconcat_8a8d1b6} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates string expressions together. + +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +stringConcat(field("firstName"), " ", field("lastName")); + +``` + +Signature: + +```typescript +export declare function stringConcat(firstString: Expression, secondString: Expression | string, ...otherStrings: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| firstString | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The initial string expression to concatenate to. | +| secondString | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string | An expression or string literal to concatenate. | +| otherStrings | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or literals (typically strings) to concatenate. A new representing the concatenated string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(ifExpr, ...) + +### ifAbsent(ifExpr, elseExpr) {:#ifabsent_0e6d161} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseExpr` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent(field("optional_field"), constant("default_value")) + +``` + +Signature: + +```typescript +export declare function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check for absence. | +| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if \[ifExpr\] is absent. A new Expression representing the ifAbsent operation. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### ifAbsent(ifExpr, elseValue) {:#ifabsent_c34e5ed} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent(field("optional_field"), "default_value") + +``` + +Signature: + +```typescript +export declare function ifAbsent(ifExpr: Expression, elseValue: unknown): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check for absence. | +| elseValue | unknown | The value that will be returned if ifExpr evaluates to an absent value. A new \[Expression\] representing the ifAbsent operation. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +## function(ifFieldName, ...) + +### ifAbsent(ifFieldName, elseExpr) {:#ifabsent_e6dabea} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseExpr` argument if `ifFieldName` is absent, else return the value of the field. + +```typescript +// Returns the value of the optional field 'optional_field', or returns the value of +// 'default_field' if 'optional_field' is absent. +ifAbsent("optional_field", field("default_field")) + +``` + +Signature: + +```typescript +export declare function ifAbsent(ifFieldName: string, elseExpr: Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifFieldName | string | The field to check for absence. | +| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if ifFieldName is absent. A new Expression representing the ifAbsent operation. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### ifAbsent(ifFieldName, elseValue) {:#ifabsent_d8f2823} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if `ifFieldName` is absent, else return the value of the field. + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent("optional_field", "default_value") + +``` + +Signature: + +```typescript +export declare function ifAbsent(ifFieldName: string | Expression, elseValue: Expression | unknown): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifFieldName | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The field to check for absence. | +| elseValue | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The value that will be returned if \[ifFieldName\] is absent. A new Expression representing the ifAbsent operation. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +## function(input, ...) + +### substring(input, position, length) {:#substring_e6e0aa3} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a substring of a string or byte array. + +Signature: + +```typescript +export declare function substring(input: Expression, position: number, length?: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| input | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression returning a string or byte array to compute the substring from. | +| position | number | Index of the first character of the substring. | +| length | number | Length of the substring. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### substring(input, position, length) {:#substring_ab56dc6} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a substring of a string or byte array. + +Signature: + +```typescript +export declare function substring(input: Expression, position: Expression, length?: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| input | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression returning a string or byte array to compute the substring from. | +| position | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that returns the index of the first character of the substring. | +| length | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that returns the length of the substring. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(left, ...) + +### divide(left, right) {:#divide_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides two expressions. + +```typescript +// Divide the 'total' field by the 'count' field +divide(field("total"), field("count")); + +``` + +Signature: + +```typescript +export declare function divide(left: Expression, right: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to be divided. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to divide by. A new representing the division operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### equal(left, right) {:#equal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if two expressions are equal. + +```typescript +// Check if the 'age' field is equal to an expression +equal(field("age"), field("minAge").add(10)); + +``` + +Signature: + +```typescript +export declare function equal(left: Expression, right: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to compare. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the equality comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### greaterThan(left, right) {:#greaterthan_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is greater than the second expression. + +```typescript +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), Constant(9).add(9)); + +``` + +Signature: + +```typescript +export declare function greaterThan(left: Expression, right: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to compare. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the greater than comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### greaterThanOrEqual(left, right) {:#greaterthanorequal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is greater than or equal to the second expression. + +```typescript +// Check if the 'quantity' field is greater than or equal to the field "threshold" +greaterThanOrEqual(field("quantity"), field("threshold")); + +``` + +Signature: + +```typescript +export declare function greaterThanOrEqual(left: Expression, right: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to compare. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the greater than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### lessThan(left, right) {:#lessthan_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is less than the second expression. + +```typescript +// Check if the 'age' field is less than 30 +lessThan(field("age"), field("limit")); + +``` + +Signature: + +```typescript +export declare function lessThan(left: Expression, right: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to compare. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the less than comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### lessThanOrEqual(left, right) {:#lessthanorequal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is less than or equal to the second expression. + +```typescript +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), field("limit")); + +``` + +Signature: + +```typescript +export declare function lessThanOrEqual(left: Expression, right: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to compare. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the less than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### mod(left, right) {:#mod_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing two expressions. + +```typescript +// Calculate the remainder of dividing 'field1' by 'field2'. +mod(field("field1"), field("field2")); + +``` + +Signature: + +```typescript +export declare function mod(left: Expression, right: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The dividend expression. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The divisor expression. A new representing the modulo operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### notEqual(left, right) {:#notequal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if two expressions are not equal. + +```typescript +// Check if the 'status' field is not equal to field 'finalState' +notEqual(field("status"), field("finalState")); + +``` + +Signature: + +```typescript +export declare function notEqual(left: Expression, right: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to compare. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the inequality comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### subtract(left, right) {:#subtract_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts two expressions. + +```typescript +// Subtract the 'discount' field from the 'price' field +subtract(field("price"), field("discount")); + +``` + +Signature: + +```typescript +export declare function subtract(left: Expression, right: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract from. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract. A new representing the subtraction operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(mapExpr, ...) + +### mapRemove(mapExpr, key) {:#mapremove_23c7d51} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map produced by evaluating an expression. + +``` +// Removes the key 'baz' from the input map. +mapRemove(map({foo: 'bar', baz: true}), 'baz'); + +``` + +Signature: + +```typescript +export declare function mapRemove(mapExpr: Expression, key: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression return a map value. | +| key | string | The name of the key to remove from the input map. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### mapRemove(mapExpr, keyExpr) {:#mapremove_9fbcaa3} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map produced by evaluating an expression. + +``` +// Removes the key 'baz' from the input map. +mapRemove(map({foo: 'bar', baz: true}), constant('baz')); + +``` + +Signature: + +```typescript +export declare function mapRemove(mapExpr: Expression, keyExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression return a map value. | +| keyExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that produces the name of the key to remove from the input map. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(mapExpression, ...) + +### mapGet(mapExpression, subField) {:#mapget_688c050} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Accesses a value from a map (object) expression using the provided key. + +```typescript +// Get the 'city' value from the 'address' map field +mapGet(field("address"), "city"); + +``` + +Signature: + +```typescript +export declare function mapGet(mapExpression: Expression, subField: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the map. | +| subField | string | The key to access in the map. A new representing the value associated with the given key in the map. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(mapField, ...) + +### mapMerge(mapField, secondMap, otherMaps) {:#mapmerge_70a564b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that merges multiple map values. + +``` +// Merges the map in the settings field with, a map literal, and a map in +// that is conditionally returned by another expression +mapMerge('settings', { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) + +``` + +Signature: + +```typescript +export declare function mapMerge(mapField: string, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | Name of a field containing a map value that will be merged. | +| secondMap | Record<string, unknown> \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A required second map to merge. Represented as a literal or an expression that returns a map. | +| otherMaps | Array<Record<string, unknown> \| [Expression](./firestore_lite_pipelines.expression.md#expression_class)> | Optional additional maps to merge. Each map is represented as a literal or an expression that returns a map. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### mapRemove(mapField, key) {:#mapremove_bd5726e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map at the specified field name. + +``` +// Removes the key 'city' field from the map in the address field of the input document. +mapRemove('address', 'city'); + +``` + +Signature: + +```typescript +export declare function mapRemove(mapField: string, key: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | The name of a field containing a map value. | +| key | string | The name of the key to remove from the input map. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### mapRemove(mapField, keyExpr) {:#mapremove_8406d13} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map at the specified field name. + +``` +// Removes the key 'city' field from the map in the address field of the input document. +mapRemove('address', constant('city')); + +``` + +Signature: + +```typescript +export declare function mapRemove(mapField: string, keyExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | The name of a field containing a map value. | +| keyExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that produces the name of the key to remove from the input map. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(name, ...) + +### field(name) {:#field_1eaaff4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a instance representing the field at the given path. + +The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). + +```typescript +// Create a Field instance for the 'title' field +const titleField = field("title"); + +// Create a Field instance for a nested field 'author.firstName' +const authorFirstNameField = field("author.firstName"); + +``` + +Signature: + +```typescript +export declare function field(name: string): Field; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | The path to the field. A new instance representing the specified field. | + +Returns: + +[Field](./firestore_lite_pipelines.field.md#field_class) + +## function(path, ...) + +### field(path) {:#field_34ee07d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a instance representing the field at the given path. + +Signature: + +```typescript +export declare function field(path: FieldPath): Field; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| path | [FieldPath](./firestore_lite.fieldpath.md#fieldpath_class) | A FieldPath specifying the field. A new instance representing the specified field. | + +Returns: + +[Field](./firestore_lite_pipelines.field.md#field_class) + +## function(pipeline, ...) + +### execute(pipeline) {:#execute_01df620} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Executes this pipeline and returns a Promise to represent the asynchronous operation. + +The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously. + +The pipeline results are returned as a that contains a list of objects. Each typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example: + +

  • If there are no stages or only transformation stages, each represents a single document.
  • If there is an aggregation, only a single is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each represents a distinct group and its associated aggregated values.
+ +

Example: + +```typescript +const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") + .where(gt(field("rating"), 4.5)) + .select("title", "author", "rating")); + +const results: PipelineResults = snapshot.results; + +``` + +Signature: + +```typescript +export declare function execute(pipeline: Pipeline): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pipeline | [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) | The pipeline to execute. A Promise representing the asynchronous pipeline execution. | + +Returns: + +Promise<[PipelineSnapshot](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshot_class)> + +## function(stringExpression, ...) + +### charLength(stringExpression) {:#charlength_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the character length of a string expression in UTF-8. + +```typescript +// Get the character length of the 'name' field in UTF-8. +strLength(field("name")); + +``` + +Signature: + +```typescript +export declare function charLength(stringExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to calculate the length of. A new representing the length of the string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### endsWith(stringExpression, suffix) {:#endswith_0a0b889} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression ends with a given postfix. + +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." +endsWith(field("fullName"), "Jr."); + +``` + +Signature: + +```typescript +export declare function endsWith(stringExpression: Expression, suffix: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | +| suffix | string | The postfix to check for. A new representing the 'ends with' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### endsWith(stringExpression, suffix) {:#endswith_13aee0d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression ends with a given postfix. + +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." +endsWith(field("fullName"), constant("Jr.")); + +``` + +Signature: + +```typescript +export declare function endsWith(stringExpression: Expression, suffix: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | +| suffix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The postfix to check for. A new representing the 'ends with' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### like(stringExpression, pattern) {:#like_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison. + +```typescript +// Check if the 'title' field contains the string "guide" +like(field("title"), "%guide%"); + +``` + +Signature: + +```typescript +export declare function like(stringExpression: Expression, pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| pattern | string | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### like(stringExpression, pattern) {:#like_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison. + +```typescript +// Check if the 'title' field contains the string "guide" +like(field("title"), field("pattern")); + +``` + +Signature: + +```typescript +export declare function like(stringExpression: Expression, pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### regexContains(stringExpression, pattern) {:#regexcontains_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a specified regular expression as a substring. + +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains(field("description"), "(?i)example"); + +``` + +Signature: + +```typescript +export declare function regexContains(stringExpression: Expression, pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| pattern | string | The regular expression to use for the search. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### regexContains(stringExpression, pattern) {:#regexcontains_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a specified regular expression as a substring. + +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains(field("description"), field("pattern")); + +``` + +Signature: + +```typescript +export declare function regexContains(stringExpression: Expression, pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the search. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### regexMatch(stringExpression, pattern) {:#regexmatch_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression matches a specified regular expression. + +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch(field("email"), "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + +``` + +Signature: + +```typescript +export declare function regexMatch(stringExpression: Expression, pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to match against. | +| pattern | string | The regular expression to use for the match. A new representing the regular expression match. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### regexMatch(stringExpression, pattern) {:#regexmatch_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression matches a specified regular expression. + +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch(field("email"), field("pattern")); + +``` + +Signature: + +```typescript +export declare function regexMatch(stringExpression: Expression, pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to match against. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the match. A new representing the regular expression match. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### reverse(stringExpression) {:#reverse_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string. + +```typescript +// Reverse the value of the 'myString' field. +reverse(field("myString")); + +``` + +Signature: + +```typescript +export declare function reverse(stringExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a string value, which will be reversed. A new representing the reversed string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### startsWith(stringExpression, prefix) {:#startswith_75c3dbb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression starts with a given prefix. + +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." +startsWith(field("fullName"), "Mr."); + +``` + +Signature: + +```typescript +export declare function startsWith(stringExpression: Expression, prefix: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | +| prefix | string | The prefix to check for. A new representing the 'starts with' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### startsWith(stringExpression, prefix) {:#startswith_52f218a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression starts with a given prefix. + +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." +startsWith(field("fullName"), field("prefix")); + +``` + +Signature: + +```typescript +export declare function startsWith(stringExpression: Expression, prefix: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | +| prefix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The prefix to check for. A new representing the 'starts with' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### stringContains(stringExpression, substring) {:#stringcontains_3e9ff32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a specified substring. + +```typescript +// Check if the 'description' field contains "example". +stringContains(field("description"), "example"); + +``` + +Signature: + +```typescript +export declare function stringContains(stringExpression: Expression, substring: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| substring | string | The substring to search for. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### stringContains(stringExpression, substring) {:#stringcontains_cc6ee02} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a substring specified by another expression. + +```typescript +// Check if the 'description' field contains the value of the 'keyword' field. +stringContains(field("description"), field("keyword")); + +``` + +Signature: + +```typescript +export declare function stringContains(stringExpression: Expression, substring: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| substring | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the substring to search for. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### stringReverse(stringExpression) {:#stringreverse_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string. + +```typescript +// Reverse the value of the 'myString' field. +strReverse(field("myString")); + +``` + +Signature: + +```typescript +export declare function stringReverse(stringExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a string value, which will be reversed. A new representing the reversed string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### toLower(stringExpression) {:#tolower_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string expression to lowercase. + +```typescript +// Convert the 'name' field to lowercase +toLower(field("name")); + +``` + +Signature: + +```typescript +export declare function toLower(stringExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to convert to lowercase. A new representing the lowercase string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### toUpper(stringExpression) {:#toupper_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string expression to uppercase. + +```typescript +// Convert the 'title' field to uppercase +toUppercase(field("title")); + +``` + +Signature: + +```typescript +export declare function toUpper(stringExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to convert to uppercase. A new representing the uppercase string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### trim(stringExpression, valueToTrim) {:#trim_dd54322} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes leading and trailing characters from a string or byte array expression. + +```typescript +// Trim whitespace from the 'userInput' field +trim(field("userInput")); + +// Trim quotes from the 'userInput' field +trim(field("userInput"), '"'); + +``` + +Signature: + +```typescript +export declare function trim(stringExpression: Expression, valueToTrim?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array to trim. | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | 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. A new representing the trimmed string or byte array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(timestamp, ...) + +### timestampAdd(timestamp, unit, amount) {:#timestampadd_98418f9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to a timestamp. + +```typescript +// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. +timestampAdd(field("timestamp"), field("unit"), field("amount")); + +``` + +Signature: + +```typescript +export declare function timestampAdd(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestamp | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| unit | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | +| amount | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### timestampAdd(timestamp, unit, amount) {:#timestampadd_ffe8e57} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to a timestamp. + +```typescript +// Add 1 day to the 'timestamp' field. +timestampAdd(field("timestamp"), "day", 1); + +``` + +Signature: + +```typescript +export declare function timestampAdd(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestamp | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | +| amount | number | The amount of time to add. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_98418f9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from a timestamp. + +```typescript +// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. +timestampSubtract(field("timestamp"), field("unit"), field("amount")); + +``` + +Signature: + +```typescript +export declare function timestampSubtract(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestamp | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| unit | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | +| amount | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_ffe8e57} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from a timestamp. + +```typescript +// Subtract 1 day from the 'timestamp' field. +timestampSubtract(field("timestamp"), "day", 1); + +``` + +Signature: + +```typescript +export declare function timestampSubtract(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestamp | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | +| amount | number | The amount of time to subtract. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(timestampExpression, ...) + +### timestampTruncate(timestampExpression, granularity, timezone) {:#timestamptruncate_ad5d843} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a timestamp to a specified granularity. + +Signature: + +```typescript +export declare function timestampTruncate(timestampExpression: Expression, granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestampExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Truncate the timestamp value that is returned by this expression. | +| granularity | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | The granularity to truncate to. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Truncate the 'createdAt' timestamp to the beginning of the day. +field('createdAt').timestampTruncate('day') + +``` + +### timestampTruncate(timestampExpression, granularity, timezone) {:#timestamptruncate_d6ab2a4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a timestamp to a specified granularity. + +Signature: + +```typescript +export declare function timestampTruncate(timestampExpression: Expression, granularity: Expression, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestampExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Truncate the timestamp value that is returned by this expression. | +| granularity | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The granularity to truncate to. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. +field('createdAt').timestampTruncate(field('granularity')) + +``` + +## function(tryExpr, ...) + +### ifError(tryExpr, catchExpr) {:#iferror_a99a327} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. + +This overload is useful when a BooleanExpression is required. + +```typescript +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +ifError(constant(50).divide('length').gt(1), constant(false)); + +``` + +Signature: + +```typescript +export declare function ifError(tryExpr: BooleanExpression, catchExpr: BooleanExpression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| tryExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The try expression. | +| catchExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The catch expression that will be evaluated and returned if the tryExpr produces an error. A new representing the 'ifError' operation. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### ifError(tryExpr, catchExpr) {:#iferror_756c12e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. + +```typescript +// Returns the first item in the title field arrays, or returns +// the entire title field if the array is empty or the field is another type. +ifError(field("title").arrayGet(0), field("title")); + +``` + +Signature: + +```typescript +export declare function ifError(tryExpr: Expression, catchExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| tryExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The try expression. | +| catchExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The catch expression that will be evaluated and returned if the tryExpr produces an error. A new representing the 'ifError' operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### ifError(tryExpr, catchValue) {:#iferror_dc532f9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. + +```typescript +// Returns the first item in the title field arrays, or returns +// "Default Title" +ifError(field("title").arrayGet(0), "Default Title"); + +``` + +Signature: + +```typescript +export declare function ifError(tryExpr: Expression, catchValue: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| tryExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The try expression. | +| catchValue | unknown | The value that will be returned if the tryExpr produces an error. A new representing the 'ifError' operation. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(value, ...) + +### constant(value) {:#constant_0c00f91} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a number value. + +Signature: + +```typescript +export declare function constant(value: number): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | number | The number value. A new Constant instance. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_6dac335} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a VectorValue value. + +Signature: + +```typescript +export declare function constant(value: VectorValue): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The VectorValue value. A new Constant instance. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_7c807cd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a string value. + +Signature: + +```typescript +export declare function constant(value: string): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | string | The string value. A new Constant instance. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_b2e4f8d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `BooleanExpression` instance for a boolean value. + +Signature: + +```typescript +export declare function constant(value: boolean): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | boolean | The boolean value. A new Constant instance. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### constant(value) {:#constant_73ebd84} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a null value. + +Signature: + +```typescript +export declare function constant(value: null): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | null | The null value. A new Constant instance. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_72a76cb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a GeoPoint value. + +Signature: + +```typescript +export declare function constant(value: GeoPoint): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [GeoPoint](./firestore_lite.geopoint.md#geopoint_class) | The GeoPoint value. A new Constant instance. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_000477d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a Timestamp value. + +Signature: + +```typescript +export declare function constant(value: Timestamp): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) | The Timestamp value. A new Constant instance. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_5131bf7} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a Date value. + +Signature: + +```typescript +export declare function constant(value: Date): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | Date | The Date value. A new Constant instance. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_fdf565d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a Bytes value. + +Signature: + +```typescript +export declare function constant(value: Bytes): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [Bytes](./firestore_lite.bytes.md#bytes_class) | The Bytes value. A new Constant instance. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_bcd2b0b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a DocumentReference value. + +Signature: + +```typescript +export declare function constant(value: DocumentReference): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [DocumentReference](./firestore_lite.documentreference.md#documentreference_class) | The DocumentReference value. A new Constant instance. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### exists(value) {:#exists_f3daf14} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field exists. + +```typescript +// Check if the document has a field named "phoneNumber" +exists(field("phoneNumber")); + +``` + +Signature: + +```typescript +export declare function exists(value: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluates to the name of the field to check. A new representing the 'exists' check. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### isAbsent(value) {:#isabsent_f3daf14} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns `true` if a value is absent. Otherwise, returns `false` even if the value is `null`. + +```typescript +// Check if the field `value` is absent. +isAbsent(field("value")); + +``` + +Signature: + +```typescript +export declare function isAbsent(value: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. A new representing the 'isAbsent' check. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### isError(value) {:#iserror_f3daf14} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a given expression produces an error. + +```typescript +// Check if the result of a calculation is an error +isError(field("title").arrayContains(1)); + +``` + +Signature: + +```typescript +export declare function isError(value: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. A new representing the 'isError' check. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +## function(vectorExpression, ...) + +### cosineDistance(vectorExpression, vector) {:#cosinedistance_3a80317} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between a vector expression and a vector literal. + +```typescript +// Calculate the cosine distance between the 'location' field and a target location +cosineDistance(field("location"), [37.7749, -122.4194]); + +``` + +Signature: + +```typescript +export declare function cosineDistance(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | +| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. A new representing the cosine distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### cosineDistance(vectorExpression, otherVectorExpression) {:#cosinedistance_17b5bcc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between two vector expressions. + +```typescript +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +cosineDistance(field("userVector"), field("itemVector")); + +``` + +Signature: + +```typescript +export declare function cosineDistance(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | +| otherVectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the cosine distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### dotProduct(vectorExpression, vector) {:#dotproduct_3a80317} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between a vector expression and a double array. + +```typescript +// Calculate the dot product between a feature vector and a target vector +dotProduct(field("features"), [0.5, 0.8, 0.2]); + +``` + +Signature: + +```typescript +export declare function dotProduct(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to calculate with. | +| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to calculate with. A new representing the dot product between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### dotProduct(vectorExpression, otherVectorExpression) {:#dotproduct_17b5bcc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between two vector expressions. + +```typescript +// Calculate the dot product between two document vectors: 'docVector1' and 'docVector2' +dotProduct(field("docVector1"), field("docVector2")); + +``` + +Signature: + +```typescript +export declare function dotProduct(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to calculate with. | +| otherVectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to calculate with. A new representing the dot product between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### euclideanDistance(vectorExpression, vector) {:#euclideandistance_3a80317} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between a vector expression and a double array. + +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location + +euclideanDistance(field("location"), [37.7749, -122.4194]); + +``` + +Signature: + +```typescript +export declare function euclideanDistance(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | +| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. A new representing the Euclidean distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### euclideanDistance(vectorExpression, otherVectorExpression) {:#euclideandistance_17b5bcc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between two vector expressions. + +```typescript +// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' +euclideanDistance(field("pointA"), field("pointB")); + +``` + +Signature: + +```typescript +export declare function euclideanDistance(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | +| otherVectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the Euclidean distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +### vectorLength(vectorExpression) {:#vectorlength_58a039b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a Firestore Vector. + +```typescript +// Get the vector length (dimension) of the field 'embedding'. +vectorLength(field("embedding")); + +``` + +Signature: + +```typescript +export declare function vectorLength(vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the Firestore Vector. A new representing the length of the array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## AddFieldsStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how an AddFieldsStage is evaluated. See . + +Signature: + +```typescript +export declare type AddFieldsStageOptions = StageOptions & { + fields: Selectable[]; +}; +``` + +## AggregateStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how an AggregateStage is evaluated. See . + +Signature: + +```typescript +export declare type AggregateStageOptions = StageOptions & { + accumulators: AliasedAggregate[]; + groups?: Array; +}; +``` + +## CollectionGroupStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Defines the configuration options for a within a pipeline. This type extends and provides specific settings for how a collection group is identified and processed during pipeline execution. + +Signature: + +```typescript +export declare type CollectionGroupStageOptions = StageOptions & { + collectionId: string; + forceIndex?: string; +}; +``` + +## CollectionStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a CollectionStage is evaluated. See . + +Signature: + +```typescript +export declare type CollectionStageOptions = StageOptions & { + collection: string | Query; + forceIndex?: string; +}; +``` + +## DatabaseStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a DatabaseStage is evaluated. See . + +Signature: + +```typescript +export declare type DatabaseStageOptions = StageOptions & {}; +``` + +## DistinctStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a DistinctStage is evaluated. See . + +Signature: + +```typescript +export declare type DistinctStageOptions = StageOptions & { + groups: Array; +}; +``` + +## DocumentsStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a DocumentsStage is evaluated. See . + +Signature: + +```typescript +export declare type DocumentsStageOptions = StageOptions & { + docs: Array; +}; +``` + +## ExpressionType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An enumeration of the different types of expressions. + +Signature: + +```typescript +export declare type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression'; +``` + +## FindNearestStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a FindNearestStage is evaluated. See . + +Signature: + +```typescript +export declare type FindNearestStageOptions = StageOptions & { + field: Field | string; + vectorValue: VectorValue | number[]; + distanceMeasure: 'euclidean' | 'cosine' | 'dot_product'; + limit?: number; + distanceField?: string; +}; +``` + +## LimitStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a LimitStage is evaluated. See . + +Signature: + +```typescript +export declare type LimitStageOptions = StageOptions & { + limit: number; +}; +``` + +## OffsetStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how an OffsetStage is evaluated. See . + +Signature: + +```typescript +export declare type OffsetStageOptions = StageOptions & { + offset: number; +}; +``` + +## OneOf + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Utility type to create an type that only allows one property of the Type param T to be set. + +type XorY = OneOf<{ x: unknown, y: unknown}> let a = { x: "foo" } // OK let b = { y: "foo" } // OK let c = { a: "foo", y: "foo" } // Not OK + +Signature: + +```typescript +export declare type OneOf = { + [K in keyof T]: Pick & { + [P in Exclude]?: undefined; + }; +}[keyof T]; +``` + +## PartialWithFieldValue + +Similar to TypeScript's `Partial`, but allows nested fields to be omitted and FieldValues to be passed in as property values. + +Signature: + +```typescript +export declare type PartialWithFieldValue = Partial | (T extends Primitive ? T : T extends {} ? { + [K in keyof T]?: PartialWithFieldValue | FieldValue; +} : never); +``` + +## Primitive + +Primitive types. + +Signature: + +```typescript +export declare type Primitive = string | number | boolean | undefined | null; +``` + +## RemoveFieldsStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a RemoveFieldsStage is evaluated. See . + +Signature: + +```typescript +export declare type RemoveFieldsStageOptions = StageOptions & { + fields: Array; +}; +``` + +## ReplaceWithStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a ReplaceWithStage is evaluated. See . + +Signature: + +```typescript +export declare type ReplaceWithStageOptions = StageOptions & { + map: Expression | string; +}; +``` + +## SampleStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Defines the options for evaluating a sample stage within a pipeline. This type combines common with a specific configuration where only one of the defined sampling methods can be applied. + +See to create a sample stage.. + +Signature: + +```typescript +export declare type SampleStageOptions = StageOptions & OneOf<{ + percentage: number; + documents: number; +}>; +``` + +## SelectStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a SelectStage is evaluated. See . + +Signature: + +```typescript +export declare type SelectStageOptions = StageOptions & { + selections: Array; +}; +``` + +## SetOptions + +An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a `SetOptions` with `merge: true`. + +Signature: + +```typescript +export declare type SetOptions = { + readonly merge?: boolean; +} | { + readonly mergeFields?: Array; +}; +``` + +## SortStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a SortStage is evaluated. See . + +Signature: + +```typescript +export declare type SortStageOptions = StageOptions & { + orderings: Ordering[]; +}; +``` + +## TimeGranularity + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Specify time granularity for expressions. + +Signature: + +```typescript +export declare type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; +``` + +## UnionStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a UnionStage is evaluated. See . + +Signature: + +```typescript +export declare type UnionStageOptions = StageOptions & { + other: Pipeline; +}; +``` + +## UnnestStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Represents the specific options available for configuring an `UnnestStage` within a pipeline. + +Signature: + +```typescript +export declare type UnnestStageOptions = StageOptions & { + selectable: Selectable; + indexField?: string; +}; +``` + +## WhereStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a WhereStage is evaluated. See . + +Signature: + +```typescript +export declare type WhereStageOptions = StageOptions & { + condition: BooleanExpression; +}; +``` + +## WithFieldValue + +Allows FieldValues to be passed in as a property value while maintaining type safety. + +Signature: + +```typescript +export declare type WithFieldValue = T | (T extends Primitive ? T : T extends {} ? { + [K in keyof T]: WithFieldValue | FieldValue; +} : never); +``` diff --git a/docs-devsite/firestore_lite_pipelines.ordering.md b/docs-devsite/firestore_lite_pipelines.ordering.md new file mode 100644 index 0000000000..2af9efcd91 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.ordering.md @@ -0,0 +1,80 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Ordering class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Represents an ordering criterion for sorting documents in a Firestore pipeline. + +You create `Ordering` instances using the `ascending` and `descending` helper functions. + +Signature: + +```typescript +export declare class Ordering +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(expr, direction, \_methodName)](./firestore_lite_pipelines.ordering.md#orderingconstructor) | | (Public Preview) Constructs a new instance of the Ordering class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [direction](./firestore_lite_pipelines.ordering.md#orderingdirection) | | 'ascending' \| 'descending' | (Public Preview) | +| [expr](./firestore_lite_pipelines.ordering.md#orderingexpr) | | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | (Public Preview) | + +## Ordering.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `Ordering` class + +Signature: + +```typescript +constructor(expr: Expression, direction: 'ascending' | 'descending', _methodName: string | undefined); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | +| direction | 'ascending' \| 'descending' | | +| \_methodName | string \| undefined | | + +## Ordering.direction + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly direction: 'ascending' | 'descending'; +``` + +## Ordering.expr + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly expr: Expression; +``` diff --git a/docs-devsite/firestore_lite_pipelines.pipeline.md b/docs-devsite/firestore_lite_pipelines.pipeline.md new file mode 100644 index 0000000000..9c3f65e046 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.pipeline.md @@ -0,0 +1,1560 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Pipeline class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The Pipeline class provides a flexible and expressive framework for building complex data transformation and query pipelines for Firestore. + +A pipeline takes data sources, such as Firestore collections or collection groups, and applies a series of stages that are chained together. Each stage takes the output from the previous stage (or the data source) and produces an output for the next stage (or as the final output of the pipeline). + +Expressions can be used within each stage to filter and transform data through the stage. + +NOTE: The chained stages do not prescribe exactly how Firestore will execute the pipeline. Instead, Firestore only guarantees that the result is the same as if the chained stages were executed in order. + +Usage Examples: + +```typescript +const db: Firestore; // Assumes a valid firestore instance. + +// Example 1: Select specific fields and rename 'rating' to 'bookRating' +const results1 = await execute(db.pipeline() + .collection("books") + .select("title", "author", field("rating").as("bookRating"))); + +// Example 2: Filter documents where 'genre' is "Science Fiction" and 'published' is after 1950 +const results2 = await execute(db.pipeline() + .collection("books") + .where(and(field("genre").eq("Science Fiction"), field("published").gt(1950)))); + +// Example 3: Calculate the average rating of books published after 1980 +const results3 = await execute(db.pipeline() + .collection("books") + .where(field("published").gt(1980)) + .aggregate(avg(field("rating")).as("averageRating"))); + +``` + +Signature: + +```typescript +export declare class Pipeline +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [addFields(field, additionalFields)](./firestore_lite_pipelines.pipeline.md#pipelineaddfields) | | (Public Preview) Adds new fields to outputs from previous stages.This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps).The added fields are defined using s, which can be:- : References an existing document field. - : Either a literal value (see ) or a computed value (see ) with an assigned alias using .Example: +```typescript +firestore.pipeline().collection("books") + .addFields( + field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' + add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' + ); + +``` + | +| [addFields(options)](./firestore_lite_pipelines.pipeline.md#pipelineaddfields) | | (Public Preview) Adds new fields to outputs from previous stages.This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps).The added fields are defined using s, which can be:- : References an existing document field. - : Either a literal value (see ) or a computed value (see ) with an assigned alias using .Example: +```typescript +firestore.pipeline().collection("books") + .addFields( + field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' + add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' + ); + +``` + | +| [aggregate(accumulator, additionalAccumulators)](./firestore_lite_pipelines.pipeline.md#pipelineaggregate) | | (Public Preview) Performs aggregation operations on the documents from previous stages.

This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using expressions which are typically results of calling on instances.

Example: +```typescript +// Calculate the average rating and the total number of books +firestore.pipeline().collection("books") + .aggregate( + field("rating").avg().as("averageRating"), + countAll().as("totalBooks") + ); + +``` + | +| [aggregate(options)](./firestore_lite_pipelines.pipeline.md#pipelineaggregate) | | (Public Preview) Performs optionally grouped aggregation operations on the documents from previous stages.

This stage allows you to calculate aggregate values over a set of documents, optionally grouped by one or more fields or functions. You can specify:

  • \*\*Grouping Fields or Functions:\*\* One or more fields or functions to group the documents by. For each distinct combination of values in these fields, a separate group is created. If no grouping fields are provided, a single group containing all documents is used. Not specifying groups is the same as putting the entire inputs into one group.
  • \*\*Accumulators:\*\* One or more accumulation operations to perform within each group. These are defined using expressions, which are typically created by calling on instances. Each aggregation calculates a value (e.g., sum, average, count) based on the documents within its group.

Example: +```typescript +// Calculate the average rating for each genre. +firestore.pipeline().collection("books") + .aggregate({ + accumulators: [avg(field("rating")).as("avg_rating")] + groups: ["genre"] + }); + +``` + | +| [distinct(group, additionalGroups)](./firestore_lite_pipelines.pipeline.md#pipelinedistinct) | | (Public Preview) Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of values (, , etc).The parameters to this stage are defined using expressions or strings:- : Name of an existing field - : References an existing document field. - : Represents the result of a function with an assigned alias name using .Example: +```typescript +// Get a list of unique author names in uppercase and genre combinations. +firestore.pipeline().collection("books") + .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") + .select("authorName"); + +``` + | +| [distinct(options)](./firestore_lite_pipelines.pipeline.md#pipelinedistinct) | | (Public Preview) Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of values (, , etc).The parameters to this stage are defined using expressions or strings:- : Name of an existing field - : References an existing document field. - : Represents the result of a function with an assigned alias name using .Example: +```typescript +// Get a list of unique author names in uppercase and genre combinations. +firestore.pipeline().collection("books") + .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") + .select("authorName"); + +``` + | +| [findNearest(options)](./firestore_lite_pipelines.pipeline.md#pipelinefindnearest) | | (Public Preview) Performs a vector proximity search on the documents from the previous stage, returning the K-nearest documents based on the specified query vectorValue and distanceMeasure. The returned documents will be sorted in order from nearest to furthest from the query vectorValue.

Example: +```typescript +// Find the 10 most similar books based on the book description. +const bookDescription = "Lorem ipsum..."; +const queryVector: number[] = ...; // compute embedding of `bookDescription` + +firestore.pipeline().collection("books") + .findNearest({ + field: 'embedding', + vectorValue: queryVector, + distanceMeasure: 'euclidean', + limit: 10, // optional + distanceField: 'computedDistance' // optional + }); + +``` + | +| [limit(limit)](./firestore_lite_pipelines.pipeline.md#pipelinelimit) | | (Public Preview) Limits the maximum number of documents returned by previous stages to limit.

This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for:

  • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
  • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.

Example: +```typescript +// Limit the results to the top 10 highest-rated books +firestore.pipeline().collection('books') + .sort(field('rating').descending()) + .limit(10); + +``` + | +| [limit(options)](./firestore_lite_pipelines.pipeline.md#pipelinelimit) | | (Public Preview) Limits the maximum number of documents returned by previous stages to limit.

This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for:

  • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
  • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.

Example: +```typescript +// Limit the results to the top 10 highest-rated books +firestore.pipeline().collection('books') + .sort(field('rating').descending()) + .limit(10); + +``` + | +| [offset(offset)](./firestore_lite_pipelines.pipeline.md#pipelineoffset) | | (Public Preview) Skips the first offset number of documents from the results of previous stages.

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page.

Example: +```typescript +// Retrieve the second page of 20 results +firestore.pipeline().collection('books') + .sort(field('published').descending()) + .offset(20) // Skip the first 20 results + .limit(20); // Take the next 20 results + +``` + | +| [offset(options)](./firestore_lite_pipelines.pipeline.md#pipelineoffset) | | (Public Preview) Skips the first offset number of documents from the results of previous stages.

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page.

Example: +```typescript +// Retrieve the second page of 20 results +firestore.pipeline().collection('books') + .sort(field('published').descending()) + .offset(20) // Skip the first 20 results + .limit(20); // Take the next 20 results + +``` + | +| [rawStage(name, params, options)](./firestore_lite_pipelines.pipeline.md#pipelinerawstage) | | (Public Preview) Adds a raw stage to the pipeline.

This method provides a flexible way to extend the pipeline's functionality by adding custom stages. Each raw stage is defined by a unique name and a set of params that control its behavior.

Example (Assuming there is no 'where' stage available in SDK): +```typescript +// Assume we don't have a built-in 'where' stage +firestore.pipeline().collection('books') + .rawStage('where', [field('published').lt(1900)]) // Custom 'where' stage + .select('title', 'author'); + +``` + | +| [removeFields(fieldValue, additionalFields)](./firestore_lite_pipelines.pipeline.md#pipelineremovefields) | | (Public Preview) Remove fields from outputs of previous stages.Example: +```typescript +firestore.pipeline().collection('books') + // removes field 'rating' and 'cost' from the previous stage outputs. + .removeFields( + field('rating'), + 'cost' + ); + +``` + | +| [removeFields(options)](./firestore_lite_pipelines.pipeline.md#pipelineremovefields) | | (Public Preview) Remove fields from outputs of previous stages.Example: +```typescript +firestore.pipeline().collection('books') + // removes field 'rating' and 'cost' from the previous stage outputs. + .removeFields( + field('rating'), + 'cost' + ); + +``` + | +| [replaceWith(fieldName)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) Fully overwrites all fields in a document with those coming from a nested map.

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

Example: +```typescript +// Input. +// { +// 'name': 'John Doe Jr.', +// 'parents': { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } +// } + +// Emit parents as document. +firestore.pipeline().collection('people').replaceWith('parents'); + +// Output +// { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } + +``` + | +| [replaceWith(expr)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) Fully overwrites all fields in a document with those coming from a map.

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

Example: +```typescript +// Input. +// { +// 'name': 'John Doe Jr.', +// 'parents': { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } +// } + +// Emit parents as document. +firestore.pipeline().collection('people').replaceWith(map({ + foo: 'bar', + info: { + name: field('name') + } +})); + +// Output +// { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } + +``` + | +| [replaceWith(options)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) Fully overwrites all fields in a document with those coming from a map.

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

Example: +```typescript +// Input. +// { +// 'name': 'John Doe Jr.', +// 'parents': { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } +// } + +// Emit parents as document. +firestore.pipeline().collection('people').replaceWith(map({ + foo: 'bar', + info: { + name: field('name') + } +})); + +// Output +// { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } + +``` + | +| [sample(documents)](./firestore_lite_pipelines.pipeline.md#pipelinesample) | | (Public Preview) Performs a pseudo-random sampling of the documents from the previous stage.

This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned.

Examples: +```typescript +// Sample 25 books, if available. +firestore.pipeline().collection('books') + .sample(25); + +``` + | +| [sample(options)](./firestore_lite_pipelines.pipeline.md#pipelinesample) | | (Public Preview) Performs a pseudo-random sampling of the documents from the previous stage.

This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See for more information.

Examples:// Sample 10 books, if available. firestore.pipeline().collection("books") .sample({ documents: 10 });// Sample 50% of books. firestore.pipeline().collection("books") .sample({ percentage: 0.5 }); | +| [select(selection, additionalSelections)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | (Public Preview) Selects or creates a set of fields from the outputs of previous stages.

The selected fields are defined using expressions, which can be:

  • : Name of an existing field
  • : References an existing field.
  • : Represents the result of a function with an assigned alias name using

If no selections are provided, the output of this stage is empty. Use instead if only additions are desired.

Example: +```typescript +db.pipeline().collection("books") + .select( + "firstName", + field("lastName"), + field("address").toUppercase().as("upperAddress"), + ); + +``` + | +| [select(options)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | (Public Preview) Selects or creates a set of fields from the outputs of previous stages.

The selected fields are defined using expressions, which can be:

  • : Name of an existing field
  • : References an existing field.
  • : Represents the result of a function with an assigned alias name using

If no selections are provided, the output of this stage is empty. Use instead if only additions are desired.

Example: +```typescript +db.pipeline().collection("books") + .select( + "firstName", + field("lastName"), + field("address").toUppercase().as("upperAddress"), + ); + +``` + | +| [sort(ordering, additionalOrderings)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | (Public Preview) Sorts the documents from previous stages based on one or more criteria.

This stage allows you to order the results of your pipeline. You can specify multiple instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

Example: +```typescript +// Sort books by rating in descending order, and then by title in ascending order for books +// with the same rating +firestore.pipeline().collection("books") + .sort( + Ordering.of(field("rating")).descending(), + Ordering.of(field("title")) // Ascending order is the default + ); + +``` + | +| [sort(options)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | (Public Preview) Sorts the documents from previous stages based on one or more criteria.

This stage allows you to order the results of your pipeline. You can specify multiple instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

Example: +```typescript +// Sort books by rating in descending order, and then by title in ascending order for books +// with the same rating +firestore.pipeline().collection("books") + .sort( + Ordering.of(field("rating")).descending(), + Ordering.of(field("title")) // Ascending order is the default + ); + +``` + | +| [union(other)](./firestore_lite_pipelines.pipeline.md#pipelineunion) | | (Public Preview) Performs union of all documents from two pipelines, including duplicates.

This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other given in parameter. The order of documents emitted from this stage is undefined.

Example: +```typescript +// Emit documents from books collection and magazines collection. +firestore.pipeline().collection('books') + .union(firestore.pipeline().collection('magazines')); + +``` + | +| [union(options)](./firestore_lite_pipelines.pipeline.md#pipelineunion) | | (Public Preview) Performs union of all documents from two pipelines, including duplicates.

This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other given in parameter. The order of documents emitted from this stage is undefined.

Example: +```typescript +// Emit documents from books collection and magazines collection. +firestore.pipeline().collection('books') + .union(firestore.pipeline().collection('magazines')); + +``` + | +| [unnest(selectable, indexField)](./firestore_lite_pipelines.pipeline.md#pipelineunnest) | | (Public Preview) Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: +```typescript +// Input: +// { "title": "The Hitchhiker's Guide to the Galaxy", "tags": [ "comedy", "space", "adventure" ], ... } + +// Emit a book document for each tag of the book. +firestore.pipeline().collection("books") + .unnest(field("tags").as('tag'), 'tagIndex'); + +// Output: +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "comedy", "tagIndex": 0, ... } +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "space", "tagIndex": 1, ... } +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "adventure", "tagIndex": 2, ... } + +``` + | +| [unnest(options)](./firestore_lite_pipelines.pipeline.md#pipelineunnest) | | (Public Preview) Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: +```typescript +// Input: +// { "title": "The Hitchhiker's Guide to the Galaxy", "tags": [ "comedy", "space", "adventure" ], ... } + +// Emit a book document for each tag of the book. +firestore.pipeline().collection("books") + .unnest(field("tags").as('tag'), 'tagIndex'); + +// Output: +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "comedy", "tagIndex": 0, ... } +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "space", "tagIndex": 1, ... } +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "adventure", "tagIndex": 2, ... } + +``` + | +| [where(condition)](./firestore_lite_pipelines.pipeline.md#pipelinewhere) | | (Public Preview) Filters the documents from previous stages to only include those matching the specified .

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of , typically including but not limited to:

  • field comparators: , (less than), (greater than), etc.
  • logical operators: , , , etc.
  • advanced functions: , , etc.

Example: +```typescript +firestore.pipeline().collection("books") + .where( + and( + gt(field("rating"), 4.0), // Filter for ratings greater than 4.0 + field("genre").eq("Science Fiction") // Equivalent to gt("genre", "Science Fiction") + ) + ); + +``` + | +| [where(options)](./firestore_lite_pipelines.pipeline.md#pipelinewhere) | | (Public Preview) Filters the documents from previous stages to only include those matching the specified .

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of , typically including but not limited to:

  • field comparators: , (less than), (greater than), etc.
  • logical operators: , , , etc.
  • advanced functions: , , etc.

Example: +```typescript +firestore.pipeline().collection("books") + .where( + and( + gt(field("rating"), 4.0), // Filter for ratings greater than 4.0 + field("genre").eq("Science Fiction") // Equivalent to gt("genre", "Science Fiction") + ) + ); + +``` + | + +## Pipeline.addFields() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Adds new fields to outputs from previous stages. + +This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps). + +The added fields are defined using s, which can be: + +- : References an existing document field. - : Either a literal value (see ) or a computed value (see ) with an assigned alias using . + +Example: + +```typescript +firestore.pipeline().collection("books") + .addFields( + field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' + add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' + ); + +``` + +Signature: + +```typescript +addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) | The first field to add to the documents, specified as a . | +| additionalFields | [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface)\[\] | Optional additional fields to add to the documents, specified as s. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.addFields() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Adds new fields to outputs from previous stages. + +This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps). + +The added fields are defined using s, which can be: + +- : References an existing document field. - : Either a literal value (see ) or a computed value (see ) with an assigned alias using . + +Example: + +```typescript +firestore.pipeline().collection("books") + .addFields( + field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' + add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' + ); + +``` + +Signature: + +```typescript +addFields(options: AddFieldsStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [AddFieldsStageOptions](./firestore_lite_pipelines.md#addfieldsstageoptions) | An object that specifies required and optional parameters for the stage. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.aggregate() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Performs aggregation operations on the documents from previous stages. + +

This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using expressions which are typically results of calling on instances. + +

Example: + +```typescript +// Calculate the average rating and the total number of books +firestore.pipeline().collection("books") + .aggregate( + field("rating").avg().as("averageRating"), + countAll().as("totalBooks") + ); + +``` + +Signature: + +```typescript +aggregate(accumulator: AliasedAggregate, ...additionalAccumulators: AliasedAggregate[]): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| accumulator | [AliasedAggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregate_class) | The first , wrapping an and providing a name for the accumulated results. | +| additionalAccumulators | [AliasedAggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregate_class)\[\] | Optional additional , each wrapping an and providing a name for the accumulated results. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.aggregate() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Performs optionally grouped aggregation operations on the documents from previous stages. + +

This stage allows you to calculate aggregate values over a set of documents, optionally grouped by one or more fields or functions. You can specify: + +

  • \*\*Grouping Fields or Functions:\*\* One or more fields or functions to group the documents by. For each distinct combination of values in these fields, a separate group is created. If no grouping fields are provided, a single group containing all documents is used. Not specifying groups is the same as putting the entire inputs into one group.
  • \*\*Accumulators:\*\* One or more accumulation operations to perform within each group. These are defined using expressions, which are typically created by calling on instances. Each aggregation calculates a value (e.g., sum, average, count) based on the documents within its group.
+ +

Example: + +```typescript +// Calculate the average rating for each genre. +firestore.pipeline().collection("books") + .aggregate({ + accumulators: [avg(field("rating")).as("avg_rating")] + groups: ["genre"] + }); + +``` + +Signature: + +```typescript +aggregate(options: AggregateStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [AggregateStageOptions](./firestore_lite_pipelines.md#aggregatestageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.distinct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns a set of distinct values from the inputs to this stage. + +This stage runs through the results from previous stages to include only results with unique combinations of values (, , etc). + +The parameters to this stage are defined using expressions or strings: + +- : Name of an existing field - : References an existing document field. - : Represents the result of a function with an assigned alias name using . + +Example: + +```typescript +// Get a list of unique author names in uppercase and genre combinations. +firestore.pipeline().collection("books") + .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") + .select("authorName"); + +``` + +Signature: + +```typescript +distinct(group: string | Selectable, ...additionalGroups: Array): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| group | string \| [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) | The expression or field name to consider when determining distinct value combinations. | +| additionalGroups | Array<string \| [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface)> | Optional additional expressions to consider when determining distinct value combinations or strings representing field names. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.distinct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns a set of distinct values from the inputs to this stage. + +This stage runs through the results from previous stages to include only results with unique combinations of values (, , etc). + +The parameters to this stage are defined using expressions or strings: + +- : Name of an existing field - : References an existing document field. - : Represents the result of a function with an assigned alias name using . + +Example: + +```typescript +// Get a list of unique author names in uppercase and genre combinations. +firestore.pipeline().collection("books") + .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") + .select("authorName"); + +``` + +Signature: + +```typescript +distinct(options: DistinctStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [DistinctStageOptions](./firestore_lite_pipelines.md#distinctstageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.findNearest() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Performs a vector proximity search on the documents from the previous stage, returning the K-nearest documents based on the specified query `vectorValue` and `distanceMeasure`. The returned documents will be sorted in order from nearest to furthest from the query `vectorValue`. + +

Example: + +```typescript +// Find the 10 most similar books based on the book description. +const bookDescription = "Lorem ipsum..."; +const queryVector: number[] = ...; // compute embedding of `bookDescription` + +firestore.pipeline().collection("books") + .findNearest({ + field: 'embedding', + vectorValue: queryVector, + distanceMeasure: 'euclidean', + limit: 10, // optional + distanceField: 'computedDistance' // optional + }); + +``` + +Signature: + +```typescript +findNearest(options: FindNearestStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [FindNearestStageOptions](./firestore_lite_pipelines.md#findneareststageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.limit() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Limits the maximum number of documents returned by previous stages to `limit`. + +

This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for: + +

  • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
  • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.
+ +

Example: + +```typescript +// Limit the results to the top 10 highest-rated books +firestore.pipeline().collection('books') + .sort(field('rating').descending()) + .limit(10); + +``` + +Signature: + +```typescript +limit(limit: number): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| limit | number | The maximum number of documents to return. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.limit() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Limits the maximum number of documents returned by previous stages to `limit`. + +

This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for: + +

  • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
  • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.
+ +

Example: + +```typescript +// Limit the results to the top 10 highest-rated books +firestore.pipeline().collection('books') + .sort(field('rating').descending()) + .limit(10); + +``` + +Signature: + +```typescript +limit(options: LimitStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [LimitStageOptions](./firestore_lite_pipelines.md#limitstageoptions) | An object that specifies required and optional parameters for the stage. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.offset() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Skips the first `offset` number of documents from the results of previous stages. + +

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page. + +

Example: + +```typescript +// Retrieve the second page of 20 results +firestore.pipeline().collection('books') + .sort(field('published').descending()) + .offset(20) // Skip the first 20 results + .limit(20); // Take the next 20 results + +``` + +Signature: + +```typescript +offset(offset: number): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| offset | number | The number of documents to skip. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.offset() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Skips the first `offset` number of documents from the results of previous stages. + +

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page. + +

Example: + +```typescript +// Retrieve the second page of 20 results +firestore.pipeline().collection('books') + .sort(field('published').descending()) + .offset(20) // Skip the first 20 results + .limit(20); // Take the next 20 results + +``` + +Signature: + +```typescript +offset(options: OffsetStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [OffsetStageOptions](./firestore_lite_pipelines.md#offsetstageoptions) | An object that specifies required and optional parameters for the stage. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.rawStage() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Adds a raw stage to the pipeline. + +

This method provides a flexible way to extend the pipeline's functionality by adding custom stages. Each raw stage is defined by a unique `name` and a set of `params` that control its behavior. + +

Example (Assuming there is no 'where' stage available in SDK): + +```typescript +// Assume we don't have a built-in 'where' stage +firestore.pipeline().collection('books') + .rawStage('where', [field('published').lt(1900)]) // Custom 'where' stage + .select('title', 'author'); + +``` + +Signature: + +```typescript +rawStage(name: string, params: unknown[], options?: { + [key: string]: Expression | unknown; + }): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | The unique name of the raw stage to add. | +| params | unknown\[\] | A list of parameters to configure the raw stage's behavior. | +| options | { \[key: string\]: [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown; } | An object of key value pairs that specifies optional parameters for the stage. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.removeFields() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Remove fields from outputs of previous stages. + +Example: + +```typescript +firestore.pipeline().collection('books') + // removes field 'rating' and 'cost' from the previous stage outputs. + .removeFields( + field('rating'), + 'cost' + ); + +``` + +Signature: + +```typescript +removeFields(fieldValue: Field | string, ...additionalFields: Array): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldValue | [Field](./firestore_lite_pipelines.field.md#field_class) \| string | The first field to remove. | +| additionalFields | Array<[Field](./firestore_lite_pipelines.field.md#field_class) \| string> | Optional additional fields to remove. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.removeFields() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Remove fields from outputs of previous stages. + +Example: + +```typescript +firestore.pipeline().collection('books') + // removes field 'rating' and 'cost' from the previous stage outputs. + .removeFields( + field('rating'), + 'cost' + ); + +``` + +Signature: + +```typescript +removeFields(options: RemoveFieldsStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [RemoveFieldsStageOptions](./firestore_lite_pipelines.md#removefieldsstageoptions) | An object that specifies required and optional parameters for the stage. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.replaceWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Fully overwrites all fields in a document with those coming from a nested map. + +

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value. + +

Example: + +```typescript +// Input. +// { +// 'name': 'John Doe Jr.', +// 'parents': { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } +// } + +// Emit parents as document. +firestore.pipeline().collection('people').replaceWith('parents'); + +// Output +// { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } + +``` + +Signature: + +```typescript +replaceWith(fieldName: string): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field containing the nested map. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.replaceWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Fully overwrites all fields in a document with those coming from a map. + +

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value. + +

Example: + +```typescript +// Input. +// { +// 'name': 'John Doe Jr.', +// 'parents': { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } +// } + +// Emit parents as document. +firestore.pipeline().collection('people').replaceWith(map({ + foo: 'bar', + info: { + name: field('name') + } +})); + +// Output +// { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } + +``` + +Signature: + +```typescript +replaceWith(expr: Expression): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An that when returned evaluates to a map. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.replaceWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Fully overwrites all fields in a document with those coming from a map. + +

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value. + +

Example: + +```typescript +// Input. +// { +// 'name': 'John Doe Jr.', +// 'parents': { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } +// } + +// Emit parents as document. +firestore.pipeline().collection('people').replaceWith(map({ + foo: 'bar', + info: { + name: field('name') + } +})); + +// Output +// { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } + +``` + +Signature: + +```typescript +replaceWith(options: ReplaceWithStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [ReplaceWithStageOptions](./firestore_lite_pipelines.md#replacewithstageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.sample() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Performs a pseudo-random sampling of the documents from the previous stage. + +

This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned. + +

Examples: + +```typescript +// Sample 25 books, if available. +firestore.pipeline().collection('books') + .sample(25); + +``` + +Signature: + +```typescript +sample(documents: number): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| documents | number | The number of documents to sample. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.sample() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Performs a pseudo-random sampling of the documents from the previous stage. + +

This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See for more information. + +

Examples: + +// Sample 10 books, if available. firestore.pipeline().collection("books") .sample({ documents: 10 }); + +// Sample 50% of books. firestore.pipeline().collection("books") .sample({ percentage: 0.5 }); + +Signature: + +```typescript +sample(options: SampleStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [SampleStageOptions](./firestore_lite_pipelines.md#samplestageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.select() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Selects or creates a set of fields from the outputs of previous stages. + +

The selected fields are defined using expressions, which can be: + +

  • : Name of an existing field
  • : References an existing field.
  • : Represents the result of a function with an assigned alias name using
+ +

If no selections are provided, the output of this stage is empty. Use instead if only additions are desired. + +

Example: + +```typescript +db.pipeline().collection("books") + .select( + "firstName", + field("lastName"), + field("address").toUppercase().as("upperAddress"), + ); + +``` + +Signature: + +```typescript +select(selection: Selectable | string, ...additionalSelections: Array): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| selection | [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) \| string | The first field to include in the output documents, specified as expression or string value representing the field name. | +| additionalSelections | Array<[Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) \| string> | Optional additional fields to include in the output documents, specified as expressions or values representing field names. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.select() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Selects or creates a set of fields from the outputs of previous stages. + +

The selected fields are defined using expressions, which can be: + +

  • : Name of an existing field
  • : References an existing field.
  • : Represents the result of a function with an assigned alias name using
+ +

If no selections are provided, the output of this stage is empty. Use instead if only additions are desired. + +

Example: + +```typescript +db.pipeline().collection("books") + .select( + "firstName", + field("lastName"), + field("address").toUppercase().as("upperAddress"), + ); + +``` + +Signature: + +```typescript +select(options: SelectStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [SelectStageOptions](./firestore_lite_pipelines.md#selectstageoptions) | An object that specifies required and optional parameters for the stage. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.sort() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Sorts the documents from previous stages based on one or more criteria. + +

This stage allows you to order the results of your pipeline. You can specify multiple instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified. + +

Example: + +```typescript +// Sort books by rating in descending order, and then by title in ascending order for books +// with the same rating +firestore.pipeline().collection("books") + .sort( + Ordering.of(field("rating")).descending(), + Ordering.of(field("title")) // Ascending order is the default + ); + +``` + +Signature: + +```typescript +sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ordering | [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) | The first instance specifying the sorting criteria. | +| additionalOrderings | [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class)\[\] | Optional additional instances specifying the additional sorting criteria. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.sort() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Sorts the documents from previous stages based on one or more criteria. + +

This stage allows you to order the results of your pipeline. You can specify multiple instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified. + +

Example: + +```typescript +// Sort books by rating in descending order, and then by title in ascending order for books +// with the same rating +firestore.pipeline().collection("books") + .sort( + Ordering.of(field("rating")).descending(), + Ordering.of(field("title")) // Ascending order is the default + ); + +``` + +Signature: + +```typescript +sort(options: SortStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.union() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Performs union of all documents from two pipelines, including duplicates. + +

This stage will pass through documents from previous stage, and also pass through documents from previous stage of the `other` given in parameter. The order of documents emitted from this stage is undefined. + +

Example: + +```typescript +// Emit documents from books collection and magazines collection. +firestore.pipeline().collection('books') + .union(firestore.pipeline().collection('magazines')); + +``` + +Signature: + +```typescript +union(other: Pipeline): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) | The other that is part of union. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.union() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Performs union of all documents from two pipelines, including duplicates. + +

This stage will pass through documents from previous stage, and also pass through documents from previous stage of the `other` given in parameter. The order of documents emitted from this stage is undefined. + +

Example: + +```typescript +// Emit documents from books collection and magazines collection. +firestore.pipeline().collection('books') + .union(firestore.pipeline().collection('magazines')); + +``` + +Signature: + +```typescript +union(options: UnionStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.unnest() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Produces a document for each element in an input array. + +For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the `selectable` parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the `alias` field with the array element value. + +When `selectable` evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the `alias` field absent. + +No documents are emitted when `selectable` evaluates to an empty array. + +Example: + +```typescript +// Input: +// { "title": "The Hitchhiker's Guide to the Galaxy", "tags": [ "comedy", "space", "adventure" ], ... } + +// Emit a book document for each tag of the book. +firestore.pipeline().collection("books") + .unnest(field("tags").as('tag'), 'tagIndex'); + +// Output: +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "comedy", "tagIndex": 0, ... } +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "space", "tagIndex": 1, ... } +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "adventure", "tagIndex": 2, ... } + +``` + +Signature: + +```typescript +unnest(selectable: Selectable, indexField?: string): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| selectable | [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) | A selectable expression defining the field to unnest and the alias to use for each un-nested element in the output documents. | +| indexField | string | An optional string value specifying the field path to write the offset (starting at zero) into the array the un-nested element is from A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.unnest() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Produces a document for each element in an input array. + +For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the `selectable` parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the `alias` field with the array element value. + +When `selectable` evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the `alias` field absent. + +No documents are emitted when `selectable` evaluates to an empty array. + +Example: + +```typescript +// Input: +// { "title": "The Hitchhiker's Guide to the Galaxy", "tags": [ "comedy", "space", "adventure" ], ... } + +// Emit a book document for each tag of the book. +firestore.pipeline().collection("books") + .unnest(field("tags").as('tag'), 'tagIndex'); + +// Output: +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "comedy", "tagIndex": 0, ... } +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "space", "tagIndex": 1, ... } +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "adventure", "tagIndex": 2, ... } + +``` + +Signature: + +```typescript +unnest(options: UnnestStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [UnnestStageOptions](./firestore_lite_pipelines.md#unneststageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.where() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Filters the documents from previous stages to only include those matching the specified . + +

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of , typically including but not limited to: + +

  • field comparators: , (less than), (greater than), etc.
  • logical operators: , , , etc.
  • advanced functions: , , etc.
+ +

Example: + +```typescript +firestore.pipeline().collection("books") + .where( + and( + gt(field("rating"), 4.0), // Filter for ratings greater than 4.0 + field("genre").eq("Science Fiction") // Equivalent to gt("genre", "Science Fiction") + ) + ); + +``` + +Signature: + +```typescript +where(condition: BooleanExpression): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| condition | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The to apply. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +## Pipeline.where() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Filters the documents from previous stages to only include those matching the specified . + +

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of , typically including but not limited to: + +

  • field comparators: , (less than), (greater than), etc.
  • logical operators: , , , etc.
  • advanced functions: , , etc.
+ +

Example: + +```typescript +firestore.pipeline().collection("books") + .where( + and( + gt(field("rating"), 4.0), // Filter for ratings greater than 4.0 + field("genre").eq("Science Fiction") // Equivalent to gt("genre", "Science Fiction") + ) + ); + +``` + +Signature: + +```typescript +where(options: WhereStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [WhereStageOptions](./firestore_lite_pipelines.md#wherestageoptions) | An object that specifies required and optional parameters for the stage. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + diff --git a/docs-devsite/firestore_lite_pipelines.pipelineresult.md b/docs-devsite/firestore_lite_pipelines.pipelineresult.md new file mode 100644 index 0000000000..a2ac28a984 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.pipelineresult.md @@ -0,0 +1,168 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# PipelineResult class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the or methods. + +

If the PipelineResult represents a non-document result, `ref` will return a undefined value. + +Signature: + +```typescript +export declare class PipelineResult +``` + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [createTime](./firestore_lite_pipelines.pipelineresult.md#pipelineresultcreatetime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was created. Undefined if this result is not a document. {Timestamp\|undefined} | +| [id](./firestore_lite_pipelines.pipelineresult.md#pipelineresultid) | | string \| undefined | (Public Preview) The ID of the document for which this PipelineResult contains data, if it is a document; otherwise undefined. {string} | +| [ref](./firestore_lite_pipelines.pipelineresult.md#pipelineresultref) | | [DocumentReference](./firestore_lite.documentreference.md#documentreference_class) \| undefined | (Public Preview) The reference of the document, if it is a document; otherwise undefined. | +| [updateTime](./firestore_lite_pipelines.pipelineresult.md#pipelineresultupdatetime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. {Timestamp\|undefined} | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [data()](./firestore_lite_pipelines.pipelineresult.md#pipelineresultdata) | | (Public Preview) Retrieves all fields in the result as an object. | +| [get(fieldPath)](./firestore_lite_pipelines.pipelineresult.md#pipelineresultget) | | (Public Preview) Retrieves the field specified by field. | + +## PipelineResult.createTime + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The time the document was created. Undefined if this result is not a document. + + {Timestamp\|undefined} + +Signature: + +```typescript +get createTime(): Timestamp | undefined; +``` + +## PipelineResult.id + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The ID of the document for which this PipelineResult contains data, if it is a document; otherwise `undefined`. + + {string} + +Signature: + +```typescript +get id(): string | undefined; +``` + +## PipelineResult.ref + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The reference of the document, if it is a document; otherwise `undefined`. + +Signature: + +```typescript +get ref(): DocumentReference | undefined; +``` + +## PipelineResult.updateTime + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. + + {Timestamp\|undefined} + +Signature: + +```typescript +get updateTime(): Timestamp | undefined; +``` + +## PipelineResult.data() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Retrieves all fields in the result as an object. + +Signature: + +```typescript +data(): AppModelType; +``` +Returns: + +AppModelType + +{T} An object containing all fields in the document or 'undefined' if the document doesn't exist. + +### Example + + +``` +let p = firestore.pipeline().collection('col'); + +p.execute().then(results => { + let data = results[0].data(); + console.log(`Retrieved data: ${JSON.stringify(data)}`); +}); + +``` + +## PipelineResult.get() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Retrieves the field specified by `field`. + +Signature: + +```typescript +get(fieldPath: string | FieldPath | Field): any; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldPath | string \| [FieldPath](./firestore_lite.fieldpath.md#fieldpath_class) \| [Field](./firestore_lite_pipelines.field.md#field_class) | | + +Returns: + +any + +{\*} The data at the specified field location or undefined if no such field exists. + +### Example + + +``` +let p = firestore.pipeline().collection('col'); + +p.execute().then(results => { + let field = results[0].get('a.b'); + console.log(`Retrieved field value: ${field}`); +}); + +``` + diff --git a/docs-devsite/firestore_lite_pipelines.pipelinesnapshot.md b/docs-devsite/firestore_lite_pipelines.pipelinesnapshot.md new file mode 100644 index 0000000000..e5370fc1d0 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.pipelinesnapshot.md @@ -0,0 +1,103 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# PipelineSnapshot class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Represents the results of a Firestore pipeline execution. + +A `PipelineSnapshot` contains zero or more objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. + +Signature: + +```typescript +export declare class PipelineSnapshot +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(pipeline, results, executionTime)](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshotconstructor) | | (Public Preview) Constructs a new instance of the PipelineSnapshot class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [executionTime](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshotexecutiontime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) | (Public Preview) The time at which the pipeline producing this result is executed. {Timestamp} | +| [results](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshotresults) | | [PipelineResult](./firestore_lite_pipelines.pipelineresult.md#pipelineresult_class)\[\] | (Public Preview) An array of all the results in the PipelineSnapshot. | + +## PipelineSnapshot.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `PipelineSnapshot` class + +Signature: + +```typescript +constructor(pipeline: Pipeline, results: PipelineResult[], executionTime?: Timestamp); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pipeline | [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) | | +| results | [PipelineResult](./firestore_lite_pipelines.pipelineresult.md#pipelineresult_class)\[\] | | +| executionTime | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) | | + +## PipelineSnapshot.executionTime + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The time at which the pipeline producing this result is executed. + + {Timestamp} + +Signature: + +```typescript +get executionTime(): Timestamp; +``` + +## PipelineSnapshot.results + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An array of all the results in the `PipelineSnapshot`. + +Signature: + +```typescript +get results(): PipelineResult[]; +``` + +### Example + + +```typescript +const snapshot: PipelineSnapshot = await firestore + .pipeline() + .collection('myCollection') + .where(field('value').greaterThan(10)) + .execute(); + +snapshot.results.forEach(doc => { + console.log(doc.id, '=>', doc.data()); +}); + +``` + diff --git a/docs-devsite/firestore_lite_pipelines.pipelinesource.md b/docs-devsite/firestore_lite_pipelines.pipelinesource.md new file mode 100644 index 0000000000..6ec4d729fa --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.pipelinesource.md @@ -0,0 +1,251 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# PipelineSource class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Provides the entry point for defining the data source of a Firestore . + +Use the methods of this class (e.g., , , , or ) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. + +Signature: + +```typescript +export declare class PipelineSource +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [collection(collection)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecollection) | | (Public Preview) Returns all documents from the entire collection. The collection can be nested. | +| [collection(options)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecollection) | | (Public Preview) Returns all documents from the entire collection. The collection can be nested. | +| [collectionGroup(collectionId)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) | | (Public Preview) Returns all documents from a collection ID regardless of the parent. | +| [collectionGroup(options)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) | | (Public Preview) Returns all documents from a collection ID regardless of the parent. | +| [createFrom(query)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecreatefrom) | | (Public Preview) Convert the given Query into an equivalent Pipeline. | +| [database()](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcedatabase) | | (Public Preview) Returns all documents from the entire database. | +| [database(options)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcedatabase) | | (Public Preview) Returns all documents from the entire database. | +| [documents(docs)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcedocuments) | | (Public Preview) Set the pipeline's source to the documents specified by the given paths and DocumentReferences. | +| [documents(options)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcedocuments) | | (Public Preview) Set the pipeline's source to the documents specified by the given paths and DocumentReferences. | + +## PipelineSource.collection() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all documents from the entire collection. The collection can be nested. + +Signature: + +```typescript +collection(collection: string | Query): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| collection | string \| [Query](./firestore_lite.query.md#query_class) | Name or reference to the collection that will be used as the Pipeline source. | + +Returns: + +PipelineType + +## PipelineSource.collection() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all documents from the entire collection. The collection can be nested. + +Signature: + +```typescript +collection(options: CollectionStageOptions): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [CollectionStageOptions](./firestore_lite_pipelines.md#collectionstageoptions) | Options defining how this CollectionStage is evaluated. | + +Returns: + +PipelineType + +## PipelineSource.collectionGroup() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all documents from a collection ID regardless of the parent. + +Signature: + +```typescript +collectionGroup(collectionId: string): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| collectionId | string | ID of the collection group to use as the Pipeline source. | + +Returns: + +PipelineType + +## PipelineSource.collectionGroup() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all documents from a collection ID regardless of the parent. + +Signature: + +```typescript +collectionGroup(options: CollectionGroupStageOptions): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [CollectionGroupStageOptions](./firestore_lite_pipelines.md#collectiongroupstageoptions) | Options defining how this CollectionGroupStage is evaluated. | + +Returns: + +PipelineType + +## PipelineSource.createFrom() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Convert the given Query into an equivalent Pipeline. + +Signature: + +```typescript +createFrom(query: Query): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| query | [Query](./firestore_lite.query.md#query_class) | A Query to be converted into a Pipeline. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +#### Exceptions + + Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. + +## PipelineSource.database() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all documents from the entire database. + +Signature: + +```typescript +database(): PipelineType; +``` +Returns: + +PipelineType + +## PipelineSource.database() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all documents from the entire database. + +Signature: + +```typescript +database(options: DatabaseStageOptions): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [DatabaseStageOptions](./firestore_lite_pipelines.md#databasestageoptions) | Options defining how a DatabaseStage is evaluated. | + +Returns: + +PipelineType + +## PipelineSource.documents() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Set the pipeline's source to the documents specified by the given paths and DocumentReferences. + +Signature: + +```typescript +documents(docs: Array): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| docs | Array<string \| [DocumentReference](./firestore_lite.documentreference.md#documentreference_class)> | An array of paths and DocumentReferences specifying the individual documents that will be the source of this pipeline. The converters for these DocumentReferences will be ignored and not have an effect on this pipeline. | + +Returns: + +PipelineType + +#### Exceptions + + Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. + +## PipelineSource.documents() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Set the pipeline's source to the documents specified by the given paths and DocumentReferences. + +Signature: + +```typescript +documents(options: DocumentsStageOptions): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [DocumentsStageOptions](./firestore_lite_pipelines.md#documentsstageoptions) | Options defining how this DocumentsStage is evaluated. | + +Returns: + +PipelineType + +#### Exceptions + + Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. + diff --git a/docs-devsite/firestore_lite_pipelines.query.md b/docs-devsite/firestore_lite_pipelines.query.md new file mode 100644 index 0000000000..3a33d866e1 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.query.md @@ -0,0 +1,125 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Query class +A `Query` refers to a query which you can read or listen to. You can also construct refined `Query` objects by adding filters and ordering. + +Signature: + +```typescript +export declare class Query +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)()](./firestore_lite_pipelines.query.md#queryconstructor) | | Constructs a new instance of the Query class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [converter](./firestore_lite_pipelines.query.md#queryconverter) | | [FirestoreDataConverter](./firestore_lite.firestoredataconverter.md#firestoredataconverter_interface)<AppModelType, DbModelType> \| null | If provided, the FirestoreDataConverter associated with this instance. | +| [firestore](./firestore_lite_pipelines.query.md#queryfirestore) | | [Firestore](./firestore_lite.firestore.md#firestore_class) | The Firestore instance for the Firestore database (useful for performing transactions, etc.). | +| [type](./firestore_lite_pipelines.query.md#querytype) | | 'query' \| 'collection' | The type of this Firestore reference. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [withConverter(converter)](./firestore_lite_pipelines.query.md#querywithconverter) | | Removes the current converter. | +| [withConverter(converter)](./firestore_lite_pipelines.query.md#querywithconverter) | | Applies a custom data converter to this query, allowing you to use your own custom model objects with Firestore. When you call [getDocs()](./firestore_.md#getdocs_4e56953) with the returned query, the provided converter will convert between Firestore data of type NewDbModelType and your custom type NewAppModelType. | + +## Query.(constructor) + +Constructs a new instance of the `Query` class + +Signature: + +```typescript +protected constructor(); +``` + +## Query.converter + +If provided, the `FirestoreDataConverter` associated with this instance. + +Signature: + +```typescript +readonly converter: FirestoreDataConverter | null; +``` + +## Query.firestore + +The `Firestore` instance for the Firestore database (useful for performing transactions, etc.). + +Signature: + +```typescript +readonly firestore: Firestore; +``` + +## Query.type + +The type of this Firestore reference. + +Signature: + +```typescript +readonly type: 'query' | 'collection'; +``` + +## Query.withConverter() + +Removes the current converter. + +Signature: + +```typescript +withConverter(converter: null): Query; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| converter | null | null removes the current converter. | + +Returns: + +[Query](./firestore_lite.query.md#query_class)<[DocumentData](./firestore_lite.documentdata.md#documentdata_interface), [DocumentData](./firestore_lite.documentdata.md#documentdata_interface)> + +A `Query` that does not use a converter. + +## Query.withConverter() + +Applies a custom data converter to this query, allowing you to use your own custom model objects with Firestore. When you call [getDocs()](./firestore_.md#getdocs_4e56953) with the returned query, the provided converter will convert between Firestore data of type `NewDbModelType` and your custom type `NewAppModelType`. + +Signature: + +```typescript +withConverter(converter: FirestoreDataConverter): Query; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| converter | [FirestoreDataConverter](./firestore_lite.firestoredataconverter.md#firestoredataconverter_interface)<NewAppModelType, NewDbModelType> | Converts objects to and from Firestore. | + +Returns: + +[Query](./firestore_lite.query.md#query_class)<NewAppModelType, NewDbModelType> + +A `Query` that uses the provided converter. + diff --git a/docs-devsite/firestore_lite_pipelines.querydocumentsnapshot.md b/docs-devsite/firestore_lite_pipelines.querydocumentsnapshot.md new file mode 100644 index 0000000000..5ad6863954 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.querydocumentsnapshot.md @@ -0,0 +1,45 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# QueryDocumentSnapshot class +A `QueryDocumentSnapshot` contains data read from a document in your Firestore database as part of a query. The document is guaranteed to exist and its data can be extracted with `.data()` or `.get()` to get a specific field. + +A `QueryDocumentSnapshot` offers the same API surface as a `DocumentSnapshot`. Since query results contain only existing documents, the `exists` property will always be true and `data()` will never return 'undefined'. + +Signature: + +```typescript +export declare class QueryDocumentSnapshot extends DocumentSnapshot +``` +Extends: [DocumentSnapshot](./firestore_lite.documentsnapshot.md#documentsnapshot_class)<AppModelType, DbModelType> + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [data()](./firestore_lite_pipelines.querydocumentsnapshot.md#querydocumentsnapshotdata) | | Retrieves all fields in the document as an Object. | + +## QueryDocumentSnapshot.data() + +Retrieves all fields in the document as an `Object`. + +Signature: + +```typescript +/** @override */ +data(): AppModelType; +``` +Returns: + +AppModelType + +An `Object` containing all fields in the document. + diff --git a/docs-devsite/firestore_lite_pipelines.selectable.md b/docs-devsite/firestore_lite_pipelines.selectable.md new file mode 100644 index 0000000000..555b613577 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.selectable.md @@ -0,0 +1,39 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Selectable interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An interface that represents a selectable expression. + +Signature: + +```typescript +export declare interface Selectable +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [selectable](./firestore_lite_pipelines.selectable.md#selectableselectable) | true | (Public Preview) | + +## Selectable.selectable + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +selectable: true; +``` diff --git a/docs-devsite/firestore_lite_pipelines.stageoptions.md b/docs-devsite/firestore_lite_pipelines.stageoptions.md new file mode 100644 index 0000000000..b751cfaa7f --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.stageoptions.md @@ -0,0 +1,51 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# StageOptions interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a Stage is evaluated. + +Signature: + +```typescript +export declare interface StageOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [rawOptions](./firestore_lite_pipelines.stageoptions.md#stageoptionsrawoptions) | { \[name: string\]: unknown; } | (Public Preview) An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Raw option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK.rawOptions supports dot notation, if you want to override a nested option. | + +## StageOptions.rawOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK. + +The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name). + +Raw option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected. + +Values specified in rawOptions will take precedence over any options with the same name set by the SDK. + +`rawOptions` supports dot notation, if you want to override a nested option. + +Signature: + +```typescript +rawOptions?: { + [name: string]: unknown; + }; +``` diff --git a/docs-devsite/firestore_lite_pipelines.timestamp.md b/docs-devsite/firestore_lite_pipelines.timestamp.md new file mode 100644 index 0000000000..58a5cbc074 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.timestamp.md @@ -0,0 +1,265 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Timestamp class +A `Timestamp` represents a point in time independent of any time zone or calendar, represented as seconds and fractions of seconds at nanosecond resolution in UTC Epoch time. + +It is encoded using the Proleptic Gregorian Calendar which extends the Gregorian calendar backwards to year one. It is encoded assuming all minutes are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. + +For examples and further specifications, refer to the [Timestamp definition](https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto). + +Signature: + +```typescript +export declare class Timestamp +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(seconds, nanoseconds)](./firestore_lite_pipelines.timestamp.md#timestampconstructor) | | Creates a new timestamp. | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [nanoseconds](./firestore_lite_pipelines.timestamp.md#timestampnanoseconds) | | number | The fractions of a second at nanosecond resolution.\* | +| [seconds](./firestore_lite_pipelines.timestamp.md#timestampseconds) | | number | The number of seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [fromDate(date)](./firestore_lite_pipelines.timestamp.md#timestampfromdate) | static | Creates a new timestamp from the given date. | +| [fromJSON(json)](./firestore_lite_pipelines.timestamp.md#timestampfromjson) | static | Builds a Timestamp instance from a JSON object created by [Timestamp.toJSON()](./firestore_.timestamp.md#timestamptojson). | +| [fromMillis(milliseconds)](./firestore_lite_pipelines.timestamp.md#timestampfrommillis) | static | Creates a new timestamp from the given number of milliseconds. | +| [isEqual(other)](./firestore_lite_pipelines.timestamp.md#timestampisequal) | | Returns true if this Timestamp is equal to the provided one. | +| [now()](./firestore_lite_pipelines.timestamp.md#timestampnow) | static | Creates a new timestamp with the current date, with millisecond precision. | +| [toDate()](./firestore_lite_pipelines.timestamp.md#timestamptodate) | | Converts a Timestamp to a JavaScript Date object. This conversion causes a loss of precision since Date objects only support millisecond precision. | +| [toJSON()](./firestore_lite_pipelines.timestamp.md#timestamptojson) | | Returns a JSON-serializable representation of this Timestamp. | +| [toMillis()](./firestore_lite_pipelines.timestamp.md#timestamptomillis) | | Converts a Timestamp to a numeric timestamp (in milliseconds since epoch). This operation causes a loss of precision. | +| [toString()](./firestore_lite_pipelines.timestamp.md#timestamptostring) | | Returns a textual representation of this Timestamp. | +| [valueOf()](./firestore_lite_pipelines.timestamp.md#timestampvalueof) | | Converts this object to a primitive string, which allows Timestamp objects to be compared using the >, <=, >= and > operators. | + +## Timestamp.(constructor) + +Creates a new timestamp. + +Signature: + +```typescript +constructor( + seconds: number, + nanoseconds: number); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| seconds | number | The number of seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive. | +| nanoseconds | number | The non-negative fractions of a second at nanosecond resolution. Negative second values with fractions must still have non-negative nanoseconds values that count forward in time. Must be from 0 to 999,999,999 inclusive. | + +## Timestamp.nanoseconds + +The fractions of a second at nanosecond resolution.\* + +Signature: + +```typescript +readonly nanoseconds: number; +``` + +## Timestamp.seconds + +The number of seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. + +Signature: + +```typescript +readonly seconds: number; +``` + +## Timestamp.fromDate() + +Creates a new timestamp from the given date. + +Signature: + +```typescript +static fromDate(date: Date): Timestamp; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| date | Date | The date to initialize the Timestamp from. | + +Returns: + +[Timestamp](./firestore_lite.timestamp.md#timestamp_class) + +A new `Timestamp` representing the same point in time as the given date. + +## Timestamp.fromJSON() + +Builds a `Timestamp` instance from a JSON object created by [Timestamp.toJSON()](./firestore_.timestamp.md#timestamptojson). + +Signature: + +```typescript +static fromJSON(json: object): Timestamp; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| json | object | | + +Returns: + +[Timestamp](./firestore_lite.timestamp.md#timestamp_class) + +## Timestamp.fromMillis() + +Creates a new timestamp from the given number of milliseconds. + +Signature: + +```typescript +static fromMillis(milliseconds: number): Timestamp; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| milliseconds | number | Number of milliseconds since Unix epoch 1970-01-01T00:00:00Z. | + +Returns: + +[Timestamp](./firestore_lite.timestamp.md#timestamp_class) + +A new `Timestamp` representing the same point in time as the given number of milliseconds. + +## Timestamp.isEqual() + +Returns true if this `Timestamp` is equal to the provided one. + +Signature: + +```typescript +isEqual(other: Timestamp): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) | The Timestamp to compare against. | + +Returns: + +boolean + +true if this `Timestamp` is equal to the provided one. + +## Timestamp.now() + +Creates a new timestamp with the current date, with millisecond precision. + +Signature: + +```typescript +static now(): Timestamp; +``` +Returns: + +[Timestamp](./firestore_lite.timestamp.md#timestamp_class) + +a new timestamp representing the current date. + +## Timestamp.toDate() + +Converts a `Timestamp` to a JavaScript `Date` object. This conversion causes a loss of precision since `Date` objects only support millisecond precision. + +Signature: + +```typescript +toDate(): Date; +``` +Returns: + +Date + +JavaScript `Date` object representing the same point in time as this `Timestamp`, with millisecond precision. + +## Timestamp.toJSON() + +Returns a JSON-serializable representation of this `Timestamp`. + +Signature: + +```typescript +toJSON(): { + seconds: number; + nanoseconds: number; + type: string; + }; +``` +Returns: + +{ seconds: number; nanoseconds: number; type: string; } + +## Timestamp.toMillis() + +Converts a `Timestamp` to a numeric timestamp (in milliseconds since epoch). This operation causes a loss of precision. + +Signature: + +```typescript +toMillis(): number; +``` +Returns: + +number + +The point in time corresponding to this timestamp, represented as the number of milliseconds since Unix epoch 1970-01-01T00:00:00Z. + +## Timestamp.toString() + +Returns a textual representation of this `Timestamp`. + +Signature: + +```typescript +toString(): string; +``` +Returns: + +string + +## Timestamp.valueOf() + +Converts this object to a primitive string, which allows `Timestamp` objects to be compared using the `>`, `<=`, `>=` and `>` operators. + +Signature: + +```typescript +valueOf(): string; +``` +Returns: + +string + diff --git a/docs-devsite/firestore_lite_pipelines.vectorvalue.md b/docs-devsite/firestore_lite_pipelines.vectorvalue.md new file mode 100644 index 0000000000..19a69f0bc2 --- /dev/null +++ b/docs-devsite/firestore_lite_pipelines.vectorvalue.md @@ -0,0 +1,101 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# VectorValue class +Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). + + VectorValue + +Signature: + +```typescript +export declare class VectorValue +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [fromJSON(json)](./firestore_lite_pipelines.vectorvalue.md#vectorvaluefromjson) | static | Builds a VectorValue instance from a JSON object created by [VectorValue.toJSON()](./firestore_.vectorvalue.md#vectorvaluetojson). | +| [isEqual(other)](./firestore_lite_pipelines.vectorvalue.md#vectorvalueisequal) | | Returns true if the two VectorValue values have the same raw number arrays, returns false otherwise. | +| [toArray()](./firestore_lite_pipelines.vectorvalue.md#vectorvaluetoarray) | | Returns a copy of the raw number array form of the vector. | +| [toJSON()](./firestore_lite_pipelines.vectorvalue.md#vectorvaluetojson) | | Returns a JSON-serializable representation of this VectorValue instance. | + +## VectorValue.fromJSON() + +Builds a `VectorValue` instance from a JSON object created by [VectorValue.toJSON()](./firestore_.vectorvalue.md#vectorvaluetojson). + +Signature: + +```typescript +static fromJSON(json: object): VectorValue; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| json | object | a JSON object represention of a VectorValue instance. | + +Returns: + +[VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) + +an instance of [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) if the JSON object could be parsed. Throws a [FirestoreError](./firestore_.firestoreerror.md#firestoreerror_class) if an error occurs. + +## VectorValue.isEqual() + +Returns `true` if the two `VectorValue` values have the same raw number arrays, returns `false` otherwise. + +Signature: + +```typescript +isEqual(other: VectorValue): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | | + +Returns: + +boolean + +## VectorValue.toArray() + +Returns a copy of the raw number array form of the vector. + +Signature: + +```typescript +toArray(): number[]; +``` +Returns: + +number\[\] + +## VectorValue.toJSON() + +Returns a JSON-serializable representation of this `VectorValue` instance. + +Signature: + +```typescript +toJSON(): object; +``` +Returns: + +object + +a JSON representation of this object. + diff --git a/docs-devsite/firestore_pipelines.aggregatefunction.md b/docs-devsite/firestore_pipelines.aggregatefunction.md new file mode 100644 index 0000000000..5373c05e5a --- /dev/null +++ b/docs-devsite/firestore_pipelines.aggregatefunction.md @@ -0,0 +1,109 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# AggregateFunction class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +A class that represents an aggregate function. + +Signature: + +```typescript +export declare class AggregateFunction +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(name, params)](./firestore_pipelines.aggregatefunction.md#aggregatefunctionconstructor) | | (Public Preview) Constructs a new instance of the AggregateFunction class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [exprType](./firestore_pipelines.aggregatefunction.md#aggregatefunctionexprtype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [as(name)](./firestore_pipelines.aggregatefunction.md#aggregatefunctionas) | | (Public Preview) Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. +```typescript +// Calculate the average price of all items and assign it the alias "averagePrice". +firestore.pipeline().collection("items") + .aggregate(field("price").average().as("averagePrice")); + +``` + | + +## AggregateFunction.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `AggregateFunction` class + +Signature: + +```typescript +constructor(name: string, params: Expression[]); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | +| params | [Expression](./firestore_pipelines.expression.md#expression_class)\[\] | | + +## AggregateFunction.exprType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +exprType: ExpressionType; +``` + +## AggregateFunction.as() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. + +```typescript +// Calculate the average price of all items and assign it the alias "averagePrice". +firestore.pipeline().collection("items") + .aggregate(field("price").average().as("averagePrice")); + +``` + +Signature: + +```typescript +as(name: string): AliasedAggregate; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | The alias to assign to this AggregateFunction. A new that wraps this AggregateFunction and associates it with the provided alias. | + +Returns: + +[AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) + diff --git a/docs-devsite/firestore_pipelines.aliasedaggregate.md b/docs-devsite/firestore_pipelines.aliasedaggregate.md new file mode 100644 index 0000000000..39826b83b6 --- /dev/null +++ b/docs-devsite/firestore_pipelines.aliasedaggregate.md @@ -0,0 +1,78 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# AliasedAggregate class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An AggregateFunction with alias. + +Signature: + +```typescript +export declare class AliasedAggregate +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(aggregate, alias, \_methodName)](./firestore_pipelines.aliasedaggregate.md#aliasedaggregateconstructor) | | (Public Preview) Constructs a new instance of the AliasedAggregate class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [aggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregateaggregate) | | [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) | (Public Preview) | +| [alias](./firestore_pipelines.aliasedaggregate.md#aliasedaggregatealias) | | string | (Public Preview) | + +## AliasedAggregate.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `AliasedAggregate` class + +Signature: + +```typescript +constructor(aggregate: AggregateFunction, alias: string, _methodName: string | undefined); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| aggregate | [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) | | +| alias | string | | +| \_methodName | string \| undefined | | + +## AliasedAggregate.aggregate + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly aggregate: AggregateFunction; +``` + +## AliasedAggregate.alias + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly alias: string; +``` diff --git a/docs-devsite/firestore_pipelines.aliasedexpression.md b/docs-devsite/firestore_pipelines.aliasedexpression.md new file mode 100644 index 0000000000..6a602a9e44 --- /dev/null +++ b/docs-devsite/firestore_pipelines.aliasedexpression.md @@ -0,0 +1,102 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# AliasedExpression class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + + +Signature: + +```typescript +export declare class AliasedExpression implements Selectable +``` +Implements: [Selectable](./firestore_pipelines.selectable.md#selectable_interface) + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(expr, alias, \_methodName)](./firestore_pipelines.aliasedexpression.md#aliasedexpressionconstructor) | | (Public Preview) Constructs a new instance of the AliasedExpression class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [alias](./firestore_pipelines.aliasedexpression.md#aliasedexpressionalias) | | string | (Public Preview) | +| [expr](./firestore_pipelines.aliasedexpression.md#aliasedexpressionexpr) | | [Expression](./firestore_pipelines.expression.md#expression_class) | (Public Preview) | +| [exprType](./firestore_pipelines.aliasedexpression.md#aliasedexpressionexprtype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) | +| [selectable](./firestore_pipelines.aliasedexpression.md#aliasedexpressionselectable) | | true | (Public Preview) | + +## AliasedExpression.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `AliasedExpression` class + +Signature: + +```typescript +constructor(expr: Expression, alias: string, _methodName: string | undefined); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | | +| alias | string | | +| \_methodName | string \| undefined | | + +## AliasedExpression.alias + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly alias: string; +``` + +## AliasedExpression.expr + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly expr: Expression; +``` + +## AliasedExpression.exprType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +exprType: ExpressionType; +``` + +## AliasedExpression.selectable + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +selectable: true; +``` diff --git a/docs-devsite/firestore_pipelines.booleanexpression.md b/docs-devsite/firestore_pipelines.booleanexpression.md new file mode 100644 index 0000000000..b4855ea111 --- /dev/null +++ b/docs-devsite/firestore_pipelines.booleanexpression.md @@ -0,0 +1,274 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# BooleanExpression class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An interface that represents a filter condition. + +Signature: + +```typescript +export declare abstract class BooleanExpression extends Expression +``` +Extends: [Expression](./firestore_pipelines.expression.md#expression_class) + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [conditional(thenExpr, elseExpr)](./firestore_pipelines.booleanexpression.md#booleanexpressionconditional) | | (Public Preview) Creates a conditional expression that evaluates to the 'then' expression if this expression evaluates to true, or evaluates to the 'else' expression if this expressions evaluates false. +```typescript +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor")); + +``` + | +| [countIf()](./firestore_pipelines.booleanexpression.md#booleanexpressioncountif) | | (Public Preview) Creates an aggregation that finds the count of input documents satisfying this boolean expression. +```typescript +// Find the count of documents with a score greater than 90 +field("score").greaterThan(90).countIf().as("highestScore"); + +``` + A new AggregateFunction representing the 'countIf' aggregation. | +| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. +```typescript +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +constant(50).divide('length').gt(1).ifError(constant(false)); + +``` + | +| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. +```typescript +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +constant(50).divide('length').gt(1).ifError(false); + +``` + | +| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. +```typescript +// Create an expression that protects against a divide by zero error. +constant(50).divide('length').gt(1).ifError(constant(0)); + +``` + | +| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. +```typescript +// Create an expression that protects against a divide by zero error. +constant(50).divide('length').gt(1).ifError(0); + +``` + | +| [not()](./firestore_pipelines.booleanexpression.md#booleanexpressionnot) | | (Public Preview) Creates an expression that negates this boolean expression. +```typescript +// Find documents where the 'tags' field does not contain 'completed' +field("tags").arrayContains("completed").not(); + +``` + A new representing the negated filter condition. | + +## BooleanExpression.conditional() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a conditional expression that evaluates to the 'then' expression if `this` expression evaluates to `true`, or evaluates to the 'else' expression if `this` expressions evaluates `false`. + +```typescript +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor")); + +``` + +Signature: + +```typescript +conditional(thenExpr: Expression, elseExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| thenExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is true. | +| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. A new representing the conditional expression. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## BooleanExpression.countIf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the count of input documents satisfying this boolean expression. + +```typescript +// Find the count of documents with a score greater than 90 +field("score").greaterThan(90).countIf().as("highestScore"); + +``` + A new `AggregateFunction` representing the 'countIf' aggregation. + +Signature: + +```typescript +countIf(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + +```typescript +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +constant(50).divide('length').gt(1).ifError(constant(false)); + +``` + +Signature: + +```typescript +ifError(catchValue: BooleanExpression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| catchValue | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + +```typescript +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +constant(50).divide('length').gt(1).ifError(false); + +``` + +Signature: + +```typescript +ifError(catchValue: boolean): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| catchValue | boolean | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + +```typescript +// Create an expression that protects against a divide by zero error. +constant(50).divide('length').gt(1).ifError(constant(0)); + +``` + +Signature: + +```typescript +ifError(catchValue: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| catchValue | [Expression](./firestore_pipelines.expression.md#expression_class) | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + +```typescript +// Create an expression that protects against a divide by zero error. +constant(50).divide('length').gt(1).ifError(0); + +``` + +Signature: + +```typescript +ifError(catchValue: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| catchValue | unknown | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## BooleanExpression.not() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that negates this boolean expression. + +```typescript +// Find documents where the 'tags' field does not contain 'completed' +field("tags").arrayContains("completed").not(); + +``` + A new representing the negated filter condition. + +Signature: + +```typescript +not(): BooleanExpression; +``` +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + diff --git a/docs-devsite/firestore_pipelines.bytes.md b/docs-devsite/firestore_pipelines.bytes.md new file mode 100644 index 0000000000..ca7674d511 --- /dev/null +++ b/docs-devsite/firestore_pipelines.bytes.md @@ -0,0 +1,177 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Bytes class +An immutable object representing an array of bytes. + +Signature: + +```typescript +export declare class Bytes +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [fromBase64String(base64)](./firestore_pipelines.bytes.md#bytesfrombase64string) | static | Creates a new Bytes object from the given Base64 string, converting it to bytes. | +| [fromJSON(json)](./firestore_pipelines.bytes.md#bytesfromjson) | static | Builds a Bytes instance from a JSON object created by [Bytes.toJSON()](./firestore_.bytes.md#bytestojson). | +| [fromUint8Array(array)](./firestore_pipelines.bytes.md#bytesfromuint8array) | static | Creates a new Bytes object from the given Uint8Array. | +| [isEqual(other)](./firestore_pipelines.bytes.md#bytesisequal) | | Returns true if this Bytes object is equal to the provided one. | +| [toBase64()](./firestore_pipelines.bytes.md#bytestobase64) | | Returns the underlying bytes as a Base64-encoded string. | +| [toJSON()](./firestore_pipelines.bytes.md#bytestojson) | | Returns a JSON-serializable representation of this Bytes instance. | +| [toString()](./firestore_pipelines.bytes.md#bytestostring) | | Returns a string representation of the Bytes object. | +| [toUint8Array()](./firestore_pipelines.bytes.md#bytestouint8array) | | Returns the underlying bytes in a new Uint8Array. | + +## Bytes.fromBase64String() + +Creates a new `Bytes` object from the given Base64 string, converting it to bytes. + +Signature: + +```typescript +static fromBase64String(base64: string): Bytes; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| base64 | string | The Base64 string used to create the Bytes object. | + +Returns: + +[Bytes](./firestore_.bytes.md#bytes_class) + +## Bytes.fromJSON() + +Builds a `Bytes` instance from a JSON object created by [Bytes.toJSON()](./firestore_.bytes.md#bytestojson). + +Signature: + +```typescript +static fromJSON(json: object): Bytes; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| json | object | a JSON object represention of a Bytes instance | + +Returns: + +[Bytes](./firestore_.bytes.md#bytes_class) + +an instance of [Bytes](./firestore_.bytes.md#bytes_class) if the JSON object could be parsed. Throws a [FirestoreError](./firestore_.firestoreerror.md#firestoreerror_class) if an error occurs. + +## Bytes.fromUint8Array() + +Creates a new `Bytes` object from the given Uint8Array. + +Signature: + +```typescript +static fromUint8Array(array: Uint8Array): Bytes; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | Uint8Array | The Uint8Array used to create the Bytes object. | + +Returns: + +[Bytes](./firestore_.bytes.md#bytes_class) + +## Bytes.isEqual() + +Returns true if this `Bytes` object is equal to the provided one. + +Signature: + +```typescript +isEqual(other: Bytes): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [Bytes](./firestore_.bytes.md#bytes_class) | The Bytes object to compare against. | + +Returns: + +boolean + +true if this `Bytes` object is equal to the provided one. + +## Bytes.toBase64() + +Returns the underlying bytes as a Base64-encoded string. + +Signature: + +```typescript +toBase64(): string; +``` +Returns: + +string + +The Base64-encoded string created from the `Bytes` object. + +## Bytes.toJSON() + +Returns a JSON-serializable representation of this `Bytes` instance. + +Signature: + +```typescript +toJSON(): object; +``` +Returns: + +object + +a JSON representation of this object. + +## Bytes.toString() + +Returns a string representation of the `Bytes` object. + +Signature: + +```typescript +toString(): string; +``` +Returns: + +string + +A string representation of the `Bytes` object. + +## Bytes.toUint8Array() + +Returns the underlying bytes in a new `Uint8Array`. + +Signature: + +```typescript +toUint8Array(): Uint8Array; +``` +Returns: + +Uint8Array + +The Uint8Array created from the `Bytes` object. + diff --git a/docs-devsite/firestore_pipelines.collectionreference.md b/docs-devsite/firestore_pipelines.collectionreference.md new file mode 100644 index 0000000000..cc7ea2d553 --- /dev/null +++ b/docs-devsite/firestore_pipelines.collectionreference.md @@ -0,0 +1,121 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# CollectionReference class +A `CollectionReference` object can be used for adding documents, getting document references, and querying for documents (using [query()](./firestore_.md#query_9f7b0f4)). + +Signature: + +```typescript +export declare class CollectionReference extends Query +``` +Extends: [Query](./firestore_.query.md#query_class)<AppModelType, DbModelType> + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [id](./firestore_pipelines.collectionreference.md#collectionreferenceid) | | string | The collection's identifier. | +| [parent](./firestore_pipelines.collectionreference.md#collectionreferenceparent) | | [DocumentReference](./firestore_.documentreference.md#documentreference_class)<[DocumentData](./firestore_.documentdata.md#documentdata_interface), [DocumentData](./firestore_.documentdata.md#documentdata_interface)> \| null | A reference to the containing DocumentReference if this is a subcollection. If this isn't a subcollection, the reference is null. | +| [path](./firestore_pipelines.collectionreference.md#collectionreferencepath) | | string | A string representing the path of the referenced collection (relative to the root of the database). | +| [type](./firestore_pipelines.collectionreference.md#collectionreferencetype) | | (not declared) | The type of this Firestore reference. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [withConverter(converter)](./firestore_pipelines.collectionreference.md#collectionreferencewithconverter) | | Applies a custom data converter to this CollectionReference, allowing you to use your own custom model objects with Firestore. When you call [addDoc()](./firestore_.md#adddoc_6e783ff) with the returned CollectionReference instance, the provided converter will convert between Firestore data of type NewDbModelType and your custom type NewAppModelType. | +| [withConverter(converter)](./firestore_pipelines.collectionreference.md#collectionreferencewithconverter) | | Removes the current converter. | + +## CollectionReference.id + +The collection's identifier. + +Signature: + +```typescript +get id(): string; +``` + +## CollectionReference.parent + +A reference to the containing `DocumentReference` if this is a subcollection. If this isn't a subcollection, the reference is null. + +Signature: + +```typescript +get parent(): DocumentReference | null; +``` + +## CollectionReference.path + +A string representing the path of the referenced collection (relative to the root of the database). + +Signature: + +```typescript +get path(): string; +``` + +## CollectionReference.type + +The type of this Firestore reference. + +Signature: + +```typescript +readonly type = "collection"; +``` + +## CollectionReference.withConverter() + +Applies a custom data converter to this `CollectionReference`, allowing you to use your own custom model objects with Firestore. When you call [addDoc()](./firestore_.md#adddoc_6e783ff) with the returned `CollectionReference` instance, the provided converter will convert between Firestore data of type `NewDbModelType` and your custom type `NewAppModelType`. + +Signature: + +```typescript +withConverter(converter: FirestoreDataConverter): CollectionReference; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| converter | [FirestoreDataConverter](./firestore_.firestoredataconverter.md#firestoredataconverter_interface)<NewAppModelType, NewDbModelType> | Converts objects to and from Firestore. | + +Returns: + +[CollectionReference](./firestore_.collectionreference.md#collectionreference_class)<NewAppModelType, NewDbModelType> + +A `CollectionReference` that uses the provided converter. + +## CollectionReference.withConverter() + +Removes the current converter. + +Signature: + +```typescript +withConverter(converter: null): CollectionReference; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| converter | null | null removes the current converter. | + +Returns: + +[CollectionReference](./firestore_.collectionreference.md#collectionreference_class)<[DocumentData](./firestore_.documentdata.md#documentdata_interface), [DocumentData](./firestore_.documentdata.md#documentdata_interface)> + +A `CollectionReference` that does not use a converter. + diff --git a/docs-devsite/firestore_pipelines.documentdata.md b/docs-devsite/firestore_pipelines.documentdata.md new file mode 100644 index 0000000000..c93565207a --- /dev/null +++ b/docs-devsite/firestore_pipelines.documentdata.md @@ -0,0 +1,19 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# DocumentData interface +Document data (for use with [setDoc()](./firestore_lite.md#setdoc_ee215ad)) consists of fields mapped to values. + +Signature: + +```typescript +export declare interface DocumentData +``` diff --git a/docs-devsite/firestore_pipelines.documentreference.md b/docs-devsite/firestore_pipelines.documentreference.md new file mode 100644 index 0000000000..246dc92150 --- /dev/null +++ b/docs-devsite/firestore_pipelines.documentreference.md @@ -0,0 +1,207 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# DocumentReference class +A `DocumentReference` refers to a document location in a Firestore database and can be used to write, read, or listen to the location. The document at the referenced location may or may not exist. + +Signature: + +```typescript +export declare class DocumentReference +``` + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [converter](./firestore_pipelines.documentreference.md#documentreferenceconverter) | | [FirestoreDataConverter](./firestore_.firestoredataconverter.md#firestoredataconverter_interface)<AppModelType, DbModelType> \| null | If provided, the FirestoreDataConverter associated with this instance. | +| [firestore](./firestore_pipelines.documentreference.md#documentreferencefirestore) | | [Firestore](./firestore_.firestore.md#firestore_class) | The [Firestore](./firestore_.firestore.md#firestore_class) instance the document is in. This is useful for performing transactions, for example. | +| [id](./firestore_pipelines.documentreference.md#documentreferenceid) | | string | The document's identifier within its collection. | +| [parent](./firestore_pipelines.documentreference.md#documentreferenceparent) | | [CollectionReference](./firestore_.collectionreference.md#collectionreference_class)<AppModelType, DbModelType> | The collection this DocumentReference belongs to. | +| [path](./firestore_pipelines.documentreference.md#documentreferencepath) | | string | A string representing the path of the referenced document (relative to the root of the database). | +| [type](./firestore_pipelines.documentreference.md#documentreferencetype) | | (not declared) | The type of this Firestore reference. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [fromJSON(firestore, json)](./firestore_pipelines.documentreference.md#documentreferencefromjson) | static | Builds a DocumentReference instance from a JSON object created by [DocumentReference.toJSON()](./firestore_.documentreference.md#documentreferencetojson). | +| [fromJSON(firestore, json, converter)](./firestore_pipelines.documentreference.md#documentreferencefromjson) | static | Builds a DocumentReference instance from a JSON object created by [DocumentReference.toJSON()](./firestore_.documentreference.md#documentreferencetojson). | +| [toJSON()](./firestore_pipelines.documentreference.md#documentreferencetojson) | | Returns a JSON-serializable representation of this DocumentReference instance. | +| [withConverter(converter)](./firestore_pipelines.documentreference.md#documentreferencewithconverter) | | Applies a custom data converter to this DocumentReference, allowing you to use your own custom model objects with Firestore. When you call [setDoc()](./firestore_lite.md#setdoc_ee215ad), [getDoc()](./firestore_lite.md#getdoc_4569087), etc. with the returned DocumentReference instance, the provided converter will convert between Firestore data of type NewDbModelType and your custom type NewAppModelType. | +| [withConverter(converter)](./firestore_pipelines.documentreference.md#documentreferencewithconverter) | | Removes the current converter. | + +## DocumentReference.converter + +If provided, the `FirestoreDataConverter` associated with this instance. + +Signature: + +```typescript +readonly converter: FirestoreDataConverter | null; +``` + +## DocumentReference.firestore + +The [Firestore](./firestore_.firestore.md#firestore_class) instance the document is in. This is useful for performing transactions, for example. + +Signature: + +```typescript +readonly firestore: Firestore; +``` + +## DocumentReference.id + +The document's identifier within its collection. + +Signature: + +```typescript +get id(): string; +``` + +## DocumentReference.parent + +The collection this `DocumentReference` belongs to. + +Signature: + +```typescript +get parent(): CollectionReference; +``` + +## DocumentReference.path + +A string representing the path of the referenced document (relative to the root of the database). + +Signature: + +```typescript +get path(): string; +``` + +## DocumentReference.type + +The type of this Firestore reference. + +Signature: + +```typescript +readonly type = "document"; +``` + +## DocumentReference.fromJSON() + +Builds a `DocumentReference` instance from a JSON object created by [DocumentReference.toJSON()](./firestore_.documentreference.md#documentreferencetojson). + +Signature: + +```typescript +static fromJSON(firestore: Firestore, json: object): DocumentReference; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| firestore | [Firestore](./firestore_.firestore.md#firestore_class) | The [Firestore](./firestore_.firestore.md#firestore_class) instance the snapshot should be loaded for. | +| json | object | a JSON object represention of a DocumentReference instance | + +Returns: + +[DocumentReference](./firestore_.documentreference.md#documentreference_class) + +an instance of [DocumentReference](./firestore_.documentreference.md#documentreference_class) if the JSON object could be parsed. Throws a [FirestoreError](./firestore_.firestoreerror.md#firestoreerror_class) if an error occurs. + +## DocumentReference.fromJSON() + +Builds a `DocumentReference` instance from a JSON object created by [DocumentReference.toJSON()](./firestore_.documentreference.md#documentreferencetojson). + +Signature: + +```typescript +static fromJSON(firestore: Firestore, json: object, converter: FirestoreDataConverter): DocumentReference; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| firestore | [Firestore](./firestore_.firestore.md#firestore_class) | The [Firestore](./firestore_.firestore.md#firestore_class) instance the snapshot should be loaded for. | +| json | object | a JSON object represention of a DocumentReference instance | +| converter | [FirestoreDataConverter](./firestore_.firestoredataconverter.md#firestoredataconverter_interface)<NewAppModelType, NewDbModelType> | Converts objects to and from Firestore. | + +Returns: + +[DocumentReference](./firestore_.documentreference.md#documentreference_class)<NewAppModelType, NewDbModelType> + +an instance of [DocumentReference](./firestore_.documentreference.md#documentreference_class) if the JSON object could be parsed. Throws a [FirestoreError](./firestore_.firestoreerror.md#firestoreerror_class) if an error occurs. + +## DocumentReference.toJSON() + +Returns a JSON-serializable representation of this `DocumentReference` instance. + +Signature: + +```typescript +toJSON(): object; +``` +Returns: + +object + +a JSON representation of this object. + +## DocumentReference.withConverter() + +Applies a custom data converter to this `DocumentReference`, allowing you to use your own custom model objects with Firestore. When you call [setDoc()](./firestore_lite.md#setdoc_ee215ad), [getDoc()](./firestore_lite.md#getdoc_4569087), etc. with the returned `DocumentReference` instance, the provided converter will convert between Firestore data of type `NewDbModelType` and your custom type `NewAppModelType`. + +Signature: + +```typescript +withConverter(converter: FirestoreDataConverter): DocumentReference; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| converter | [FirestoreDataConverter](./firestore_.firestoredataconverter.md#firestoredataconverter_interface)<NewAppModelType, NewDbModelType> | Converts objects to and from Firestore. | + +Returns: + +[DocumentReference](./firestore_.documentreference.md#documentreference_class)<NewAppModelType, NewDbModelType> + +A `DocumentReference` that uses the provided converter. + +## DocumentReference.withConverter() + +Removes the current converter. + +Signature: + +```typescript +withConverter(converter: null): DocumentReference; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| converter | null | null removes the current converter. | + +Returns: + +[DocumentReference](./firestore_.documentreference.md#documentreference_class)<[DocumentData](./firestore_.documentdata.md#documentdata_interface), [DocumentData](./firestore_.documentdata.md#documentdata_interface)> + +A `DocumentReference` that does not use a converter. + diff --git a/docs-devsite/firestore_pipelines.documentsnapshot.md b/docs-devsite/firestore_pipelines.documentsnapshot.md new file mode 100644 index 0000000000..59752e41fc --- /dev/null +++ b/docs-devsite/firestore_pipelines.documentsnapshot.md @@ -0,0 +1,162 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# DocumentSnapshot class +A `DocumentSnapshot` contains data read from a document in your Firestore database. The data can be extracted with `.data()` or `.get()` to get a specific field. + +For a `DocumentSnapshot` that points to a non-existing document, any data access will return 'undefined'. You can use the `exists()` method to explicitly verify a document's existence. + +Signature: + +```typescript +export declare class DocumentSnapshot +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)()](./firestore_pipelines.documentsnapshot.md#documentsnapshotconstructor) | | Constructs a new instance of the DocumentSnapshot class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [id](./firestore_pipelines.documentsnapshot.md#documentsnapshotid) | | string | Property of the DocumentSnapshot that provides the document's ID. | +| [metadata](./firestore_pipelines.documentsnapshot.md#documentsnapshotmetadata) | | [SnapshotMetadata](./firestore_.snapshotmetadata.md#snapshotmetadata_class) | Metadata about the DocumentSnapshot, including information about its source and local modifications. | +| [ref](./firestore_pipelines.documentsnapshot.md#documentsnapshotref) | | [DocumentReference](./firestore_.documentreference.md#documentreference_class)<AppModelType, DbModelType> | The DocumentReference for the document included in the DocumentSnapshot. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [data(options)](./firestore_pipelines.documentsnapshot.md#documentsnapshotdata) | | Retrieves all fields in the document as an Object. Returns undefined if the document doesn't exist.By default, serverTimestamp() values that have not yet been set to their final value will be returned as null. You can override this by passing an options object. | +| [exists()](./firestore_pipelines.documentsnapshot.md#documentsnapshotexists) | | Returns whether or not the data exists. True if the document exists. | +| [get(fieldPath, options)](./firestore_pipelines.documentsnapshot.md#documentsnapshotget) | | Retrieves the field specified by fieldPath. Returns undefined if the document or field doesn't exist.By default, a serverTimestamp() that has not yet been set to its final value will be returned as null. You can override this by passing an options object. | +| [toJSON()](./firestore_pipelines.documentsnapshot.md#documentsnapshottojson) | | Returns a JSON-serializable representation of this DocumentSnapshot instance. | + +## DocumentSnapshot.(constructor) + +Constructs a new instance of the `DocumentSnapshot` class + +Signature: + +```typescript +protected constructor(); +``` + +## DocumentSnapshot.id + +Property of the `DocumentSnapshot` that provides the document's ID. + +Signature: + +```typescript +get id(): string; +``` + +## DocumentSnapshot.metadata + +Metadata about the `DocumentSnapshot`, including information about its source and local modifications. + +Signature: + +```typescript +readonly metadata: SnapshotMetadata; +``` + +## DocumentSnapshot.ref + +The `DocumentReference` for the document included in the `DocumentSnapshot`. + +Signature: + +```typescript +get ref(): DocumentReference; +``` + +## DocumentSnapshot.data() + +Retrieves all fields in the document as an `Object`. Returns `undefined` if the document doesn't exist. + +By default, `serverTimestamp()` values that have not yet been set to their final value will be returned as `null`. You can override this by passing an options object. + +Signature: + +```typescript +data(options?: SnapshotOptions): AppModelType | undefined; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [SnapshotOptions](./firestore_.snapshotoptions.md#snapshotoptions_interface) | An options object to configure how data is retrieved from the snapshot (for example the desired behavior for server timestamps that have not yet been set to their final value). | + +Returns: + +AppModelType \| undefined + +An `Object` containing all fields in the document or `undefined` if the document doesn't exist. + +## DocumentSnapshot.exists() + +Returns whether or not the data exists. True if the document exists. + +Signature: + +```typescript +exists(): this is QueryDocumentSnapshot; +``` +Returns: + +this is [QueryDocumentSnapshot](./firestore_.querydocumentsnapshot.md#querydocumentsnapshot_class)<AppModelType, DbModelType> + +## DocumentSnapshot.get() + +Retrieves the field specified by `fieldPath`. Returns `undefined` if the document or field doesn't exist. + +By default, a `serverTimestamp()` that has not yet been set to its final value will be returned as `null`. You can override this by passing an options object. + +Signature: + +```typescript +get(fieldPath: string | FieldPath, options?: SnapshotOptions): any; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldPath | string \| [FieldPath](./firestore_.fieldpath.md#fieldpath_class) | The path (for example 'foo' or 'foo.bar') to a specific field. | +| options | [SnapshotOptions](./firestore_.snapshotoptions.md#snapshotoptions_interface) | An options object to configure how the field is retrieved from the snapshot (for example the desired behavior for server timestamps that have not yet been set to their final value). | + +Returns: + +any + +The data at the specified field location or undefined if no such field exists in the document. + +## DocumentSnapshot.toJSON() + +Returns a JSON-serializable representation of this `DocumentSnapshot` instance. + +Signature: + +```typescript +toJSON(): object; +``` +Returns: + +object + +a JSON representation of this object. Throws a [FirestoreError](./firestore_.firestoreerror.md#firestoreerror_class) if this `DocumentSnapshot` has pending writes. + diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md new file mode 100644 index 0000000000..c082bbfd5f --- /dev/null +++ b/docs-devsite/firestore_pipelines.expression.md @@ -0,0 +1,4173 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Expression class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Represents an expression that can be evaluated to a value within the execution of a . + +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 `Expr` class provides a fluent API for building expressions. You can chain together method calls to create complex expressions. + +Signature: + +```typescript +export declare abstract class Expression +``` + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [expressionType](./firestore_pipelines.expression.md#expressionexpressiontype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [abs()](./firestore_pipelines.expression.md#expressionabs) | | (Public Preview) Creates an expression that computes the absolute value of a numeric value. +```typescript +// Compute the absolute value of the 'price' field. +field("price").abs(); + +``` + A new representing the absolute value of the numeric value. | +| [add(second)](./firestore_pipelines.expression.md#expressionadd) | | (Public Preview) Creates an expression that adds this expression to another expression. +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +field("quantity").add(field("reserve")); + +``` + | +| [arrayConcat(secondArray, otherArrays)](./firestore_pipelines.expression.md#expressionarrayconcat) | | (Public Preview) Creates an expression that concatenates an array expression with one or more other arrays. +```typescript +// Combine the 'items' array with another array field. +field("items").arrayConcat(field("otherItems")); + +``` + | +| [arrayContains(expression)](./firestore_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific element. +```typescript +// Check if the 'sizes' array contains the value from the 'selectedSize' field +field("sizes").arrayContains(field("selectedSize")); + +``` + | +| [arrayContains(value)](./firestore_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific value. +```typescript +// Check if the 'colors' array contains "red" +field("colors").arrayContains("red"); + +``` + | +| [arrayContainsAll(values)](./firestore_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. +```typescript +// Check if the 'tags' array contains both the value in field "tag1" and the literal value "tag2" +field("tags").arrayContainsAll([field("tag1"), "tag2"]); + +``` + | +| [arrayContainsAll(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. +```typescript +// Check if the 'tags' array contains both of the values from field "tag1" and the literal value "tag2" +field("tags").arrayContainsAll(array([field("tag1"), "tag2"])); + +``` + | +| [arrayContainsAny(values)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. +```typescript +// Check if the 'categories' array contains either values from field "cate1" or "cate2" +field("categories").arrayContainsAny([field("cate1"), field("cate2")]); + +``` + | +| [arrayContainsAny(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. +```typescript +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); + +``` + | +| [arrayGet(offset)](./firestore_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +```typescript +// Return the value in the 'tags' field array at index `1`. +field('tags').arrayGet(1); + +``` + | +| [arrayGet(offsetExpr)](./firestore_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +field('tags').arrayGet(field('favoriteTag')); + +``` + | +| [arrayLength()](./firestore_pipelines.expression.md#expressionarraylength) | | (Public Preview) Creates an expression that calculates the length of an array. +```typescript +// Get the number of items in the 'cart' array +field("cart").arrayLength(); + +``` + A new Expr representing the length of the array. | +| [arrayReverse()](./firestore_pipelines.expression.md#expressionarrayreverse) | | (Public Preview) Creates an expression that reverses an array. +```typescript +// Reverse the value of the 'myArray' field. +field("myArray").arrayReverse(); + +``` + A new representing the reversed array. | +| [arraySum()](./firestore_pipelines.expression.md#expressionarraysum) | | (Public Preview) Creates an expression that computes the sum of the elements in an array. +```typescript +// Compute the sum of the elements in the 'scores' field. +field("scores").arraySum(); + +``` + A new representing the sum of the elements in the array. | +| [as(name)](./firestore_pipelines.expression.md#expressionas) | | (Public Preview) 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. +```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")); + +``` + | +| [asBoolean()](./firestore_pipelines.expression.md#expressionasboolean) | | (Public Preview) Wraps the expression in a \[BooleanExpression\]. A \[BooleanExpression\] representing the same expression. | +| [ascending()](./firestore_pipelines.expression.md#expressionascending) | | (Public Preview) Creates an that sorts documents in ascending order based on this expression. +```typescript +// Sort documents by the 'name' field in ascending order +pipeline().collection("users") + .sort(field("name").ascending()); + +``` + A new Ordering for ascending sorting. | +| [average()](./firestore_pipelines.expression.md#expressionaverage) | | (Public Preview) Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. +```typescript +// Calculate the average age of users +field("age").average().as("averageAge"); + +``` + A new AggregateFunction representing the 'average' aggregation. | +| [byteLength()](./firestore_pipelines.expression.md#expressionbytelength) | | (Public Preview) Creates an expression that calculates the length of this string expression in bytes. +```typescript +// Calculate the length of the 'myString' field in bytes. +field("myString").byteLength(); + +``` + A new representing the length of the string in bytes. | +| [ceil()](./firestore_pipelines.expression.md#expressionceil) | | (Public Preview) Creates an expression that computes the ceiling of a numeric value. +```typescript +// Compute the ceiling of the 'price' field. +field("price").ceil(); + +``` + A new representing the ceiling of the numeric value. | +| [charLength()](./firestore_pipelines.expression.md#expressioncharlength) | | (Public Preview) Creates an expression that calculates the character length of a string in UTF-8. +```typescript +// Get the character length of the 'name' field in its UTF-8 form. +field("name").charLength(); + +``` + A new Expr representing the length of the string. | +| [collectionId()](./firestore_pipelines.expression.md#expressioncollectionid) | | (Public Preview) Creates an expression that returns the collection ID from a path. +```typescript +// Get the collection ID from a path. +field("__path__").collectionId(); + +``` + A new representing the collectionId operation. | +| [concat(second, others)](./firestore_pipelines.expression.md#expressionconcat) | | (Public Preview) Creates an expression that concatenates expression results together. +```typescript +// Combine the 'firstName', ' ', and 'lastName' fields into a single value. +field("firstName").concat(constant(" "), field("lastName")); + +``` + | +| [cosineDistance(vectorExpression)](./firestore_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the cosine distance between two vectors. +```typescript +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +field("userVector").cosineDistance(field("itemVector")); + +``` + | +| [cosineDistance(vector)](./firestore_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the Cosine distance between two vectors. +```typescript +// Calculate the Cosine distance between the 'location' field and a target location +field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); + +``` + | +| [count()](./firestore_pipelines.expression.md#expressioncount) | | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. +```typescript +// Count the total number of products +field("productId").count().as("totalProducts"); + +``` + A new AggregateFunction representing the 'count' aggregation. | +| [countDistinct()](./firestore_pipelines.expression.md#expressioncountdistinct) | | (Public Preview) Creates an aggregation that counts the number of distinct values of the expression or field. +```typescript +// Count the distinct number of products +field("productId").countDistinct().as("distinctProducts"); + +``` + A new AggregateFunction representing the 'count\_distinct' aggregation. | +| [descending()](./firestore_pipelines.expression.md#expressiondescending) | | (Public Preview) Creates an that sorts documents in descending order based on this expression. +```typescript +// Sort documents by the 'createdAt' field in descending order +firestore.pipeline().collection("users") + .sort(field("createdAt").descending()); + +``` + A new Ordering for descending sorting. | +| [divide(divisor)](./firestore_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by another expression. +```typescript +// Divide the 'total' field by the 'count' field +field("total").divide(field("count")); + +``` + | +| [divide(divisor)](./firestore_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by a constant value. +```typescript +// Divide the 'value' field by 10 +field("value").divide(10); + +``` + | +| [documentId()](./firestore_pipelines.expression.md#expressiondocumentid) | | (Public Preview) Creates an expression that returns the document ID from a path. +```typescript +// Get the document ID from a path. +field("__path__").documentId(); + +``` + A new representing the documentId operation. | +| [dotProduct(vectorExpression)](./firestore_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. +```typescript +// Calculate the dot product between a feature vector and a target vector +field("features").dotProduct([0.5, 0.8, 0.2]); + +``` + | +| [dotProduct(vector)](./firestore_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. +```typescript +// Calculate the dot product between a feature vector and a target vector +field("features").dotProduct(new VectorValue([0.5, 0.8, 0.2])); + +``` + | +| [endsWith(suffix)](./firestore_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix. +```typescript +// Check if the 'filename' field ends with ".txt" +field("filename").endsWith(".txt"); + +``` + | +| [endsWith(suffix)](./firestore_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix (represented as an expression). +```typescript +// Check if the 'url' field ends with the value of the 'extension' field +field("url").endsWith(field("extension")); + +``` + | +| [equal(expression)](./firestore_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to another expression. +```typescript +// Check if the 'age' field is equal to 21 +field("age").equal(21); + +``` + | +| [equal(value)](./firestore_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to a constant value. +```typescript +// Check if the 'city' field is equal to "London" +field("city").equal("London"); + +``` + | +| [equalAny(values)](./firestore_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +field("category").equalAny("Electronics", field("primaryType")); + +``` + | +| [equalAny(arrayExpression)](./firestore_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +field("category").equalAny(array(["Electronics", field("primaryType")])); + +``` + | +| [euclideanDistance(vectorExpression)](./firestore_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location +field("location").euclideanDistance([37.7749, -122.4194]); + +``` + | +| [euclideanDistance(vector)](./firestore_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location +field("location").euclideanDistance(new VectorValue([37.7749, -122.4194])); + +``` + | +| [exists()](./firestore_pipelines.expression.md#expressionexists) | | (Public Preview) Creates an expression that checks if a field exists in the document. +```typescript +// Check if the document has a field named "phoneNumber" +field("phoneNumber").exists(); + +``` + A new Expr representing the 'exists' check. | +| [exp()](./firestore_pipelines.expression.md#expressionexp) | | (Public Preview) Creates an expression that computes e to the power of this expression. +```typescript +// Compute e to the power of the 'value' field. +field("value").exp(); + +``` + A new representing the exp of the numeric value. | +| [floor()](./firestore_pipelines.expression.md#expressionfloor) | | (Public Preview) Creates an expression that computes the floor of a numeric value. +```typescript +// Compute the floor of the 'price' field. +field("price").floor(); + +``` + A new representing the floor of the numeric value. | +| [greaterThan(expression)](./firestore_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than another expression. +```typescript +// Check if the 'age' field is greater than the 'limit' field +field("age").greaterThan(field("limit")); + +``` + | +| [greaterThan(value)](./firestore_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than a constant value. +```typescript +// Check if the 'price' field is greater than 100 +field("price").greaterThan(100); + +``` + | +| [greaterThanOrEqual(expression)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to another expression. +```typescript +// Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1 +field("quantity").greaterThanOrEqual(field('requirement').add(1)); + +``` + | +| [greaterThanOrEqual(value)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to a constant value. +```typescript +// Check if the 'score' field is greater than or equal to 80 +field("score").greaterThanOrEqual(80); + +``` + | +| [ifAbsent(elseValue)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of the this expression evaluation. +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +field("optional_field").ifAbsent("default_value") + +``` + | +| [ifAbsent(elseExpression)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. +```typescript +// Returns the value of the optional field 'optional_field', or if that is +// absent, then returns the value of the field ` +field("optional_field").ifAbsent(field('default_field')) + +``` + | +| [ifError(catchExpr)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. +```typescript +// Returns the first item in the title field arrays, or returns +// the entire title field if the array is empty or the field is another type. +field("title").arrayGet(0).ifError(field("title")); + +``` + | +| [ifError(catchValue)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. +```typescript +// Returns the first item in the title field arrays, or returns +// "Default Title" +field("title").arrayGet(0).ifError("Default Title"); + +``` + | +| [isAbsent()](./firestore_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. +```typescript +// Check if the field `value` is absent. +field("value").isAbsent(); + +``` + A new representing the 'isAbsent' check. | +| [isError()](./firestore_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. +```typescript +// Check if the result of a calculation is an error +field("title").arrayContains(1).isError(); + +``` + A new representing the 'isError' check. | +| [join(delimiterExpression)](./firestore_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array into a string. +```typescript +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +field("tags").join(field("separator")) + +``` + | +| [join(delimiter)](./firestore_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array field into a string. +```typescript +// Join the elements of the 'tags' field with a comma and space. +field("tags").join(", ") + +``` + | +| [length()](./firestore_pipelines.expression.md#expressionlength) | | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. +```typescript +// Get the length of the 'name' field. +field("name").length(); + +// Get the number of items in the 'cart' array. +field("cart").length(); + +``` + A new Expr representing the length of the string, array, map, vector, or bytes. | +| [lessThan(experession)](./firestore_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than another expression. +```typescript +// Check if the 'age' field is less than 'limit' +field("age").lessThan(field('limit')); + +``` + | +| [lessThan(value)](./firestore_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than a constant value. +```typescript +// Check if the 'price' field is less than 50 +field("price").lessThan(50); + +``` + | +| [lessThanOrEqual(expression)](./firestore_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to another expression. +```typescript +// Check if the 'quantity' field is less than or equal to 20 +field("quantity").lessThan(constant(20)); + +``` + | +| [lessThanOrEqual(value)](./firestore_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to a constant value. +```typescript +// Check if the 'score' field is less than or equal to 70 +field("score").lessThan(70); + +``` + | +| [like(pattern)](./firestore_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. +```typescript +// Check if the 'title' field contains the word "guide" (case-sensitive) +field("title").like("%guide%"); + +``` + | +| [like(pattern)](./firestore_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. +```typescript +// Check if the 'title' field contains the word "guide" (case-sensitive) +field("title").like("%guide%"); + +``` + | +| [ln()](./firestore_pipelines.expression.md#expressionln) | | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. +```typescript +// Compute the natural logarithm of the 'value' field. +field("value").ln(); + +``` + A new representing the natural logarithm of the numeric value. | +| [log10()](./firestore_pipelines.expression.md#expressionlog10) | | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. +```typescript +// Compute the base-10 logarithm of the 'value' field. +field("value").log10(); + +``` + A new representing the base-10 logarithm of the numeric value. | +| [logicalMaximum(second, others)](./firestore_pipelines.expression.md#expressionlogicalmaximum) | | (Public Preview) Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. +```typescript +// Returns the larger value between the 'timestamp' field and the current timestamp. +field("timestamp").logicalMaximum(Function.currentTimestamp()); + +``` + | +| [logicalMinimum(second, others)](./firestore_pipelines.expression.md#expressionlogicalminimum) | | (Public Preview) Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. +```typescript +// Returns the smaller value between the 'timestamp' field and the current timestamp. +field("timestamp").logicalMinimum(Function.currentTimestamp()); + +``` + | +| [mapGet(subfield)](./firestore_pipelines.expression.md#expressionmapget) | | (Public Preview) Accesses a value from a map (object) field using the provided key. +```typescript +// Get the 'city' value from the 'address' map field +field("address").mapGet("city"); + +``` + | +| [mapMerge(secondMap, otherMaps)](./firestore_pipelines.expression.md#expressionmapmerge) | | (Public Preview) Creates an expression that merges multiple map values. +``` +// 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}, {}) + +``` + | +| [mapRemove(key)](./firestore_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. +``` +// Removes the key 'baz' from the input map. +map({foo: 'bar', baz: true}).mapRemove('baz'); + +``` + | +| [mapRemove(keyExpr)](./firestore_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. +``` +// Removes the key 'baz' from the input map. +map({foo: 'bar', baz: true}).mapRemove(constant('baz')); + +``` + | +| [maximum()](./firestore_pipelines.expression.md#expressionmaximum) | | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. +```typescript +// Find the highest score in a leaderboard +field("score").maximum().as("highestScore"); + +``` + A new AggregateFunction representing the 'maximum' aggregation. | +| [minimum()](./firestore_pipelines.expression.md#expressionminimum) | | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. +```typescript +// Find the lowest price of all products +field("price").minimum().as("lowestPrice"); + +``` + A new AggregateFunction representing the 'minimum' aggregation. | +| [mod(expression)](./firestore_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. +```typescript +// Calculate the remainder of dividing the 'value' field by the 'divisor' field +field("value").mod(field("divisor")); + +``` + | +| [mod(value)](./firestore_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. +```typescript +// Calculate the remainder of dividing the 'value' field by 10 +field("value").mod(10); + +``` + | +| [multiply(second)](./firestore_pipelines.expression.md#expressionmultiply) | | (Public Preview) Creates an expression that multiplies this expression by another expression. +```typescript +// Multiply the 'quantity' field by the 'price' field +field("quantity").multiply(field("price")); + +``` + | +| [notEqual(expression)](./firestore_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to another expression. +```typescript +// Check if the 'status' field is not equal to "completed" +field("status").notEqual("completed"); + +``` + | +| [notEqual(value)](./firestore_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to a constant value. +```typescript +// Check if the 'country' field is not equal to "USA" +field("country").notEqual("USA"); + +``` + | +| [notEqualAny(values)](./firestore_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the provided values or expressions. +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +field("status").notEqualAny(["pending", field("rejectedStatus")]); + +``` + | +| [notEqualAny(arrayExpression)](./firestore_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. +```typescript +// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' +field("status").notEqualAny(field('rejectedStatuses')); + +``` + | +| [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of another expression. +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +field("base").pow(field("exponent")); + +``` + | +| [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of a constant value. +```typescript +// Raise the value of the 'base' field to the power of 2. +field("base").pow(2); + +``` + | +| [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +field("description").regexContains("(?i)example"); + +``` + | +| [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. +```typescript +// Check if the 'description' field contains the regular expression stored in field 'regex' +field("description").regexContains(field("regex")); + +``` + | +| [regexMatch(pattern)](./firestore_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. +```typescript +// Check if the 'email' field matches a valid email pattern +field("email").regexMatch("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + +``` + | +| [regexMatch(pattern)](./firestore_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. +```typescript +// Check if the 'email' field matches a regular expression stored in field 'regex' +field("email").regexMatch(field("regex")); + +``` + | +| [reverse()](./firestore_pipelines.expression.md#expressionreverse) | | (Public Preview) Creates an expression that reverses this string expression. +```typescript +// Reverse the value of the 'myString' field. +field("myString").reverse(); + +``` + A new representing the reversed string. | +| [round()](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. +```typescript +// Round the value of the 'price' field. +field("price").round(); + +``` + A new Expr representing the rounded value. | +| [round(decimalPlaces)](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. +```typescript +// Round the value of the 'price' field to two decimal places. +field("price").round(2); + +``` + | +| [round(decimalPlaces)](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. +```typescript +// Round the value of the 'price' field to two decimal places. +field("price").round(constant(2)); + +``` + | +| [split(delimiter)](./firestore_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | +| [split(delimiter)](./firestore_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | +| [sqrt()](./firestore_pipelines.expression.md#expressionsqrt) | | (Public Preview) Creates an expression that computes the square root of a numeric value. +```typescript +// Compute the square root of the 'value' field. +field("value").sqrt(); + +``` + A new representing the square root of the numeric value. | +| [startsWith(prefix)](./firestore_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix. +```typescript +// Check if the 'name' field starts with "Mr." +field("name").startsWith("Mr."); + +``` + | +| [startsWith(prefix)](./firestore_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix (represented as an expression). +```typescript +// Check if the 'fullName' field starts with the value of the 'firstName' field +field("fullName").startsWith(field("firstName")); + +``` + | +| [stringConcat(secondString, otherStrings)](./firestore_pipelines.expression.md#expressionstringconcat) | | (Public Preview) Creates an expression that concatenates string expressions together. +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +field("firstName").stringConcat(constant(" "), field("lastName")); + +``` + | +| [stringContains(substring)](./firestore_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified substring. +```typescript +// Check if the 'description' field contains "example". +field("description").stringContains("example"); + +``` + | +| [stringContains(expr)](./firestore_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains the string represented by another expression. +```typescript +// Check if the 'description' field contains the value of the 'keyword' field. +field("description").stringContains(field("keyword")); + +``` + | +| [stringReverse()](./firestore_pipelines.expression.md#expressionstringreverse) | | (Public Preview) Creates an expression that reverses a string. +```typescript +// Reverse the value of the 'myString' field. +field("myString").stringReverse(); + +``` + A new representing the reversed string. | +| [substring(position, length)](./firestore_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | +| [substring(position, length)](./firestore_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | +| [subtract(subtrahend)](./firestore_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts another expression from this expression. +```typescript +// Subtract the 'discount' field from the 'price' field +field("price").subtract(field("discount")); + +``` + | +| [subtract(subtrahend)](./firestore_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts a constant value from this expression. +```typescript +// Subtract 20 from the value of the 'total' field +field("total").subtract(20); + +``` + | +| [sum()](./firestore_pipelines.expression.md#expressionsum) | | (Public Preview) Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. +```typescript +// Calculate the total revenue from a set of orders +field("orderAmount").sum().as("totalRevenue"); + +``` + A new AggregateFunction representing the 'sum' aggregation. | +| [timestampAdd(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. +```typescript +// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. +field("timestamp").timestampAdd(field("unit"), field("amount")); + +``` + | +| [timestampAdd(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. +```typescript +// Add 1 day to the 'timestamp' field. +field("timestamp").timestampAdd("day", 1); + +``` + | +| [timestampSubtract(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. +```typescript +// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. +field("timestamp").timestampSubtract(field("unit"), field("amount")); + +``` + | +| [timestampSubtract(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. +```typescript +// Subtract 1 day from the 'timestamp' field. +field("timestamp").timestampSubtract("day", 1); + +``` + | +| [timestampToUnixMicros()](./firestore_pipelines.expression.md#expressiontimestamptounixmicros) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +field("timestamp").timestampToUnixMicros(); + +``` + A new representing the number of microseconds since epoch. | +| [timestampToUnixMillis()](./firestore_pipelines.expression.md#expressiontimestamptounixmillis) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +field("timestamp").timestampToUnixMillis(); + +``` + A new representing the number of milliseconds since epoch. | +| [timestampToUnixSeconds()](./firestore_pipelines.expression.md#expressiontimestamptounixseconds) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to seconds since epoch. +field("timestamp").timestampToUnixSeconds(); + +``` + A new representing the number of seconds since epoch. | +| [timestampTruncate(granularity, timezone)](./firestore_pipelines.expression.md#expressiontimestamptruncate) | | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(granularity, timezone)](./firestore_pipelines.expression.md#expressiontimestamptruncate) | | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [toLower()](./firestore_pipelines.expression.md#expressiontolower) | | (Public Preview) Creates an expression that converts a string to lowercase. +```typescript +// Convert the 'name' field to lowercase +field("name").toLower(); + +``` + A new Expr representing the lowercase string. | +| [toUpper()](./firestore_pipelines.expression.md#expressiontoupper) | | (Public Preview) Creates an expression that converts a string to uppercase. +```typescript +// Convert the 'title' field to uppercase +field("title").toUpper(); + +``` + A new Expr representing the uppercase string. | +| [trim(valueToTrim)](./firestore_pipelines.expression.md#expressiontrim) | | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array. +```typescript +// Trim whitespace from the 'userInput' field +field("userInput").trim(); + +// Trim quotes from the 'userInput' field +field("userInput").trim('"'); + +``` + | +| [type()](./firestore_pipelines.expression.md#expressiontype) | | (Public Preview) Creates an expression that returns the data type of this expression's result, as a string. | +| [unixMicrosToTimestamp()](./firestore_pipelines.expression.md#expressionunixmicrostotimestamp) | | (Public Preview) 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. +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +field("microseconds").unixMicrosToTimestamp(); + +``` + A new representing the timestamp. | +| [unixMillisToTimestamp()](./firestore_pipelines.expression.md#expressionunixmillistotimestamp) | | (Public Preview) 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. +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +field("milliseconds").unixMillisToTimestamp(); + +``` + A new representing the timestamp. | +| [unixSecondsToTimestamp()](./firestore_pipelines.expression.md#expressionunixsecondstotimestamp) | | (Public Preview) 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. +```typescript +// Interpret the 'seconds' field as seconds since epoch. +field("seconds").unixSecondsToTimestamp(); + +``` + A new representing the timestamp. | +| [vectorLength()](./firestore_pipelines.expression.md#expressionvectorlength) | | (Public Preview) Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. +```typescript +// Get the vector length (dimension) of the field 'embedding'. +field("embedding").vectorLength(); + +``` + A new representing the length of the vector. | + +## Expression.expressionType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +abstract readonly expressionType: ExpressionType; +``` + +## Expression.abs() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the absolute value of a numeric value. + +```typescript +// Compute the absolute value of the 'price' field. +field("price").abs(); + +``` + A new representing the absolute value of the numeric value. + +Signature: + +```typescript +abs(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.add() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds this expression to another expression. + +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +field("quantity").add(field("reserve")); + +``` + +Signature: + +```typescript +add(second: Expression | unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The expression or literal to add to this expression. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.arrayConcat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates an array expression with one or more other arrays. + +```typescript +// Combine the 'items' array with another array field. +field("items").arrayConcat(field("otherItems")); + +``` + +Signature: + +```typescript +arrayConcat(secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| secondArray | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\] | Second array expression or array literal to concatenate. | +| otherArrays | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. A new Expr representing the concatenated array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.arrayContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains a specific element. + +```typescript +// Check if the 'sizes' array contains the value from the 'selectedSize' field +field("sizes").arrayContains(field("selectedSize")); + +``` + +Signature: + +```typescript +arrayContains(expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The element to search for in the array. A new Expr representing the 'array\_contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.arrayContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains a specific value. + +```typescript +// Check if the 'colors' array contains "red" +field("colors").arrayContains("red"); + +``` + +Signature: + +```typescript +arrayContains(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The element to search for in the array. A new Expr representing the 'array\_contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.arrayContainsAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains all the specified elements. + +```typescript +// Check if the 'tags' array contains both the value in field "tag1" and the literal value "tag2" +field("tags").arrayContainsAll([field("tag1"), "tag2"]); + +``` + +Signature: + +```typescript +arrayContainsAll(values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new Expr representing the 'array\_contains\_all' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.arrayContainsAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains all the specified elements. + +```typescript +// Check if the 'tags' array contains both of the values from field "tag1" and the literal value "tag2" +field("tags").arrayContainsAll(array([field("tag1"), "tag2"])); + +``` + +Signature: + +```typescript +arrayContainsAll(arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. A new Expr representing the 'array\_contains\_all' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.arrayContainsAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains any of the specified elements. + +```typescript +// Check if the 'categories' array contains either values from field "cate1" or "cate2" +field("categories").arrayContainsAny([field("cate1"), field("cate2")]); + +``` + +Signature: + +```typescript +arrayContainsAny(values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new Expr representing the 'array\_contains\_any' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.arrayContainsAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains any of the specified elements. + +```typescript +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); + +``` + +Signature: + +```typescript +arrayContainsAny(arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. A new Expr representing the 'array\_contains\_any' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.arrayGet() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + +```typescript +// Return the value in the 'tags' field array at index `1`. +field('tags').arrayGet(1); + +``` + +Signature: + +```typescript +arrayGet(offset: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| offset | number | The index of the element to return. A new Expr representing the 'arrayGet' operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.arrayGet() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +field('tags').arrayGet(field('favoriteTag')); + +``` + +Signature: + +```typescript +arrayGet(offsetExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expr evaluating to the index of the element to return. A new Expr representing the 'arrayGet' operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.arrayLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of an array. + +```typescript +// Get the number of items in the 'cart' array +field("cart").arrayLength(); + +``` + A new `Expr` representing the length of the array. + +Signature: + +```typescript +arrayLength(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.arrayReverse() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses an array. + +```typescript +// Reverse the value of the 'myArray' field. +field("myArray").arrayReverse(); + +``` + A new representing the reversed array. + +Signature: + +```typescript +arrayReverse(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.arraySum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. + +```typescript +// Compute the sum of the elements in the 'scores' field. +field("scores").arraySum(); + +``` + A new representing the sum of the elements in the array. + +Signature: + +```typescript +arraySum(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.as() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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. + +```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")); + +``` + +Signature: + +```typescript +as(name: string): AliasedExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | The alias to assign to this expression. A new that wraps this expression and associates it with the provided alias. | + +Returns: + +[AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class) + +## Expression.asBoolean() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Wraps the expression in a \[BooleanExpression\]. + + A \[BooleanExpression\] representing the same expression. + +Signature: + +```typescript +asBoolean(): BooleanExpression; +``` +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.ascending() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an that sorts documents in ascending order based on this expression. + +```typescript +// Sort documents by the 'name' field in ascending order +pipeline().collection("users") + .sort(field("name").ascending()); + +``` + A new `Ordering` for ascending sorting. + +Signature: + +```typescript +ascending(): Ordering; +``` +Returns: + +[Ordering](./firestore_pipelines.ordering.md#ordering_class) + +## Expression.average() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. + +```typescript +// Calculate the average age of users +field("age").average().as("averageAge"); + +``` + A new `AggregateFunction` representing the 'average' aggregation. + +Signature: + +```typescript +average(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +## Expression.byteLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of this string expression in bytes. + +```typescript +// Calculate the length of the 'myString' field in bytes. +field("myString").byteLength(); + +``` + A new representing the length of the string in bytes. + +Signature: + +```typescript +byteLength(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.ceil() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. + +```typescript +// Compute the ceiling of the 'price' field. +field("price").ceil(); + +``` + A new representing the ceiling of the numeric value. + +Signature: + +```typescript +ceil(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.charLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the character length of a string in UTF-8. + +```typescript +// Get the character length of the 'name' field in its UTF-8 form. +field("name").charLength(); + +``` + A new `Expr` representing the length of the string. + +Signature: + +```typescript +charLength(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.collectionId() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. + +```typescript +// Get the collection ID from a path. +field("__path__").collectionId(); + +``` + A new representing the collectionId operation. + +Signature: + +```typescript +collectionId(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.concat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates expression results together. + +```typescript +// Combine the 'firstName', ' ', and 'lastName' fields into a single value. +field("firstName").concat(constant(" "), field("lastName")); + +``` + +Signature: + +```typescript +concat(second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The additional expression or literal to concatenate. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals to concatenate. A new Expr representing the concatenated value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.cosineDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the cosine distance between two vectors. + +```typescript +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +field("userVector").cosineDistance(field("itemVector")); + +``` + +Signature: + +```typescript +cosineDistance(vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new Expr representing the cosine distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.cosineDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between two vectors. + +```typescript +// Calculate the Cosine distance between the 'location' field and a target location +field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); + +``` + +Signature: + +```typescript +cosineDistance(vector: VectorValue | number[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vector | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as a VectorValue) to compare against. A new Expr representing the Cosine\* distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.count() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. + +```typescript +// Count the total number of products +field("productId").count().as("totalProducts"); + +``` + A new `AggregateFunction` representing the 'count' aggregation. + +Signature: + +```typescript +count(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +## Expression.countDistinct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of distinct values of the expression or field. + +```typescript +// Count the distinct number of products +field("productId").countDistinct().as("distinctProducts"); + +``` + A new `AggregateFunction` representing the 'count\_distinct' aggregation. + +Signature: + +```typescript +countDistinct(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +## Expression.descending() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an that sorts documents in descending order based on this expression. + +```typescript +// Sort documents by the 'createdAt' field in descending order +firestore.pipeline().collection("users") + .sort(field("createdAt").descending()); + +``` + A new `Ordering` for descending sorting. + +Signature: + +```typescript +descending(): Ordering; +``` +Returns: + +[Ordering](./firestore_pipelines.ordering.md#ordering_class) + +## Expression.divide() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides this expression by another expression. + +```typescript +// Divide the 'total' field by the 'count' field +field("total").divide(field("count")); + +``` + +Signature: + +```typescript +divide(divisor: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| divisor | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to divide by. A new Expr representing the division operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.divide() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides this expression by a constant value. + +```typescript +// Divide the 'value' field by 10 +field("value").divide(10); + +``` + +Signature: + +```typescript +divide(divisor: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| divisor | number | The constant value to divide by. A new Expr representing the division operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.documentId() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the document ID from a path. + +```typescript +// Get the document ID from a path. +field("__path__").documentId(); + +``` + A new representing the documentId operation. + +Signature: + +```typescript +documentId(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.dotProduct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between two vectors. + +```typescript +// Calculate the dot product between a feature vector and a target vector +field("features").dotProduct([0.5, 0.8, 0.2]); + +``` + +Signature: + +```typescript +dotProduct(vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (as an array of numbers) to calculate with. A new Expr representing the dot product between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.dotProduct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between two vectors. + +```typescript +// Calculate the dot product between a feature vector and a target vector +field("features").dotProduct(new VectorValue([0.5, 0.8, 0.2])); + +``` + +Signature: + +```typescript +dotProduct(vector: VectorValue | number[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vector | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as an array of numbers) to calculate with. A new Expr representing the dot product between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.endsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string ends with a given postfix. + +```typescript +// Check if the 'filename' field ends with ".txt" +field("filename").endsWith(".txt"); + +``` + +Signature: + +```typescript +endsWith(suffix: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| suffix | string | The postfix to check for. A new Expr representing the 'ends with' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.endsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string ends with a given postfix (represented as an expression). + +```typescript +// Check if the 'url' field ends with the value of the 'extension' field +field("url").endsWith(field("extension")); + +``` + +Signature: + +```typescript +endsWith(suffix: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| suffix | [Expression](./firestore_pipelines.expression.md#expression_class) | The postfix expression to check for. A new Expr representing the 'ends with' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.equal() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to another expression. + +```typescript +// Check if the 'age' field is equal to 21 +field("age").equal(21); + +``` + +Signature: + +```typescript +equal(expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for equality. A new Expr representing the equality comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.equal() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to a constant value. + +```typescript +// Check if the 'city' field is equal to "London" +field("city").equal("London"); + +``` + +Signature: + +```typescript +equal(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The constant value to compare for equality. A new Expr representing the equality comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.equalAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to any of the provided values or expressions. + +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +field("category").equalAny("Electronics", field("primaryType")); + +``` + +Signature: + +```typescript +equalAny(values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values or expressions to check against. A new Expr representing the 'IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.equalAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to any of the provided values or expressions. + +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +field("category").equalAny(array(["Electronics", field("primaryType")])); + +``` + +Signature: + +```typescript +equalAny(arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array of values to check against. A new Expr representing the 'IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.euclideanDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between two vectors. + +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location +field("location").euclideanDistance([37.7749, -122.4194]); + +``` + +Signature: + +```typescript +euclideanDistance(vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (as an array of numbers) to calculate with. A new Expr representing the Euclidean distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.euclideanDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between two vectors. + +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location +field("location").euclideanDistance(new VectorValue([37.7749, -122.4194])); + +``` + +Signature: + +```typescript +euclideanDistance(vector: VectorValue | number[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vector | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as a VectorValue) to compare against. A new Expr representing the Euclidean distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.exists() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field exists in the document. + +```typescript +// Check if the document has a field named "phoneNumber" +field("phoneNumber").exists(); + +``` + A new `Expr` representing the 'exists' check. + +Signature: + +```typescript +exists(): BooleanExpression; +``` +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.exp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes e to the power of this expression. + +```typescript +// Compute e to the power of the 'value' field. +field("value").exp(); + +``` + A new representing the exp of the numeric value. + +Signature: + +```typescript +exp(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.floor() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the floor of a numeric value. + +```typescript +// Compute the floor of the 'price' field. +field("price").floor(); + +``` + A new representing the floor of the numeric value. + +Signature: + +```typescript +floor(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.greaterThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than another expression. + +```typescript +// Check if the 'age' field is greater than the 'limit' field +field("age").greaterThan(field("limit")); + +``` + +Signature: + +```typescript +greaterThan(expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for greater than. A new Expr representing the greater than comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.greaterThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than a constant value. + +```typescript +// Check if the 'price' field is greater than 100 +field("price").greaterThan(100); + +``` + +Signature: + +```typescript +greaterThan(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The constant value to compare for greater than. A new Expr representing the greater than comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.greaterThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than or equal to another expression. + +```typescript +// Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1 +field("quantity").greaterThanOrEqual(field('requirement').add(1)); + +``` + +Signature: + +```typescript +greaterThanOrEqual(expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for greater than or equal to. A new Expr representing the greater than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.greaterThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than or equal to a constant value. + +```typescript +// Check if the 'score' field is greater than or equal to 80 +field("score").greaterThanOrEqual(80); + +``` + +Signature: + +```typescript +greaterThanOrEqual(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The constant value to compare for greater than or equal to. A new Expr representing the greater than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.ifAbsent() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of the this expression evaluation. + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +field("optional_field").ifAbsent("default_value") + +``` + +Signature: + +```typescript +ifAbsent(elseValue: unknown): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elseValue | unknown | The value that will be returned if this Expression evaluates to an absent value. A new \[Expression\] representing the ifAbsent operation. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +## Expression.ifAbsent() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of this expression evaluation. + +```typescript +// Returns the value of the optional field 'optional_field', or if that is +// absent, then returns the value of the field ` +field("optional_field").ifAbsent(field('default_field')) + +``` + +Signature: + +```typescript +ifAbsent(elseExpression: unknown): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elseExpression | unknown | The Expression that will be evaluated if this Expression evaluates to an absent value. A new \[Expression\] representing the ifAbsent operation. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +## Expression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the result of the `catchExpr` argument if there is an error, else return the result of this expression. + +```typescript +// Returns the first item in the title field arrays, or returns +// the entire title field if the array is empty or the field is another type. +field("title").arrayGet(0).ifError(field("title")); + +``` + +Signature: + +```typescript +ifError(catchExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| catchExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The catch expression that will be evaluated and returned if this expression produces an error. A new representing the 'ifError' operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + +```typescript +// Returns the first item in the title field arrays, or returns +// "Default Title" +field("title").arrayGet(0).ifError("Default Title"); + +``` + +Signature: + +```typescript +ifError(catchValue: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| catchValue | unknown | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.isAbsent() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns `true` if the result of this expression is absent. Otherwise, returns `false` even if the value is `null`. + +```typescript +// Check if the field `value` is absent. +field("value").isAbsent(); + +``` + A new representing the 'isAbsent' check. + +Signature: + +```typescript +isAbsent(): BooleanExpression; +``` +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.isError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a given expression produces an error. + +```typescript +// Check if the result of a calculation is an error +field("title").arrayContains(1).isError(); + +``` + A new representing the 'isError' check. + +Signature: + +```typescript +isError(): BooleanExpression; +``` +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.join() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + +```typescript +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +field("tags").join(field("separator")) + +``` + +Signature: + +```typescript +join(delimiterExpression: Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. A new Expression representing the join operation. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +## Expression.join() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array field into a string. + +```typescript +// Join the elements of the 'tags' field with a comma and space. +field("tags").join(", ") + +``` + +Signature: + +```typescript +join(delimiter: string): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| delimiter | string | The string to use as a delimiter. A new Expression representing the join operation. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +## Expression.length() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string, array, map, vector, or bytes. + +```typescript +// Get the length of the 'name' field. +field("name").length(); + +// Get the number of items in the 'cart' array. +field("cart").length(); + +``` + A new `Expr` representing the length of the string, array, map, vector, or bytes. + +Signature: + +```typescript +length(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.lessThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than another expression. + +```typescript +// Check if the 'age' field is less than 'limit' +field("age").lessThan(field('limit')); + +``` + +Signature: + +```typescript +lessThan(experession: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| experession | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for less than. A new Expr representing the less than comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.lessThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than a constant value. + +```typescript +// Check if the 'price' field is less than 50 +field("price").lessThan(50); + +``` + +Signature: + +```typescript +lessThan(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The constant value to compare for less than. A new Expr representing the less than comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.lessThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than or equal to another expression. + +```typescript +// Check if the 'quantity' field is less than or equal to 20 +field("quantity").lessThan(constant(20)); + +``` + +Signature: + +```typescript +lessThanOrEqual(expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for less than or equal to. A new Expr representing the less than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.lessThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than or equal to a constant value. + +```typescript +// Check if the 'score' field is less than or equal to 70 +field("score").lessThan(70); + +``` + +Signature: + +```typescript +lessThanOrEqual(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The constant value to compare for less than or equal to. A new Expr representing the less than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.like() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive string comparison. + +```typescript +// Check if the 'title' field contains the word "guide" (case-sensitive) +field("title").like("%guide%"); + +``` + +Signature: + +```typescript +like(pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | string | The pattern to search for. You can use "%" as a wildcard character. A new Expr representing the 'like' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.like() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive string comparison. + +```typescript +// Check if the 'title' field contains the word "guide" (case-sensitive) +field("title").like("%guide%"); + +``` + +Signature: + +```typescript +like(pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. A new Expr representing the 'like' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.ln() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the natural logarithm of a numeric value. + +```typescript +// Compute the natural logarithm of the 'value' field. +field("value").ln(); + +``` + A new representing the natural logarithm of the numeric value. + +Signature: + +```typescript +ln(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.log10() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the base-10 logarithm of a numeric value. + +```typescript +// Compute the base-10 logarithm of the 'value' field. +field("value").log10(); + +``` + A new representing the base-10 logarithm of the numeric value. + +Signature: + +```typescript +log10(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.logicalMaximum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. + +```typescript +// Returns the larger value between the 'timestamp' field and the current timestamp. +field("timestamp").logicalMaximum(Function.currentTimestamp()); + +``` + +Signature: + +```typescript +logicalMaximum(second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to compare with. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals to compare with. A new representing the logical maximum operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.logicalMinimum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. + +```typescript +// Returns the smaller value between the 'timestamp' field and the current timestamp. +field("timestamp").logicalMinimum(Function.currentTimestamp()); + +``` + +Signature: + +```typescript +logicalMinimum(second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to compare with. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals to compare with. A new representing the logical minimum operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.mapGet() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Accesses a value from a map (object) field using the provided key. + +```typescript +// Get the 'city' value from the 'address' map field +field("address").mapGet("city"); + +``` + +Signature: + +```typescript +mapGet(subfield: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| subfield | string | The key to access in the map. A new Expr representing the value associated with the given key in the map. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.mapMerge() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that merges multiple map values. + +``` +// 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}, {}) + +``` + +Signature: + +```typescript +mapMerge(secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| secondMap | Record<string, unknown> \| [Expression](./firestore_pipelines.expression.md#expression_class) | A required second map to merge. Represented as a literal or an expression that returns a map. | +| otherMaps | Array<Record<string, unknown> \| [Expression](./firestore_pipelines.expression.md#expression_class)> | Optional additional maps to merge. Each map is represented as a literal or an expression that returns a map. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new representing the 'mapMerge' operation. + +## Expression.mapRemove() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map produced by evaluating this expression. + +``` +// Removes the key 'baz' from the input map. +map({foo: 'bar', baz: true}).mapRemove('baz'); + +``` + +Signature: + +```typescript +mapRemove(key: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| key | string | The name of the key to remove from the input map. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new representing the 'mapRemove' operation. + +## Expression.mapRemove() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map produced by evaluating this expression. + +``` +// Removes the key 'baz' from the input map. +map({foo: 'bar', baz: true}).mapRemove(constant('baz')); + +``` + +Signature: + +```typescript +mapRemove(keyExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| keyExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that produces the name of the key to remove from the input map. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new representing the 'mapRemove' operation. + +## Expression.maximum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the maximum value of a field across multiple stage inputs. + +```typescript +// Find the highest score in a leaderboard +field("score").maximum().as("highestScore"); + +``` + A new `AggregateFunction` representing the 'maximum' aggregation. + +Signature: + +```typescript +maximum(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +## Expression.minimum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the minimum value of a field across multiple stage inputs. + +```typescript +// Find the lowest price of all products +field("price").minimum().as("lowestPrice"); + +``` + A new `AggregateFunction` representing the 'minimum' aggregation. + +Signature: + +```typescript +minimum(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +## Expression.mod() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. + +```typescript +// Calculate the remainder of dividing the 'value' field by the 'divisor' field +field("value").mod(field("divisor")); + +``` + +Signature: + +```typescript +mod(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to divide by. A new Expr representing the modulo operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.mod() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. + +```typescript +// Calculate the remainder of dividing the 'value' field by 10 +field("value").mod(10); + +``` + +Signature: + +```typescript +mod(value: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | number | The constant value to divide by. A new Expr representing the modulo operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.multiply() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that multiplies this expression by another expression. + +```typescript +// Multiply the 'quantity' field by the 'price' field +field("quantity").multiply(field("price")); + +``` + +Signature: + +```typescript +multiply(second: Expression | number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| number | The second expression or literal to multiply by. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.notEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to another expression. + +```typescript +// Check if the 'status' field is not equal to "completed" +field("status").notEqual("completed"); + +``` + +Signature: + +```typescript +notEqual(expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for inequality. A new Expr representing the inequality comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.notEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to a constant value. + +```typescript +// Check if the 'country' field is not equal to "USA" +field("country").notEqual("USA"); + +``` + +Signature: + +```typescript +notEqual(value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | unknown | The constant value to compare for inequality. A new Expr representing the inequality comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.notEqualAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to any of the provided values or expressions. + +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +field("status").notEqualAny(["pending", field("rejectedStatus")]); + +``` + +Signature: + +```typescript +notEqualAny(values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values or expressions to check against. A new Expr representing the 'notEqualAny' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.notEqualAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. + +```typescript +// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' +field("status").notEqualAny(field('rejectedStatuses')); + +``` + +Signature: + +```typescript +notEqualAny(arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The values or expressions to check against. A new Expr representing the 'notEqualAny' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.pow() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of this expression raised to the power of another expression. + +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +field("base").pow(field("exponent")); + +``` + +Signature: + +```typescript +pow(exponent: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise this expression to the power of. A new Expr representing the power operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.pow() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of this expression raised to the power of a constant value. + +```typescript +// Raise the value of the 'base' field to the power of 2. +field("base").pow(2); + +``` + +Signature: + +```typescript +pow(exponent: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| exponent | number | The constant value to raise this expression to the power of. A new Expr representing the power operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.regexContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains a specified regular expression as a substring. + +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +field("description").regexContains("(?i)example"); + +``` + +Signature: + +```typescript +regexContains(pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | string | The regular expression to use for the search. A new Expr representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.regexContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains a specified regular expression as a substring. + +```typescript +// Check if the 'description' field contains the regular expression stored in field 'regex' +field("description").regexContains(field("regex")); + +``` + +Signature: + +```typescript +regexContains(pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the search. A new Expr representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.regexMatch() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string matches a specified regular expression. + +```typescript +// Check if the 'email' field matches a valid email pattern +field("email").regexMatch("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + +``` + +Signature: + +```typescript +regexMatch(pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | string | The regular expression to use for the match. A new Expr representing the regular expression match. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.regexMatch() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string matches a specified regular expression. + +```typescript +// Check if the 'email' field matches a regular expression stored in field 'regex' +field("email").regexMatch(field("regex")); + +``` + +Signature: + +```typescript +regexMatch(pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the match. A new Expr representing the regular expression match. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.reverse() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses this string expression. + +```typescript +// Reverse the value of the 'myString' field. +field("myString").reverse(); + +``` + A new representing the reversed string. + +Signature: + +```typescript +reverse(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.round() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the nearest whole number. + +```typescript +// Round the value of the 'price' field. +field("price").round(); + +``` + A new `Expr` representing the rounded value. + +Signature: + +```typescript +round(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.round() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + +```typescript +// Round the value of the 'price' field to two decimal places. +field("price").round(2); + +``` + +Signature: + +```typescript +round(decimalPlaces: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| decimalPlaces | number | A constant specifying the rounding precision in decimal places. A new Expr representing the rounded value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.round() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + +```typescript +// Round the value of the 'price' field to two decimal places. +field("price").round(constant(2)); + +``` + +Signature: + +```typescript +round(decimalPlaces: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| decimalPlaces | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression specifying the rounding precision in decimal places. A new Expr representing the rounded value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.split() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. + +Signature: + +```typescript +split(delimiter: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| delimiter | string | | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Split the 'scoresCsv' field on delimiter ',' +field('scoresCsv').split(',') + +``` + A new representing the split function. + +## Expression.split() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. + +Signature: + +```typescript +split(delimiter: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| delimiter | [Expression](./firestore_pipelines.expression.md#expression_class) | | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Split the 'scores' field on delimiter ',' or ':' depending on the stored format +field('scores').split(conditional(field('format').equal('csv'), constant(','), constant(':')) + +``` + A new representing the split function. + +## Expression.sqrt() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the square root of a numeric value. + +```typescript +// Compute the square root of the 'value' field. +field("value").sqrt(); + +``` + A new representing the square root of the numeric value. + +Signature: + +```typescript +sqrt(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.startsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string starts with a given prefix. + +```typescript +// Check if the 'name' field starts with "Mr." +field("name").startsWith("Mr."); + +``` + +Signature: + +```typescript +startsWith(prefix: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| prefix | string | The prefix to check for. A new Expr representing the 'starts with' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.startsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string starts with a given prefix (represented as an expression). + +```typescript +// Check if the 'fullName' field starts with the value of the 'firstName' field +field("fullName").startsWith(field("firstName")); + +``` + +Signature: + +```typescript +startsWith(prefix: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| prefix | [Expression](./firestore_pipelines.expression.md#expression_class) | The prefix expression to check for. A new Expr representing the 'starts with' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.stringConcat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates string expressions together. + +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +field("firstName").stringConcat(constant(" "), field("lastName")); + +``` + +Signature: + +```typescript +stringConcat(secondString: Expression | string, ...otherStrings: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| secondString | [Expression](./firestore_pipelines.expression.md#expression_class) \| string | The additional expression or string literal to concatenate. | +| otherStrings | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or string literals to concatenate. A new Expr representing the concatenated string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.stringContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains a specified substring. + +```typescript +// Check if the 'description' field contains "example". +field("description").stringContains("example"); + +``` + +Signature: + +```typescript +stringContains(substring: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| substring | string | The substring to search for. A new Expr representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.stringContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains the string represented by another expression. + +```typescript +// Check if the 'description' field contains the value of the 'keyword' field. +field("description").stringContains(field("keyword")); + +``` + +Signature: + +```typescript +stringContains(expr: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the substring to search for. A new Expr representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## Expression.stringReverse() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string. + +```typescript +// Reverse the value of the 'myString' field. +field("myString").stringReverse(); + +``` + A new representing the reversed string. + +Signature: + +```typescript +stringReverse(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.substring() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a substring of the results of this expression. + +Signature: + +```typescript +substring(position: number, length?: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| position | number | Index of the first character of the substring. | +| length | number | Length of the substring. If not provided, the substring will end at the end of the input. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.substring() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a substring of the results of this expression. + +Signature: + +```typescript +substring(position: Expression, length?: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| position | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression returning the index of the first character of the substring. | +| length | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression returning the length of the substring. If not provided the substring will end at the end of the input. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.subtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts another expression from this expression. + +```typescript +// Subtract the 'discount' field from the 'price' field +field("price").subtract(field("discount")); + +``` + +Signature: + +```typescript +subtract(subtrahend: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| subtrahend | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract from this expression. A new Expr representing the subtraction operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.subtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a constant value from this expression. + +```typescript +// Subtract 20 from the value of the 'total' field +field("total").subtract(20); + +``` + +Signature: + +```typescript +subtract(subtrahend: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| subtrahend | number | The constant value to subtract. A new Expr representing the subtraction operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.sum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. + +```typescript +// Calculate the total revenue from a set of orders +field("orderAmount").sum().as("totalRevenue"); + +``` + A new `AggregateFunction` representing the 'sum' aggregation. + +Signature: + +```typescript +sum(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +## Expression.timestampAdd() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to this timestamp expression. + +```typescript +// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. +field("timestamp").timestampAdd(field("unit"), field("amount")); + +``` + +Signature: + +```typescript +timestampAdd(unit: Expression, amount: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| unit | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | +| amount | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampAdd() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to this timestamp expression. + +```typescript +// Add 1 day to the 'timestamp' field. +field("timestamp").timestampAdd("day", 1); + +``` + +Signature: + +```typescript +timestampAdd(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | +| amount | number | The amount of time to add. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampSubtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from this timestamp expression. + +```typescript +// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. +field("timestamp").timestampSubtract(field("unit"), field("amount")); + +``` + +Signature: + +```typescript +timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| unit | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | +| amount | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampSubtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from this timestamp expression. + +```typescript +// Subtract 1 day from the 'timestamp' field. +field("timestamp").timestampSubtract("day", 1); + +``` + +Signature: + +```typescript +timestampSubtract(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | +| amount | number | The amount of time to subtract. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampToUnixMicros() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +field("timestamp").timestampToUnixMicros(); + +``` + A new representing the number of microseconds since epoch. + +Signature: + +```typescript +timestampToUnixMicros(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampToUnixMillis() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +field("timestamp").timestampToUnixMillis(); + +``` + A new representing the number of milliseconds since epoch. + +Signature: + +```typescript +timestampToUnixMillis(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampToUnixSeconds() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to seconds since epoch. +field("timestamp").timestampToUnixSeconds(); + +``` + A new representing the number of seconds since epoch. + +Signature: + +```typescript +timestampToUnixSeconds(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.timestampTruncate() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a timestamp to a specified granularity. + +Signature: + +```typescript +timestampTruncate(granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| granularity | [TimeGranularity](./firestore_pipelines.md#timegranularity) | The granularity to truncate to. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Truncate the 'createdAt' timestamp to the beginning of the day. +field('createdAt').timestampTruncate('day') + +``` + +## Expression.timestampTruncate() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a timestamp to a specified granularity. + +Signature: + +```typescript +timestampTruncate(granularity: Expression, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| granularity | [Expression](./firestore_pipelines.expression.md#expression_class) | The granularity to truncate to. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. +field('createdAt').timestampTruncate(field('granularity')) + +``` + +## Expression.toLower() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string to lowercase. + +```typescript +// Convert the 'name' field to lowercase +field("name").toLower(); + +``` + A new `Expr` representing the lowercase string. + +Signature: + +```typescript +toLower(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.toUpper() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string to uppercase. + +```typescript +// Convert the 'title' field to uppercase +field("title").toUpper(); + +``` + A new `Expr` representing the uppercase string. + +Signature: + +```typescript +toUpper(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.trim() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes leading and trailing characters from a string or byte array. + +```typescript +// Trim whitespace from the 'userInput' field +field("userInput").trim(); + +// Trim quotes from the 'userInput' field +field("userInput").trim('"'); + +``` + +Signature: + +```typescript +trim(valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | 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. A new Expr representing the trimmed string or byte array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.type() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the data type of this expression's result, as a string. + +Signature: + +```typescript +type(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Get the data type of the value in field 'title' +field('title').type() + +``` + A new {Expression} representing the data type. + +## Expression.unixMicrosToTimestamp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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. + +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +field("microseconds").unixMicrosToTimestamp(); + +``` + A new representing the timestamp. + +Signature: + +```typescript +unixMicrosToTimestamp(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.unixMillisToTimestamp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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. + +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +field("milliseconds").unixMillisToTimestamp(); + +``` + A new representing the timestamp. + +Signature: + +```typescript +unixMillisToTimestamp(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.unixSecondsToTimestamp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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. + +```typescript +// Interpret the 'seconds' field as seconds since epoch. +field("seconds").unixSecondsToTimestamp(); + +``` + A new representing the timestamp. + +Signature: + +```typescript +unixSecondsToTimestamp(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## Expression.vectorLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. + +```typescript +// Get the vector length (dimension) of the field 'embedding'. +field("embedding").vectorLength(); + +``` + A new representing the length of the vector. + +Signature: + +```typescript +vectorLength(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + diff --git a/docs-devsite/firestore_pipelines.field.md b/docs-devsite/firestore_pipelines.field.md new file mode 100644 index 0000000000..de4e5fb7b2 --- /dev/null +++ b/docs-devsite/firestore_pipelines.field.md @@ -0,0 +1,103 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Field class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Represents a reference to a field in a Firestore document, or outputs of a stage. + +

Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines. + +

You can create a `Field` instance using the static method: + +```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"); + +``` + +Signature: + +```typescript +export declare class Field extends Expression implements Selectable +``` +Extends: [Expression](./firestore_pipelines.expression.md#expression_class) + +Implements: [Selectable](./firestore_pipelines.selectable.md#selectable_interface) + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [alias](./firestore_pipelines.field.md#fieldalias) | | string | (Public Preview) | +| [expr](./firestore_pipelines.field.md#fieldexpr) | | [Expression](./firestore_pipelines.expression.md#expression_class) | (Public Preview) | +| [expressionType](./firestore_pipelines.field.md#fieldexpressiontype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) | +| [fieldName](./firestore_pipelines.field.md#fieldfieldname) | | string | (Public Preview) | +| [selectable](./firestore_pipelines.field.md#fieldselectable) | | true | (Public Preview) | + +## Field.alias + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +get alias(): string; +``` + +## Field.expr + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +get expr(): Expression; +``` + +## Field.expressionType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly expressionType: ExpressionType; +``` + +## Field.fieldName + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +get fieldName(): string; +``` + +## Field.selectable + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +selectable: true; +``` diff --git a/docs-devsite/firestore_pipelines.fieldpath.md b/docs-devsite/firestore_pipelines.fieldpath.md new file mode 100644 index 0000000000..38bfdadd73 --- /dev/null +++ b/docs-devsite/firestore_pipelines.fieldpath.md @@ -0,0 +1,72 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FieldPath class +A `FieldPath` refers to a field in a document. The path may consist of a single field name (referring to a top-level field in the document), or a list of field names (referring to a nested field in the document). + +Create a `FieldPath` by providing field names. If more than one field name is provided, the path will point to a nested field in a document. + +Signature: + +```typescript +export declare class FieldPath +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(fieldNames)](./firestore_pipelines.fieldpath.md#fieldpathconstructor) | | Creates a FieldPath from the provided field names. If more than one field name is provided, the path will point to a nested field in a document. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [isEqual(other)](./firestore_pipelines.fieldpath.md#fieldpathisequal) | | Returns true if this FieldPath is equal to the provided one. | + +## FieldPath.(constructor) + +Creates a `FieldPath` from the provided field names. If more than one field name is provided, the path will point to a nested field in a document. + +Signature: + +```typescript +constructor(...fieldNames: string[]); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldNames | string\[\] | A list of field names. | + +## FieldPath.isEqual() + +Returns true if this `FieldPath` is equal to the provided one. + +Signature: + +```typescript +isEqual(other: FieldPath): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [FieldPath](./firestore_.fieldpath.md#fieldpath_class) | The FieldPath to compare against. | + +Returns: + +boolean + +true if this `FieldPath` is equal to the provided one. + diff --git a/docs-devsite/firestore_pipelines.fieldvalue.md b/docs-devsite/firestore_pipelines.fieldvalue.md new file mode 100644 index 0000000000..2ca4ce713d --- /dev/null +++ b/docs-devsite/firestore_pipelines.fieldvalue.md @@ -0,0 +1,46 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FieldValue class +Sentinel values that can be used when writing document fields with `set()` or `update()`. + +Signature: + +```typescript +export declare abstract class FieldValue +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [isEqual(other)](./firestore_pipelines.fieldvalue.md#fieldvalueisequal) | | Compares FieldValues for equality. | + +## FieldValue.isEqual() + +Compares `FieldValue`s for equality. + +Signature: + +```typescript +abstract isEqual(other: FieldValue): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [FieldValue](./firestore_.fieldvalue.md#fieldvalue_class) | | + +Returns: + +boolean + diff --git a/docs-devsite/firestore_pipelines.firestore.md b/docs-devsite/firestore_pipelines.firestore.md new file mode 100644 index 0000000000..8d43257921 --- /dev/null +++ b/docs-devsite/firestore_pipelines.firestore.md @@ -0,0 +1,68 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Firestore class +The Cloud Firestore service interface. + +Do not call this constructor directly. Instead, use [getFirestore()](./firestore_.md#getfirestore). + +Signature: + +```typescript +export declare class Firestore +``` + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [app](./firestore_pipelines.firestore.md#firestoreapp) | | [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) | The [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) associated with this Firestore service instance. | +| [type](./firestore_pipelines.firestore.md#firestoretype) | | 'firestore-lite' \| 'firestore' | Whether it's a [Firestore](./firestore_.firestore.md#firestore_class) or Firestore Lite instance. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [toJSON()](./firestore_pipelines.firestore.md#firestoretojson) | | Returns a JSON-serializable representation of this Firestore instance. | + +## Firestore.app + +The [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) associated with this `Firestore` service instance. + +Signature: + +```typescript +get app(): FirebaseApp; +``` + +## Firestore.type + +Whether it's a [Firestore](./firestore_.firestore.md#firestore_class) or Firestore Lite instance. + +Signature: + +```typescript +type: 'firestore-lite' | 'firestore'; +``` + +## Firestore.toJSON() + +Returns a JSON-serializable representation of this `Firestore` instance. + +Signature: + +```typescript +toJSON(): object; +``` +Returns: + +object + diff --git a/docs-devsite/firestore_pipelines.firestoredataconverter.md b/docs-devsite/firestore_pipelines.firestoredataconverter.md new file mode 100644 index 0000000000..1be9d180bd --- /dev/null +++ b/docs-devsite/firestore_pipelines.firestoredataconverter.md @@ -0,0 +1,264 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FirestoreDataConverter interface +Converter used by `withConverter()` to transform user objects of type `AppModelType` into Firestore data of type `DbModelType`. + +Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore. + +In this context, an "AppModel" is a class that is used in an application to package together related information and functionality. Such a class could, for example, have properties with complex, nested data types, properties used for memoization, properties of types not supported by Firestore (such as `symbol` and `bigint`), and helper functions that perform compound operations. Such classes are not suitable and/or possible to store into a Firestore database. Instead, instances of such classes need to be converted to "plain old JavaScript objects" (POJOs) with exclusively primitive properties, potentially nested inside other POJOs or arrays of POJOs. In this context, this type is referred to as the "DbModel" and would be an object suitable for persisting into Firestore. For convenience, applications can implement `FirestoreDataConverter` and register the converter with Firestore objects, such as `DocumentReference` or `Query`, to automatically convert `AppModel` to `DbModel` when storing into Firestore, and convert `DbModel` to `AppModel` when retrieving from Firestore. + +Signature: + +```typescript +export declare interface FirestoreDataConverter +``` + +## Methods + +| Method | Description | +| --- | --- | +| [fromFirestore(snapshot, options)](./firestore_pipelines.firestoredataconverter.md#firestoredataconverterfromfirestore) | Called by the Firestore SDK to convert Firestore data into an object of type AppModelType. You can access your data by calling: snapshot.data(options).Generally, the data returned from snapshot.data() can be cast to DbModelType; however, this is not guaranteed because Firestore does not enforce a schema on the database. For example, writes from a previous version of the application or writes from another client that did not use a type converter could have written data with different properties and/or property types. The implementation will need to choose whether to gracefully recover from non-conforming data or throw an error.To override this method, see . | +| [toFirestore(modelObject)](./firestore_pipelines.firestoredataconverter.md#firestoredataconvertertofirestore) | Called by the Firestore SDK to convert a custom model object of type AppModelType into a plain JavaScript object (suitable for writing directly to the Firestore database) of type DbModelType. To use set() with merge and mergeFields, toFirestore() must be defined with PartialWithFieldValue<AppModelType>.The WithFieldValue<T> type extends T to also allow FieldValues such as [deleteField()](./firestore_.md#deletefield) to be used as property values. | +| [toFirestore(modelObject, options)](./firestore_pipelines.firestoredataconverter.md#firestoredataconvertertofirestore) | Called by the Firestore SDK to convert a custom model object of type AppModelType into a plain JavaScript object (suitable for writing directly to the Firestore database) of type DbModelType. Used with [setDoc()](./firestore_.md#setdoc_ee215ad), and with merge:true or mergeFields.The PartialWithFieldValue<T> type extends Partial<T> to allow FieldValues such as [arrayUnion()](./firestore_.md#arrayunion_7d853aa) to be used as property values. It also supports nested Partial by allowing nested fields to be omitted. | + +## FirestoreDataConverter.fromFirestore() + +Called by the Firestore SDK to convert Firestore data into an object of type `AppModelType`. You can access your data by calling: `snapshot.data(options)`. + +Generally, the data returned from `snapshot.data()` can be cast to `DbModelType`; however, this is not guaranteed because Firestore does not enforce a schema on the database. For example, writes from a previous version of the application or writes from another client that did not use a type converter could have written data with different properties and/or property types. The implementation will need to choose whether to gracefully recover from non-conforming data or throw an error. + +To override this method, see . + +Signature: + +```typescript +fromFirestore(snapshot: QueryDocumentSnapshot, options?: SnapshotOptions): AppModelType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| snapshot | [QueryDocumentSnapshot](./firestore_.querydocumentsnapshot.md#querydocumentsnapshot_class)<[DocumentData](./firestore_.documentdata.md#documentdata_interface), [DocumentData](./firestore_.documentdata.md#documentdata_interface)> | A QueryDocumentSnapshot containing your data and metadata. | +| options | [SnapshotOptions](./firestore_.snapshotoptions.md#snapshotoptions_interface) | The SnapshotOptions from the initial call to data(). | + +Returns: + +AppModelType + +## FirestoreDataConverter.toFirestore() + +Called by the Firestore SDK to convert a custom model object of type `AppModelType` into a plain JavaScript object (suitable for writing directly to the Firestore database) of type `DbModelType`. To use `set()` with `merge` and `mergeFields`, `toFirestore()` must be defined with `PartialWithFieldValue`. + +The `WithFieldValue` type extends `T` to also allow FieldValues such as [deleteField()](./firestore_.md#deletefield) to be used as property values. + +Signature: + +```typescript +toFirestore(modelObject: WithFieldValue): WithFieldValue; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| modelObject | [WithFieldValue](./firestore_.md#withfieldvalue)<AppModelType> | | + +Returns: + +[WithFieldValue](./firestore_.md#withfieldvalue)<DbModelType> + +## FirestoreDataConverter.toFirestore() + +Called by the Firestore SDK to convert a custom model object of type `AppModelType` into a plain JavaScript object (suitable for writing directly to the Firestore database) of type `DbModelType`. Used with [setDoc()](./firestore_.md#setdoc_ee215ad), and with `merge:true` or `mergeFields`. + +The `PartialWithFieldValue` type extends `Partial` to allow FieldValues such as [arrayUnion()](./firestore_.md#arrayunion_7d853aa) to be used as property values. It also supports nested `Partial` by allowing nested fields to be omitted. + +Signature: + +```typescript +toFirestore(modelObject: PartialWithFieldValue, options: SetOptions): PartialWithFieldValue; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| modelObject | [PartialWithFieldValue](./firestore_.md#partialwithfieldvalue)<AppModelType> | | +| options | [SetOptions](./firestore_.md#setoptions) | | + +Returns: + +[PartialWithFieldValue](./firestore_.md#partialwithfieldvalue)<DbModelType> + +### Example + +Simple Example + +```typescript +const numberConverter = { + toFirestore(value: WithFieldValue) { + return { value }; + }, + fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions) { + return snapshot.data(options).value as number; + } +}; + +async function simpleDemo(db: Firestore): Promise { + const documentRef = doc(db, 'values/value123').withConverter(numberConverter); + + // converters are used with `setDoc`, `addDoc`, and `getDoc` + await setDoc(documentRef, 42); + const snapshot1 = await getDoc(documentRef); + assertEqual(snapshot1.data(), 42); + + // converters are not used when writing data with `updateDoc` + await updateDoc(documentRef, { value: 999 }); + const snapshot2 = await getDoc(documentRef); + assertEqual(snapshot2.data(), 999); +} + +``` +Advanced Example + +```typescript +// The Post class is a model that is used by our application. +// This class may have properties and methods that are specific +// to our application execution, which do not need to be persisted +// to Firestore. +class Post { + constructor( + readonly title: string, + readonly author: string, + readonly lastUpdatedMillis: number + ) {} + toString(): string { + return `${this.title} by ${this.author}`; + } +} + +// The PostDbModel represents how we want our posts to be stored +// in Firestore. This DbModel has different properties (`ttl`, +// `aut`, and `lut`) from the Post class we use in our application. +interface PostDbModel { + ttl: string; + aut: { firstName: string; lastName: string }; + lut: Timestamp; +} + +// The `PostConverter` implements `FirestoreDataConverter` and specifies +// how the Firestore SDK can convert `Post` objects to `PostDbModel` +// objects and vice versa. +class PostConverter implements FirestoreDataConverter { + toFirestore(post: WithFieldValue): WithFieldValue { + return { + ttl: post.title, + aut: this._autFromAuthor(post.author), + lut: this._lutFromLastUpdatedMillis(post.lastUpdatedMillis) + }; + } + + fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions): Post { + const data = snapshot.data(options) as PostDbModel; + const author = `${data.aut.firstName} ${data.aut.lastName}`; + return new Post(data.ttl, author, data.lut.toMillis()); + } + + _autFromAuthor( + author: string | FieldValue + ): { firstName: string; lastName: string } | FieldValue { + if (typeof author !== 'string') { + // `author` is a FieldValue, so just return it. + return author; + } + const [firstName, lastName] = author.split(' '); + return {firstName, lastName}; + } + + _lutFromLastUpdatedMillis( + lastUpdatedMillis: number | FieldValue + ): Timestamp | FieldValue { + if (typeof lastUpdatedMillis !== 'number') { + // `lastUpdatedMillis` must be a FieldValue, so just return it. + return lastUpdatedMillis; + } + return Timestamp.fromMillis(lastUpdatedMillis); + } +} + +async function advancedDemo(db: Firestore): Promise { + // Create a `DocumentReference` with a `FirestoreDataConverter`. + const documentRef = doc(db, 'posts/post123').withConverter(new PostConverter()); + + // The `data` argument specified to `setDoc()` is type checked by the + // TypeScript compiler to be compatible with `Post`. Since the `data` + // argument is typed as `WithFieldValue` rather than just `Post`, + // this allows properties of the `data` argument to also be special + // Firestore values that perform server-side mutations, such as + // `arrayRemove()`, `deleteField()`, and `serverTimestamp()`. + await setDoc(documentRef, { + title: 'My Life', + author: 'Foo Bar', + lastUpdatedMillis: serverTimestamp() + }); + + // The TypeScript compiler will fail to compile if the `data` argument to + // `setDoc()` is _not_ compatible with `WithFieldValue`. This + // type checking prevents the caller from specifying objects with incorrect + // properties or property values. + // @ts-expect-error "Argument of type { ttl: string; } is not assignable + // to parameter of type WithFieldValue" + await setDoc(documentRef, { ttl: 'The Title' }); + + // When retrieving a document with `getDoc()` the `DocumentSnapshot` + // object's `data()` method returns a `Post`, rather than a generic object, + // which would have been returned if the `DocumentReference` did _not_ have a + // `FirestoreDataConverter` attached to it. + const snapshot1: DocumentSnapshot = await getDoc(documentRef); + const post1: Post = snapshot1.data()!; + if (post1) { + assertEqual(post1.title, 'My Life'); + assertEqual(post1.author, 'Foo Bar'); + } + + // The `data` argument specified to `updateDoc()` is type checked by the + // TypeScript compiler to be compatible with `PostDbModel`. Note that + // unlike `setDoc()`, whose `data` argument must be compatible with `Post`, + // the `data` argument to `updateDoc()` must be compatible with + // `PostDbModel`. Similar to `setDoc()`, since the `data` argument is typed + // as `WithFieldValue` rather than just `PostDbModel`, this + // allows properties of the `data` argument to also be those special + // Firestore values, like `arrayRemove()`, `deleteField()`, and + // `serverTimestamp()`. + await updateDoc(documentRef, { + 'aut.firstName': 'NewFirstName', + lut: serverTimestamp() + }); + + // The TypeScript compiler will fail to compile if the `data` argument to + // `updateDoc()` is _not_ compatible with `WithFieldValue`. + // This type checking prevents the caller from specifying objects with + // incorrect properties or property values. + // @ts-expect-error "Argument of type { title: string; } is not assignable + // to parameter of type WithFieldValue" + await updateDoc(documentRef, { title: 'New Title' }); + const snapshot2: DocumentSnapshot = await getDoc(documentRef); + const post2: Post = snapshot2.data()!; + if (post2) { + assertEqual(post2.title, 'My Life'); + assertEqual(post2.author, 'NewFirstName Bar'); + } +} + +``` + diff --git a/docs-devsite/firestore_pipelines.functionexpression.md b/docs-devsite/firestore_pipelines.functionexpression.md new file mode 100644 index 0000000000..6ba0bb3367 --- /dev/null +++ b/docs-devsite/firestore_pipelines.functionexpression.md @@ -0,0 +1,90 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FunctionExpression class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +This class defines the base class for Firestore functions, which can be evaluated within pipeline execution. + +Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_.md#and_e72c712), , or the methods on (, , etc.) to construct new Function instances. + +Signature: + +```typescript +export declare class FunctionExpression extends Expression +``` +Extends: [Expression](./firestore_pipelines.expression.md#expression_class) + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(name, params)](./firestore_pipelines.functionexpression.md#functionexpressionconstructor) | | (Public Preview) Constructs a new instance of the FunctionExpression class | +| [(constructor)(name, params, \_methodName)](./firestore_pipelines.functionexpression.md#functionexpressionconstructor) | | (Public Preview) Constructs a new instance of the FunctionExpression class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [expressionType](./firestore_pipelines.functionexpression.md#functionexpressionexpressiontype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) | + +## FunctionExpression.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `FunctionExpression` class + +Signature: + +```typescript +constructor(name: string, params: Expression[]); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | +| params | [Expression](./firestore_pipelines.expression.md#expression_class)\[\] | | + +## FunctionExpression.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `FunctionExpression` class + +Signature: + +```typescript +constructor(name: string, params: Expression[], _methodName: string | undefined); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | +| params | [Expression](./firestore_pipelines.expression.md#expression_class)\[\] | | +| \_methodName | string \| undefined | | + +## FunctionExpression.expressionType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly expressionType: ExpressionType; +``` diff --git a/docs-devsite/firestore_pipelines.geopoint.md b/docs-devsite/firestore_pipelines.geopoint.md new file mode 100644 index 0000000000..d8563428fb --- /dev/null +++ b/docs-devsite/firestore_pipelines.geopoint.md @@ -0,0 +1,143 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GeoPoint class +An immutable object representing a geographic location in Firestore. The location is represented as latitude/longitude pair. + +Latitude values are in the range of \[-90, 90\]. Longitude values are in the range of \[-180, 180\]. + +Signature: + +```typescript +export declare class GeoPoint +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(latitude, longitude)](./firestore_pipelines.geopoint.md#geopointconstructor) | | Creates a new immutable GeoPoint object with the provided latitude and longitude values. | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [latitude](./firestore_pipelines.geopoint.md#geopointlatitude) | | number | The latitude of this GeoPoint instance. | +| [longitude](./firestore_pipelines.geopoint.md#geopointlongitude) | | number | The longitude of this GeoPoint instance. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [fromJSON(json)](./firestore_pipelines.geopoint.md#geopointfromjson) | static | Builds a GeoPoint instance from a JSON object created by [GeoPoint.toJSON()](./firestore_.geopoint.md#geopointtojson). | +| [isEqual(other)](./firestore_pipelines.geopoint.md#geopointisequal) | | Returns true if this GeoPoint is equal to the provided one. | +| [toJSON()](./firestore_pipelines.geopoint.md#geopointtojson) | | Returns a JSON-serializable representation of this GeoPoint instance. | + +## GeoPoint.(constructor) + +Creates a new immutable `GeoPoint` object with the provided latitude and longitude values. + +Signature: + +```typescript +constructor(latitude: number, longitude: number); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| latitude | number | The latitude as number between -90 and 90. | +| longitude | number | The longitude as number between -180 and 180. | + +## GeoPoint.latitude + +The latitude of this `GeoPoint` instance. + +Signature: + +```typescript +get latitude(): number; +``` + +## GeoPoint.longitude + +The longitude of this `GeoPoint` instance. + +Signature: + +```typescript +get longitude(): number; +``` + +## GeoPoint.fromJSON() + +Builds a `GeoPoint` instance from a JSON object created by [GeoPoint.toJSON()](./firestore_.geopoint.md#geopointtojson). + +Signature: + +```typescript +static fromJSON(json: object): GeoPoint; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| json | object | a JSON object represention of a GeoPoint instance | + +Returns: + +[GeoPoint](./firestore_.geopoint.md#geopoint_class) + +an instance of [GeoPoint](./firestore_.geopoint.md#geopoint_class) if the JSON object could be parsed. Throws a [FirestoreError](./firestore_.firestoreerror.md#firestoreerror_class) if an error occurs. + +## GeoPoint.isEqual() + +Returns true if this `GeoPoint` is equal to the provided one. + +Signature: + +```typescript +isEqual(other: GeoPoint): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [GeoPoint](./firestore_.geopoint.md#geopoint_class) | The GeoPoint to compare against. | + +Returns: + +boolean + +true if this `GeoPoint` is equal to the provided one. + +## GeoPoint.toJSON() + +Returns a JSON-serializable representation of this `GeoPoint` instance. + +Signature: + +```typescript +toJSON(): { + latitude: number; + longitude: number; + type: string; + }; +``` +Returns: + +{ latitude: number; longitude: number; type: string; } + +a JSON representation of this object. + diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md new file mode 100644 index 0000000000..2a3ba65e1f --- /dev/null +++ b/docs-devsite/firestore_pipelines.md @@ -0,0 +1,9899 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# @firebase/firestore/pipelines + +## Functions + +| Function | Description | +| --- | --- | +| function() | +| [countAll()](./firestore_pipelines.md#countall) | (Public Preview) Creates an aggregation that counts the total number of stage inputs. +```typescript +// Count the total number of input documents +countAll().as("totalDocument"); + +``` + A new representing the 'countAll' aggregation. | +| [currentTimestamp()](./firestore_pipelines.md#currenttimestamp) | (Public Preview) Creates an expression that evaluates to the current server timestamp. +```typescript +// Get the current server timestamp +currentTimestamp() + +``` + A new Expression representing the current server timestamp. | +| function(array, ...) | +| [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_a00ea48) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. +```typescript +// Check if the 'colors' array contains the value of field 'selectedColor' +arrayContains(field("colors"), field("selectedColor")); + +``` + | +| [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_7328608) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. +```typescript +// Check if the 'colors' array contains "red" +arrayContains(field("colors"), "red"); + +``` + | +| [arrayContainsAll(array, values)](./firestore_pipelines.md#arraycontainsall_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. +```typescript +// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" +arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); + +``` + | +| [arrayContainsAll(array, arrayExpression)](./firestore_pipelines.md#arraycontainsall_7b535db) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. +```typescript +// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" +arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); + +``` + | +| [arrayContainsAny(array, values)](./firestore_pipelines.md#arraycontainsany_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. +```typescript +// Check if the 'categories' array contains either values from field "cate1" or "Science" +arrayContainsAny(field("categories"), [field("cate1"), "Science"]); + +``` + | +| [arrayContainsAny(array, values)](./firestore_pipelines.md#arraycontainsany_c381a96) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. +```typescript +// Check if the 'categories' array contains either values from field "cate1" or "Science" +arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); + +``` + | +| [arrayLength(array)](./firestore_pipelines.md#arraylength_195e339) | (Public Preview) Creates an expression that calculates the length of an array expression. +```typescript +// Get the number of items in the 'cart' array +arrayLength(field("cart")); + +``` + | +| function(arrayExpression, ...) | +| [arrayGet(arrayExpression, offset)](./firestore_pipelines.md#arrayget_f2e27cc) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +```typescript +// Return the value in the tags field array at index 1. +arrayGet(field('tags'), 1); + +``` + | +| [arrayGet(arrayExpression, offsetExpr)](./firestore_pipelines.md#arrayget_484550d) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet(field('tags'), field('favoriteTag')); + +``` + | +| [join(arrayExpression, delimiterExpression)](./firestore_pipelines.md#join_313e6aa) | (Public Preview) Creates an expression that joins the elements of an array into a string. +```typescript +// Join an array of string using the delimiter from the 'separator' field. +join(array(['foo', 'bar']), field("separator")) + +``` + | +| [join(arrayExpression, delimiter)](./firestore_pipelines.md#join_d088d29) | (Public Preview) Creates an expression that joins the elements of an array into a string. +```typescript +// Join the elements of the 'tags' field with a comma and space. +join(field("tags"), ", ") + +``` + | +| function(arrayField, ...) | +| [arrayGet(arrayField, offset)](./firestore_pipelines.md#arrayget_3f58471) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +```typescript +// Return the value in the tags field array at index 1. +arrayGet('tags', 1); + +``` + | +| [arrayGet(arrayField, offsetExpr)](./firestore_pipelines.md#arrayget_1904c9a) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet('tags', field('favoriteTag')); + +``` + | +| function(arrayFieldName, ...) | +| [join(arrayFieldName, delimiter)](./firestore_pipelines.md#join_478ef36) | (Public Preview) Creates an expression that joins the elements of an array into a string. +```typescript +// Join the elements of the 'tags' field with a comma and space. +join("tags", ", ") + +``` + | +| [join(arrayFieldName, delimiterExpression)](./firestore_pipelines.md#join_829294c) | (Public Preview) Creates an expression that joins the elements of an array into a string. +```typescript +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +join('tags', field("separator")) + +``` + | +| function(base, ...) | +| [pow(base, exponent)](./firestore_pipelines.md#pow_e4a9e64) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent expression. +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow(field("base"), field("exponent")); + +``` + | +| [pow(base, exponent)](./firestore_pipelines.md#pow_93eae7f) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent. +```typescript +// Raise the value of the 'base' field to the power of 2. +pow(field("base"), 2); + +``` + | +| [pow(base, exponent)](./firestore_pipelines.md#pow_a237721) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent expression. +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow("base", field("exponent")); + +``` + | +| [pow(base, exponent)](./firestore_pipelines.md#pow_f4d7908) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent. +```typescript +// Raise the value of the 'base' field to the power of 2. +pow("base", 2); + +``` + | +| function(booleanExpr, ...) | +| [countIf(booleanExpr)](./firestore_pipelines.md#countif_c5b8fb1) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. +```typescript +// Count the number of documents where 'is_active' field equals true +countIf(field("is_active").equal(true)).as("numActiveDocuments"); + +``` + | +| [not(booleanExpr)](./firestore_pipelines.md#not_c5b8fb1) | (Public Preview) Creates an expression that negates a filter condition. +```typescript +// Find documents where the 'completed' field is NOT true +not(equal("completed", true)); + +``` + | +| function(condition, ...) | +| [conditional(condition, thenExpr, elseExpr)](./firestore_pipelines.md#conditional_07a206d) | (Public Preview) Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. +```typescript +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +conditional( + greaterThan("age", 18), constant("Adult"), constant("Minor")); + +``` + | +| function(documentPath, ...) | +| [documentId(documentPath)](./firestore_pipelines.md#documentid_cef293c) | (Public Preview) Creates an expression that returns the document ID from a path. +```typescript +// Get the document ID from a path. +documentId(myDocumentReference); + +``` + A new representing the documentId operation. | +| function(documentPathExpr, ...) | +| [documentId(documentPathExpr)](./firestore_pipelines.md#documentid_9a69021) | (Public Preview) Creates an expression that returns the document ID from a path. +```typescript +// Get the document ID from a path. +documentId(field("__path__")); + +``` + A new representing the documentId operation. | +| function(element, ...) | +| [notEqualAny(element, values)](./firestore_pipelines.md#notequalany_c2c5bcb) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + | +| [notEqualAny(element, arrayExpression)](./firestore_pipelines.md#notequalany_16b2851) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. +```typescript +// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + | +| function(elements, ...) | +| [array(elements)](./firestore_pipelines.md#array_7d853aa) | (Public Preview) Creates an expression that creates a Firestore array value from an input array. +```typescript +// Create an array value from the input array and reference the 'baz' field value from the input document. +array(['bar', Field.of('baz')]).as('foo'); + +``` + | +| [map(elements)](./firestore_pipelines.md#map_ce5dee1) | (Public Preview) Creates an expression that creates a Firestore map value from an input object. +```typescript +// Create a map from the input object and reference the 'baz' field value from the input document. +map({foo: 'bar', baz: Field.of('baz')}).as('data'); + +``` + | +| function(expr, ...) | +| [abs(expr)](./firestore_pipelines.md#abs_005f3d4) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | +| [ascending(expr)](./firestore_pipelines.md#ascending_005f3d4) | (Public Preview) Creates an that sorts documents in ascending order based on an expression. +```typescript +// Sort documents by the 'name' field in lowercase in ascending order +firestore.pipeline().collection("users") + .sort(ascending(field("name").toLower())); + +``` + | +| [byteLength(expr)](./firestore_pipelines.md#bytelength_005f3d4) | (Public Preview) Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. +```typescript +// Calculate the length of the 'myString' field in bytes. +byteLength(field("myString")); + +``` + | +| [countDistinct(expr)](./firestore_pipelines.md#countdistinct_3c28b08) | (Public Preview) Creates an aggregation that counts the number of distinct values of a field. | +| [descending(expr)](./firestore_pipelines.md#descending_005f3d4) | (Public Preview) Creates an that sorts documents in descending order based on an expression. +```typescript +// Sort documents by the 'name' field in lowercase in descending order +firestore.pipeline().collection("users") + .sort(descending(field("name").toLower())); + +``` + | +| [floor(expr)](./firestore_pipelines.md#floor_005f3d4) | (Public Preview) Creates an expression that computes the floor of a numeric value. | +| [timestampToUnixMicros(expr)](./firestore_pipelines.md#timestamptounixmicros_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros(field("timestamp")); + +``` + | +| [timestampToUnixMillis(expr)](./firestore_pipelines.md#timestamptounixmillis_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis(field("timestamp")); + +``` + | +| [timestampToUnixSeconds(expr)](./firestore_pipelines.md#timestamptounixseconds_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds(field("timestamp")); + +``` + | +| [unixMicrosToTimestamp(expr)](./firestore_pipelines.md#unixmicrostotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp(field("microseconds")); + +``` + | +| [unixMillisToTimestamp(expr)](./firestore_pipelines.md#unixmillistotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp(field("milliseconds")); + +``` + | +| [unixSecondsToTimestamp(expr)](./firestore_pipelines.md#unixsecondstotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +```typescript +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp(field("seconds")); + +``` + | +| function(expression, ...) | +| [arraySum(expression)](./firestore_pipelines.md#arraysum_1138a27) | (Public Preview) Creates an expression that computes the sum of the elements in an array. +```typescript +// Compute the sum of the elements in the 'scores' field. +arraySum(field("scores")); + +``` + | +| [average(expression)](./firestore_pipelines.md#average_1138a27) | (Public Preview) Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. +```typescript +// Calculate the average age of users +average(field("age")).as("averageAge"); + +``` + | +| [ceil(expression)](./firestore_pipelines.md#ceil_1138a27) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. +```typescript +// Compute the ceiling of the 'price' field. +ceil(field("price")); + +``` + | +| [collectionId(expression)](./firestore_pipelines.md#collectionid_1138a27) | (Public Preview) Creates an expression that returns the collection ID from a path. +```typescript +// Get the collection ID from a path. +collectionId(field("__name__")); + +``` + | +| [count(expression)](./firestore_pipelines.md#count_1138a27) | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. +```typescript +// Count the number of items where the price is greater than 10 +count(field("price").greaterThan(10)).as("expensiveItemCount"); + +``` + | +| [divide(expression, value)](./firestore_pipelines.md#divide_01df3cf) | (Public Preview) Creates an expression that divides an expression by a constant value. +```typescript +// Divide the 'value' field by 10 +divide(field("value"), 10); + +``` + | +| [equal(expression, value)](./firestore_pipelines.md#equal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is equal to a constant value. +```typescript +// Check if the 'age' field is equal to 21 +equal(field("age"), 21); + +``` + | +| [equalAny(expression, values)](./firestore_pipelines.md#equalany_7e759b5) | (Public Preview) Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny(field("category"), [constant("Electronics"), field("primaryType")]); + +``` + | +| [equalAny(expression, arrayExpression)](./firestore_pipelines.md#equalany_214ce68) | (Public Preview) Creates an expression that checks if an expression is equal to any of the provided values. +```typescript +// Check if the 'category' field is set to a value in the disabledCategories field +equalAny(field("category"), field('disabledCategories')); + +``` + | +| [exp(expression)](./firestore_pipelines.md#exp_1138a27) | (Public Preview) Creates an expression that computes e to the power of the expression's result. +```typescript +// Compute e to the power of 2. +exp(constant(2)); + +``` + A new representing the exp of the numeric value. | +| [greaterThan(expression, value)](./firestore_pipelines.md#greaterthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than a constant value. +```typescript +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), 18); + +``` + | +| [greaterThanOrEqual(expression, value)](./firestore_pipelines.md#greaterthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than or equal to a constant value. +```typescript +// Check if the 'quantity' field is greater than or equal to 10 +greaterThanOrEqual(field("quantity"), 10); + +``` + | +| [length\_2(expression)](./firestore_pipelines.md#length_2_1138a27) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. +```typescript +// Get the length of the 'name' field. +length(field("name")); + +// Get the number of items in the 'cart' array. +length(field("cart")); + +``` + | +| [lessThan(expression, value)](./firestore_pipelines.md#lessthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than a constant value. +```typescript +// Check if the 'age' field is less than 30 +lessThan(field("age"), 30); + +``` + | +| [lessThanOrEqual(expression, value)](./firestore_pipelines.md#lessthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than or equal to a constant value. +```typescript +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), 20); + +``` + | +| [ln(expression)](./firestore_pipelines.md#ln_1138a27) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. +```typescript +// Compute the natural logarithm of the 'value' field. +ln(field("value")); + +``` + | +| [log(expression, base)](./firestore_pipelines.md#log_ac183e2) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. +```typescript +// Compute the logarithm of the 'value' field with base 10. +log(field("value"), 10); + +``` + | +| [log(expression, base)](./firestore_pipelines.md#log_1894737) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. +```typescript +// Compute the logarithm of the 'value' field with the base in the 'base' field. +log(field("value"), field("base")); + +``` + | +| [log10(expression)](./firestore_pipelines.md#log10_1138a27) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. +```typescript +// Compute the base-10 logarithm of the 'value' field. +log10(field("value")); + +``` + | +| [maximum(expression)](./firestore_pipelines.md#maximum_1138a27) | (Public Preview) Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. +```typescript +// Find the highest score in a leaderboard +maximum(field("score")).as("highestScore"); + +``` + | +| [minimum(expression)](./firestore_pipelines.md#minimum_1138a27) | (Public Preview) Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. +```typescript +// Find the lowest price of all products +minimum(field("price")).as("lowestPrice"); + +``` + | +| [mod(expression, value)](./firestore_pipelines.md#mod_01df3cf) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. +```typescript +// Calculate the remainder of dividing 'field1' by 5. +mod(field("field1"), 5); + +``` + | +| [notEqual(expression, value)](./firestore_pipelines.md#notequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is not equal to a constant value. +```typescript +// Check if the 'status' field is not equal to "completed" +notEqual(field("status"), "completed"); + +``` + | +| [round(expression)](./firestore_pipelines.md#round_1138a27) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. +```typescript +// Round the value of the 'price' field. +round(field("price")); + +``` + | +| [round(expression, decimalPlaces)](./firestore_pipelines.md#round_a3a92d0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. +```typescript +// Round the value of the 'price' field to two decimal places. +round(field("price"), constant(2)); + +``` + | +| [split(expression, delimiter)](./firestore_pipelines.md#split_5b5612b) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | +| [split(expression, delimiter)](./firestore_pipelines.md#split_5a171ed) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | +| [sqrt(expression)](./firestore_pipelines.md#sqrt_1138a27) | (Public Preview) Creates an expression that computes the square root of a numeric value. +```typescript +// Compute the square root of the 'value' field. +sqrt(field("value")); + +``` + | +| [subtract(expression, value)](./firestore_pipelines.md#subtract_01df3cf) | (Public Preview) Creates an expression that subtracts a constant value from an expression. +```typescript +// Subtract the constant value 2 from the 'value' field +subtract(field("value"), 2); + +``` + | +| [sum(expression)](./firestore_pipelines.md#sum_1138a27) | (Public Preview) Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. +```typescript +// Calculate the total revenue from a set of orders +sum(field("orderAmount")).as("totalRevenue"); + +``` + | +| [type(expression)](./firestore_pipelines.md#type_1138a27) | (Public Preview) Creates an expression that returns the data type of an expression's result. | +| function(field, ...) | +| [isAbsent(field)](./firestore_pipelines.md#isabsent_0fb8cd4) | (Public Preview) Creates an expression that returns true if a field is absent. Otherwise, returns false even if the field value is null. +```typescript +// Check if the field `value` is absent. +isAbsent("value"); + +``` + | +| [reverse(field)](./firestore_pipelines.md#reverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. +```typescript +// Reverse the value of the 'myString' field. +reverse("myString"); + +``` + | +| [stringReverse(field)](./firestore_pipelines.md#stringreverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. +```typescript +// Reverse the value of the 'myString' field. +strReverse("myString"); + +``` + | +| [substring(field, position, length)](./firestore_pipelines.md#substring_0d9573a) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| [substring(field, position, length)](./firestore_pipelines.md#substring_05cb14e) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| function(fieldName, ...) | +| [abs(fieldName)](./firestore_pipelines.md#abs_e5b0480) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | +| [add(fieldName, second)](./firestore_pipelines.md#add_b75bb8b) | (Public Preview) Creates an expression that adds a field's value to an expression. +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +add("quantity", field("reserve")); + +``` + | +| [arrayContains(fieldName, element)](./firestore_pipelines.md#arraycontains_aaace4a) | (Public Preview) Creates an expression that checks if a field's array value contains a specific element. +```typescript +// Check if the 'colors' array contains the value of field 'selectedColor' +arrayContains("colors", field("selectedColor")); + +``` + | +| [arrayContains(fieldName, element)](./firestore_pipelines.md#arraycontains_999590f) | (Public Preview) Creates an expression that checks if a field's array value contains a specific value. +```typescript +// Check if the 'colors' array contains "red" +arrayContains("colors", "red"); + +``` + | +| [arrayContainsAll(fieldName, values)](./firestore_pipelines.md#arraycontainsall_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. +```typescript +// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" +arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); + +``` + | +| [arrayContainsAll(fieldName, arrayExpression)](./firestore_pipelines.md#arraycontainsall_48da8d9) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. +```typescript +// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" +arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); + +``` + | +| [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. +```typescript +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +arrayContainsAny("categories", [field("cate1"), "Science"]); + +``` + | +| [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_1b4f7cd) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. +```typescript +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +arrayContainsAny("categories", array([field("cate1"), "Science"])); + +``` + | +| [arrayLength(fieldName)](./firestore_pipelines.md#arraylength_e5b0480) | (Public Preview) Creates an expression that calculates the length of an array in a specified field. +```typescript +// Get the number of items in field 'cart' +arrayLength('cart'); + +``` + | +| [arraySum(fieldName)](./firestore_pipelines.md#arraysum_e5b0480) | (Public Preview) Creates an expression that computes the sum of the elements in an array. +```typescript +// Compute the sum of the elements in the 'scores' field. +arraySum("scores"); + +``` + | +| [ascending(fieldName)](./firestore_pipelines.md#ascending_e5b0480) | (Public Preview) Creates an that sorts documents in ascending order based on a field. +```typescript +// Sort documents by the 'name' field in ascending order +firestore.pipeline().collection("users") + .sort(ascending("name")); + +``` + | +| [average(fieldName)](./firestore_pipelines.md#average_e5b0480) | (Public Preview) Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. +```typescript +// Calculate the average age of users +average("age").as("averageAge"); + +``` + | +| [byteLength(fieldName)](./firestore_pipelines.md#bytelength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. +```typescript +// Calculate the length of the 'myString' field in bytes. +byteLength("myString"); + +``` + | +| [ceil(fieldName)](./firestore_pipelines.md#ceil_e5b0480) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. +```typescript +// Compute the ceiling of the 'price' field. +ceil("price"); + +``` + | +| [charLength(fieldName)](./firestore_pipelines.md#charlength_e5b0480) | (Public Preview) Creates an expression that calculates the character length of a string field in UTF8. +```typescript +// Get the character length of the 'name' field in UTF-8. +strLength("name"); + +``` + | +| [collectionId(fieldName)](./firestore_pipelines.md#collectionid_e5b0480) | (Public Preview) Creates an expression that returns the collection ID from a path. +```typescript +// Get the collection ID from a path. +collectionId("__name__"); + +``` + | +| [concat(fieldName, second, others)](./firestore_pipelines.md#concat_828272e) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. +```typescript +// Concatenate a field with a literal string. +concat(field("firstName"), "Doe") + +``` + | +| [cosineDistance(fieldName, vector)](./firestore_pipelines.md#cosinedistance_463a23e) | (Public Preview) Calculates the Cosine distance between a field's vector value and a literal vector value. +```typescript +// Calculate the Cosine distance between the 'location' field and a target location +cosineDistance("location", [37.7749, -122.4194]); + +``` + | +| [cosineDistance(fieldName, vectorExpression)](./firestore_pipelines.md#cosinedistance_ed766a1) | (Public Preview) Calculates the Cosine distance between a field's vector value and a vector expression. +```typescript +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +cosineDistance("userVector", field("itemVector")); + +``` + | +| [count(fieldName)](./firestore_pipelines.md#count_e5b0480) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the input field exists. +```typescript +// Count the total number of products +count("productId").as("totalProducts"); + +``` + | +| [descending(fieldName)](./firestore_pipelines.md#descending_e5b0480) | (Public Preview) Creates an that sorts documents in descending order based on a field. +```typescript +// Sort documents by the 'name' field in descending order +firestore.pipeline().collection("users") + .sort(descending("name")); + +``` + | +| [divide(fieldName, expressions)](./firestore_pipelines.md#divide_cf36e43) | (Public Preview) Creates an expression that divides a field's value by an expression. +```typescript +// Divide the 'total' field by the 'count' field +divide("total", field("count")); + +``` + | +| [divide(fieldName, value)](./firestore_pipelines.md#divide_65e2f32) | (Public Preview) Creates an expression that divides a field's value by a constant value. +```typescript +// Divide the 'value' field by 10 +divide("value", 10); + +``` + | +| [dotProduct(fieldName, vector)](./firestore_pipelines.md#dotproduct_463a23e) | (Public Preview) Calculates the dot product between a field's vector value and a double array. +```typescript +// Calculate the dot product distance between a feature vector and a target vector +dotProduct("features", [0.5, 0.8, 0.2]); + +``` + | +| [dotProduct(fieldName, vectorExpression)](./firestore_pipelines.md#dotproduct_ed766a1) | (Public Preview) Calculates the dot product between a field's vector value and a vector expression. +```typescript +// Calculate the dot product distance between two document vectors: 'docVector1' and 'docVector2' +dotProduct("docVector1", field("docVector2")); + +``` + | +| [endsWith(fieldName, suffix)](./firestore_pipelines.md#endswith_05ca3b0) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. +```typescript +// Check if the 'filename' field ends with ".txt" +endsWith("filename", ".txt"); + +``` + | +| [endsWith(fieldName, suffix)](./firestore_pipelines.md#endswith_8fc0ebc) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. +```typescript +// Check if the 'url' field ends with the value of the 'extension' field +endsWith("url", field("extension")); + +``` + | +| [equal(fieldName, expression)](./firestore_pipelines.md#equal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is equal to an expression. +```typescript +// Check if the 'age' field is equal to the 'limit' field +equal("age", field("limit")); + +``` + | +| [equal(fieldName, value)](./firestore_pipelines.md#equal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is equal to a constant value. +```typescript +// Check if the 'city' field is equal to string constant "London" +equal("city", "London"); + +``` + | +| [equalAny(fieldName, values)](./firestore_pipelines.md#equalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny("category", [constant("Electronics"), field("primaryType")]); + +``` + | +| [equalAny(fieldName, arrayExpression)](./firestore_pipelines.md#equalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny("category", ["Electronics", field("primaryType")]); + +``` + | +| [euclideanDistance(fieldName, vector)](./firestore_pipelines.md#euclideandistance_463a23e) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a double array. +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location +euclideanDistance("location", [37.7749, -122.4194]); + +``` + | +| [euclideanDistance(fieldName, vectorExpression)](./firestore_pipelines.md#euclideandistance_ed766a1) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a vector expression. +```typescript +// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' +euclideanDistance("pointA", field("pointB")); + +``` + | +| [exists(fieldName)](./firestore_pipelines.md#exists_e5b0480) | (Public Preview) Creates an expression that checks if a field exists. +```typescript +// Check if the document has a field named "phoneNumber" +exists("phoneNumber"); + +``` + | +| [exp(fieldName)](./firestore_pipelines.md#exp_e5b0480) | (Public Preview) Creates an expression that computes e to the power of the expression's result. +```typescript +// Compute e to the power of the 'value' field. +exp('value'); + +``` + A new representing the exp of the numeric value. | +| [floor(fieldName)](./firestore_pipelines.md#floor_e5b0480) | (Public Preview) Creates an expression that computes the floor of a numeric value. | +| [greaterThan(fieldName, expression)](./firestore_pipelines.md#greaterthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is greater than an expression. +```typescript +// Check if the value of field 'age' is greater than the value of field 'limit' +greaterThan("age", field("limit")); + +``` + | +| [greaterThan(fieldName, value)](./firestore_pipelines.md#greaterthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than a constant value. +```typescript +// Check if the 'price' field is greater than 100 +greaterThan("price", 100); + +``` + | +| [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_2e16acb) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to an expression. +```typescript +// Check if the value of field 'age' is greater than or equal to the value of field 'limit' +greaterThanOrEqual("age", field("limit")); + +``` + | +| [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to a constant value. +```typescript +// Check if the 'score' field is greater than or equal to 80 +greaterThanOrEqual("score", 80); + +``` + | +| [length\_2(fieldName)](./firestore_pipelines.md#length_2_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. +```typescript +// Get the length of the 'name' field. +length("name"); + +// Get the number of items in the 'cart' array. +length("cart"); + +``` + | +| [lessThan(fieldName, expression)](./firestore_pipelines.md#lessthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than an expression. +```typescript +// Check if the 'age' field is less than the 'limit' field +lessThan("age", field("limit")); + +``` + | +| [lessThan(fieldName, value)](./firestore_pipelines.md#lessthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than a constant value. +```typescript +// Check if the 'price' field is less than 50 +lessThan("price", 50); + +``` + | +| [lessThanOrEqual(fieldName, expression)](./firestore_pipelines.md#lessthanorequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to an expression. +```typescript +// Check if the 'quantity' field is less than or equal to the 'limit' field +lessThan("quantity", field("limit")); + +``` + | +| [lessThanOrEqual(fieldName, value)](./firestore_pipelines.md#lessthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to a constant value. +```typescript +// Check if the 'score' field is less than or equal to 70 +lessThan("score", 70); + +``` + | +| [like(fieldName, pattern)](./firestore_pipelines.md#like_67f7432) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. +```typescript +// Check if the 'title' field contains the string "guide" +like("title", "%guide%"); + +``` + | +| [like(fieldName, pattern)](./firestore_pipelines.md#like_cb1318d) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. +```typescript +// Check if the 'title' field contains the string "guide" +like("title", field("pattern")); + +``` + | +| [ln(fieldName)](./firestore_pipelines.md#ln_e5b0480) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. +```typescript +// Compute the natural logarithm of the 'value' field. +ln("value"); + +``` + | +| [log(fieldName, base)](./firestore_pipelines.md#log_a89e21b) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. +```typescript +// Compute the logarithm of the 'value' field with base 10. +log("value", 10); + +``` + | +| [log(fieldName, base)](./firestore_pipelines.md#log_805b11f) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. +```typescript +// Compute the logarithm of the 'value' field with the base in the 'base' field. +log("value", field("base")); + +``` + | +| [log10(fieldName)](./firestore_pipelines.md#log10_e5b0480) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. +```typescript +// Compute the base-10 logarithm of the 'value' field. +log10("value"); + +``` + | +| [logicalMaximum(fieldName, second, others)](./firestore_pipelines.md#logicalmaximum_828272e) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. +```typescript +// Returns the largest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMaximum("field1", field("field2"), 1000); + +``` + | +| [logicalMinimum(fieldName, second, others)](./firestore_pipelines.md#logicalminimum_828272e) | (Public Preview) Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. +```typescript +// Returns the smallest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMinimum("field1", field("field2"), 1000); + +``` + | +| [mapGet(fieldName, subField)](./firestore_pipelines.md#mapget_06663cf) | (Public Preview) Accesses a value from a map (object) field using the provided key. +```typescript +// Get the 'city' value from the 'address' map field +mapGet("address", "city"); + +``` + | +| [maximum(fieldName)](./firestore_pipelines.md#maximum_e5b0480) | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. +```typescript +// Find the highest score in a leaderboard +maximum("score").as("highestScore"); + +``` + | +| [minimum(fieldName)](./firestore_pipelines.md#minimum_e5b0480) | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. +```typescript +// Find the lowest price of all products +minimum("price").as("lowestPrice"); + +``` + | +| [mod(fieldName, expression)](./firestore_pipelines.md#mod_1e91657) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. +```typescript +// Calculate the remainder of dividing 'field1' by 'field2'. +mod("field1", field("field2")); + +``` + | +| [mod(fieldName, value)](./firestore_pipelines.md#mod_65e2f32) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. +```typescript +// Calculate the remainder of dividing 'field1' by 5. +mod("field1", 5); + +``` + | +| [multiply(fieldName, second)](./firestore_pipelines.md#multiply_b75bb8b) | (Public Preview) Creates an expression that multiplies a field's value by an expression. +```typescript +// Multiply the 'quantity' field by the 'price' field +multiply("quantity", field("price")); + +``` + | +| [notEqual(fieldName, expression)](./firestore_pipelines.md#notequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is not equal to an expression. +```typescript +// Check if the 'status' field is not equal to the value of 'expectedStatus' +notEqual("status", field("expectedStatus")); + +``` + | +| [notEqual(fieldName, value)](./firestore_pipelines.md#notequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is not equal to a constant value. +```typescript +// Check if the 'country' field is not equal to "USA" +notEqual("country", "USA"); + +``` + | +| [notEqualAny(fieldName, values)](./firestore_pipelines.md#notequalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +notEqualAny("status", [constant("pending"), field("rejectedStatus")]); + +``` + | +| [notEqualAny(fieldName, arrayExpression)](./firestore_pipelines.md#notequalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. +```typescript +// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' +notEqualAny("status", field("rejectedStatuses")); + +``` + | +| [regexContains(fieldName, pattern)](./firestore_pipelines.md#regexcontains_67f7432) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains("description", "(?i)example"); + +``` + | +| [regexContains(fieldName, pattern)](./firestore_pipelines.md#regexcontains_cb1318d) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains("description", field("pattern")); + +``` + | +| [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_67f7432) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + +``` + | +| [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_cb1318d) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch("email", field("pattern")); + +``` + | +| [round(fieldName)](./firestore_pipelines.md#round_e5b0480) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. +```typescript +// Round the value of the 'price' field. +round("price"); + +``` + | +| [round(fieldName, decimalPlaces)](./firestore_pipelines.md#round_07d0cf0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. +```typescript +// Round the value of the 'price' field to two decimal places. +round("price", 2); + +``` + | +| [split(fieldName, delimiter)](./firestore_pipelines.md#split_2cfdd37) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | +| [split(fieldName, delimiter)](./firestore_pipelines.md#split_f4fe06a) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | +| [sqrt(fieldName)](./firestore_pipelines.md#sqrt_e5b0480) | (Public Preview) Creates an expression that computes the square root of a numeric value. +```typescript +// Compute the square root of the 'value' field. +sqrt("value"); + +``` + | +| [startsWith(fieldName, prefix)](./firestore_pipelines.md#startswith_89325cc) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. +```typescript +// Check if the 'name' field starts with "Mr." +startsWith("name", "Mr."); + +``` + | +| [startsWith(fieldName, prefix)](./firestore_pipelines.md#startswith_266c338) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. +```typescript +// Check if the 'fullName' field starts with the value of the 'firstName' field +startsWith("fullName", field("firstName")); + +``` + | +| [stringConcat(fieldName, secondString, otherStrings)](./firestore_pipelines.md#stringconcat_d80077e) | (Public Preview) Creates an expression that concatenates string functions, fields or constants together. +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +stringConcat("firstName", " ", field("lastName")); + +``` + | +| [stringContains(fieldName, substring)](./firestore_pipelines.md#stringcontains_5b94cfe) | (Public Preview) Creates an expression that checks if a string field contains a specified substring. +```typescript +// Check if the 'description' field contains "example". +stringContains("description", "example"); + +``` + | +| [stringContains(fieldName, substring)](./firestore_pipelines.md#stringcontains_ac3ba47) | (Public Preview) Creates an expression that checks if a string field contains a substring specified by an expression. +```typescript +// Check if the 'description' field contains the value of the 'keyword' field. +stringContains("description", field("keyword")); + +``` + | +| [subtract(fieldName, expression)](./firestore_pipelines.md#subtract_1e91657) | (Public Preview) Creates an expression that subtracts an expression from a field's value. +```typescript +// Subtract the 'discount' field from the 'price' field +subtract("price", field("discount")); + +``` + | +| [subtract(fieldName, value)](./firestore_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. +```typescript +// Subtract 20 from the value of the 'total' field +subtract("total", 20); + +``` + | +| [sum(fieldName)](./firestore_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. +```typescript +// Calculate the total revenue from a set of orders +sum("orderAmount").as("totalRevenue"); + +``` + | +| [timestampAdd(fieldName, unit, amount)](./firestore_pipelines.md#timestampadd_341fe7d) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. +```typescript +// Add 1 day to the 'timestamp' field. +timestampAdd("timestamp", "day", 1); + +``` + | +| [timestampSubtract(fieldName, unit, amount)](./firestore_pipelines.md#timestampsubtract_341fe7d) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. +```typescript +// Subtract 1 day from the 'timestamp' field. +timestampSubtract("timestamp", "day", 1); + +``` + | +| [timestampToUnixMicros(fieldName)](./firestore_pipelines.md#timestamptounixmicros_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros("timestamp"); + +``` + | +| [timestampToUnixMillis(fieldName)](./firestore_pipelines.md#timestamptounixmillis_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis("timestamp"); + +``` + | +| [timestampToUnixSeconds(fieldName)](./firestore_pipelines.md#timestamptounixseconds_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). +```typescript +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds("timestamp"); + +``` + | +| [timestampTruncate(fieldName, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_b6c7512) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(fieldName, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_ed83d46) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [toLower(fieldName)](./firestore_pipelines.md#tolower_e5b0480) | (Public Preview) Creates an expression that converts a string field to lowercase. +```typescript +// Convert the 'name' field to lowercase +toLower("name"); + +``` + | +| [toUpper(fieldName)](./firestore_pipelines.md#toupper_e5b0480) | (Public Preview) Creates an expression that converts a string field to uppercase. +```typescript +// Convert the 'title' field to uppercase +toUpper("title"); + +``` + | +| [trim(fieldName, valueToTrim)](./firestore_pipelines.md#trim_c9f90ee) | (Public Preview) Creates an expression that removes leading and trailing whitespace from a string or byte array. +```typescript +// Trim whitespace from the 'userInput' field +trim("userInput"); + +// Trim quotes from the 'userInput' field +trim("userInput", '"'); + +``` + | +| [type(fieldName)](./firestore_pipelines.md#type_e5b0480) | (Public Preview) Creates an expression that returns the data type of the data in the specified field. | +| [unixMicrosToTimestamp(fieldName)](./firestore_pipelines.md#unixmicrostotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp("microseconds"); + +``` + | +| [unixMillisToTimestamp(fieldName)](./firestore_pipelines.md#unixmillistotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp("milliseconds"); + +``` + | +| [unixSecondsToTimestamp(fieldName)](./firestore_pipelines.md#unixsecondstotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +```typescript +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp("seconds"); + +``` + | +| [vectorLength(fieldName)](./firestore_pipelines.md#vectorlength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector represented by a field. +```typescript +// Get the vector length (dimension) of the field 'embedding'. +vectorLength("embedding"); + +``` + | +| function(first, ...) | +| [add(first, second)](./firestore_pipelines.md#add_846ca1b) | (Public Preview) Creates an expression that adds two expressions together. +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +add(field("quantity"), field("reserve")); + +``` + | +| [and(first, second, more)](./firestore_pipelines.md#and_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'AND' operation on multiple filter conditions. +```typescript +// Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND +// the 'status' field is "active" +const condition = and(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); + +``` + | +| [concat(first, second, others)](./firestore_pipelines.md#concat_83be015) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. +```typescript +// Concatenate the 'firstName' and 'lastName' fields with a space in between. +concat(field("firstName"), " ", field("lastName")) + +``` + | +| [logicalMaximum(first, second, others)](./firestore_pipelines.md#logicalmaximum_83be015) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. +```typescript +// Returns the largest value between the 'field1' field, the 'field2' field, +// and 1000 +logicalMaximum(field("field1"), field("field2"), 1000); + +``` + | +| [logicalMinimum(first, second, others)](./firestore_pipelines.md#logicalminimum_83be015) | (Public Preview) Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. +```typescript +// Returns the smallest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMinimum(field("field1"), field("field2"), 1000); + +``` + | +| [multiply(first, second)](./firestore_pipelines.md#multiply_846ca1b) | (Public Preview) Creates an expression that multiplies two expressions together. +```typescript +// Multiply the 'quantity' field by the 'price' field +multiply(field("quantity"), field("price")); + +``` + | +| [or(first, second, more)](./firestore_pipelines.md#or_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'OR' operation on multiple filter conditions. +```typescript +// Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR +// the 'status' field is "active" +const condition = or(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); + +``` + | +| [xor(first, second, additionalConditions)](./firestore_pipelines.md#xor_8197113) | (Public Preview) Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. +```typescript +// Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London", +// or 'status' is "active". +const condition = xor( + greaterThan("age", 18), + equal("city", "London"), + equal("status", "active")); + +``` + | +| function(firstArray, ...) | +| [arrayConcat(firstArray, secondArray, otherArrays)](./firestore_pipelines.md#arrayconcat_c00d5d7) | (Public Preview) Creates an expression that concatenates an array expression with other arrays. +```typescript +// Combine the 'items' array with two new item arrays +arrayConcat(field("items"), [field("newItems"), field("otherItems")]); + +``` + | +| function(firstArrayField, ...) | +| [arrayConcat(firstArrayField, secondArray, otherArrays)](./firestore_pipelines.md#arrayconcat_f92063d) | (Public Preview) Creates an expression that concatenates a field's array value with other arrays. +```typescript +// Combine the 'items' array with two new item arrays +arrayConcat("items", [field("newItems"), field("otherItems")]); + +``` + | +| function(firstMap, ...) | +| [mapMerge(firstMap, secondMap, otherMaps)](./firestore_pipelines.md#mapmerge_cfe77ce) | (Public Preview) Creates an expression that merges multiple map values. +``` +// Merges the map in the settings field with, a map literal, and a map in +// that is conditionally returned by another expression +mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) + +``` + | +| function(firstString, ...) | +| [stringConcat(firstString, secondString, otherStrings)](./firestore_pipelines.md#stringconcat_8a8d1b6) | (Public Preview) Creates an expression that concatenates string expressions together. +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +stringConcat(field("firstName"), " ", field("lastName")); + +``` + | +| function(ifExpr, ...) | +| [ifAbsent(ifExpr, elseExpr)](./firestore_pipelines.md#ifabsent_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent(field("optional_field"), constant("default_value")) + +``` + | +| [ifAbsent(ifExpr, elseValue)](./firestore_pipelines.md#ifabsent_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent(field("optional_field"), "default_value") + +``` + | +| function(ifFieldName, ...) | +| [ifAbsent(ifFieldName, elseExpr)](./firestore_pipelines.md#ifabsent_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName is absent, else return the value of the field. +```typescript +// Returns the value of the optional field 'optional_field', or returns the value of +// 'default_field' if 'optional_field' is absent. +ifAbsent("optional_field", field("default_field")) + +``` + | +| [ifAbsent(ifFieldName, elseValue)](./firestore_pipelines.md#ifabsent_d8f2823) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName is absent, else return the value of the field. +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent("optional_field", "default_value") + +``` + | +| function(input, ...) | +| [substring(input, position, length)](./firestore_pipelines.md#substring_e6e0aa3) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| [substring(input, position, length)](./firestore_pipelines.md#substring_ab56dc6) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| function(left, ...) | +| [divide(left, right)](./firestore_pipelines.md#divide_b3c3382) | (Public Preview) Creates an expression that divides two expressions. +```typescript +// Divide the 'total' field by the 'count' field +divide(field("total"), field("count")); + +``` + | +| [equal(left, right)](./firestore_pipelines.md#equal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are equal. +```typescript +// Check if the 'age' field is equal to an expression +equal(field("age"), field("minAge").add(10)); + +``` + | +| [greaterThan(left, right)](./firestore_pipelines.md#greaterthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than the second expression. +```typescript +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), Constant(9).add(9)); + +``` + | +| [greaterThanOrEqual(left, right)](./firestore_pipelines.md#greaterthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than or equal to the second expression. +```typescript +// Check if the 'quantity' field is greater than or equal to the field "threshold" +greaterThanOrEqual(field("quantity"), field("threshold")); + +``` + | +| [lessThan(left, right)](./firestore_pipelines.md#lessthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than the second expression. +```typescript +// Check if the 'age' field is less than 30 +lessThan(field("age"), field("limit")); + +``` + | +| [lessThanOrEqual(left, right)](./firestore_pipelines.md#lessthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than or equal to the second expression. +```typescript +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), field("limit")); + +``` + | +| [mod(left, right)](./firestore_pipelines.md#mod_b3c3382) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing two expressions. +```typescript +// Calculate the remainder of dividing 'field1' by 'field2'. +mod(field("field1"), field("field2")); + +``` + | +| [notEqual(left, right)](./firestore_pipelines.md#notequal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are not equal. +```typescript +// Check if the 'status' field is not equal to field 'finalState' +notEqual(field("status"), field("finalState")); + +``` + | +| [pipelineResultEqual(left, right)](./firestore_pipelines.md#pipelineresultequal_707a755) | (Public Preview) Test equality of two PipelineResults. | +| [subtract(left, right)](./firestore_pipelines.md#subtract_b3c3382) | (Public Preview) Creates an expression that subtracts two expressions. +```typescript +// Subtract the 'discount' field from the 'price' field +subtract(field("price"), field("discount")); + +``` + | +| function(mapExpr, ...) | +| [mapRemove(mapExpr, key)](./firestore_pipelines.md#mapremove_23c7d51) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. +``` +// Removes the key 'baz' from the input map. +mapRemove(map({foo: 'bar', baz: true}), 'baz'); + +``` + | +| [mapRemove(mapExpr, keyExpr)](./firestore_pipelines.md#mapremove_9fbcaa3) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. +``` +// Removes the key 'baz' from the input map. +mapRemove(map({foo: 'bar', baz: true}), constant('baz')); + +``` + | +| function(mapExpression, ...) | +| [mapGet(mapExpression, subField)](./firestore_pipelines.md#mapget_688c050) | (Public Preview) Accesses a value from a map (object) expression using the provided key. +```typescript +// Get the 'city' value from the 'address' map field +mapGet(field("address"), "city"); + +``` + | +| function(mapField, ...) | +| [mapMerge(mapField, secondMap, otherMaps)](./firestore_pipelines.md#mapmerge_70a564b) | (Public Preview) Creates an expression that merges multiple map values. +``` +// Merges the map in the settings field with, a map literal, and a map in +// that is conditionally returned by another expression +mapMerge('settings', { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) + +``` + | +| [mapRemove(mapField, key)](./firestore_pipelines.md#mapremove_bd5726e) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. +``` +// Removes the key 'city' field from the map in the address field of the input document. +mapRemove('address', 'city'); + +``` + | +| [mapRemove(mapField, keyExpr)](./firestore_pipelines.md#mapremove_8406d13) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. +``` +// Removes the key 'city' field from the map in the address field of the input document. +mapRemove('address', constant('city')); + +``` + | +| function(name, ...) | +| [field(name)](./firestore_pipelines.md#field_1eaaff4) | (Public Preview) Creates a instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). +```typescript +// Create a Field instance for the 'title' field +const titleField = field("title"); + +// Create a Field instance for a nested field 'author.firstName' +const authorFirstNameField = field("author.firstName"); + +``` + | +| function(options, ...) | +| [execute(options)](./firestore_pipelines.md#execute_9e87e31) | (Public Preview) Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a that contains a list of objects. Each typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:

  • If there are no stages or only transformation stages, each represents a single document.
  • If there is an aggregation, only a single is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each represents a distinct group and its associated aggregated values.

Example: +```typescript +const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") + .where(gt(field("rating"), 4.5)) + .select("title", "author", "rating")); + +const results: PipelineResults = snapshot.results; + +``` + | +| function(path, ...) | +| [field(path)](./firestore_pipelines.md#field_34ee07d) | (Public Preview) Creates a instance representing the field at the given path. | +| function(pipeline, ...) | +| [execute(pipeline)](./firestore_pipelines.md#execute_01df620) | (Public Preview) Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a that contains a list of objects. Each typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:

  • If there are no stages or only transformation stages, each represents a single document.
  • If there is an aggregation, only a single is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each represents a distinct group and its associated aggregated values.

Example: +```typescript +const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") + .where(gt(field("rating"), 4.5)) + .select("title", "author", "rating")); + +const results: PipelineResults = snapshot.results; + +``` + | +| function(stringExpression, ...) | +| [charLength(stringExpression)](./firestore_pipelines.md#charlength_c25a54a) | (Public Preview) Creates an expression that calculates the character length of a string expression in UTF-8. +```typescript +// Get the character length of the 'name' field in UTF-8. +strLength(field("name")); + +``` + | +| [endsWith(stringExpression, suffix)](./firestore_pipelines.md#endswith_0a0b889) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." +endsWith(field("fullName"), "Jr."); + +``` + | +| [endsWith(stringExpression, suffix)](./firestore_pipelines.md#endswith_13aee0d) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." +endsWith(field("fullName"), constant("Jr.")); + +``` + | +| [like(stringExpression, pattern)](./firestore_pipelines.md#like_a84c581) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. +```typescript +// Check if the 'title' field contains the string "guide" +like(field("title"), "%guide%"); + +``` + | +| [like(stringExpression, pattern)](./firestore_pipelines.md#like_b534848) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. +```typescript +// Check if the 'title' field contains the string "guide" +like(field("title"), field("pattern")); + +``` + | +| [regexContains(stringExpression, pattern)](./firestore_pipelines.md#regexcontains_a84c581) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains(field("description"), "(?i)example"); + +``` + | +| [regexContains(stringExpression, pattern)](./firestore_pipelines.md#regexcontains_b534848) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains(field("description"), field("pattern")); + +``` + | +| [regexMatch(stringExpression, pattern)](./firestore_pipelines.md#regexmatch_a84c581) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch(field("email"), "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + +``` + | +| [regexMatch(stringExpression, pattern)](./firestore_pipelines.md#regexmatch_b534848) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch(field("email"), field("pattern")); + +``` + | +| [reverse(stringExpression)](./firestore_pipelines.md#reverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. +```typescript +// Reverse the value of the 'myString' field. +reverse(field("myString")); + +``` + | +| [startsWith(stringExpression, prefix)](./firestore_pipelines.md#startswith_75c3dbb) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." +startsWith(field("fullName"), "Mr."); + +``` + | +| [startsWith(stringExpression, prefix)](./firestore_pipelines.md#startswith_52f218a) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." +startsWith(field("fullName"), field("prefix")); + +``` + | +| [stringContains(stringExpression, substring)](./firestore_pipelines.md#stringcontains_3e9ff32) | (Public Preview) Creates an expression that checks if a string expression contains a specified substring. +```typescript +// Check if the 'description' field contains "example". +stringContains(field("description"), "example"); + +``` + | +| [stringContains(stringExpression, substring)](./firestore_pipelines.md#stringcontains_cc6ee02) | (Public Preview) Creates an expression that checks if a string expression contains a substring specified by another expression. +```typescript +// Check if the 'description' field contains the value of the 'keyword' field. +stringContains(field("description"), field("keyword")); + +``` + | +| [stringReverse(stringExpression)](./firestore_pipelines.md#stringreverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. +```typescript +// Reverse the value of the 'myString' field. +strReverse(field("myString")); + +``` + | +| [toLower(stringExpression)](./firestore_pipelines.md#tolower_c25a54a) | (Public Preview) Creates an expression that converts a string expression to lowercase. +```typescript +// Convert the 'name' field to lowercase +toLower(field("name")); + +``` + | +| [toUpper(stringExpression)](./firestore_pipelines.md#toupper_c25a54a) | (Public Preview) Creates an expression that converts a string expression to uppercase. +```typescript +// Convert the 'title' field to uppercase +toUppercase(field("title")); + +``` + | +| [trim(stringExpression, valueToTrim)](./firestore_pipelines.md#trim_dd54322) | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array expression. +```typescript +// Trim whitespace from the 'userInput' field +trim(field("userInput")); + +// Trim quotes from the 'userInput' field +trim(field("userInput"), '"'); + +``` + | +| function(timestamp, ...) | +| [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_98418f9) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. +```typescript +// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. +timestampAdd(field("timestamp"), field("unit"), field("amount")); + +``` + | +| [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_ffe8e57) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. +```typescript +// Add 1 day to the 'timestamp' field. +timestampAdd(field("timestamp"), "day", 1); + +``` + | +| [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_98418f9) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. +```typescript +// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. +timestampSubtract(field("timestamp"), field("unit"), field("amount")); + +``` + | +| [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_ffe8e57) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. +```typescript +// Subtract 1 day from the 'timestamp' field. +timestampSubtract(field("timestamp"), "day", 1); + +``` + | +| function(timestampExpression, ...) | +| [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_ad5d843) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_d6ab2a4) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| function(tryExpr, ...) | +| [ifError(tryExpr, catchExpr)](./firestore_pipelines.md#iferror_a99a327) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation.This overload is useful when a BooleanExpression is required. +```typescript +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +ifError(constant(50).divide('length').gt(1), constant(false)); + +``` + | +| [ifError(tryExpr, catchExpr)](./firestore_pipelines.md#iferror_756c12e) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. +```typescript +// Returns the first item in the title field arrays, or returns +// the entire title field if the array is empty or the field is another type. +ifError(field("title").arrayGet(0), field("title")); + +``` + | +| [ifError(tryExpr, catchValue)](./firestore_pipelines.md#iferror_dc532f9) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. +```typescript +// Returns the first item in the title field arrays, or returns +// "Default Title" +ifError(field("title").arrayGet(0), "Default Title"); + +``` + | +| function(value, ...) | +| [constant(value)](./firestore_pipelines.md#constant_0c00f91) | (Public Preview) Creates a Constant instance for a number value. | +| [constant(value)](./firestore_pipelines.md#constant_6dac335) | (Public Preview) Creates a Constant instance for a VectorValue value. | +| [constant(value)](./firestore_pipelines.md#constant_7c807cd) | (Public Preview) Creates a Constant instance for a string value. | +| [constant(value)](./firestore_pipelines.md#constant_b2e4f8d) | (Public Preview) Creates a BooleanExpression instance for a boolean value. | +| [constant(value)](./firestore_pipelines.md#constant_73ebd84) | (Public Preview) Creates a Constant instance for a null value. | +| [constant(value)](./firestore_pipelines.md#constant_72a76cb) | (Public Preview) Creates a Constant instance for a GeoPoint value. | +| [constant(value)](./firestore_pipelines.md#constant_000477d) | (Public Preview) Creates a Constant instance for a Timestamp value. | +| [constant(value)](./firestore_pipelines.md#constant_5131bf7) | (Public Preview) Creates a Constant instance for a Date value. | +| [constant(value)](./firestore_pipelines.md#constant_fdf565d) | (Public Preview) Creates a Constant instance for a Bytes value. | +| [constant(value)](./firestore_pipelines.md#constant_bcd2b0b) | (Public Preview) Creates a Constant instance for a DocumentReference value. | +| [exists(value)](./firestore_pipelines.md#exists_f3daf14) | (Public Preview) Creates an expression that checks if a field exists. +```typescript +// Check if the document has a field named "phoneNumber" +exists(field("phoneNumber")); + +``` + | +| [isAbsent(value)](./firestore_pipelines.md#isabsent_f3daf14) | (Public Preview) Creates an expression that returns true if a value is absent. Otherwise, returns false even if the value is null. +```typescript +// Check if the field `value` is absent. +isAbsent(field("value")); + +``` + | +| [isError(value)](./firestore_pipelines.md#iserror_f3daf14) | (Public Preview) Creates an expression that checks if a given expression produces an error. +```typescript +// Check if the result of a calculation is an error +isError(field("title").arrayContains(1)); + +``` + | +| function(vectorExpression, ...) | +| [cosineDistance(vectorExpression, vector)](./firestore_pipelines.md#cosinedistance_3a80317) | (Public Preview) Calculates the Cosine distance between a vector expression and a vector literal. +```typescript +// Calculate the cosine distance between the 'location' field and a target location +cosineDistance(field("location"), [37.7749, -122.4194]); + +``` + | +| [cosineDistance(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#cosinedistance_17b5bcc) | (Public Preview) Calculates the Cosine distance between two vector expressions. +```typescript +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +cosineDistance(field("userVector"), field("itemVector")); + +``` + | +| [dotProduct(vectorExpression, vector)](./firestore_pipelines.md#dotproduct_3a80317) | (Public Preview) Calculates the dot product between a vector expression and a double array. +```typescript +// Calculate the dot product between a feature vector and a target vector +dotProduct(field("features"), [0.5, 0.8, 0.2]); + +``` + | +| [dotProduct(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#dotproduct_17b5bcc) | (Public Preview) Calculates the dot product between two vector expressions. +```typescript +// Calculate the dot product between two document vectors: 'docVector1' and 'docVector2' +dotProduct(field("docVector1"), field("docVector2")); + +``` + | +| [euclideanDistance(vectorExpression, vector)](./firestore_pipelines.md#euclideandistance_3a80317) | (Public Preview) Calculates the Euclidean distance between a vector expression and a double array. +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location + +euclideanDistance(field("location"), [37.7749, -122.4194]); + +``` + | +| [euclideanDistance(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#euclideandistance_17b5bcc) | (Public Preview) Calculates the Euclidean distance between two vector expressions. +```typescript +// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' +euclideanDistance(field("pointA"), field("pointB")); + +``` + | +| [vectorLength(vectorExpression)](./firestore_pipelines.md#vectorlength_58a039b) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector. +```typescript +// Get the vector length (dimension) of the field 'embedding'. +vectorLength(field("embedding")); + +``` + | + +## Classes + +| Class | Description | +| --- | --- | +| [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) | (Public Preview) A class that represents an aggregate function. | +| [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) | (Public Preview) An AggregateFunction with alias. | +| [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class) | (Public Preview) | +| [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | (Public Preview) An interface that represents a filter condition. | +| [Bytes](./firestore_pipelines.bytes.md#bytes_class) | An immutable object representing an array of bytes. | +| [CollectionReference](./firestore_pipelines.collectionreference.md#collectionreference_class) | A CollectionReference object can be used for adding documents, getting document references, and querying for documents (using [query()](./firestore_.md#query_9f7b0f4)). | +| [DocumentReference](./firestore_pipelines.documentreference.md#documentreference_class) | A DocumentReference refers to a document location in a Firestore database and can be used to write, read, or listen to the location. The document at the referenced location may or may not exist. | +| [DocumentSnapshot](./firestore_pipelines.documentsnapshot.md#documentsnapshot_class) | A DocumentSnapshot contains data read from a document in your Firestore database. The data can be extracted with .data() or .get(<field>) to get a specific field.For a DocumentSnapshot that points to a non-existing document, any data access will return 'undefined'. You can use the exists() method to explicitly verify a document's existence. | +| [Expression](./firestore_pipelines.expression.md#expression_class) | (Public Preview) Represents an expression that can be evaluated to a value within the execution of a .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 Expr class provides a fluent API for building expressions. You can chain together method calls to create complex expressions. | +| [Field](./firestore_pipelines.field.md#field_class) | (Public Preview) Represents a reference to a field in a Firestore document, or outputs of a stage.

Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines.

You can create a Field instance using the static method: +```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"); + +``` + | +| [FieldPath](./firestore_pipelines.fieldpath.md#fieldpath_class) | A FieldPath refers to a field in a document. The path may consist of a single field name (referring to a top-level field in the document), or a list of field names (referring to a nested field in the document).Create a FieldPath by providing field names. If more than one field name is provided, the path will point to a nested field in a document. | +| [FieldValue](./firestore_pipelines.fieldvalue.md#fieldvalue_class) | Sentinel values that can be used when writing document fields with set() or update(). | +| [Firestore](./firestore_pipelines.firestore.md#firestore_class) | The Cloud Firestore service interface.Do not call this constructor directly. Instead, use [getFirestore()](./firestore_.md#getfirestore). | +| [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) | (Public Preview) This class defines the base class for Firestore functions, which can be evaluated within pipeline execution.Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_.md#and_e72c712), , or the methods on (, , etc.) to construct new Function instances. | +| [GeoPoint](./firestore_pipelines.geopoint.md#geopoint_class) | An immutable object representing a geographic location in Firestore. The location is represented as latitude/longitude pair.Latitude values are in the range of \[-90, 90\]. Longitude values are in the range of \[-180, 180\]. | +| [Ordering](./firestore_pipelines.ordering.md#ordering_class) | (Public Preview) Represents an ordering criterion for sorting documents in a Firestore pipeline.You create Ordering instances using the ascending and descending helper functions. | +| [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | (Public Preview) | +| [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) | (Public Preview) A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the or methods.

If the PipelineResult represents a non-document result, ref will return a undefined value. | +| [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) | (Public Preview) Represents the results of a Firestore pipeline execution.A PipelineSnapshot contains zero or more objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. | +| [PipelineSource](./firestore_pipelines.pipelinesource.md#pipelinesource_class) | (Public Preview) Provides the entry point for defining the data source of a Firestore .Use the methods of this class (e.g., , , , or ) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. | +| [Query](./firestore_pipelines.query.md#query_class) | A Query refers to a query which you can read or listen to. You can also construct refined Query objects by adding filters and ordering. | +| [QueryDocumentSnapshot](./firestore_pipelines.querydocumentsnapshot.md#querydocumentsnapshot_class) | A QueryDocumentSnapshot contains data read from a document in your Firestore database as part of a query. The document is guaranteed to exist and its data can be extracted with .data() or .get(<field>) to get a specific field.A QueryDocumentSnapshot offers the same API surface as a DocumentSnapshot. Since query results contain only existing documents, the exists property will always be true and data() will never return 'undefined'. | +| [SnapshotMetadata](./firestore_pipelines.snapshotmetadata.md#snapshotmetadata_class) | Metadata about a snapshot, describing the state of the snapshot. | +| [Timestamp](./firestore_pipelines.timestamp.md#timestamp_class) | A Timestamp represents a point in time independent of any time zone or calendar, represented as seconds and fractions of seconds at nanosecond resolution in UTC Epoch time.It is encoded using the Proleptic Gregorian Calendar which extends the Gregorian calendar backwards to year one. It is encoded assuming all minutes are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.For examples and further specifications, refer to the [Timestamp definition](https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto). | +| [VectorValue](./firestore_pipelines.vectorvalue.md#vectorvalue_class) | Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). VectorValue | + +## Interfaces + +| Interface | Description | +| --- | --- | +| [DocumentData](./firestore_pipelines.documentdata.md#documentdata_interface) | Document data (for use with [setDoc()](./firestore_lite.md#setdoc_ee215ad)) consists of fields mapped to values. | +| [FirestoreDataConverter](./firestore_pipelines.firestoredataconverter.md#firestoredataconverter_interface) | Converter used by withConverter() to transform user objects of type AppModelType into Firestore data of type DbModelType.Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore.In this context, an "AppModel" is a class that is used in an application to package together related information and functionality. Such a class could, for example, have properties with complex, nested data types, properties used for memoization, properties of types not supported by Firestore (such as symbol and bigint), and helper functions that perform compound operations. Such classes are not suitable and/or possible to store into a Firestore database. Instead, instances of such classes need to be converted to "plain old JavaScript objects" (POJOs) with exclusively primitive properties, potentially nested inside other POJOs or arrays of POJOs. In this context, this type is referred to as the "DbModel" and would be an object suitable for persisting into Firestore. For convenience, applications can implement FirestoreDataConverter and register the converter with Firestore objects, such as DocumentReference or Query, to automatically convert AppModel to DbModel when storing into Firestore, and convert DbModel to AppModel when retrieving from Firestore. | +| [PipelineExecuteOptions](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptions_interface) | (Public Preview) Options defining Pipeline execution. | +| [Selectable](./firestore_pipelines.selectable.md#selectable_interface) | (Public Preview) An interface that represents a selectable expression. | +| [SnapshotOptions](./firestore_pipelines.snapshotoptions.md#snapshotoptions_interface) | Options that configure how data is retrieved from a DocumentSnapshot (for example the desired behavior for server timestamps that have not yet been set to their final value). | +| [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) | (Public Preview) Options defining how a Stage is evaluated. | + +## Type Aliases + +| Type Alias | Description | +| --- | --- | +| [AddFieldsStageOptions](./firestore_pipelines.md#addfieldsstageoptions) | (Public Preview) Options defining how an AddFieldsStage is evaluated. See . | +| [AggregateStageOptions](./firestore_pipelines.md#aggregatestageoptions) | (Public Preview) Options defining how an AggregateStage is evaluated. See . | +| [CollectionGroupStageOptions](./firestore_pipelines.md#collectiongroupstageoptions) | (Public Preview) Defines the configuration options for a within a pipeline. This type extends and provides specific settings for how a collection group is identified and processed during pipeline execution. | +| [CollectionStageOptions](./firestore_pipelines.md#collectionstageoptions) | (Public Preview) Options defining how a CollectionStage is evaluated. See . | +| [DatabaseStageOptions](./firestore_pipelines.md#databasestageoptions) | (Public Preview) Options defining how a DatabaseStage is evaluated. See . | +| [DistinctStageOptions](./firestore_pipelines.md#distinctstageoptions) | (Public Preview) Options defining how a DistinctStage is evaluated. See . | +| [DocumentsStageOptions](./firestore_pipelines.md#documentsstageoptions) | (Public Preview) Options defining how a DocumentsStage is evaluated. See . | +| [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) An enumeration of the different types of expressions. | +| [FindNearestStageOptions](./firestore_pipelines.md#findneareststageoptions) | (Public Preview) Options defining how a FindNearestStage is evaluated. See . | +| [LimitStageOptions](./firestore_pipelines.md#limitstageoptions) | (Public Preview) Options defining how a LimitStage is evaluated. See . | +| [OffsetStageOptions](./firestore_pipelines.md#offsetstageoptions) | (Public Preview) Options defining how an OffsetStage is evaluated. See . | +| [OneOf](./firestore_pipelines.md#oneof) | (Public Preview) Utility type to create an type that only allows one property of the Type param T to be set.type XorY = OneOf<{ x: unknown, y: unknown}> let a = { x: "foo" } // OK let b = { y: "foo" } // OK let c = { a: "foo", y: "foo" } // Not OK | +| [PartialWithFieldValue](./firestore_pipelines.md#partialwithfieldvalue) | Similar to TypeScript's Partial<T>, but allows nested fields to be omitted and FieldValues to be passed in as property values. | +| [Primitive](./firestore_pipelines.md#primitive) | Primitive types. | +| [RemoveFieldsStageOptions](./firestore_pipelines.md#removefieldsstageoptions) | (Public Preview) Options defining how a RemoveFieldsStage is evaluated. See . | +| [ReplaceWithStageOptions](./firestore_pipelines.md#replacewithstageoptions) | (Public Preview) Options defining how a ReplaceWithStage is evaluated. See . | +| [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) | (Public Preview) Defines the options for evaluating a sample stage within a pipeline. This type combines common with a specific configuration where only one of the defined sampling methods can be applied.See to create a sample stage.. | +| [SelectStageOptions](./firestore_pipelines.md#selectstageoptions) | (Public Preview) Options defining how a SelectStage is evaluated. See . | +| [SetOptions](./firestore_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | +| [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See . | +| [TimeGranularity](./firestore_pipelines.md#timegranularity) | (Public Preview) Specify time granularity for expressions. | +| [UnionStageOptions](./firestore_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See . | +| [UnnestStageOptions](./firestore_pipelines.md#unneststageoptions) | (Public Preview) Represents the specific options available for configuring an UnnestStage within a pipeline. | +| [WhereStageOptions](./firestore_pipelines.md#wherestageoptions) | (Public Preview) Options defining how a WhereStage is evaluated. See . | +| [WithFieldValue](./firestore_pipelines.md#withfieldvalue) | Allows FieldValues to be passed in as a property value while maintaining type safety. | + +## function() + +### countAll() {:#countall} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the total number of stage inputs. + +```typescript +// Count the total number of input documents +countAll().as("totalDocument"); + +``` + A new representing the 'countAll' aggregation. + +Signature: + +```typescript +export declare function countAll(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +### currentTimestamp() {:#currenttimestamp} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to the current server timestamp. + +```typescript +// Get the current server timestamp +currentTimestamp() + +``` + A new Expression representing the current server timestamp. + +Signature: + +```typescript +export declare function currentTimestamp(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(array, ...) + +### arrayContains(array, element) {:#arraycontains_a00ea48} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains a specific element. + +```typescript +// Check if the 'colors' array contains the value of field 'selectedColor' +arrayContains(field("colors"), field("selectedColor")); + +``` + +Signature: + +```typescript +export declare function arrayContains(array: Expression, element: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to check. | +| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The element to search for in the array. A new representing the 'array\_contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContains(array, element) {:#arraycontains_7328608} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains a specific element. + +```typescript +// Check if the 'colors' array contains "red" +arrayContains(field("colors"), "red"); + +``` + +Signature: + +```typescript +export declare function arrayContains(array: Expression, element: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to check. | +| element | unknown | The element to search for in the array. A new representing the 'array\_contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAll(array, values) {:#arraycontainsall_c658ad5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains all the specified elements. + +```typescript +// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" +arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); + +``` + +Signature: + +```typescript +export declare function arrayContainsAll(array: Expression, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to check. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new representing the 'array\_contains\_all' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAll(array, arrayExpression) {:#arraycontainsall_7b535db} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains all the specified elements. + +```typescript +// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" +arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); + +``` + +Signature: + +```typescript +export declare function arrayContainsAll(array: Expression, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to check. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. A new representing the 'array\_contains\_all' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAny(array, values) {:#arraycontainsany_c658ad5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains any of the specified elements. + +```typescript +// Check if the 'categories' array contains either values from field "cate1" or "Science" +arrayContainsAny(field("categories"), [field("cate1"), "Science"]); + +``` + +Signature: + +```typescript +export declare function arrayContainsAny(array: Expression, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to check. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new representing the 'array\_contains\_any' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAny(array, values) {:#arraycontainsany_c381a96} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains any of the specified elements. + +```typescript +// Check if the 'categories' array contains either values from field "cate1" or "Science" +arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); + +``` + +Signature: + +```typescript +export declare function arrayContainsAny(array: Expression, values: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to check. | +| values | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array. A new representing the 'array\_contains\_any' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayLength(array) {:#arraylength_195e339} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of an array expression. + +```typescript +// Get the number of items in the 'cart' array +arrayLength(field("cart")); + +``` + +Signature: + +```typescript +export declare function arrayLength(array: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to calculate the length of. A new representing the length of the array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(arrayExpression, ...) + +### arrayGet(arrayExpression, offset) {:#arrayget_f2e27cc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + +```typescript +// Return the value in the tags field array at index 1. +arrayGet(field('tags'), 1); + +``` + +Signature: + +```typescript +export declare function arrayGet(arrayExpression: Expression, offset: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expr evaluating to an array. | +| offset | number | The index of the element to return. A new Expr representing the 'arrayGet' operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### arrayGet(arrayExpression, offsetExpr) {:#arrayget_484550d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet(field('tags'), field('favoriteTag')); + +``` + +Signature: + +```typescript +export declare function arrayGet(arrayExpression: Expression, offsetExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expr evaluating to an array. | +| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expr evaluating to the index of the element to return. A new Expr representing the 'arrayGet' operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### join(arrayExpression, delimiterExpression) {:#join_313e6aa} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + +```typescript +// Join an array of string using the delimiter from the 'separator' field. +join(array(['foo', 'bar']), field("separator")) + +``` + +Signature: + +```typescript +export declare function join(arrayExpression: Expression, delimiterExpression: Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | +| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. A new Expression representing the join operation. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### join(arrayExpression, delimiter) {:#join_d088d29} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + +```typescript +// Join the elements of the 'tags' field with a comma and space. +join(field("tags"), ", ") + +``` + +Signature: + +```typescript +export declare function join(arrayExpression: Expression, delimiter: string): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | +| delimiter | string | The string to use as a delimiter. A new Expression representing the join operation. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +## function(arrayField, ...) + +### arrayGet(arrayField, offset) {:#arrayget_3f58471} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + +```typescript +// Return the value in the tags field array at index 1. +arrayGet('tags', 1); + +``` + +Signature: + +```typescript +export declare function arrayGet(arrayField: string, offset: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayField | string | The name of the array field. | +| offset | number | The index of the element to return. A new Expr representing the 'arrayGet' operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### arrayGet(arrayField, offsetExpr) {:#arrayget_1904c9a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet('tags', field('favoriteTag')); + +``` + +Signature: + +```typescript +export declare function arrayGet(arrayField: string, offsetExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayField | string | The name of the array field. | +| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expr evaluating to the index of the element to return. A new Expr representing the 'arrayGet' operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(arrayFieldName, ...) + +### join(arrayFieldName, delimiter) {:#join_478ef36} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + +```typescript +// Join the elements of the 'tags' field with a comma and space. +join("tags", ", ") + +``` + +Signature: + +```typescript +export declare function join(arrayFieldName: string, delimiter: string): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayFieldName | string | The name of the field containing the array. | +| delimiter | string | The string to use as a delimiter. A new Expression representing the join operation. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### join(arrayFieldName, delimiterExpression) {:#join_829294c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + +```typescript +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +join('tags', field("separator")) + +``` + +Signature: + +```typescript +export declare function join(arrayFieldName: string, delimiterExpression: Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayFieldName | string | The name of the field containing the array. | +| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. A new Expression representing the join operation. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +## function(base, ...) + +### pow(base, exponent) {:#pow_e4a9e64} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base expression raised to the power of the exponent expression. + +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow(field("base"), field("exponent")); + +``` + +Signature: + +```typescript +export declare function pow(base: Expression, exponent: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | +| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. A new Expr representing the power operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### pow(base, exponent) {:#pow_93eae7f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base expression raised to the power of the exponent. + +```typescript +// Raise the value of the 'base' field to the power of 2. +pow(field("base"), 2); + +``` + +Signature: + +```typescript +export declare function pow(base: Expression, exponent: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | +| exponent | number | The constant value to raise the base to the power of. A new Expr representing the power operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### pow(base, exponent) {:#pow_a237721} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base field raised to the power of the exponent expression. + +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow("base", field("exponent")); + +``` + +Signature: + +```typescript +export declare function pow(base: string, exponent: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| base | string | The name of the field to raise to the power of the exponent. | +| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. A new Expr representing the power operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### pow(base, exponent) {:#pow_f4d7908} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base field raised to the power of the exponent. + +```typescript +// Raise the value of the 'base' field to the power of 2. +pow("base", 2); + +``` + +Signature: + +```typescript +export declare function pow(base: string, exponent: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| base | string | The name of the field to raise to the power of the exponent. | +| exponent | number | The constant value to raise the base to the power of. A new Expr representing the power operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(booleanExpr, ...) + +### countIf(booleanExpr) {:#countif_c5b8fb1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. + +```typescript +// Count the number of documents where 'is_active' field equals true +countIf(field("is_active").equal(true)).as("numActiveDocuments"); + +``` + +Signature: + +```typescript +export declare function countIf(booleanExpr: BooleanExpression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| booleanExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The boolean expression to evaluate on each input. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'countIf' aggregation. + +### not(booleanExpr) {:#not_c5b8fb1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that negates a filter condition. + +```typescript +// Find documents where the 'completed' field is NOT true +not(equal("completed", true)); + +``` + +Signature: + +```typescript +export declare function not(booleanExpr: BooleanExpression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| booleanExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The filter condition to negate. A new representing the negated filter condition. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## function(condition, ...) + +### conditional(condition, thenExpr, elseExpr) {:#conditional_07a206d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. + +```typescript +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +conditional( + greaterThan("age", 18), constant("Adult"), constant("Minor")); + +``` + +Signature: + +```typescript +export declare function conditional(condition: BooleanExpression, thenExpr: Expression, elseExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| condition | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The condition to evaluate. | +| thenExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is true. | +| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. A new representing the conditional expression. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(documentPath, ...) + +### documentId(documentPath) {:#documentid_cef293c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the document ID from a path. + +```typescript +// Get the document ID from a path. +documentId(myDocumentReference); + +``` + A new representing the documentId operation. + +Signature: + +```typescript +export declare function documentId(documentPath: string | DocumentReference): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| documentPath | string \| [DocumentReference](./firestore_.documentreference.md#documentreference_class) | | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(documentPathExpr, ...) + +### documentId(documentPathExpr) {:#documentid_9a69021} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the document ID from a path. + +```typescript +// Get the document ID from a path. +documentId(field("__path__")); + +``` + A new representing the documentId operation. + +Signature: + +```typescript +export declare function documentId(documentPathExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| documentPathExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(element, ...) + +### notEqualAny(element, values) {:#notequalany_c2c5bcb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to any of the provided values or expressions. + +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + +Signature: + +```typescript +export declare function notEqualAny(element: Expression, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values to check against. A new representing the 'NOT IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### notEqualAny(element, arrayExpression) {:#notequalany_16b2851} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to any of the provided values or expressions. + +```typescript +// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + +Signature: + +```typescript +export declare function notEqualAny(element: Expression, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The values to check against. A new representing the 'NOT IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## function(elements, ...) + +### array(elements) {:#array_7d853aa} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that creates a Firestore array value from an input array. + +```typescript +// Create an array value from the input array and reference the 'baz' field value from the input document. +array(['bar', Field.of('baz')]).as('foo'); + +``` + +Signature: + +```typescript +export declare function array(elements: unknown[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elements | unknown\[\] | The input array to evaluate in the expression. A new representing the array function. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### map(elements) {:#map_ce5dee1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that creates a Firestore map value from an input object. + +```typescript +// Create a map from the input object and reference the 'baz' field value from the input document. +map({foo: 'bar', baz: Field.of('baz')}).as('data'); + +``` + +Signature: + +```typescript +export declare function map(elements: Record): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elements | Record<string, unknown> | The input map to evaluate in the expression. A new representing the map function. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(expr, ...) + +### abs(expr) {:#abs_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the absolute value of a numeric value. + +Signature: + +```typescript +export declare function abs(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compute the absolute value of. A new representing the absolute value of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### ascending(expr) {:#ascending_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an that sorts documents in ascending order based on an expression. + +```typescript +// Sort documents by the 'name' field in lowercase in ascending order +firestore.pipeline().collection("users") + .sort(ascending(field("name").toLower())); + +``` + +Signature: + +```typescript +export declare function ascending(expr: Expression): Ordering; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to create an ascending ordering for. A new Ordering for ascending sorting. | + +Returns: + +[Ordering](./firestore_pipelines.ordering.md#ordering_class) + +### byteLength(expr) {:#bytelength_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. + +```typescript +// Calculate the length of the 'myString' field in bytes. +byteLength(field("myString")); + +``` + +Signature: + +```typescript +export declare function byteLength(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string. A new representing the length of the string in bytes. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### countDistinct(expr) {:#countdistinct_3c28b08} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of distinct values of a field. + +Signature: + +```typescript +export declare function countDistinct(expr: Expression | string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) \| string | The expression or field to count distinct values of. A new AggregateFunction representing the 'count\_distinct' aggregation. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +### descending(expr) {:#descending_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an that sorts documents in descending order based on an expression. + +```typescript +// Sort documents by the 'name' field in lowercase in descending order +firestore.pipeline().collection("users") + .sort(descending(field("name").toLower())); + +``` + +Signature: + +```typescript +export declare function descending(expr: Expression): Ordering; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to create a descending ordering for. A new Ordering for descending sorting. | + +Returns: + +[Ordering](./firestore_pipelines.ordering.md#ordering_class) + +### floor(expr) {:#floor_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the floor of a numeric value. + +Signature: + +```typescript +export declare function floor(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compute the floor of. A new representing the floor of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### timestampToUnixMicros(expr) {:#timestamptounixmicros_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros(field("timestamp")); + +``` + +Signature: + +```typescript +export declare function timestampToUnixMicros(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. A new representing the number of microseconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### timestampToUnixMillis(expr) {:#timestamptounixmillis_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis(field("timestamp")); + +``` + +Signature: + +```typescript +export declare function timestampToUnixMillis(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. A new representing the number of milliseconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### timestampToUnixSeconds(expr) {:#timestamptounixseconds_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds(field("timestamp")); + +``` + +Signature: + +```typescript +export declare function timestampToUnixSeconds(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. A new representing the number of seconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### unixMicrosToTimestamp(expr) {:#unixmicrostotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp(field("microseconds")); + +``` + +Signature: + +```typescript +export declare function unixMicrosToTimestamp(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of microseconds since epoch. A new representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### unixMillisToTimestamp(expr) {:#unixmillistotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp(field("milliseconds")); + +``` + +Signature: + +```typescript +export declare function unixMillisToTimestamp(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of milliseconds since epoch. A new representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### unixSecondsToTimestamp(expr) {:#unixsecondstotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +```typescript +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp(field("seconds")); + +``` + +Signature: + +```typescript +export declare function unixSecondsToTimestamp(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of seconds since epoch. A new representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(expression, ...) + +### arraySum(expression) {:#arraysum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. + +```typescript +// Compute the sum of the elements in the 'scores' field. +arraySum(field("scores")); + +``` + +Signature: + +```typescript +export declare function arraySum(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric array, which the sum will be computed for. A new Expr representing the sum of the elements in the array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### average(expression) {:#average_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. + +```typescript +// Calculate the average age of users +average(field("age")).as("averageAge"); + +``` + +Signature: + +```typescript +export declare function average(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the values to average. A new representing the 'average' aggregation. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +### ceil(expression) {:#ceil_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. + +```typescript +// Compute the ceiling of the 'price' field. +ceil(field("price")); + +``` + +Signature: + +```typescript +export declare function ceil(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the ceiling will be computed for. A new representing the ceiling of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### collectionId(expression) {:#collectionid_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. + +```typescript +// Get the collection ID from a path. +collectionId(field("__name__")); + +``` + +Signature: + +```typescript +export declare function collectionId(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a path, which the collection ID will be extracted from. A new representing the collectionId operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### count(expression) {:#count_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. + +```typescript +// Count the number of items where the price is greater than 10 +count(field("price").greaterThan(10)).as("expensiveItemCount"); + +``` + +Signature: + +```typescript +export declare function count(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to count. A new representing the 'count' aggregation. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +### divide(expression, value) {:#divide_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides an expression by a constant value. + +```typescript +// Divide the 'value' field by 10 +divide(field("value"), 10); + +``` + +Signature: + +```typescript +export declare function divide(expression: Expression, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to be divided. | +| value | unknown | The constant value to divide by. A new representing the division operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### equal(expression, value) {:#equal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is equal to a constant value. + +```typescript +// Check if the 'age' field is equal to 21 +equal(field("age"), 21); + +``` + +Signature: + +```typescript +export declare function equal(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the equality comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### equalAny(expression, values) {:#equalany_7e759b5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. + +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny(field("category"), [constant("Electronics"), field("primaryType")]); + +``` + +Signature: + +```typescript +export declare function equalAny(expression: Expression, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression whose results to compare. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values to check against. A new representing the 'IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### equalAny(expression, arrayExpression) {:#equalany_214ce68} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is equal to any of the provided values. + +```typescript +// Check if the 'category' field is set to a value in the disabledCategories field +equalAny(field("category"), field('disabledCategories')); + +``` + +Signature: + +```typescript +export declare function equalAny(expression: Expression, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression whose results to compare. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input. A new representing the 'IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### exp(expression) {:#exp_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes e to the power of the expression's result. + +```typescript +// Compute e to the power of 2. +exp(constant(2)); + +``` + A new representing the exp of the numeric value. + +Signature: + +```typescript +export declare function exp(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### greaterThan(expression, value) {:#greaterthan_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is greater than a constant value. + +```typescript +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), 18); + +``` + +Signature: + +```typescript +export declare function greaterThan(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the greater than comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### greaterThanOrEqual(expression, value) {:#greaterthanorequal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is greater than or equal to a constant value. + +```typescript +// Check if the 'quantity' field is greater than or equal to 10 +greaterThanOrEqual(field("quantity"), 10); + +``` + +Signature: + +```typescript +export declare function greaterThanOrEqual(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the greater than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### length\_2(expression) {:#length_2_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string, array, map, vector, or bytes. + +```typescript +// Get the length of the 'name' field. +length(field("name")); + +// Get the number of items in the 'cart' array. +length(field("cart")); + +``` + +Signature: + +```typescript +declare function length_2(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. A new Expr representing the length of the string, array, map, vector, or bytes. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### lessThan(expression, value) {:#lessthan_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is less than a constant value. + +```typescript +// Check if the 'age' field is less than 30 +lessThan(field("age"), 30); + +``` + +Signature: + +```typescript +export declare function lessThan(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the less than comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### lessThanOrEqual(expression, value) {:#lessthanorequal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is less than or equal to a constant value. + +```typescript +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), 20); + +``` + +Signature: + +```typescript +export declare function lessThanOrEqual(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the less than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### ln(expression) {:#ln_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the natural logarithm of a numeric value. + +```typescript +// Compute the natural logarithm of the 'value' field. +ln(field("value")); + +``` + +Signature: + +```typescript +export declare function ln(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the natural logarithm will be computed for. A new Expr representing the natural logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### log(expression, base) {:#log_ac183e2} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of an expression to a given base. + +```typescript +// Compute the logarithm of the 'value' field with base 10. +log(field("value"), 10); + +``` + +Signature: + +```typescript +export declare function log(expression: Expression, base: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | +| base | number | The base of the logarithm. A new representing the logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### log(expression, base) {:#log_1894737} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of an expression to a given base. + +```typescript +// Compute the logarithm of the 'value' field with the base in the 'base' field. +log(field("value"), field("base")); + +``` + +Signature: + +```typescript +export declare function log(expression: Expression, base: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | +| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The base of the logarithm. A new representing the logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### log10(expression) {:#log10_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the base-10 logarithm of a numeric value. + +```typescript +// Compute the base-10 logarithm of the 'value' field. +log10(field("value")); + +``` + +Signature: + +```typescript +export declare function log10(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. A new Expr representing the base-10 logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### maximum(expression) {:#maximum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. + +```typescript +// Find the highest score in a leaderboard +maximum(field("score")).as("highestScore"); + +``` + +Signature: + +```typescript +export declare function maximum(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the maximum value of. A new representing the 'maximum' aggregation. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +### minimum(expression) {:#minimum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. + +```typescript +// Find the lowest price of all products +minimum(field("price")).as("lowestPrice"); + +``` + +Signature: + +```typescript +export declare function minimum(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the minimum value of. A new representing the 'minimum' aggregation. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +### mod(expression, value) {:#mod_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. + +```typescript +// Calculate the remainder of dividing 'field1' by 5. +mod(field("field1"), 5); + +``` + +Signature: + +```typescript +export declare function mod(expression: Expression, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The dividend expression. | +| value | unknown | The divisor constant. A new representing the modulo operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### notEqual(expression, value) {:#notequal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to a constant value. + +```typescript +// Check if the 'status' field is not equal to "completed" +notEqual(field("status"), "completed"); + +``` + +Signature: + +```typescript +export declare function notEqual(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the inequality comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### round(expression) {:#round_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the nearest whole number. + +```typescript +// Round the value of the 'price' field. +round(field("price")); + +``` + +Signature: + +```typescript +export declare function round(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. A new Expr representing the rounded value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### round(expression, decimalPlaces) {:#round_a3a92d0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + +```typescript +// Round the value of the 'price' field to two decimal places. +round(field("price"), constant(2)); + +``` + +Signature: + +```typescript +export declare function round(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | +| decimalPlaces | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. A new Expr representing the rounded value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### split(expression, delimiter) {:#split_5b5612b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that splits a string into an array of substrings based on the provided delimiter. + +Signature: + +```typescript +export declare function split(expression: Expression, delimiter: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | Split the result of this expression. | +| delimiter | string | Split on this delimiter. A new representing the split function. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Split the 'scoresCsv' field on delimiter ',' +split(field('scoresCsv'), ',') + +``` + +### split(expression, delimiter) {:#split_5a171ed} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that splits a string into an array of substrings based on the provided delimiter. + +Signature: + +```typescript +export declare function split(expression: Expression, delimiter: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | Split the result of this expression. | +| delimiter | [Expression](./firestore_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. A new representing the split function. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Split the 'scores' field on delimiter ',' or ':' depending on the stored format +split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':')) + +``` + +### sqrt(expression) {:#sqrt_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the square root of a numeric value. + +```typescript +// Compute the square root of the 'value' field. +sqrt(field("value")); + +``` + +Signature: + +```typescript +export declare function sqrt(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the square root will be computed for. A new representing the square root of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### subtract(expression, value) {:#subtract_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a constant value from an expression. + +```typescript +// Subtract the constant value 2 from the 'value' field +subtract(field("value"), 2); + +``` + +Signature: + +```typescript +export declare function subtract(expression: Expression, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract from. | +| value | unknown | The constant value to subtract. A new representing the subtraction operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### sum(expression) {:#sum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. + +```typescript +// Calculate the total revenue from a set of orders +sum(field("orderAmount")).as("totalRevenue"); + +``` + +Signature: + +```typescript +export declare function sum(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to sum up. A new representing the 'sum' aggregation. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +### type(expression) {:#type_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the data type of an expression's result. + +Signature: + +```typescript +export declare function type(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Get the data type of a conditional expression +type(conditional(exists('foo'), constant(1), constant(true))) + +``` + A new {Expression} representing the data type. + +## function(field, ...) + +### isAbsent(field) {:#isabsent_0fb8cd4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns `true` if a field is absent. Otherwise, returns `false` even if the field value is `null`. + +```typescript +// Check if the field `value` is absent. +isAbsent("value"); + +``` + +Signature: + +```typescript +export declare function isAbsent(field: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | string | The field to check. A new representing the 'isAbsent' check. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### reverse(field) {:#reverse_0fb8cd4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string value in the specified field. + +```typescript +// Reverse the value of the 'myString' field. +reverse("myString"); + +``` + +Signature: + +```typescript +export declare function reverse(field: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | string | The name of the field representing the string to reverse. A new representing the reversed string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### stringReverse(field) {:#stringreverse_0fb8cd4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string value in the specified field. + +```typescript +// Reverse the value of the 'myString' field. +strReverse("myString"); + +``` + +Signature: + +```typescript +export declare function stringReverse(field: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | string | The name of the field representing the string to reverse. A new representing the reversed string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### substring(field, position, length) {:#substring_0d9573a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a substring of a string or byte array. + +Signature: + +```typescript +export declare function substring(field: string, position: number, length?: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | string | The name of a field containing a string or byte array to compute the substring from. | +| position | number | Index of the first character of the substring. | +| length | number | Length of the substring. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### substring(field, position, length) {:#substring_05cb14e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a substring of a string or byte array. + +Signature: + +```typescript +export declare function substring(field: string, position: Expression, length?: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | string | The name of a field containing a string or byte array to compute the substring from. | +| position | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that returns the index of the first character of the substring. | +| length | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that returns the length of the substring. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(fieldName, ...) + +### abs(fieldName) {:#abs_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the absolute value of a numeric value. + +Signature: + +```typescript +export declare function abs(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field to compute the absolute value of. A new representing the absolute value of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### add(fieldName, second) {:#add_b75bb8b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a field's value to an expression. + +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +add("quantity", field("reserve")); + +``` + +Signature: + +```typescript +export declare function add(fieldName: string, second: Expression | unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the value to add. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### arrayContains(fieldName, element) {:#arraycontains_aaace4a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains a specific element. + +```typescript +// Check if the 'colors' array contains the value of field 'selectedColor' +arrayContains("colors", field("selectedColor")); + +``` + +Signature: + +```typescript +export declare function arrayContains(fieldName: string, element: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The element to search for in the array. A new representing the 'array\_contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContains(fieldName, element) {:#arraycontains_999590f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains a specific value. + +```typescript +// Check if the 'colors' array contains "red" +arrayContains("colors", "red"); + +``` + +Signature: + +```typescript +export declare function arrayContains(fieldName: string, element: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| element | unknown | The element to search for in the array. A new representing the 'array\_contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAll(fieldName, values) {:#arraycontainsall_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains all the specified values or expressions. + +```typescript +// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" +arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); + +``` + +Signature: + +```typescript +export declare function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new representing the 'array\_contains\_all' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAll(fieldName, arrayExpression) {:#arraycontainsall_48da8d9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains all the specified values or expressions. + +```typescript +// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" +arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); + +``` + +Signature: + +```typescript +export declare function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. A new representing the 'array\_contains\_all' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAny(fieldName, values) {:#arraycontainsany_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains any of the specified elements. + +```typescript +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +arrayContainsAny("categories", [field("cate1"), "Science"]); + +``` + +Signature: + +```typescript +export declare function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new representing the 'array\_contains\_any' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayContainsAny(fieldName, values) {:#arraycontainsany_1b4f7cd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains any of the specified elements. + +```typescript +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +arrayContainsAny("categories", array([field("cate1"), "Science"])); + +``` + +Signature: + +```typescript +export declare function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| values | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array field. A new representing the 'array\_contains\_any' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### arrayLength(fieldName) {:#arraylength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of an array in a specified field. + +```typescript +// Get the number of items in field 'cart' +arrayLength('cart'); + +``` + +Signature: + +```typescript +export declare function arrayLength(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing an array to calculate the length of. A new representing the length of the array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### arraySum(fieldName) {:#arraysum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. + +```typescript +// Compute the sum of the elements in the 'scores' field. +arraySum("scores"); + +``` + +Signature: + +```typescript +export declare function arraySum(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the sum of. A new Expr representing the sum of the elements in the array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### ascending(fieldName) {:#ascending_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an that sorts documents in ascending order based on a field. + +```typescript +// Sort documents by the 'name' field in ascending order +firestore.pipeline().collection("users") + .sort(ascending("name")); + +``` + +Signature: + +```typescript +export declare function ascending(fieldName: string): Ordering; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field to create an ascending ordering for. A new Ordering for ascending sorting. | + +Returns: + +[Ordering](./firestore_pipelines.ordering.md#ordering_class) + +### average(fieldName) {:#average_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. + +```typescript +// Calculate the average age of users +average("age").as("averageAge"); + +``` + +Signature: + +```typescript +export declare function average(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing numeric values to average. A new representing the 'average' aggregation. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +### byteLength(fieldName) {:#bytelength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. + +```typescript +// Calculate the length of the 'myString' field in bytes. +byteLength("myString"); + +``` + +Signature: + +```typescript +export declare function byteLength(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. A new representing the length of the string in bytes. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### ceil(fieldName) {:#ceil_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. + +```typescript +// Compute the ceiling of the 'price' field. +ceil("price"); + +``` + +Signature: + +```typescript +export declare function ceil(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the ceiling of. A new representing the ceiling of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### charLength(fieldName) {:#charlength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the character length of a string field in UTF8. + +```typescript +// Get the character length of the 'name' field in UTF-8. +strLength("name"); + +``` + +Signature: + +```typescript +export declare function charLength(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. A new representing the length of the string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### collectionId(fieldName) {:#collectionid_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. + +```typescript +// Get the collection ID from a path. +collectionId("__name__"); + +``` + +Signature: + +```typescript +export declare function collectionId(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to get the collection ID from. A new representing the collectionId operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### concat(fieldName, second, others) {:#concat_828272e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. + +```typescript +// Concatenate a field with a literal string. +concat(field("firstName"), "Doe") + +``` + +Signature: + +```typescript +export declare function concat(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of a field to concatenate. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second literal or expression to concatenate. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Additional literal or expressions to concatenate. A new Expression representing the concatenation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### cosineDistance(fieldName, vector) {:#cosinedistance_463a23e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between a field's vector value and a literal vector value. + +```typescript +// Calculate the Cosine distance between the 'location' field and a target location +cosineDistance("location", [37.7749, -122.4194]); + +``` + +Signature: + +```typescript +export declare function cosineDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the first vector. | +| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles) or [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) to compare against. A new representing the Cosine distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### cosineDistance(fieldName, vectorExpression) {:#cosinedistance_ed766a1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between a field's vector value and a vector expression. + +```typescript +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +cosineDistance("userVector", field("itemVector")); + +``` + +Signature: + +```typescript +export declare function cosineDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the first vector. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the cosine distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### count(fieldName) {:#count_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs where the input field exists. + +```typescript +// Count the total number of products +count("productId").as("totalProducts"); + +``` + +Signature: + +```typescript +export declare function count(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to count. A new representing the 'count' aggregation. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +### descending(fieldName) {:#descending_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an that sorts documents in descending order based on a field. + +```typescript +// Sort documents by the 'name' field in descending order +firestore.pipeline().collection("users") + .sort(descending("name")); + +``` + +Signature: + +```typescript +export declare function descending(fieldName: string): Ordering; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field to create a descending ordering for. A new Ordering for descending sorting. | + +Returns: + +[Ordering](./firestore_pipelines.ordering.md#ordering_class) + +### divide(fieldName, expressions) {:#divide_cf36e43} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides a field's value by an expression. + +```typescript +// Divide the 'total' field by the 'count' field +divide("total", field("count")); + +``` + +Signature: + +```typescript +export declare function divide(fieldName: string, expressions: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to be divided. | +| expressions | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to divide by. A new representing the division operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### divide(fieldName, value) {:#divide_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides a field's value by a constant value. + +```typescript +// Divide the 'value' field by 10 +divide("value", 10); + +``` + +Signature: + +```typescript +export declare function divide(fieldName: string, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to be divided. | +| value | unknown | The constant value to divide by. A new representing the division operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### dotProduct(fieldName, vector) {:#dotproduct_463a23e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between a field's vector value and a double array. + +```typescript +// Calculate the dot product distance between a feature vector and a target vector +dotProduct("features", [0.5, 0.8, 0.2]); + +``` + +Signature: + +```typescript +export declare function dotProduct(fieldName: string, vector: number[] | VectorValue): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the first vector. | +| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to calculate with. A new representing the dot product between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### dotProduct(fieldName, vectorExpression) {:#dotproduct_ed766a1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between a field's vector value and a vector expression. + +```typescript +// Calculate the dot product distance between two document vectors: 'docVector1' and 'docVector2' +dotProduct("docVector1", field("docVector2")); + +``` + +Signature: + +```typescript +export declare function dotProduct(fieldName: string, vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the first vector. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to calculate with. A new representing the dot product between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### endsWith(fieldName, suffix) {:#endswith_05ca3b0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value ends with a given postfix. + +```typescript +// Check if the 'filename' field ends with ".txt" +endsWith("filename", ".txt"); + +``` + +Signature: + +```typescript +export declare function endsWith(fieldName: string, suffix: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| suffix | string | The postfix to check for. A new representing the 'ends with' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### endsWith(fieldName, suffix) {:#endswith_8fc0ebc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value ends with a given postfix. + +```typescript +// Check if the 'url' field ends with the value of the 'extension' field +endsWith("url", field("extension")); + +``` + +Signature: + +```typescript +export declare function endsWith(fieldName: string, suffix: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| suffix | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the postfix. A new representing the 'ends with' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### equal(fieldName, expression) {:#equal_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to an expression. + +```typescript +// Check if the 'age' field is equal to the 'limit' field +equal("age", field("limit")); + +``` + +Signature: + +```typescript +export declare function equal(fieldName: string, expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the equality comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### equal(fieldName, value) {:#equal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to a constant value. + +```typescript +// Check if the 'city' field is equal to string constant "London" +equal("city", "London"); + +``` + +Signature: + +```typescript +export declare function equal(fieldName: string, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the equality comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### equalAny(fieldName, values) {:#equalany_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to any of the provided values or expressions. + +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny("category", [constant("Electronics"), field("primaryType")]); + +``` + +Signature: + +```typescript +export declare function equalAny(fieldName: string, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field to compare. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values to check against. A new representing the 'IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### equalAny(fieldName, arrayExpression) {:#equalany_48da8d9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to any of the provided values or expressions. + +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny("category", ["Electronics", field("primaryType")]); + +``` + +Signature: + +```typescript +export declare function equalAny(fieldName: string, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field to compare. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input field. A new representing the 'IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### euclideanDistance(fieldName, vector) {:#euclideandistance_463a23e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between a field's vector value and a double array. + +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location +euclideanDistance("location", [37.7749, -122.4194]); + +``` + +Signature: + +```typescript +export declare function euclideanDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the first vector. | +| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. A new representing the Euclidean distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### euclideanDistance(fieldName, vectorExpression) {:#euclideandistance_ed766a1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between a field's vector value and a vector expression. + +```typescript +// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' +euclideanDistance("pointA", field("pointB")); + +``` + +Signature: + +```typescript +export declare function euclideanDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the first vector. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the Euclidean distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### exists(fieldName) {:#exists_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field exists. + +```typescript +// Check if the document has a field named "phoneNumber" +exists("phoneNumber"); + +``` + +Signature: + +```typescript +export declare function exists(fieldName: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. A new representing the 'exists' check. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### exp(fieldName) {:#exp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes e to the power of the expression's result. + +```typescript +// Compute e to the power of the 'value' field. +exp('value'); + +``` + A new representing the exp of the numeric value. + +Signature: + +```typescript +export declare function exp(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### floor(fieldName) {:#floor_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the floor of a numeric value. + +Signature: + +```typescript +export declare function floor(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the floor of. A new representing the floor of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### greaterThan(fieldName, expression) {:#greaterthan_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than an expression. + +```typescript +// Check if the value of field 'age' is greater than the value of field 'limit' +greaterThan("age", field("limit")); + +``` + +Signature: + +```typescript +export declare function greaterThan(fieldName: string, expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the greater than comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### greaterThan(fieldName, value) {:#greaterthan_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than a constant value. + +```typescript +// Check if the 'price' field is greater than 100 +greaterThan("price", 100); + +``` + +Signature: + +```typescript +export declare function greaterThan(fieldName: string, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the greater than comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_2e16acb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than or equal to an expression. + +```typescript +// Check if the value of field 'age' is greater than or equal to the value of field 'limit' +greaterThanOrEqual("age", field("limit")); + +``` + +Signature: + +```typescript +export declare function greaterThanOrEqual(fieldName: string, value: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the greater than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than or equal to a constant value. + +```typescript +// Check if the 'score' field is greater than or equal to 80 +greaterThanOrEqual("score", 80); + +``` + +Signature: + +```typescript +export declare function greaterThanOrEqual(fieldName: string, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the greater than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### length\_2(fieldName) {:#length_2_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string, array, map, vector, or bytes. + +```typescript +// Get the length of the 'name' field. +length("name"); + +// Get the number of items in the 'cart' array. +length("cart"); + +``` + +Signature: + +```typescript +declare function length_2(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to calculate the length of. A new Expr representing the length of the string, array, map, vector, or bytes. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### lessThan(fieldName, expression) {:#lessthan_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than an expression. + +```typescript +// Check if the 'age' field is less than the 'limit' field +lessThan("age", field("limit")); + +``` + +Signature: + +```typescript +export declare function lessThan(fieldName: string, expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the less than comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### lessThan(fieldName, value) {:#lessthan_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than a constant value. + +```typescript +// Check if the 'price' field is less than 50 +lessThan("price", 50); + +``` + +Signature: + +```typescript +export declare function lessThan(fieldName: string, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the less than comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### lessThanOrEqual(fieldName, expression) {:#lessthanorequal_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than or equal to an expression. + +```typescript +// Check if the 'quantity' field is less than or equal to the 'limit' field +lessThan("quantity", field("limit")); + +``` + +Signature: + +```typescript +export declare function lessThanOrEqual(fieldName: string, expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the less than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### lessThanOrEqual(fieldName, value) {:#lessthanorequal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than or equal to a constant value. + +```typescript +// Check if the 'score' field is less than or equal to 70 +lessThan("score", 70); + +``` + +Signature: + +```typescript +export declare function lessThanOrEqual(fieldName: string, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the less than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### like(fieldName, pattern) {:#like_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison against a field. + +```typescript +// Check if the 'title' field contains the string "guide" +like("title", "%guide%"); + +``` + +Signature: + +```typescript +export declare function like(fieldName: string, pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| pattern | string | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### like(fieldName, pattern) {:#like_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison against a field. + +```typescript +// Check if the 'title' field contains the string "guide" +like("title", field("pattern")); + +``` + +Signature: + +```typescript +export declare function like(fieldName: string, pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### ln(fieldName) {:#ln_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the natural logarithm of a numeric value. + +```typescript +// Compute the natural logarithm of the 'value' field. +ln("value"); + +``` + +Signature: + +```typescript +export declare function ln(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the natural logarithm of. A new Expr representing the natural logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### log(fieldName, base) {:#log_a89e21b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of a field to a given base. + +```typescript +// Compute the logarithm of the 'value' field with base 10. +log("value", 10); + +``` + +Signature: + +```typescript +export declare function log(fieldName: string, base: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the logarithm of. | +| base | number | The base of the logarithm. A new representing the logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### log(fieldName, base) {:#log_805b11f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of a field to a given base. + +```typescript +// Compute the logarithm of the 'value' field with the base in the 'base' field. +log("value", field("base")); + +``` + +Signature: + +```typescript +export declare function log(fieldName: string, base: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the logarithm of. | +| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The base of the logarithm. A new representing the logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### log10(fieldName) {:#log10_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the base-10 logarithm of a numeric value. + +```typescript +// Compute the base-10 logarithm of the 'value' field. +log10("value"); + +``` + +Signature: + +```typescript +export declare function log10(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the base-10 logarithm of. A new Expr representing the base-10 logarithm of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### logicalMaximum(fieldName, second, others) {:#logicalmaximum_828272e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. + +```typescript +// Returns the largest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMaximum("field1", field("field2"), 1000); + +``` + +Signature: + +```typescript +export declare function logicalMaximum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The first operand field name. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical maximum operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### logicalMinimum(fieldName, second, others) {:#logicalminimum_828272e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. + +```typescript +// Returns the smallest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMinimum("field1", field("field2"), 1000); + +``` + +Signature: + +```typescript +export declare function logicalMinimum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The first operand field name. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical minimum operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### mapGet(fieldName, subField) {:#mapget_06663cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Accesses a value from a map (object) field using the provided key. + +```typescript +// Get the 'city' value from the 'address' map field +mapGet("address", "city"); + +``` + +Signature: + +```typescript +export declare function mapGet(fieldName: string, subField: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name of the map field. | +| subField | string | The key to access in the map. A new representing the value associated with the given key in the map. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### maximum(fieldName) {:#maximum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the maximum value of a field across multiple stage inputs. + +```typescript +// Find the highest score in a leaderboard +maximum("score").as("highestScore"); + +``` + +Signature: + +```typescript +export declare function maximum(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to find the maximum value of. A new representing the 'maximum' aggregation. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +### minimum(fieldName) {:#minimum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the minimum value of a field across multiple stage inputs. + +```typescript +// Find the lowest price of all products +minimum("price").as("lowestPrice"); + +``` + +Signature: + +```typescript +export declare function minimum(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to find the minimum value of. A new representing the 'minimum' aggregation. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +### mod(fieldName, expression) {:#mod_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. + +```typescript +// Calculate the remainder of dividing 'field1' by 'field2'. +mod("field1", field("field2")); + +``` + +Signature: + +```typescript +export declare function mod(fieldName: string, expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The dividend field name. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The divisor expression. A new representing the modulo operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### mod(fieldName, value) {:#mod_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. + +```typescript +// Calculate the remainder of dividing 'field1' by 5. +mod("field1", 5); + +``` + +Signature: + +```typescript +export declare function mod(fieldName: string, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The dividend field name. | +| value | unknown | The divisor constant. A new representing the modulo operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### multiply(fieldName, second) {:#multiply_b75bb8b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that multiplies a field's value by an expression. + +```typescript +// Multiply the 'quantity' field by the 'price' field +multiply("quantity", field("price")); + +``` + +Signature: + +```typescript +export declare function multiply(fieldName: string, second: Expression | unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the value to add. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### notEqual(fieldName, expression) {:#notequal_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to an expression. + +```typescript +// Check if the 'status' field is not equal to the value of 'expectedStatus' +notEqual("status", field("expectedStatus")); + +``` + +Signature: + +```typescript +export declare function notEqual(fieldName: string, expression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the inequality comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### notEqual(fieldName, value) {:#notequal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to a constant value. + +```typescript +// Check if the 'country' field is not equal to "USA" +notEqual("country", "USA"); + +``` + +Signature: + +```typescript +export declare function notEqual(fieldName: string, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| value | unknown | The constant value to compare to. A new Expr representing the inequality comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### notEqualAny(fieldName, values) {:#notequalany_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. + +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +notEqualAny("status", [constant("pending"), field("rejectedStatus")]); + +``` + +Signature: + +```typescript +export declare function notEqualAny(fieldName: string, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values to check against. A new representing the 'NOT IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### notEqualAny(fieldName, arrayExpression) {:#notequalany_48da8d9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. + +```typescript +// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' +notEqualAny("status", field("rejectedStatuses")); + +``` + +Signature: + +```typescript +export declare function notEqualAny(fieldName: string, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to compare. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The values to check against. A new representing the 'NOT IN' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### regexContains(fieldName, pattern) {:#regexcontains_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a specified regular expression as a substring. + +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains("description", "(?i)example"); + +``` + +Signature: + +```typescript +export declare function regexContains(fieldName: string, pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| pattern | string | The regular expression to use for the search. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### regexContains(fieldName, pattern) {:#regexcontains_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a specified regular expression as a substring. + +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains("description", field("pattern")); + +``` + +Signature: + +```typescript +export declare function regexContains(fieldName: string, pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the search. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### regexMatch(fieldName, pattern) {:#regexmatch_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field matches a specified regular expression. + +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + +``` + +Signature: + +```typescript +export declare function regexMatch(fieldName: string, pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| pattern | string | The regular expression to use for the match. A new representing the regular expression match. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### regexMatch(fieldName, pattern) {:#regexmatch_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field matches a specified regular expression. + +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch("email", field("pattern")); + +``` + +Signature: + +```typescript +export declare function regexMatch(fieldName: string, pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the match. A new representing the regular expression match. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### round(fieldName) {:#round_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the nearest whole number. + +```typescript +// Round the value of the 'price' field. +round("price"); + +``` + +Signature: + +```typescript +export declare function round(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to round. A new Expr representing the rounded value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### round(fieldName, decimalPlaces) {:#round_07d0cf0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + +```typescript +// Round the value of the 'price' field to two decimal places. +round("price", 2); + +``` + +Signature: + +```typescript +export declare function round(fieldName: string, decimalPlaces: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to round. | +| decimalPlaces | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. A new Expr representing the rounded value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### split(fieldName, delimiter) {:#split_2cfdd37} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that splits the value of a field on the provided delimiter. + +Signature: + +```typescript +export declare function split(fieldName: string, delimiter: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | Split the value in this field. | +| delimiter | string | Split on this delimiter. A new representing the split function. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Split the 'scoresCsv' field on delimiter ',' +split('scoresCsv', ',') + +``` + +### split(fieldName, delimiter) {:#split_f4fe06a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that splits the value of a field on the provided delimiter. + +Signature: + +```typescript +export declare function split(fieldName: string, delimiter: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | Split the value in this field. | +| delimiter | [Expression](./firestore_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. A new representing the split function. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Split the 'scores' field on delimiter ',' or ':' depending on the stored format +split('scores', conditional(field('format').equal('csv'), constant(','), constant(':')) + +``` + +### sqrt(fieldName) {:#sqrt_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the square root of a numeric value. + +```typescript +// Compute the square root of the 'value' field. +sqrt("value"); + +``` + +Signature: + +```typescript +export declare function sqrt(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the square root of. A new representing the square root of the numeric value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### startsWith(fieldName, prefix) {:#startswith_89325cc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value starts with a given prefix. + +```typescript +// Check if the 'name' field starts with "Mr." +startsWith("name", "Mr."); + +``` + +Signature: + +```typescript +export declare function startsWith(fieldName: string, prefix: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| prefix | string | The prefix to check for. A new representing the 'starts with' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### startsWith(fieldName, prefix) {:#startswith_266c338} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value starts with a given prefix. + +```typescript +// Check if the 'fullName' field starts with the value of the 'firstName' field +startsWith("fullName", field("firstName")); + +``` + +Signature: + +```typescript +export declare function startsWith(fieldName: string, prefix: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| prefix | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the prefix. A new representing the 'starts with' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### stringConcat(fieldName, secondString, otherStrings) {:#stringconcat_d80077e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates string functions, fields or constants together. + +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +stringConcat("firstName", " ", field("lastName")); + +``` + +Signature: + +```typescript +export declare function stringConcat(fieldName: string, secondString: Expression | string, ...otherStrings: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name containing the initial string value. | +| secondString | [Expression](./firestore_pipelines.expression.md#expression_class) \| string | An expression or string literal to concatenate. | +| otherStrings | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or literals (typically strings) to concatenate. A new representing the concatenated string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### stringContains(fieldName, substring) {:#stringcontains_5b94cfe} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a specified substring. + +```typescript +// Check if the 'description' field contains "example". +stringContains("description", "example"); + +``` + +Signature: + +```typescript +export declare function stringContains(fieldName: string, substring: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| substring | string | The substring to search for. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### stringContains(fieldName, substring) {:#stringcontains_ac3ba47} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a substring specified by an expression. + +```typescript +// Check if the 'description' field contains the value of the 'keyword' field. +stringContains("description", field("keyword")); + +``` + +Signature: + +```typescript +export declare function stringContains(fieldName: string, substring: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | +| substring | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the substring to search for. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### subtract(fieldName, expression) {:#subtract_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts an expression from a field's value. + +```typescript +// Subtract the 'discount' field from the 'price' field +subtract("price", field("discount")); + +``` + +Signature: + +```typescript +export declare function subtract(fieldName: string, expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to subtract from. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract. A new representing the subtraction operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### subtract(fieldName, value) {:#subtract_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a constant value from a field's value. + +```typescript +// Subtract 20 from the value of the 'total' field +subtract("total", 20); + +``` + +Signature: + +```typescript +export declare function subtract(fieldName: string, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to subtract from. | +| value | unknown | The constant value to subtract. A new representing the subtraction operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### sum(fieldName) {:#sum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. + +```typescript +// Calculate the total revenue from a set of orders +sum("orderAmount").as("totalRevenue"); + +``` + +Signature: + +```typescript +export declare function sum(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing numeric values to sum up. A new representing the 'sum' aggregation. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +### timestampAdd(fieldName, unit, amount) {:#timestampadd_341fe7d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to a timestamp represented by a field. + +```typescript +// Add 1 day to the 'timestamp' field. +timestampAdd("timestamp", "day", 1); + +``` + +Signature: + +```typescript +export declare function timestampAdd(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | +| amount | number | The amount of time to add. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_341fe7d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. + +```typescript +// Subtract 1 day from the 'timestamp' field. +timestampSubtract("timestamp", "day", 1); + +``` + +Signature: + +```typescript +export declare function timestampSubtract(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | +| amount | number | The amount of time to subtract. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### timestampToUnixMicros(fieldName) {:#timestamptounixmicros_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros("timestamp"); + +``` + +Signature: + +```typescript +export declare function timestampToUnixMicros(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. A new representing the number of microseconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### timestampToUnixMillis(fieldName) {:#timestamptounixmillis_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis("timestamp"); + +``` + +Signature: + +```typescript +export declare function timestampToUnixMillis(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. A new representing the number of milliseconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### timestampToUnixSeconds(fieldName) {:#timestamptounixseconds_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +```typescript +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds("timestamp"); + +``` + +Signature: + +```typescript +export declare function timestampToUnixSeconds(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. A new representing the number of seconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### timestampTruncate(fieldName, granularity, timezone) {:#timestamptruncate_b6c7512} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a timestamp to a specified granularity. + +Signature: + +```typescript +export declare function timestampTruncate(fieldName: string, granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | Truncate the timestamp value contained in this field. | +| granularity | [TimeGranularity](./firestore_pipelines.md#timegranularity) | The granularity to truncate to. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Truncate the 'createdAt' timestamp to the beginning of the day. +field('createdAt').timestampTruncate('day') + +``` + +### timestampTruncate(fieldName, granularity, timezone) {:#timestamptruncate_ed83d46} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a timestamp to a specified granularity. + +Signature: + +```typescript +export declare function timestampTruncate(fieldName: string, granularity: Expression, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | Truncate the timestamp value contained in this field. | +| granularity | [Expression](./firestore_pipelines.expression.md#expression_class) | The granularity to truncate to. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. +field('createdAt').timestampTruncate(field('granularity')) + +``` + +### toLower(fieldName) {:#tolower_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string field to lowercase. + +```typescript +// Convert the 'name' field to lowercase +toLower("name"); + +``` + +Signature: + +```typescript +export declare function toLower(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. A new representing the lowercase string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### toUpper(fieldName) {:#toupper_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string field to uppercase. + +```typescript +// Convert the 'title' field to uppercase +toUpper("title"); + +``` + +Signature: + +```typescript +export declare function toUpper(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. A new representing the uppercase string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### trim(fieldName, valueToTrim) {:#trim_c9f90ee} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes leading and trailing whitespace from a string or byte array. + +```typescript +// Trim whitespace from the 'userInput' field +trim("userInput"); + +// Trim quotes from the 'userInput' field +trim("userInput", '"'); + +``` + +Signature: + +```typescript +export declare function trim(fieldName: string, valueToTrim?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | 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. A new representing the trimmed string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### type(fieldName) {:#type_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the data type of the data in the specified field. + +Signature: + +```typescript +export declare function type(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Get the data type of the value in field 'title' +type('title') + +``` + A new {Expression} representing the data type. + +### unixMicrosToTimestamp(fieldName) {:#unixmicrostotimestamp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp("microseconds"); + +``` + +Signature: + +```typescript +export declare function unixMicrosToTimestamp(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the number of microseconds since epoch. A new representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### unixMillisToTimestamp(fieldName) {:#unixmillistotimestamp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp("milliseconds"); + +``` + +Signature: + +```typescript +export declare function unixMillisToTimestamp(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the number of milliseconds since epoch. A new representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### unixSecondsToTimestamp(fieldName) {:#unixsecondstotimestamp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +```typescript +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp("seconds"); + +``` + +Signature: + +```typescript +export declare function unixSecondsToTimestamp(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the number of seconds since epoch. A new representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### vectorLength(fieldName) {:#vectorlength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a Firestore Vector represented by a field. + +```typescript +// Get the vector length (dimension) of the field 'embedding'. +vectorLength("embedding"); + +``` + +Signature: + +```typescript +export declare function vectorLength(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the Firestore Vector. A new representing the length of the array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(first, ...) + +### add(first, second) {:#add_846ca1b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds two expressions together. + +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +add(field("quantity"), field("reserve")); + +``` + +Signature: + +```typescript +export declare function add(first: Expression, second: Expression | unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to add. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### and(first, second, more) {:#and_e0c48bd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'AND' operation on multiple filter conditions. + +```typescript +// Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND +// the 'status' field is "active" +const condition = and(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); + +``` + +Signature: + +```typescript +export declare function and(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The first filter condition. | +| second | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The second filter condition. | +| more | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'AND' together. A new representing the logical 'AND' operation. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### concat(first, second, others) {:#concat_83be015} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. + +```typescript +// Concatenate the 'firstName' and 'lastName' fields with a space in between. +concat(field("firstName"), " ", field("lastName")) + +``` + +Signature: + +```typescript +export declare function concat(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expressions to concatenate. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second literal or expression to concatenate. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Additional literals or expressions to concatenate. A new Expression representing the concatenation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### logicalMaximum(first, second, others) {:#logicalmaximum_83be015} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. + +```typescript +// Returns the largest value between the 'field1' field, the 'field2' field, +// and 1000 +logicalMaximum(field("field1"), field("field2"), 1000); + +``` + +Signature: + +```typescript +export declare function logicalMaximum(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [Expression](./firestore_pipelines.expression.md#expression_class) | The first operand expression. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical maximum operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### logicalMinimum(first, second, others) {:#logicalminimum_83be015} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. + +```typescript +// Returns the smallest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMinimum(field("field1"), field("field2"), 1000); + +``` + +Signature: + +```typescript +export declare function logicalMinimum(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [Expression](./firestore_pipelines.expression.md#expression_class) | The first operand expression. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical minimum operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### multiply(first, second) {:#multiply_846ca1b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that multiplies two expressions together. + +```typescript +// Multiply the 'quantity' field by the 'price' field +multiply(field("quantity"), field("price")); + +``` + +Signature: + +```typescript +export declare function multiply(first: Expression, second: Expression | unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to multiply. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to multiply. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### or(first, second, more) {:#or_e0c48bd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'OR' operation on multiple filter conditions. + +```typescript +// Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR +// the 'status' field is "active" +const condition = or(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); + +``` + +Signature: + +```typescript +export declare function or(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The first filter condition. | +| second | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The second filter condition. | +| more | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'OR' together. A new representing the logical 'OR' operation. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### xor(first, second, additionalConditions) {:#xor_8197113} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. + +```typescript +// Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London", +// or 'status' is "active". +const condition = xor( + greaterThan("age", 18), + equal("city", "London"), + equal("status", "active")); + +``` + +Signature: + +```typescript +export declare function xor(first: BooleanExpression, second: BooleanExpression, ...additionalConditions: BooleanExpression[]): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The first condition. | +| second | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The second condition. | +| additionalConditions | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional conditions to 'XOR' together. A new representing the logical 'XOR' operation. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## function(firstArray, ...) + +### arrayConcat(firstArray, secondArray, otherArrays) {:#arrayconcat_c00d5d7} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates an array expression with other arrays. + +```typescript +// Combine the 'items' array with two new item arrays +arrayConcat(field("items"), [field("newItems"), field("otherItems")]); + +``` + +Signature: + +```typescript +export declare function arrayConcat(firstArray: Expression, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| firstArray | [Expression](./firestore_pipelines.expression.md#expression_class) | The first array expression to concatenate to. | +| secondArray | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\] | The second array expression or array literal to concatenate to. | +| otherArrays | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. A new representing the concatenated array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(firstArrayField, ...) + +### arrayConcat(firstArrayField, secondArray, otherArrays) {:#arrayconcat_f92063d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates a field's array value with other arrays. + +```typescript +// Combine the 'items' array with two new item arrays +arrayConcat("items", [field("newItems"), field("otherItems")]); + +``` + +Signature: + +```typescript +export declare function arrayConcat(firstArrayField: string, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| firstArrayField | string | The first array to concatenate to. | +| secondArray | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\] | The second array expression or array literal to concatenate to. | +| otherArrays | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. A new representing the concatenated array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(firstMap, ...) + +### mapMerge(firstMap, secondMap, otherMaps) {:#mapmerge_cfe77ce} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that merges multiple map values. + +``` +// Merges the map in the settings field with, a map literal, and a map in +// that is conditionally returned by another expression +mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) + +``` + +Signature: + +```typescript +export declare function mapMerge(firstMap: Record | Expression, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| firstMap | Record<string, unknown> \| [Expression](./firestore_pipelines.expression.md#expression_class) | An expression or literal map value that will be merged. | +| secondMap | Record<string, unknown> \| [Expression](./firestore_pipelines.expression.md#expression_class) | A required second map to merge. Represented as a literal or an expression that returns a map. | +| otherMaps | Array<Record<string, unknown> \| [Expression](./firestore_pipelines.expression.md#expression_class)> | Optional additional maps to merge. Each map is represented as a literal or an expression that returns a map. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(firstString, ...) + +### stringConcat(firstString, secondString, otherStrings) {:#stringconcat_8a8d1b6} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates string expressions together. + +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +stringConcat(field("firstName"), " ", field("lastName")); + +``` + +Signature: + +```typescript +export declare function stringConcat(firstString: Expression, secondString: Expression | string, ...otherStrings: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| firstString | [Expression](./firestore_pipelines.expression.md#expression_class) | The initial string expression to concatenate to. | +| secondString | [Expression](./firestore_pipelines.expression.md#expression_class) \| string | An expression or string literal to concatenate. | +| otherStrings | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or literals (typically strings) to concatenate. A new representing the concatenated string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(ifExpr, ...) + +### ifAbsent(ifExpr, elseExpr) {:#ifabsent_0e6d161} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseExpr` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent(field("optional_field"), constant("default_value")) + +``` + +Signature: + +```typescript +export declare function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check for absence. | +| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if \[ifExpr\] is absent. A new Expression representing the ifAbsent operation. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### ifAbsent(ifExpr, elseValue) {:#ifabsent_c34e5ed} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent(field("optional_field"), "default_value") + +``` + +Signature: + +```typescript +export declare function ifAbsent(ifExpr: Expression, elseValue: unknown): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check for absence. | +| elseValue | unknown | The value that will be returned if ifExpr evaluates to an absent value. A new \[Expression\] representing the ifAbsent operation. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +## function(ifFieldName, ...) + +### ifAbsent(ifFieldName, elseExpr) {:#ifabsent_e6dabea} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseExpr` argument if `ifFieldName` is absent, else return the value of the field. + +```typescript +// Returns the value of the optional field 'optional_field', or returns the value of +// 'default_field' if 'optional_field' is absent. +ifAbsent("optional_field", field("default_field")) + +``` + +Signature: + +```typescript +export declare function ifAbsent(ifFieldName: string, elseExpr: Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifFieldName | string | The field to check for absence. | +| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if ifFieldName is absent. A new Expression representing the ifAbsent operation. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### ifAbsent(ifFieldName, elseValue) {:#ifabsent_d8f2823} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if `ifFieldName` is absent, else return the value of the field. + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent("optional_field", "default_value") + +``` + +Signature: + +```typescript +export declare function ifAbsent(ifFieldName: string | Expression, elseValue: Expression | unknown): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifFieldName | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The field to check for absence. | +| elseValue | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The value that will be returned if \[ifFieldName\] is absent. A new Expression representing the ifAbsent operation. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +## function(input, ...) + +### substring(input, position, length) {:#substring_e6e0aa3} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a substring of a string or byte array. + +Signature: + +```typescript +export declare function substring(input: Expression, position: number, length?: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| input | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression returning a string or byte array to compute the substring from. | +| position | number | Index of the first character of the substring. | +| length | number | Length of the substring. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### substring(input, position, length) {:#substring_ab56dc6} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a substring of a string or byte array. + +Signature: + +```typescript +export declare function substring(input: Expression, position: Expression, length?: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| input | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression returning a string or byte array to compute the substring from. | +| position | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that returns the index of the first character of the substring. | +| length | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that returns the length of the substring. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(left, ...) + +### divide(left, right) {:#divide_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides two expressions. + +```typescript +// Divide the 'total' field by the 'count' field +divide(field("total"), field("count")); + +``` + +Signature: + +```typescript +export declare function divide(left: Expression, right: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to be divided. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to divide by. A new representing the division operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### equal(left, right) {:#equal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if two expressions are equal. + +```typescript +// Check if the 'age' field is equal to an expression +equal(field("age"), field("minAge").add(10)); + +``` + +Signature: + +```typescript +export declare function equal(left: Expression, right: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to compare. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the equality comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### greaterThan(left, right) {:#greaterthan_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is greater than the second expression. + +```typescript +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), Constant(9).add(9)); + +``` + +Signature: + +```typescript +export declare function greaterThan(left: Expression, right: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to compare. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the greater than comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### greaterThanOrEqual(left, right) {:#greaterthanorequal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is greater than or equal to the second expression. + +```typescript +// Check if the 'quantity' field is greater than or equal to the field "threshold" +greaterThanOrEqual(field("quantity"), field("threshold")); + +``` + +Signature: + +```typescript +export declare function greaterThanOrEqual(left: Expression, right: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to compare. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the greater than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### lessThan(left, right) {:#lessthan_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is less than the second expression. + +```typescript +// Check if the 'age' field is less than 30 +lessThan(field("age"), field("limit")); + +``` + +Signature: + +```typescript +export declare function lessThan(left: Expression, right: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to compare. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the less than comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### lessThanOrEqual(left, right) {:#lessthanorequal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is less than or equal to the second expression. + +```typescript +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), field("limit")); + +``` + +Signature: + +```typescript +export declare function lessThanOrEqual(left: Expression, right: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to compare. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the less than or equal to comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### mod(left, right) {:#mod_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing two expressions. + +```typescript +// Calculate the remainder of dividing 'field1' by 'field2'. +mod(field("field1"), field("field2")); + +``` + +Signature: + +```typescript +export declare function mod(left: Expression, right: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_pipelines.expression.md#expression_class) | The dividend expression. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The divisor expression. A new representing the modulo operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### notEqual(left, right) {:#notequal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if two expressions are not equal. + +```typescript +// Check if the 'status' field is not equal to field 'finalState' +notEqual(field("status"), field("finalState")); + +``` + +Signature: + +```typescript +export declare function notEqual(left: Expression, right: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to compare. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the inequality comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### pipelineResultEqual(left, right) {:#pipelineresultequal_707a755} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Test equality of two PipelineResults. + +Signature: + +```typescript +export declare function pipelineResultEqual(left: PipelineResult, right: PipelineResult): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) | | +| right | [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) | | + +Returns: + +boolean + +### subtract(left, right) {:#subtract_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts two expressions. + +```typescript +// Subtract the 'discount' field from the 'price' field +subtract(field("price"), field("discount")); + +``` + +Signature: + +```typescript +export declare function subtract(left: Expression, right: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| left | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract from. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract. A new representing the subtraction operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(mapExpr, ...) + +### mapRemove(mapExpr, key) {:#mapremove_23c7d51} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map produced by evaluating an expression. + +``` +// Removes the key 'baz' from the input map. +mapRemove(map({foo: 'bar', baz: true}), 'baz'); + +``` + +Signature: + +```typescript +export declare function mapRemove(mapExpr: Expression, key: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression return a map value. | +| key | string | The name of the key to remove from the input map. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### mapRemove(mapExpr, keyExpr) {:#mapremove_9fbcaa3} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map produced by evaluating an expression. + +``` +// Removes the key 'baz' from the input map. +mapRemove(map({foo: 'bar', baz: true}), constant('baz')); + +``` + +Signature: + +```typescript +export declare function mapRemove(mapExpr: Expression, keyExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression return a map value. | +| keyExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that produces the name of the key to remove from the input map. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(mapExpression, ...) + +### mapGet(mapExpression, subField) {:#mapget_688c050} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Accesses a value from a map (object) expression using the provided key. + +```typescript +// Get the 'city' value from the 'address' map field +mapGet(field("address"), "city"); + +``` + +Signature: + +```typescript +export declare function mapGet(mapExpression: Expression, subField: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the map. | +| subField | string | The key to access in the map. A new representing the value associated with the given key in the map. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(mapField, ...) + +### mapMerge(mapField, secondMap, otherMaps) {:#mapmerge_70a564b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that merges multiple map values. + +``` +// Merges the map in the settings field with, a map literal, and a map in +// that is conditionally returned by another expression +mapMerge('settings', { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) + +``` + +Signature: + +```typescript +export declare function mapMerge(mapField: string, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | Name of a field containing a map value that will be merged. | +| secondMap | Record<string, unknown> \| [Expression](./firestore_pipelines.expression.md#expression_class) | A required second map to merge. Represented as a literal or an expression that returns a map. | +| otherMaps | Array<Record<string, unknown> \| [Expression](./firestore_pipelines.expression.md#expression_class)> | Optional additional maps to merge. Each map is represented as a literal or an expression that returns a map. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### mapRemove(mapField, key) {:#mapremove_bd5726e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map at the specified field name. + +``` +// Removes the key 'city' field from the map in the address field of the input document. +mapRemove('address', 'city'); + +``` + +Signature: + +```typescript +export declare function mapRemove(mapField: string, key: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | The name of a field containing a map value. | +| key | string | The name of the key to remove from the input map. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### mapRemove(mapField, keyExpr) {:#mapremove_8406d13} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map at the specified field name. + +``` +// Removes the key 'city' field from the map in the address field of the input document. +mapRemove('address', constant('city')); + +``` + +Signature: + +```typescript +export declare function mapRemove(mapField: string, keyExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | The name of a field containing a map value. | +| keyExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that produces the name of the key to remove from the input map. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(name, ...) + +### field(name) {:#field_1eaaff4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a instance representing the field at the given path. + +The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). + +```typescript +// Create a Field instance for the 'title' field +const titleField = field("title"); + +// Create a Field instance for a nested field 'author.firstName' +const authorFirstNameField = field("author.firstName"); + +``` + +Signature: + +```typescript +export declare function field(name: string): Field; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | The path to the field. A new instance representing the specified field. | + +Returns: + +[Field](./firestore_pipelines.field.md#field_class) + +## function(options, ...) + +### execute(options) {:#execute_9e87e31} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Executes a pipeline and returns a Promise to represent the asynchronous operation. + +The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously. + +The pipeline results are returned as a that contains a list of objects. Each typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example: + +

  • If there are no stages or only transformation stages, each represents a single document.
  • If there is an aggregation, only a single is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each represents a distinct group and its associated aggregated values.
+ +

Example: + +```typescript +const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") + .where(gt(field("rating"), 4.5)) + .select("title", "author", "rating")); + +const results: PipelineResults = snapshot.results; + +``` + +Signature: + +```typescript +export declare function execute(options: PipelineExecuteOptions): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [PipelineExecuteOptions](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptions_interface) | Specifies the pipeline to execute and other options for execute. A Promise representing the asynchronous pipeline execution. | + +Returns: + +Promise<[PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class)> + +## function(path, ...) + +### field(path) {:#field_34ee07d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a instance representing the field at the given path. + +Signature: + +```typescript +export declare function field(path: FieldPath): Field; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| path | [FieldPath](./firestore_.fieldpath.md#fieldpath_class) | A FieldPath specifying the field. A new instance representing the specified field. | + +Returns: + +[Field](./firestore_pipelines.field.md#field_class) + +## function(pipeline, ...) + +### execute(pipeline) {:#execute_01df620} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Executes a pipeline and returns a Promise to represent the asynchronous operation. + +The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously. + +The pipeline results are returned as a that contains a list of objects. Each typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example: + +

  • If there are no stages or only transformation stages, each represents a single document.
  • If there is an aggregation, only a single is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each represents a distinct group and its associated aggregated values.
+ +

Example: + +```typescript +const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") + .where(gt(field("rating"), 4.5)) + .select("title", "author", "rating")); + +const results: PipelineResults = snapshot.results; + +``` + +Signature: + +```typescript +export declare function execute(pipeline: Pipeline): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pipeline | [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | The pipeline to execute. A Promise representing the asynchronous pipeline execution. | + +Returns: + +Promise<[PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class)> + +## function(stringExpression, ...) + +### charLength(stringExpression) {:#charlength_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the character length of a string expression in UTF-8. + +```typescript +// Get the character length of the 'name' field in UTF-8. +strLength(field("name")); + +``` + +Signature: + +```typescript +export declare function charLength(stringExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to calculate the length of. A new representing the length of the string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### endsWith(stringExpression, suffix) {:#endswith_0a0b889} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression ends with a given postfix. + +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." +endsWith(field("fullName"), "Jr."); + +``` + +Signature: + +```typescript +export declare function endsWith(stringExpression: Expression, suffix: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | +| suffix | string | The postfix to check for. A new representing the 'ends with' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### endsWith(stringExpression, suffix) {:#endswith_13aee0d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression ends with a given postfix. + +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." +endsWith(field("fullName"), constant("Jr.")); + +``` + +Signature: + +```typescript +export declare function endsWith(stringExpression: Expression, suffix: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | +| suffix | [Expression](./firestore_pipelines.expression.md#expression_class) | The postfix to check for. A new representing the 'ends with' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### like(stringExpression, pattern) {:#like_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison. + +```typescript +// Check if the 'title' field contains the string "guide" +like(field("title"), "%guide%"); + +``` + +Signature: + +```typescript +export declare function like(stringExpression: Expression, pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| pattern | string | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### like(stringExpression, pattern) {:#like_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison. + +```typescript +// Check if the 'title' field contains the string "guide" +like(field("title"), field("pattern")); + +``` + +Signature: + +```typescript +export declare function like(stringExpression: Expression, pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### regexContains(stringExpression, pattern) {:#regexcontains_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a specified regular expression as a substring. + +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains(field("description"), "(?i)example"); + +``` + +Signature: + +```typescript +export declare function regexContains(stringExpression: Expression, pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| pattern | string | The regular expression to use for the search. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### regexContains(stringExpression, pattern) {:#regexcontains_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a specified regular expression as a substring. + +```typescript +// Check if the 'description' field contains "example" (case-insensitive) +regexContains(field("description"), field("pattern")); + +``` + +Signature: + +```typescript +export declare function regexContains(stringExpression: Expression, pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the search. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### regexMatch(stringExpression, pattern) {:#regexmatch_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression matches a specified regular expression. + +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch(field("email"), "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + +``` + +Signature: + +```typescript +export declare function regexMatch(stringExpression: Expression, pattern: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to match against. | +| pattern | string | The regular expression to use for the match. A new representing the regular expression match. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### regexMatch(stringExpression, pattern) {:#regexmatch_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression matches a specified regular expression. + +```typescript +// Check if the 'email' field matches a valid email pattern +regexMatch(field("email"), field("pattern")); + +``` + +Signature: + +```typescript +export declare function regexMatch(stringExpression: Expression, pattern: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to match against. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the match. A new representing the regular expression match. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### reverse(stringExpression) {:#reverse_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string. + +```typescript +// Reverse the value of the 'myString' field. +reverse(field("myString")); + +``` + +Signature: + +```typescript +export declare function reverse(stringExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a string value, which will be reversed. A new representing the reversed string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### startsWith(stringExpression, prefix) {:#startswith_75c3dbb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression starts with a given prefix. + +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." +startsWith(field("fullName"), "Mr."); + +``` + +Signature: + +```typescript +export declare function startsWith(stringExpression: Expression, prefix: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | +| prefix | string | The prefix to check for. A new representing the 'starts with' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### startsWith(stringExpression, prefix) {:#startswith_52f218a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression starts with a given prefix. + +```typescript +// Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." +startsWith(field("fullName"), field("prefix")); + +``` + +Signature: + +```typescript +export declare function startsWith(stringExpression: Expression, prefix: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | +| prefix | [Expression](./firestore_pipelines.expression.md#expression_class) | The prefix to check for. A new representing the 'starts with' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### stringContains(stringExpression, substring) {:#stringcontains_3e9ff32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a specified substring. + +```typescript +// Check if the 'description' field contains "example". +stringContains(field("description"), "example"); + +``` + +Signature: + +```typescript +export declare function stringContains(stringExpression: Expression, substring: string): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| substring | string | The substring to search for. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### stringContains(stringExpression, substring) {:#stringcontains_cc6ee02} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a substring specified by another expression. + +```typescript +// Check if the 'description' field contains the value of the 'keyword' field. +stringContains(field("description"), field("keyword")); + +``` + +Signature: + +```typescript +export declare function stringContains(stringExpression: Expression, substring: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| substring | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the substring to search for. A new representing the 'contains' comparison. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### stringReverse(stringExpression) {:#stringreverse_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string. + +```typescript +// Reverse the value of the 'myString' field. +strReverse(field("myString")); + +``` + +Signature: + +```typescript +export declare function stringReverse(stringExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a string value, which will be reversed. A new representing the reversed string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### toLower(stringExpression) {:#tolower_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string expression to lowercase. + +```typescript +// Convert the 'name' field to lowercase +toLower(field("name")); + +``` + +Signature: + +```typescript +export declare function toLower(stringExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to convert to lowercase. A new representing the lowercase string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### toUpper(stringExpression) {:#toupper_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string expression to uppercase. + +```typescript +// Convert the 'title' field to uppercase +toUppercase(field("title")); + +``` + +Signature: + +```typescript +export declare function toUpper(stringExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to convert to uppercase. A new representing the uppercase string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### trim(stringExpression, valueToTrim) {:#trim_dd54322} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes leading and trailing characters from a string or byte array expression. + +```typescript +// Trim whitespace from the 'userInput' field +trim(field("userInput")); + +// Trim quotes from the 'userInput' field +trim(field("userInput"), '"'); + +``` + +Signature: + +```typescript +export declare function trim(stringExpression: Expression, valueToTrim?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array to trim. | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | 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. A new representing the trimmed string or byte array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(timestamp, ...) + +### timestampAdd(timestamp, unit, amount) {:#timestampadd_98418f9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to a timestamp. + +```typescript +// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. +timestampAdd(field("timestamp"), field("unit"), field("amount")); + +``` + +Signature: + +```typescript +export declare function timestampAdd(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestamp | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| unit | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | +| amount | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### timestampAdd(timestamp, unit, amount) {:#timestampadd_ffe8e57} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to a timestamp. + +```typescript +// Add 1 day to the 'timestamp' field. +timestampAdd(field("timestamp"), "day", 1); + +``` + +Signature: + +```typescript +export declare function timestampAdd(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestamp | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | +| amount | number | The amount of time to add. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_98418f9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from a timestamp. + +```typescript +// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. +timestampSubtract(field("timestamp"), field("unit"), field("amount")); + +``` + +Signature: + +```typescript +export declare function timestampSubtract(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestamp | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| unit | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | +| amount | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_ffe8e57} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from a timestamp. + +```typescript +// Subtract 1 day from the 'timestamp' field. +timestampSubtract(field("timestamp"), "day", 1); + +``` + +Signature: + +```typescript +export declare function timestampSubtract(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestamp | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | +| amount | number | The amount of time to subtract. A new representing the resulting timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(timestampExpression, ...) + +### timestampTruncate(timestampExpression, granularity, timezone) {:#timestamptruncate_ad5d843} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a timestamp to a specified granularity. + +Signature: + +```typescript +export declare function timestampTruncate(timestampExpression: Expression, granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestampExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | Truncate the timestamp value that is returned by this expression. | +| granularity | [TimeGranularity](./firestore_pipelines.md#timegranularity) | The granularity to truncate to. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Truncate the 'createdAt' timestamp to the beginning of the day. +field('createdAt').timestampTruncate('day') + +``` + +### timestampTruncate(timestampExpression, granularity, timezone) {:#timestamptruncate_d6ab2a4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a timestamp to a specified granularity. + +Signature: + +```typescript +export declare function timestampTruncate(timestampExpression: Expression, granularity: Expression, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestampExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | Truncate the timestamp value that is returned by this expression. | +| granularity | [Expression](./firestore_pipelines.expression.md#expression_class) | The granularity to truncate to. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### Example + + +```typescript +// Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. +field('createdAt').timestampTruncate(field('granularity')) + +``` + +## function(tryExpr, ...) + +### ifError(tryExpr, catchExpr) {:#iferror_a99a327} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. + +This overload is useful when a BooleanExpression is required. + +```typescript +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +ifError(constant(50).divide('length').gt(1), constant(false)); + +``` + +Signature: + +```typescript +export declare function ifError(tryExpr: BooleanExpression, catchExpr: BooleanExpression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| tryExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The try expression. | +| catchExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The catch expression that will be evaluated and returned if the tryExpr produces an error. A new representing the 'ifError' operation. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### ifError(tryExpr, catchExpr) {:#iferror_756c12e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. + +```typescript +// Returns the first item in the title field arrays, or returns +// the entire title field if the array is empty or the field is another type. +ifError(field("title").arrayGet(0), field("title")); + +``` + +Signature: + +```typescript +export declare function ifError(tryExpr: Expression, catchExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| tryExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The try expression. | +| catchExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The catch expression that will be evaluated and returned if the tryExpr produces an error. A new representing the 'ifError' operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### ifError(tryExpr, catchValue) {:#iferror_dc532f9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. + +```typescript +// Returns the first item in the title field arrays, or returns +// "Default Title" +ifError(field("title").arrayGet(0), "Default Title"); + +``` + +Signature: + +```typescript +export declare function ifError(tryExpr: Expression, catchValue: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| tryExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The try expression. | +| catchValue | unknown | The value that will be returned if the tryExpr produces an error. A new representing the 'ifError' operation. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(value, ...) + +### constant(value) {:#constant_0c00f91} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a number value. + +Signature: + +```typescript +export declare function constant(value: number): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | number | The number value. A new Constant instance. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_6dac335} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a VectorValue value. + +Signature: + +```typescript +export declare function constant(value: VectorValue): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The VectorValue value. A new Constant instance. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_7c807cd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a string value. + +Signature: + +```typescript +export declare function constant(value: string): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | string | The string value. A new Constant instance. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_b2e4f8d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `BooleanExpression` instance for a boolean value. + +Signature: + +```typescript +export declare function constant(value: boolean): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | boolean | The boolean value. A new Constant instance. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### constant(value) {:#constant_73ebd84} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a null value. + +Signature: + +```typescript +export declare function constant(value: null): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | null | The null value. A new Constant instance. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_72a76cb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a GeoPoint value. + +Signature: + +```typescript +export declare function constant(value: GeoPoint): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [GeoPoint](./firestore_.geopoint.md#geopoint_class) | The GeoPoint value. A new Constant instance. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_000477d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a Timestamp value. + +Signature: + +```typescript +export declare function constant(value: Timestamp): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [Timestamp](./firestore_.timestamp.md#timestamp_class) | The Timestamp value. A new Constant instance. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_5131bf7} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a Date value. + +Signature: + +```typescript +export declare function constant(value: Date): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | Date | The Date value. A new Constant instance. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_fdf565d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a Bytes value. + +Signature: + +```typescript +export declare function constant(value: Bytes): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [Bytes](./firestore_.bytes.md#bytes_class) | The Bytes value. A new Constant instance. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### constant(value) {:#constant_bcd2b0b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates a `Constant` instance for a DocumentReference value. + +Signature: + +```typescript +export declare function constant(value: DocumentReference): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [DocumentReference](./firestore_.documentreference.md#documentreference_class) | The DocumentReference value. A new Constant instance. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### exists(value) {:#exists_f3daf14} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field exists. + +```typescript +// Check if the document has a field named "phoneNumber" +exists(field("phoneNumber")); + +``` + +Signature: + +```typescript +export declare function exists(value: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluates to the name of the field to check. A new representing the 'exists' check. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### isAbsent(value) {:#isabsent_f3daf14} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns `true` if a value is absent. Otherwise, returns `false` even if the value is `null`. + +```typescript +// Check if the field `value` is absent. +isAbsent(field("value")); + +``` + +Signature: + +```typescript +export declare function isAbsent(value: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. A new representing the 'isAbsent' check. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### isError(value) {:#iserror_f3daf14} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a given expression produces an error. + +```typescript +// Check if the result of a calculation is an error +isError(field("title").arrayContains(1)); + +``` + +Signature: + +```typescript +export declare function isError(value: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. A new representing the 'isError' check. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +## function(vectorExpression, ...) + +### cosineDistance(vectorExpression, vector) {:#cosinedistance_3a80317} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between a vector expression and a vector literal. + +```typescript +// Calculate the cosine distance between the 'location' field and a target location +cosineDistance(field("location"), [37.7749, -122.4194]); + +``` + +Signature: + +```typescript +export declare function cosineDistance(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | +| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. A new representing the cosine distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### cosineDistance(vectorExpression, otherVectorExpression) {:#cosinedistance_17b5bcc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between two vector expressions. + +```typescript +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +cosineDistance(field("userVector"), field("itemVector")); + +``` + +Signature: + +```typescript +export declare function cosineDistance(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | +| otherVectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the cosine distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### dotProduct(vectorExpression, vector) {:#dotproduct_3a80317} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between a vector expression and a double array. + +```typescript +// Calculate the dot product between a feature vector and a target vector +dotProduct(field("features"), [0.5, 0.8, 0.2]); + +``` + +Signature: + +```typescript +export declare function dotProduct(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to calculate with. | +| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to calculate with. A new representing the dot product between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### dotProduct(vectorExpression, otherVectorExpression) {:#dotproduct_17b5bcc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between two vector expressions. + +```typescript +// Calculate the dot product between two document vectors: 'docVector1' and 'docVector2' +dotProduct(field("docVector1"), field("docVector2")); + +``` + +Signature: + +```typescript +export declare function dotProduct(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to calculate with. | +| otherVectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to calculate with. A new representing the dot product between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### euclideanDistance(vectorExpression, vector) {:#euclideandistance_3a80317} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between a vector expression and a double array. + +```typescript +// Calculate the Euclidean distance between the 'location' field and a target location + +euclideanDistance(field("location"), [37.7749, -122.4194]); + +``` + +Signature: + +```typescript +export declare function euclideanDistance(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | +| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. A new representing the Euclidean distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### euclideanDistance(vectorExpression, otherVectorExpression) {:#euclideandistance_17b5bcc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between two vector expressions. + +```typescript +// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' +euclideanDistance(field("pointA"), field("pointB")); + +``` + +Signature: + +```typescript +export declare function euclideanDistance(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | +| otherVectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the Euclidean distance between the two vectors. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +### vectorLength(vectorExpression) {:#vectorlength_58a039b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a Firestore Vector. + +```typescript +// Get the vector length (dimension) of the field 'embedding'. +vectorLength(field("embedding")); + +``` + +Signature: + +```typescript +export declare function vectorLength(vectorExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the Firestore Vector. A new representing the length of the array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## AddFieldsStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how an AddFieldsStage is evaluated. See . + +Signature: + +```typescript +export declare type AddFieldsStageOptions = StageOptions & { + fields: Selectable[]; +}; +``` + +## AggregateStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how an AggregateStage is evaluated. See . + +Signature: + +```typescript +export declare type AggregateStageOptions = StageOptions & { + accumulators: AliasedAggregate[]; + groups?: Array; +}; +``` + +## CollectionGroupStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Defines the configuration options for a within a pipeline. This type extends and provides specific settings for how a collection group is identified and processed during pipeline execution. + +Signature: + +```typescript +export declare type CollectionGroupStageOptions = StageOptions & { + collectionId: string; + forceIndex?: string; +}; +``` + +## CollectionStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a CollectionStage is evaluated. See . + +Signature: + +```typescript +export declare type CollectionStageOptions = StageOptions & { + collection: string | Query; + forceIndex?: string; +}; +``` + +## DatabaseStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a DatabaseStage is evaluated. See . + +Signature: + +```typescript +export declare type DatabaseStageOptions = StageOptions & {}; +``` + +## DistinctStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a DistinctStage is evaluated. See . + +Signature: + +```typescript +export declare type DistinctStageOptions = StageOptions & { + groups: Array; +}; +``` + +## DocumentsStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a DocumentsStage is evaluated. See . + +Signature: + +```typescript +export declare type DocumentsStageOptions = StageOptions & { + docs: Array; +}; +``` + +## ExpressionType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An enumeration of the different types of expressions. + +Signature: + +```typescript +export declare type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression'; +``` + +## FindNearestStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a FindNearestStage is evaluated. See . + +Signature: + +```typescript +export declare type FindNearestStageOptions = StageOptions & { + field: Field | string; + vectorValue: VectorValue | number[]; + distanceMeasure: 'euclidean' | 'cosine' | 'dot_product'; + limit?: number; + distanceField?: string; +}; +``` + +## LimitStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a LimitStage is evaluated. See . + +Signature: + +```typescript +export declare type LimitStageOptions = StageOptions & { + limit: number; +}; +``` + +## OffsetStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how an OffsetStage is evaluated. See . + +Signature: + +```typescript +export declare type OffsetStageOptions = StageOptions & { + offset: number; +}; +``` + +## OneOf + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Utility type to create an type that only allows one property of the Type param T to be set. + +type XorY = OneOf<{ x: unknown, y: unknown}> let a = { x: "foo" } // OK let b = { y: "foo" } // OK let c = { a: "foo", y: "foo" } // Not OK + +Signature: + +```typescript +export declare type OneOf = { + [K in keyof T]: Pick & { + [P in Exclude]?: undefined; + }; +}[keyof T]; +``` + +## PartialWithFieldValue + +Similar to TypeScript's `Partial`, but allows nested fields to be omitted and FieldValues to be passed in as property values. + +Signature: + +```typescript +export declare type PartialWithFieldValue = Partial | (T extends Primitive ? T : T extends {} ? { + [K in keyof T]?: PartialWithFieldValue | FieldValue; +} : never); +``` + +## Primitive + +Primitive types. + +Signature: + +```typescript +export declare type Primitive = string | number | boolean | undefined | null; +``` + +## RemoveFieldsStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a RemoveFieldsStage is evaluated. See . + +Signature: + +```typescript +export declare type RemoveFieldsStageOptions = StageOptions & { + fields: Array; +}; +``` + +## ReplaceWithStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a ReplaceWithStage is evaluated. See . + +Signature: + +```typescript +export declare type ReplaceWithStageOptions = StageOptions & { + map: Expression | string; +}; +``` + +## SampleStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Defines the options for evaluating a sample stage within a pipeline. This type combines common with a specific configuration where only one of the defined sampling methods can be applied. + +See to create a sample stage.. + +Signature: + +```typescript +export declare type SampleStageOptions = StageOptions & OneOf<{ + percentage: number; + documents: number; +}>; +``` + +## SelectStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a SelectStage is evaluated. See . + +Signature: + +```typescript +export declare type SelectStageOptions = StageOptions & { + selections: Array; +}; +``` + +## SetOptions + +An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a `SetOptions` with `merge: true`. + +Signature: + +```typescript +export declare type SetOptions = { + readonly merge?: boolean; +} | { + readonly mergeFields?: Array; +}; +``` + +## SortStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a SortStage is evaluated. See . + +Signature: + +```typescript +export declare type SortStageOptions = StageOptions & { + orderings: Ordering[]; +}; +``` + +## TimeGranularity + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Specify time granularity for expressions. + +Signature: + +```typescript +export declare type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; +``` + +## UnionStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a UnionStage is evaluated. See . + +Signature: + +```typescript +export declare type UnionStageOptions = StageOptions & { + other: Pipeline; +}; +``` + +## UnnestStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Represents the specific options available for configuring an `UnnestStage` within a pipeline. + +Signature: + +```typescript +export declare type UnnestStageOptions = StageOptions & { + selectable: Selectable; + indexField?: string; +}; +``` + +## WhereStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a WhereStage is evaluated. See . + +Signature: + +```typescript +export declare type WhereStageOptions = StageOptions & { + condition: BooleanExpression; +}; +``` + +## WithFieldValue + +Allows FieldValues to be passed in as a property value while maintaining type safety. + +Signature: + +```typescript +export declare type WithFieldValue = T | (T extends Primitive ? T : T extends {} ? { + [K in keyof T]: WithFieldValue | FieldValue; +} : never); +``` diff --git a/docs-devsite/firestore_pipelines.ordering.md b/docs-devsite/firestore_pipelines.ordering.md new file mode 100644 index 0000000000..373f962aee --- /dev/null +++ b/docs-devsite/firestore_pipelines.ordering.md @@ -0,0 +1,80 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Ordering class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Represents an ordering criterion for sorting documents in a Firestore pipeline. + +You create `Ordering` instances using the `ascending` and `descending` helper functions. + +Signature: + +```typescript +export declare class Ordering +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(expr, direction, \_methodName)](./firestore_pipelines.ordering.md#orderingconstructor) | | (Public Preview) Constructs a new instance of the Ordering class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [direction](./firestore_pipelines.ordering.md#orderingdirection) | | 'ascending' \| 'descending' | (Public Preview) | +| [expr](./firestore_pipelines.ordering.md#orderingexpr) | | [Expression](./firestore_pipelines.expression.md#expression_class) | (Public Preview) | + +## Ordering.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `Ordering` class + +Signature: + +```typescript +constructor(expr: Expression, direction: 'ascending' | 'descending', _methodName: string | undefined); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | | +| direction | 'ascending' \| 'descending' | | +| \_methodName | string \| undefined | | + +## Ordering.direction + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly direction: 'ascending' | 'descending'; +``` + +## Ordering.expr + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +readonly expr: Expression; +``` diff --git a/docs-devsite/firestore_pipelines.pipeline.md b/docs-devsite/firestore_pipelines.pipeline.md new file mode 100644 index 0000000000..4ba1ba716c --- /dev/null +++ b/docs-devsite/firestore_pipelines.pipeline.md @@ -0,0 +1,674 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Pipeline class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + + +Signature: + +```typescript +export declare class Pipeline +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [addFields(field, additionalFields)](./firestore_pipelines.pipeline.md#pipelineaddfields) | | (Public Preview) | +| [addFields(options)](./firestore_pipelines.pipeline.md#pipelineaddfields) | | (Public Preview) | +| [aggregate(accumulator, additionalAccumulators)](./firestore_pipelines.pipeline.md#pipelineaggregate) | | (Public Preview) | +| [aggregate(options)](./firestore_pipelines.pipeline.md#pipelineaggregate) | | (Public Preview) | +| [distinct(group, additionalGroups)](./firestore_pipelines.pipeline.md#pipelinedistinct) | | (Public Preview) | +| [distinct(options)](./firestore_pipelines.pipeline.md#pipelinedistinct) | | (Public Preview) | +| [findNearest(options)](./firestore_pipelines.pipeline.md#pipelinefindnearest) | | (Public Preview) | +| [limit(limit)](./firestore_pipelines.pipeline.md#pipelinelimit) | | (Public Preview) | +| [limit(options)](./firestore_pipelines.pipeline.md#pipelinelimit) | | (Public Preview) | +| [offset(offset)](./firestore_pipelines.pipeline.md#pipelineoffset) | | (Public Preview) | +| [offset(options)](./firestore_pipelines.pipeline.md#pipelineoffset) | | (Public Preview) | +| [rawStage(name, params, options)](./firestore_pipelines.pipeline.md#pipelinerawstage) | | (Public Preview) | +| [removeFields(fieldValue, additionalFields)](./firestore_pipelines.pipeline.md#pipelineremovefields) | | (Public Preview) | +| [removeFields(options)](./firestore_pipelines.pipeline.md#pipelineremovefields) | | (Public Preview) | +| [replaceWith(fieldName)](./firestore_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) | +| [replaceWith(expr)](./firestore_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) | +| [replaceWith(options)](./firestore_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) | +| [sample(documents)](./firestore_pipelines.pipeline.md#pipelinesample) | | (Public Preview) | +| [sample(options)](./firestore_pipelines.pipeline.md#pipelinesample) | | (Public Preview) | +| [select(selection, additionalSelections)](./firestore_pipelines.pipeline.md#pipelineselect) | | (Public Preview) | +| [select(options)](./firestore_pipelines.pipeline.md#pipelineselect) | | (Public Preview) | +| [sort(ordering, additionalOrderings)](./firestore_pipelines.pipeline.md#pipelinesort) | | (Public Preview) | +| [sort(options)](./firestore_pipelines.pipeline.md#pipelinesort) | | (Public Preview) | +| [union(other)](./firestore_pipelines.pipeline.md#pipelineunion) | | (Public Preview) | +| [union(options)](./firestore_pipelines.pipeline.md#pipelineunion) | | (Public Preview) | +| [unnest(selectable, indexField)](./firestore_pipelines.pipeline.md#pipelineunnest) | | (Public Preview) | +| [unnest(options)](./firestore_pipelines.pipeline.md#pipelineunnest) | | (Public Preview) | +| [where(condition)](./firestore_pipelines.pipeline.md#pipelinewhere) | | (Public Preview) | +| [where(options)](./firestore_pipelines.pipeline.md#pipelinewhere) | | (Public Preview) | + +## Pipeline.addFields() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | [Selectable](./firestore_pipelines.selectable.md#selectable_interface) | | +| additionalFields | [Selectable](./firestore_pipelines.selectable.md#selectable_interface)\[\] | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.addFields() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +addFields(options: AddFieldsStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [AddFieldsStageOptions](./firestore_pipelines.md#addfieldsstageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.aggregate() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +aggregate(accumulator: AliasedAggregate, ...additionalAccumulators: AliasedAggregate[]): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| accumulator | [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) | | +| additionalAccumulators | [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class)\[\] | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.aggregate() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +aggregate(options: AggregateStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [AggregateStageOptions](./firestore_pipelines.md#aggregatestageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.distinct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +distinct(group: string | Selectable, ...additionalGroups: Array): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| group | string \| [Selectable](./firestore_pipelines.selectable.md#selectable_interface) | | +| additionalGroups | Array<string \| [Selectable](./firestore_pipelines.selectable.md#selectable_interface)> | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.distinct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +distinct(options: DistinctStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [DistinctStageOptions](./firestore_pipelines.md#distinctstageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.findNearest() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +findNearest(options: FindNearestStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [FindNearestStageOptions](./firestore_pipelines.md#findneareststageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.limit() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +limit(limit: number): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| limit | number | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.limit() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +limit(options: LimitStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [LimitStageOptions](./firestore_pipelines.md#limitstageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.offset() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +offset(offset: number): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| offset | number | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.offset() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +offset(options: OffsetStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [OffsetStageOptions](./firestore_pipelines.md#offsetstageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.rawStage() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +rawStage(name: string, params: unknown[], options?: { [key: string]: Expression | unknown; }): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | +| params | unknown\[\] | | +| options | { \[key: string\]: [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown; } | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.removeFields() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +removeFields(fieldValue: Field | string, ...additionalFields: Array): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldValue | [Field](./firestore_pipelines.field.md#field_class) \| string | | +| additionalFields | Array<[Field](./firestore_pipelines.field.md#field_class) \| string> | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.removeFields() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +removeFields(options: RemoveFieldsStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [RemoveFieldsStageOptions](./firestore_pipelines.md#removefieldsstageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.replaceWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +replaceWith(fieldName: string): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.replaceWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +replaceWith(expr: Expression): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.replaceWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +replaceWith(options: ReplaceWithStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [ReplaceWithStageOptions](./firestore_pipelines.md#replacewithstageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.sample() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +sample(documents: number): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| documents | number | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.sample() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +sample(options: SampleStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.select() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +select(selection: Selectable | string, ...additionalSelections: Array): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| selection | [Selectable](./firestore_pipelines.selectable.md#selectable_interface) \| string | | +| additionalSelections | Array<[Selectable](./firestore_pipelines.selectable.md#selectable_interface) \| string> | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.select() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +select(options: SelectStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [SelectStageOptions](./firestore_pipelines.md#selectstageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.sort() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ordering | [Ordering](./firestore_pipelines.ordering.md#ordering_class) | | +| additionalOrderings | [Ordering](./firestore_pipelines.ordering.md#ordering_class)\[\] | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.sort() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +sort(options: SortStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.union() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +union(other: Pipeline): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.union() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +union(options: UnionStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [UnionStageOptions](./firestore_pipelines.md#unionstageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.unnest() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +unnest(selectable: Selectable, indexField?: string): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| selectable | [Selectable](./firestore_pipelines.selectable.md#selectable_interface) | | +| indexField | string | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.unnest() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +unnest(options: UnnestStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [UnnestStageOptions](./firestore_pipelines.md#unneststageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.where() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +where(condition: BooleanExpression): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| condition | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.where() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +where(options: WhereStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [WhereStageOptions](./firestore_pipelines.md#wherestageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + diff --git a/docs-devsite/firestore_pipelines.pipelineexecuteoptions.md b/docs-devsite/firestore_pipelines.pipelineexecuteoptions.md new file mode 100644 index 0000000000..fc0ed90769 --- /dev/null +++ b/docs-devsite/firestore_pipelines.pipelineexecuteoptions.md @@ -0,0 +1,132 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# PipelineExecuteOptions interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining Pipeline execution. + +Signature: + +```typescript +export declare interface PipelineExecuteOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [indexMode](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionsindexmode) | 'recommended' | (Public Preview) Specify the index mode. | +| [pipeline](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionspipeline) | [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | (Public Preview) Pipeline to be evaluated. | +| [rawOptions](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionsrawoptions) | { \[name: string\]: unknown; } | (Public Preview) An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Custom option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK.Override the example_option: +``` + execute({ + pipeline: myPipeline, + rawOptions: { + // Override `example_option`. This will not + // merge with the existing `example_option` object. + "example_option": { + foo: "bar" + } + } + } + +``` +rawOptions supports dot notation, if you want to override a nested option. +``` + execute({ + pipeline: myPipeline, + rawOptions: { + // Override `example_option.foo` and do not override + // any other properties of `example_option`. + "example_option.foo": "bar" + } + } + +``` + | + +## PipelineExecuteOptions.indexMode + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Specify the index mode. + +Signature: + +```typescript +indexMode?: 'recommended'; +``` + +## PipelineExecuteOptions.pipeline + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Pipeline to be evaluated. + +Signature: + +```typescript +pipeline: Pipeline; +``` + +## PipelineExecuteOptions.rawOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK. + +The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name). + +Custom option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected. + +Values specified in rawOptions will take precedence over any options with the same name set by the SDK. + +Override the `example_option`: + +``` + execute({ + pipeline: myPipeline, + rawOptions: { + // Override `example_option`. This will not + // merge with the existing `example_option` object. + "example_option": { + foo: "bar" + } + } + } + +``` +`rawOptions` supports dot notation, if you want to override a nested option. + +``` + execute({ + pipeline: myPipeline, + rawOptions: { + // Override `example_option.foo` and do not override + // any other properties of `example_option`. + "example_option.foo": "bar" + } + } + +``` + +Signature: + +```typescript +rawOptions?: { + [name: string]: unknown; + }; +``` diff --git a/docs-devsite/firestore_pipelines.pipelineresult.md b/docs-devsite/firestore_pipelines.pipelineresult.md new file mode 100644 index 0000000000..b5dfb1a41d --- /dev/null +++ b/docs-devsite/firestore_pipelines.pipelineresult.md @@ -0,0 +1,168 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# PipelineResult class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the or methods. + +

If the PipelineResult represents a non-document result, `ref` will return a undefined value. + +Signature: + +```typescript +export declare class PipelineResult +``` + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [createTime](./firestore_pipelines.pipelineresult.md#pipelineresultcreatetime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was created. Undefined if this result is not a document. {Timestamp\|undefined} | +| [id](./firestore_pipelines.pipelineresult.md#pipelineresultid) | | string \| undefined | (Public Preview) The ID of the document for which this PipelineResult contains data, if it is a document; otherwise undefined. {string} | +| [ref](./firestore_pipelines.pipelineresult.md#pipelineresultref) | | [DocumentReference](./firestore_.documentreference.md#documentreference_class) \| undefined | (Public Preview) The reference of the document, if it is a document; otherwise undefined. | +| [updateTime](./firestore_pipelines.pipelineresult.md#pipelineresultupdatetime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. {Timestamp\|undefined} | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) | | (Public Preview) Retrieves all fields in the result as an object. | +| [get(fieldPath)](./firestore_pipelines.pipelineresult.md#pipelineresultget) | | (Public Preview) Retrieves the field specified by field. | + +## PipelineResult.createTime + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The time the document was created. Undefined if this result is not a document. + + {Timestamp\|undefined} + +Signature: + +```typescript +get createTime(): Timestamp | undefined; +``` + +## PipelineResult.id + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The ID of the document for which this PipelineResult contains data, if it is a document; otherwise `undefined`. + + {string} + +Signature: + +```typescript +get id(): string | undefined; +``` + +## PipelineResult.ref + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The reference of the document, if it is a document; otherwise `undefined`. + +Signature: + +```typescript +get ref(): DocumentReference | undefined; +``` + +## PipelineResult.updateTime + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. + + {Timestamp\|undefined} + +Signature: + +```typescript +get updateTime(): Timestamp | undefined; +``` + +## PipelineResult.data() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Retrieves all fields in the result as an object. + +Signature: + +```typescript +data(): AppModelType; +``` +Returns: + +AppModelType + +{T} An object containing all fields in the document or 'undefined' if the document doesn't exist. + +### Example + + +``` +let p = firestore.pipeline().collection('col'); + +p.execute().then(results => { + let data = results[0].data(); + console.log(`Retrieved data: ${JSON.stringify(data)}`); +}); + +``` + +## PipelineResult.get() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Retrieves the field specified by `field`. + +Signature: + +```typescript +get(fieldPath: string | FieldPath | Field): any; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldPath | string \| [FieldPath](./firestore_.fieldpath.md#fieldpath_class) \| [Field](./firestore_pipelines.field.md#field_class) | | + +Returns: + +any + +{\*} The data at the specified field location or undefined if no such field exists. + +### Example + + +``` +let p = firestore.pipeline().collection('col'); + +p.execute().then(results => { + let field = results[0].get('a.b'); + console.log(`Retrieved field value: ${field}`); +}); + +``` + diff --git a/docs-devsite/firestore_pipelines.pipelinesnapshot.md b/docs-devsite/firestore_pipelines.pipelinesnapshot.md new file mode 100644 index 0000000000..7f6d4744f4 --- /dev/null +++ b/docs-devsite/firestore_pipelines.pipelinesnapshot.md @@ -0,0 +1,103 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# PipelineSnapshot class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Represents the results of a Firestore pipeline execution. + +A `PipelineSnapshot` contains zero or more objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. + +Signature: + +```typescript +export declare class PipelineSnapshot +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(pipeline, results, executionTime)](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshotconstructor) | | (Public Preview) Constructs a new instance of the PipelineSnapshot class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [executionTime](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshotexecutiontime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) | (Public Preview) The time at which the pipeline producing this result is executed. {Timestamp} | +| [results](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshotresults) | | [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class)\[\] | (Public Preview) An array of all the results in the PipelineSnapshot. | + +## PipelineSnapshot.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `PipelineSnapshot` class + +Signature: + +```typescript +constructor(pipeline: Pipeline, results: PipelineResult[], executionTime?: Timestamp); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pipeline | [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | | +| results | [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class)\[\] | | +| executionTime | [Timestamp](./firestore_.timestamp.md#timestamp_class) | | + +## PipelineSnapshot.executionTime + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The time at which the pipeline producing this result is executed. + + {Timestamp} + +Signature: + +```typescript +get executionTime(): Timestamp; +``` + +## PipelineSnapshot.results + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An array of all the results in the `PipelineSnapshot`. + +Signature: + +```typescript +get results(): PipelineResult[]; +``` + +### Example + + +```typescript +const snapshot: PipelineSnapshot = await firestore + .pipeline() + .collection('myCollection') + .where(field('value').greaterThan(10)) + .execute(); + +snapshot.results.forEach(doc => { + console.log(doc.id, '=>', doc.data()); +}); + +``` + diff --git a/docs-devsite/firestore_pipelines.pipelinesource.md b/docs-devsite/firestore_pipelines.pipelinesource.md new file mode 100644 index 0000000000..383f31f7fd --- /dev/null +++ b/docs-devsite/firestore_pipelines.pipelinesource.md @@ -0,0 +1,251 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# PipelineSource class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Provides the entry point for defining the data source of a Firestore . + +Use the methods of this class (e.g., , , , or ) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. + +Signature: + +```typescript +export declare class PipelineSource +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [collection(collection)](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection) | | (Public Preview) Returns all documents from the entire collection. The collection can be nested. | +| [collection(options)](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection) | | (Public Preview) Returns all documents from the entire collection. The collection can be nested. | +| [collectionGroup(collectionId)](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) | | (Public Preview) Returns all documents from a collection ID regardless of the parent. | +| [collectionGroup(options)](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) | | (Public Preview) Returns all documents from a collection ID regardless of the parent. | +| [createFrom(query)](./firestore_pipelines.pipelinesource.md#pipelinesourcecreatefrom) | | (Public Preview) Convert the given Query into an equivalent Pipeline. | +| [database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase) | | (Public Preview) Returns all documents from the entire database. | +| [database(options)](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase) | | (Public Preview) Returns all documents from the entire database. | +| [documents(docs)](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments) | | (Public Preview) Set the pipeline's source to the documents specified by the given paths and DocumentReferences. | +| [documents(options)](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments) | | (Public Preview) Set the pipeline's source to the documents specified by the given paths and DocumentReferences. | + +## PipelineSource.collection() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all documents from the entire collection. The collection can be nested. + +Signature: + +```typescript +collection(collection: string | Query): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| collection | string \| [Query](./firestore_.query.md#query_class) | Name or reference to the collection that will be used as the Pipeline source. | + +Returns: + +PipelineType + +## PipelineSource.collection() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all documents from the entire collection. The collection can be nested. + +Signature: + +```typescript +collection(options: CollectionStageOptions): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [CollectionStageOptions](./firestore_pipelines.md#collectionstageoptions) | Options defining how this CollectionStage is evaluated. | + +Returns: + +PipelineType + +## PipelineSource.collectionGroup() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all documents from a collection ID regardless of the parent. + +Signature: + +```typescript +collectionGroup(collectionId: string): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| collectionId | string | ID of the collection group to use as the Pipeline source. | + +Returns: + +PipelineType + +## PipelineSource.collectionGroup() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all documents from a collection ID regardless of the parent. + +Signature: + +```typescript +collectionGroup(options: CollectionGroupStageOptions): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [CollectionGroupStageOptions](./firestore_pipelines.md#collectiongroupstageoptions) | Options defining how this CollectionGroupStage is evaluated. | + +Returns: + +PipelineType + +## PipelineSource.createFrom() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Convert the given Query into an equivalent Pipeline. + +Signature: + +```typescript +createFrom(query: Query): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| query | [Query](./firestore_.query.md#query_class) | A Query to be converted into a Pipeline. | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +#### Exceptions + + Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. + +## PipelineSource.database() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all documents from the entire database. + +Signature: + +```typescript +database(): PipelineType; +``` +Returns: + +PipelineType + +## PipelineSource.database() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all documents from the entire database. + +Signature: + +```typescript +database(options: DatabaseStageOptions): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [DatabaseStageOptions](./firestore_pipelines.md#databasestageoptions) | Options defining how a DatabaseStage is evaluated. | + +Returns: + +PipelineType + +## PipelineSource.documents() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Set the pipeline's source to the documents specified by the given paths and DocumentReferences. + +Signature: + +```typescript +documents(docs: Array): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| docs | Array<string \| [DocumentReference](./firestore_.documentreference.md#documentreference_class)> | An array of paths and DocumentReferences specifying the individual documents that will be the source of this pipeline. The converters for these DocumentReferences will be ignored and not have an effect on this pipeline. | + +Returns: + +PipelineType + +#### Exceptions + + Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. + +## PipelineSource.documents() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Set the pipeline's source to the documents specified by the given paths and DocumentReferences. + +Signature: + +```typescript +documents(options: DocumentsStageOptions): PipelineType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [DocumentsStageOptions](./firestore_pipelines.md#documentsstageoptions) | Options defining how this DocumentsStage is evaluated. | + +Returns: + +PipelineType + +#### Exceptions + + Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. + diff --git a/docs-devsite/firestore_pipelines.query.md b/docs-devsite/firestore_pipelines.query.md new file mode 100644 index 0000000000..6b47d2485a --- /dev/null +++ b/docs-devsite/firestore_pipelines.query.md @@ -0,0 +1,125 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Query class +A `Query` refers to a query which you can read or listen to. You can also construct refined `Query` objects by adding filters and ordering. + +Signature: + +```typescript +export declare class Query +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)()](./firestore_pipelines.query.md#queryconstructor) | | Constructs a new instance of the Query class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [converter](./firestore_pipelines.query.md#queryconverter) | | [FirestoreDataConverter](./firestore_.firestoredataconverter.md#firestoredataconverter_interface)<AppModelType, DbModelType> \| null | If provided, the FirestoreDataConverter associated with this instance. | +| [firestore](./firestore_pipelines.query.md#queryfirestore) | | [Firestore](./firestore_.firestore.md#firestore_class) | The Firestore instance for the Firestore database (useful for performing transactions, etc.). | +| [type](./firestore_pipelines.query.md#querytype) | | 'query' \| 'collection' | The type of this Firestore reference. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [withConverter(converter)](./firestore_pipelines.query.md#querywithconverter) | | Removes the current converter. | +| [withConverter(converter)](./firestore_pipelines.query.md#querywithconverter) | | Applies a custom data converter to this query, allowing you to use your own custom model objects with Firestore. When you call [getDocs()](./firestore_.md#getdocs_4e56953) with the returned query, the provided converter will convert between Firestore data of type NewDbModelType and your custom type NewAppModelType. | + +## Query.(constructor) + +Constructs a new instance of the `Query` class + +Signature: + +```typescript +protected constructor(); +``` + +## Query.converter + +If provided, the `FirestoreDataConverter` associated with this instance. + +Signature: + +```typescript +readonly converter: FirestoreDataConverter | null; +``` + +## Query.firestore + +The `Firestore` instance for the Firestore database (useful for performing transactions, etc.). + +Signature: + +```typescript +readonly firestore: Firestore; +``` + +## Query.type + +The type of this Firestore reference. + +Signature: + +```typescript +readonly type: 'query' | 'collection'; +``` + +## Query.withConverter() + +Removes the current converter. + +Signature: + +```typescript +withConverter(converter: null): Query; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| converter | null | null removes the current converter. | + +Returns: + +[Query](./firestore_.query.md#query_class)<[DocumentData](./firestore_.documentdata.md#documentdata_interface), [DocumentData](./firestore_.documentdata.md#documentdata_interface)> + +A `Query` that does not use a converter. + +## Query.withConverter() + +Applies a custom data converter to this query, allowing you to use your own custom model objects with Firestore. When you call [getDocs()](./firestore_.md#getdocs_4e56953) with the returned query, the provided converter will convert between Firestore data of type `NewDbModelType` and your custom type `NewAppModelType`. + +Signature: + +```typescript +withConverter(converter: FirestoreDataConverter): Query; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| converter | [FirestoreDataConverter](./firestore_.firestoredataconverter.md#firestoredataconverter_interface)<NewAppModelType, NewDbModelType> | Converts objects to and from Firestore. | + +Returns: + +[Query](./firestore_.query.md#query_class)<NewAppModelType, NewDbModelType> + +A `Query` that uses the provided converter. + diff --git a/docs-devsite/firestore_pipelines.querydocumentsnapshot.md b/docs-devsite/firestore_pipelines.querydocumentsnapshot.md new file mode 100644 index 0000000000..ae64c7c1b9 --- /dev/null +++ b/docs-devsite/firestore_pipelines.querydocumentsnapshot.md @@ -0,0 +1,54 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# QueryDocumentSnapshot class +A `QueryDocumentSnapshot` contains data read from a document in your Firestore database as part of a query. The document is guaranteed to exist and its data can be extracted with `.data()` or `.get()` to get a specific field. + +A `QueryDocumentSnapshot` offers the same API surface as a `DocumentSnapshot`. Since query results contain only existing documents, the `exists` property will always be true and `data()` will never return 'undefined'. + +Signature: + +```typescript +export declare class QueryDocumentSnapshot extends DocumentSnapshot +``` +Extends: [DocumentSnapshot](./firestore_.documentsnapshot.md#documentsnapshot_class)<AppModelType, DbModelType> + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [data(options)](./firestore_pipelines.querydocumentsnapshot.md#querydocumentsnapshotdata) | | Retrieves all fields in the document as an Object.By default, serverTimestamp() values that have not yet been set to their final value will be returned as null. You can override this by passing an options object. | + +## QueryDocumentSnapshot.data() + +Retrieves all fields in the document as an `Object`. + +By default, `serverTimestamp()` values that have not yet been set to their final value will be returned as `null`. You can override this by passing an options object. + +Signature: + +```typescript +/** @override */ +data(options?: SnapshotOptions): AppModelType; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [SnapshotOptions](./firestore_.snapshotoptions.md#snapshotoptions_interface) | An options object to configure how data is retrieved from the snapshot (for example the desired behavior for server timestamps that have not yet been set to their final value). | + +Returns: + +AppModelType + +An `Object` containing all fields in the document. + diff --git a/docs-devsite/firestore_pipelines.selectable.md b/docs-devsite/firestore_pipelines.selectable.md new file mode 100644 index 0000000000..53bde7320b --- /dev/null +++ b/docs-devsite/firestore_pipelines.selectable.md @@ -0,0 +1,39 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Selectable interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An interface that represents a selectable expression. + +Signature: + +```typescript +export declare interface Selectable +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [selectable](./firestore_pipelines.selectable.md#selectableselectable) | true | (Public Preview) | + +## Selectable.selectable + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +selectable: true; +``` diff --git a/docs-devsite/firestore_pipelines.snapshotmetadata.md b/docs-devsite/firestore_pipelines.snapshotmetadata.md new file mode 100644 index 0000000000..be104c3034 --- /dev/null +++ b/docs-devsite/firestore_pipelines.snapshotmetadata.md @@ -0,0 +1,75 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# SnapshotMetadata class +Metadata about a snapshot, describing the state of the snapshot. + +Signature: + +```typescript +export declare class SnapshotMetadata +``` + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [fromCache](./firestore_pipelines.snapshotmetadata.md#snapshotmetadatafromcache) | | boolean | True if the snapshot was created from cached data rather than guaranteed up-to-date server data. If your listener has opted into metadata updates (via SnapshotListenOptions) you will receive another snapshot with fromCache set to false once the client has received up-to-date data from the backend. | +| [hasPendingWrites](./firestore_pipelines.snapshotmetadata.md#snapshotmetadatahaspendingwrites) | | boolean | True if the snapshot contains the result of local writes (for example set() or update() calls) that have not yet been committed to the backend. If your listener has opted into metadata updates (via SnapshotListenOptions) you will receive another snapshot with hasPendingWrites equal to false once the writes have been committed to the backend. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [isEqual(other)](./firestore_pipelines.snapshotmetadata.md#snapshotmetadataisequal) | | Returns true if this SnapshotMetadata is equal to the provided one. | + +## SnapshotMetadata.fromCache + +True if the snapshot was created from cached data rather than guaranteed up-to-date server data. If your listener has opted into metadata updates (via `SnapshotListenOptions`) you will receive another snapshot with `fromCache` set to false once the client has received up-to-date data from the backend. + +Signature: + +```typescript +readonly fromCache: boolean; +``` + +## SnapshotMetadata.hasPendingWrites + +True if the snapshot contains the result of local writes (for example `set()` or `update()` calls) that have not yet been committed to the backend. If your listener has opted into metadata updates (via `SnapshotListenOptions`) you will receive another snapshot with `hasPendingWrites` equal to false once the writes have been committed to the backend. + +Signature: + +```typescript +readonly hasPendingWrites: boolean; +``` + +## SnapshotMetadata.isEqual() + +Returns true if this `SnapshotMetadata` is equal to the provided one. + +Signature: + +```typescript +isEqual(other: SnapshotMetadata): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [SnapshotMetadata](./firestore_.snapshotmetadata.md#snapshotmetadata_class) | The SnapshotMetadata to compare against. | + +Returns: + +boolean + +true if this `SnapshotMetadata` is equal to the provided one. + diff --git a/docs-devsite/firestore_pipelines.snapshotoptions.md b/docs-devsite/firestore_pipelines.snapshotoptions.md new file mode 100644 index 0000000000..cee6bb93eb --- /dev/null +++ b/docs-devsite/firestore_pipelines.snapshotoptions.md @@ -0,0 +1,41 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# SnapshotOptions interface +Options that configure how data is retrieved from a `DocumentSnapshot` (for example the desired behavior for server timestamps that have not yet been set to their final value). + +Signature: + +```typescript +export declare interface SnapshotOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [serverTimestamps](./firestore_pipelines.snapshotoptions.md#snapshotoptionsservertimestamps) | 'estimate' \| 'previous' \| 'none' | If set, controls the return value for server timestamps that have not yet been set to their final value.By specifying 'estimate', pending server timestamps return an estimate based on the local clock. This estimate will differ from the final value and cause these values to change once the server result becomes available.By specifying 'previous', pending timestamps will be ignored and return their previous value instead.If omitted or set to 'none', null will be returned by default until the server value becomes available. | + +## SnapshotOptions.serverTimestamps + +If set, controls the return value for server timestamps that have not yet been set to their final value. + +By specifying 'estimate', pending server timestamps return an estimate based on the local clock. This estimate will differ from the final value and cause these values to change once the server result becomes available. + +By specifying 'previous', pending timestamps will be ignored and return their previous value instead. + +If omitted or set to 'none', `null` will be returned by default until the server value becomes available. + +Signature: + +```typescript +readonly serverTimestamps?: 'estimate' | 'previous' | 'none'; +``` diff --git a/docs-devsite/firestore_pipelines.stageoptions.md b/docs-devsite/firestore_pipelines.stageoptions.md new file mode 100644 index 0000000000..e85f6809dd --- /dev/null +++ b/docs-devsite/firestore_pipelines.stageoptions.md @@ -0,0 +1,51 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# StageOptions interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a Stage is evaluated. + +Signature: + +```typescript +export declare interface StageOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [rawOptions](./firestore_pipelines.stageoptions.md#stageoptionsrawoptions) | { \[name: string\]: unknown; } | (Public Preview) An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Raw option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK.rawOptions supports dot notation, if you want to override a nested option. | + +## StageOptions.rawOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK. + +The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name). + +Raw option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected. + +Values specified in rawOptions will take precedence over any options with the same name set by the SDK. + +`rawOptions` supports dot notation, if you want to override a nested option. + +Signature: + +```typescript +rawOptions?: { + [name: string]: unknown; + }; +``` diff --git a/docs-devsite/firestore_pipelines.timestamp.md b/docs-devsite/firestore_pipelines.timestamp.md new file mode 100644 index 0000000000..c81df6f992 --- /dev/null +++ b/docs-devsite/firestore_pipelines.timestamp.md @@ -0,0 +1,265 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Timestamp class +A `Timestamp` represents a point in time independent of any time zone or calendar, represented as seconds and fractions of seconds at nanosecond resolution in UTC Epoch time. + +It is encoded using the Proleptic Gregorian Calendar which extends the Gregorian calendar backwards to year one. It is encoded assuming all minutes are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. + +For examples and further specifications, refer to the [Timestamp definition](https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto). + +Signature: + +```typescript +export declare class Timestamp +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(seconds, nanoseconds)](./firestore_pipelines.timestamp.md#timestampconstructor) | | Creates a new timestamp. | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [nanoseconds](./firestore_pipelines.timestamp.md#timestampnanoseconds) | | number | The fractions of a second at nanosecond resolution.\* | +| [seconds](./firestore_pipelines.timestamp.md#timestampseconds) | | number | The number of seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [fromDate(date)](./firestore_pipelines.timestamp.md#timestampfromdate) | static | Creates a new timestamp from the given date. | +| [fromJSON(json)](./firestore_pipelines.timestamp.md#timestampfromjson) | static | Builds a Timestamp instance from a JSON object created by [Timestamp.toJSON()](./firestore_.timestamp.md#timestamptojson). | +| [fromMillis(milliseconds)](./firestore_pipelines.timestamp.md#timestampfrommillis) | static | Creates a new timestamp from the given number of milliseconds. | +| [isEqual(other)](./firestore_pipelines.timestamp.md#timestampisequal) | | Returns true if this Timestamp is equal to the provided one. | +| [now()](./firestore_pipelines.timestamp.md#timestampnow) | static | Creates a new timestamp with the current date, with millisecond precision. | +| [toDate()](./firestore_pipelines.timestamp.md#timestamptodate) | | Converts a Timestamp to a JavaScript Date object. This conversion causes a loss of precision since Date objects only support millisecond precision. | +| [toJSON()](./firestore_pipelines.timestamp.md#timestamptojson) | | Returns a JSON-serializable representation of this Timestamp. | +| [toMillis()](./firestore_pipelines.timestamp.md#timestamptomillis) | | Converts a Timestamp to a numeric timestamp (in milliseconds since epoch). This operation causes a loss of precision. | +| [toString()](./firestore_pipelines.timestamp.md#timestamptostring) | | Returns a textual representation of this Timestamp. | +| [valueOf()](./firestore_pipelines.timestamp.md#timestampvalueof) | | Converts this object to a primitive string, which allows Timestamp objects to be compared using the >, <=, >= and > operators. | + +## Timestamp.(constructor) + +Creates a new timestamp. + +Signature: + +```typescript +constructor( + seconds: number, + nanoseconds: number); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| seconds | number | The number of seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive. | +| nanoseconds | number | The non-negative fractions of a second at nanosecond resolution. Negative second values with fractions must still have non-negative nanoseconds values that count forward in time. Must be from 0 to 999,999,999 inclusive. | + +## Timestamp.nanoseconds + +The fractions of a second at nanosecond resolution.\* + +Signature: + +```typescript +readonly nanoseconds: number; +``` + +## Timestamp.seconds + +The number of seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. + +Signature: + +```typescript +readonly seconds: number; +``` + +## Timestamp.fromDate() + +Creates a new timestamp from the given date. + +Signature: + +```typescript +static fromDate(date: Date): Timestamp; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| date | Date | The date to initialize the Timestamp from. | + +Returns: + +[Timestamp](./firestore_.timestamp.md#timestamp_class) + +A new `Timestamp` representing the same point in time as the given date. + +## Timestamp.fromJSON() + +Builds a `Timestamp` instance from a JSON object created by [Timestamp.toJSON()](./firestore_.timestamp.md#timestamptojson). + +Signature: + +```typescript +static fromJSON(json: object): Timestamp; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| json | object | | + +Returns: + +[Timestamp](./firestore_.timestamp.md#timestamp_class) + +## Timestamp.fromMillis() + +Creates a new timestamp from the given number of milliseconds. + +Signature: + +```typescript +static fromMillis(milliseconds: number): Timestamp; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| milliseconds | number | Number of milliseconds since Unix epoch 1970-01-01T00:00:00Z. | + +Returns: + +[Timestamp](./firestore_.timestamp.md#timestamp_class) + +A new `Timestamp` representing the same point in time as the given number of milliseconds. + +## Timestamp.isEqual() + +Returns true if this `Timestamp` is equal to the provided one. + +Signature: + +```typescript +isEqual(other: Timestamp): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [Timestamp](./firestore_.timestamp.md#timestamp_class) | The Timestamp to compare against. | + +Returns: + +boolean + +true if this `Timestamp` is equal to the provided one. + +## Timestamp.now() + +Creates a new timestamp with the current date, with millisecond precision. + +Signature: + +```typescript +static now(): Timestamp; +``` +Returns: + +[Timestamp](./firestore_.timestamp.md#timestamp_class) + +a new timestamp representing the current date. + +## Timestamp.toDate() + +Converts a `Timestamp` to a JavaScript `Date` object. This conversion causes a loss of precision since `Date` objects only support millisecond precision. + +Signature: + +```typescript +toDate(): Date; +``` +Returns: + +Date + +JavaScript `Date` object representing the same point in time as this `Timestamp`, with millisecond precision. + +## Timestamp.toJSON() + +Returns a JSON-serializable representation of this `Timestamp`. + +Signature: + +```typescript +toJSON(): { + seconds: number; + nanoseconds: number; + type: string; + }; +``` +Returns: + +{ seconds: number; nanoseconds: number; type: string; } + +## Timestamp.toMillis() + +Converts a `Timestamp` to a numeric timestamp (in milliseconds since epoch). This operation causes a loss of precision. + +Signature: + +```typescript +toMillis(): number; +``` +Returns: + +number + +The point in time corresponding to this timestamp, represented as the number of milliseconds since Unix epoch 1970-01-01T00:00:00Z. + +## Timestamp.toString() + +Returns a textual representation of this `Timestamp`. + +Signature: + +```typescript +toString(): string; +``` +Returns: + +string + +## Timestamp.valueOf() + +Converts this object to a primitive string, which allows `Timestamp` objects to be compared using the `>`, `<=`, `>=` and `>` operators. + +Signature: + +```typescript +valueOf(): string; +``` +Returns: + +string + diff --git a/docs-devsite/firestore_pipelines.vectorvalue.md b/docs-devsite/firestore_pipelines.vectorvalue.md new file mode 100644 index 0000000000..8185645466 --- /dev/null +++ b/docs-devsite/firestore_pipelines.vectorvalue.md @@ -0,0 +1,101 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# VectorValue class +Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). + + VectorValue + +Signature: + +```typescript +export declare class VectorValue +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [fromJSON(json)](./firestore_pipelines.vectorvalue.md#vectorvaluefromjson) | static | Builds a VectorValue instance from a JSON object created by [VectorValue.toJSON()](./firestore_.vectorvalue.md#vectorvaluetojson). | +| [isEqual(other)](./firestore_pipelines.vectorvalue.md#vectorvalueisequal) | | Returns true if the two VectorValue values have the same raw number arrays, returns false otherwise. | +| [toArray()](./firestore_pipelines.vectorvalue.md#vectorvaluetoarray) | | Returns a copy of the raw number array form of the vector. | +| [toJSON()](./firestore_pipelines.vectorvalue.md#vectorvaluetojson) | | Returns a JSON-serializable representation of this VectorValue instance. | + +## VectorValue.fromJSON() + +Builds a `VectorValue` instance from a JSON object created by [VectorValue.toJSON()](./firestore_.vectorvalue.md#vectorvaluetojson). + +Signature: + +```typescript +static fromJSON(json: object): VectorValue; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| json | object | a JSON object represention of a VectorValue instance. | + +Returns: + +[VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) + +an instance of [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) if the JSON object could be parsed. Throws a [FirestoreError](./firestore_.firestoreerror.md#firestoreerror_class) if an error occurs. + +## VectorValue.isEqual() + +Returns `true` if the two `VectorValue` values have the same raw number arrays, returns `false` otherwise. + +Signature: + +```typescript +isEqual(other: VectorValue): boolean; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| other | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | | + +Returns: + +boolean + +## VectorValue.toArray() + +Returns a copy of the raw number array form of the vector. + +Signature: + +```typescript +toArray(): number[]; +``` +Returns: + +number\[\] + +## VectorValue.toJSON() + +Returns a JSON-serializable representation of this `VectorValue` instance. + +Signature: + +```typescript +toJSON(): object; +``` +Returns: + +object + +a JSON representation of this object. + diff --git a/integration/firestore/gulpfile.js b/integration/firestore/gulpfile.js index 57dc674606..601c12b8dd 100644 --- a/integration/firestore/gulpfile.js +++ b/integration/firestore/gulpfile.js @@ -48,7 +48,8 @@ function copyTests() { testBase + '/integration/util/settings.ts', testBase + '/integration/util/testing_hooks_util.ts', testBase + '/util/equality_matcher.ts', - testBase + '/util/promise.ts' + testBase + '/util/promise.ts', + testBase + '/util/mocha_extensions.ts' ], { base: '../../packages/firestore' } ) @@ -69,6 +70,16 @@ if (typeof process === 'undefined') { ` ) ) + .pipe( + replace( + /** + * This regex is designed to match the Firebase import in our + * integration tests. + */ + /\s+from '\.(\.\/util)?\/pipeline_export';/, + ` from '${resolve(__dirname, './pipeline_export')}';` + ) + ) .pipe( /** * Fixing the project.json require to properly reference the file diff --git a/integration/firestore/package.json b/integration/firestore/package.json index 97fd26e548..c87a2b1c89 100644 --- a/integration/firestore/package.json +++ b/integration/firestore/package.json @@ -3,9 +3,10 @@ "version": "1.0.1", "private": true, "scripts": { - "build:deps": "lerna run --scope @firebase/'{app,firestore}' --include-dependencies build", - "build:persistence": "INCLUDE_FIRESTORE_PERSISTENCE=true gulp compile-tests", - "build:memory": "INCLUDE_FIRESTORE_PERSISTENCE=false gulp compile-tests", + "build:deps": "lerna run --scope @firebase/'{app,firestore}' --include-dependencies build && npm run typings:public", + "typings:public": "lerna run --scope @firebase/'{app,firestore}' --include-dependencies typings:public", + "build:persistence": "yarn typings:public && INCLUDE_FIRESTORE_PERSISTENCE=true gulp compile-tests", + "build:memory": "yarn typings:public && INCLUDE_FIRESTORE_PERSISTENCE=false gulp compile-tests", "karma:singlerun": "karma start", "prettier": "prettier --write '*.js' '*.ts'", "test:persistence": " yarn build:persistence; karma start", diff --git a/integration/firestore/pipeline_export.ts b/integration/firestore/pipeline_export.ts new file mode 100644 index 0000000000..15383ae558 --- /dev/null +++ b/integration/firestore/pipeline_export.ts @@ -0,0 +1,21 @@ +/** + * @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. + */ + +// This file replaces "packages/firestore/test/integration/util/pipeline_export" +// and depends on the minified sources. + +export * from '@firebase/firestore/pipelines'; diff --git a/package.json b/package.json index 39455ef116..49fe50d236 100644 --- a/package.json +++ b/package.json @@ -142,6 +142,7 @@ "postinstall-postinstall": "2.1.0", "prettier": "2.8.8", "protractor": "5.4.2", + "protobufjs-cli": "^1.1.3", "request": "2.88.2", "semver": "7.7.1", "simple-git": "3.27.0", diff --git a/packages/firebase/firestore/lite/pipelines/index.ts b/packages/firebase/firestore/lite/pipelines/index.ts new file mode 100644 index 0000000000..8ef0f25b90 --- /dev/null +++ b/packages/firebase/firestore/lite/pipelines/index.ts @@ -0,0 +1,18 @@ +/** + * @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. + */ + +export * from '@firebase/firestore/lite/pipelines'; diff --git a/packages/firebase/firestore/lite/pipelines/package.json b/packages/firebase/firestore/lite/pipelines/package.json new file mode 100644 index 0000000000..d0d28ab6af --- /dev/null +++ b/packages/firebase/firestore/lite/pipelines/package.json @@ -0,0 +1,7 @@ +{ + "name": "firebase/firestore/lite/pipelines", + "main": "dist/pipelines.cjs.js", + "browser": "dist/esm/pipelines.esm.js", + "module": "dist/esm/pipelines.esm.js", + "typings": "dist/firestore/lite/pipelines/index.d.ts" +} diff --git a/packages/firebase/firestore/package.json b/packages/firebase/firestore/package.json index cf9bb8b2d7..4fe0292c9d 100644 --- a/packages/firebase/firestore/package.json +++ b/packages/firebase/firestore/package.json @@ -4,4 +4,4 @@ "browser": "dist/esm/index.esm.js", "module": "dist/esm/index.esm.js", "typings": "dist/firestore/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/firebase/firestore/pipelines/index.cdn.ts b/packages/firebase/firestore/pipelines/index.cdn.ts new file mode 100644 index 0000000000..81e81b39d8 --- /dev/null +++ b/packages/firebase/firestore/pipelines/index.cdn.ts @@ -0,0 +1,21 @@ +/** + * @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. + */ + +export * from '@firebase/firestore'; + +import * as pipelines from '@firebase/firestore/pipelines'; +export { pipelines }; diff --git a/packages/firebase/firestore/pipelines/index.ts b/packages/firebase/firestore/pipelines/index.ts new file mode 100644 index 0000000000..be062f16e9 --- /dev/null +++ b/packages/firebase/firestore/pipelines/index.ts @@ -0,0 +1,18 @@ +/** + * @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. + */ + +export * from '@firebase/firestore/pipelines'; diff --git a/packages/firebase/firestore/pipelines/package.json b/packages/firebase/firestore/pipelines/package.json new file mode 100644 index 0000000000..b52d1749ce --- /dev/null +++ b/packages/firebase/firestore/pipelines/package.json @@ -0,0 +1,7 @@ +{ + "name": "firebase/firestore/pipelines", + "main": "dist/pipelines.cjs.js", + "browser": "dist/esm/pipelines.esm.js", + "module": "dist/esm/pipelines.esm.js", + "typings": "dist/firestore/pipelines/index.d.ts" +} diff --git a/packages/firebase/gulpfile.js b/packages/firebase/gulpfile.js index 4ea24182af..e05345fbdf 100644 --- a/packages/firebase/gulpfile.js +++ b/packages/firebase/gulpfile.js @@ -21,7 +21,7 @@ const replace = require('gulp-replace'); const pkgJson = require('./package.json'); const files = pkgJson.components.map(component => { - const componentName = component.replace('/', '-'); + const componentName = component.replaceAll('/', '-'); return `firebase-${componentName}.js`; }); const FIREBASE_APP_URL = `https://www.gstatic.com/firebasejs/${pkgJson.version}/firebase-app.js`; diff --git a/packages/firebase/package.json b/packages/firebase/package.json index c71928a0ef..d3c6172b18 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -131,6 +131,18 @@ }, "default": "./firestore/dist/esm/index.esm.js" }, + "./firestore/pipelines": { + "types": "./firestore/pipelines/dist/firestore/pipelines/index.d.ts", + "node": { + "require": "./firestore/pipelines/dist/pipelines.cjs.js", + "import": "./firestore/pipelines/dist/pipelines.mjs" + }, + "browser": { + "require": "./firestore/pipelines/dist/pipelines.cjs.js", + "import": "./firestore/pipelines/dist/esm/pipelines.esm.js" + }, + "default": "./firestore/pipelines/dist/esm/pipelines.esm.js" + }, "./firestore/lite": { "types": "./firestore/lite/dist/firestore/lite/index.d.ts", "node": { @@ -143,6 +155,18 @@ }, "default": "./firestore/lite/dist/esm/index.esm.js" }, + "./firestore/lite/pipelines": { + "types": "./firestore/lite/pipelines/dist/firestore/lite/pipelines/index.d.ts", + "node": { + "require": "./firestore/lite/pipelines/dist/pipelines.cjs.js", + "import": "./firestore/lite/pipelines/dist/pipelines.mjs" + }, + "browser": { + "require": "./firestore/lite/pipelines/dist/pipelines.cjs.js", + "import": "./firestore/lite/pipelines/dist/esm/pipelines.esm.js" + }, + "default": "./firestore/lite/pipelines/dist/esm/pipelines.esm.js" + }, "./functions": { "types": "./functions/dist/functions/index.d.ts", "node": { @@ -453,6 +477,8 @@ "functions", "firestore", "firestore/lite", + "firestore/pipelines", + "firestore/lite/pipelines", "installations", "storage", "performance", diff --git a/packages/firebase/rollup.config.js b/packages/firebase/rollup.config.js index f96ff01666..87b9f7c834 100644 --- a/packages/firebase/rollup.config.js +++ b/packages/firebase/rollup.config.js @@ -20,6 +20,7 @@ import commonjs from '@rollup/plugin-commonjs'; import json from '@rollup/plugin-json'; import pkg from './package.json'; import { resolve } from 'path'; +import { existsSync } from 'fs'; import resolveModule from '@rollup/plugin-node-resolve'; import rollupTypescriptPlugin from 'rollup-plugin-typescript2'; import sourcemaps from 'rollup-plugin-sourcemaps'; @@ -149,10 +150,12 @@ const cdnBuilds = [ .map(component => { // It is needed for handling sub modules, for example firestore/lite which should produce firebase-firestore-lite.js // Otherwise, we will create a directory with '/' in the name. - const componentName = component.replace('/', '-'); + const componentName = component.replaceAll('/', '-'); return { - input: `${component}/index.ts`, + input: existsSync(`${component}/index.cdn.ts`) + ? `${component}/index.cdn.ts` + : `${component}/index.ts`, output: { file: `firebase-${componentName}.js`, sourcemap: true, diff --git a/packages/firestore/.eslintrc.js b/packages/firestore/.eslintrc.js index 5dd443333d..9ffb1d0279 100644 --- a/packages/firestore/.eslintrc.js +++ b/packages/firestore/.eslintrc.js @@ -24,7 +24,7 @@ module.exports = { tsconfigRootDir: __dirname }, plugins: ['import'], - ignorePatterns: ['compat/*'], + ignorePatterns: ['compat/*', 'pipelines.d.ts'], rules: { 'no-console': ['error', { allow: ['warn', 'error'] }], '@typescript-eslint/no-unused-vars': [ diff --git a/packages/firestore/api-extractor.json b/packages/firestore/api-extractor.json index ed10a0d62a..dfa3ae3736 100644 --- a/packages/firestore/api-extractor.json +++ b/packages/firestore/api-extractor.json @@ -4,13 +4,21 @@ * apiReport and d.ts rollup are handled by scripts/api-report.ts. */ "extends": "../../config/api-extractor.json", - // Point it to your entry point d.ts file. + // Point it to your entry point d.ts file. "mainEntryPointFilePath": "/dist/index.d.ts", "additionalEntryPoints": [ - { - "modulePath": "lite", - "filePath": "/dist/lite/index.d.ts" - } + { + "modulePath": "lite", + "filePath": "/dist/lite/index.d.ts" + }, + { + "modulePath": "pipelines", + "filePath": "/dist/pipelines.d.ts" + }, + { + "modulePath": "lite/pipelines", + "filePath": "/dist/lite/pipelines.d.ts" + } ], "apiReport": { /** @@ -18,4 +26,4 @@ */ "enabled": false } -} \ No newline at end of file +} diff --git a/packages/firestore/externs.json b/packages/firestore/externs.json index c56b078ddd..ae68fe87be 100644 --- a/packages/firestore/externs.json +++ b/packages/firestore/externs.json @@ -17,7 +17,9 @@ "packages/app-check-interop-types/index.d.ts", "packages/auth-interop-types/index.d.ts", "packages/firestore/dist/lite/internal.d.ts", + "packages/firestore/dist/lite/internal.pipelines.d.ts", "packages/firestore/dist/internal.d.ts", + "packages/firestore/dist/internal.pipelines.d.ts", "packages/firestore-types/index.d.ts", "packages/firebase/compat/index.d.ts", "packages/component/dist/src/component.d.ts", diff --git a/packages/firestore/lite/pipelines/package.json b/packages/firestore/lite/pipelines/package.json new file mode 100644 index 0000000000..aff9ad6671 --- /dev/null +++ b/packages/firestore/lite/pipelines/package.json @@ -0,0 +1,14 @@ +{ + "name": "@firebase/firestore-lite-pipelines", + "description": "Pipelines for the lite Firestore SDK", + "main": "../../dist/lite/pipelines.node.cjs.js", + "main-esm": "../../dist/lite/pipelines.node.mjs", + "module": "../../dist/lite/pipelines.browser.esm.js", + "browser": "../../dist/lite/pipelines.browser.esm.js", + "react-native": "../../dist/lite/pipelines.rn.esm.js", + "typings": "./pipelines.d.ts", + "private": true, + "engines": { + "node": ">=20.0.0" + } +} diff --git a/packages/firestore/lite/pipelines/pipelines.d.ts b/packages/firestore/lite/pipelines/pipelines.d.ts new file mode 100644 index 0000000000..dd0183e782 --- /dev/null +++ b/packages/firestore/lite/pipelines/pipelines.d.ts @@ -0,0 +1,28 @@ +/** + * @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. + */ +import { PipelineSource, Pipeline } from '../../dist/lite/pipelines'; + +// Augument the Firestore class with the pipeline() method. +// This is stripped from dist/lite/pipelines.d.ts during the build +// so it needs to be re-added here. +declare module '@firebase/firestore/lite' { + interface Firestore { + pipeline(): PipelineSource; + } +} + +export * from '../../dist/lite/pipelines'; diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts new file mode 100644 index 0000000000..ba5b3f61d3 --- /dev/null +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -0,0 +1,194 @@ +/** + * Firestore Lite Pipelines + * + * @remarks Firestore Lite is a small online-only SDK that allows read + * and write access to your Firestore database. All operations connect + * directly to the backend, and `onSnapshot()` APIs are not supported. + * @packageDocumentation + */ +/** + * @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. + */ + +// External exports: ./index +// These external exports will be stripped from the dist/pipelines.d.ts file +// by the prune-dts script, in order to reduce type duplication. However, these +// types need to be exported here to ensure that api-extractor behaves +// correctly. If a type from api.ts is missing from this export, then +// api-extractor may rename it with a suffix `_#`, e.g. `YourType_2`. +export type { + Timestamp, + DocumentReference, + VectorValue, + GeoPoint, + FieldPath, + DocumentData, + Query, + Firestore, + FirestoreDataConverter, + WithFieldValue, + PartialWithFieldValue, + SetOptions, + QueryDocumentSnapshot, + Primitive, + FieldValue, + Bytes +} from '../index'; + +export { PipelineSource } from '../../src/lite-api/pipeline-source'; + +export { OneOf } from '../../src/util/types'; + +export { + PipelineResult, + PipelineSnapshot +} from '../../src/lite-api/pipeline-result'; + +export { Pipeline } from '../../src/lite-api/pipeline'; + +export { execute } from '../../src/lite-api/pipeline_impl'; + +export { + StageOptions, + CollectionStageOptions, + CollectionGroupStageOptions, + DatabaseStageOptions, + DocumentsStageOptions, + AddFieldsStageOptions, + RemoveFieldsStageOptions, + SelectStageOptions, + WhereStageOptions, + OffsetStageOptions, + LimitStageOptions, + DistinctStageOptions, + AggregateStageOptions, + FindNearestStageOptions, + ReplaceWithStageOptions, + SampleStageOptions, + UnionStageOptions, + UnnestStageOptions, + SortStageOptions +} from '../../src/lite-api/stage_options'; + +export { + Expression, + field, + and, + array, + constant, + add, + subtract, + multiply, + average, + substring, + count, + mapMerge, + mapRemove, + ifError, + isAbsent, + isError, + or, + divide, + map, + mod, + documentId, + equal, + notEqual, + lessThan, + countIf, + lessThanOrEqual, + greaterThan, + greaterThanOrEqual, + arrayConcat, + arrayContains, + arrayContainsAny, + arrayContainsAll, + arrayLength, + equalAny, + notEqualAny, + xor, + conditional, + not, + logicalMaximum, + logicalMinimum, + exists, + reverse, + byteLength, + charLength, + like, + regexContains, + regexMatch, + stringContains, + startsWith, + endsWith, + toLower, + toUpper, + trim, + stringConcat, + mapGet, + countAll, + minimum, + maximum, + cosineDistance, + dotProduct, + euclideanDistance, + vectorLength, + unixMicrosToTimestamp, + timestampToUnixMicros, + unixMillisToTimestamp, + timestampToUnixMillis, + unixSecondsToTimestamp, + timestampToUnixSeconds, + timestampAdd, + timestampSubtract, + ascending, + descending, + arrayGet, + abs, + sum, + countDistinct, + ceil, + floor, + exp, + pow, + round, + collectionId, + ln, + log, + sqrt, + stringReverse, + log10, + concat, + currentTimestamp, + ifAbsent, + join, + length, + arraySum, + split, + timestampTruncate, + type, + AliasedExpression, + Field, + Constant, + FunctionExpression, + Ordering, + ExpressionType, + AliasedAggregate, + Selectable, + BooleanExpression, + AggregateFunction, + TimeGranularity +} from '../../src/lite-api/expressions'; diff --git a/packages/firestore/package.json b/packages/firestore/package.json index a421f06687..9eef54816a 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -8,6 +8,7 @@ "author": "Firebase (https://firebase.google.com/)", "scripts": { "bundle": "rollup -c", + "compile": "tsc --emitDeclarationOnly --declaration -p tsconfig.json", "prebuild": "tsc --emitDeclarationOnly --declaration -p tsconfig.json; yarn api-report", "build": "run-p --npm-path npm build:lite build:main", "build:release": "yarn build && yarn typings:public", @@ -50,9 +51,11 @@ "test:minified": "(cd ../../integration/firestore ; yarn test)", "trusted-type-check": "tsec -p tsconfig.json --noEmit", "api-report:main": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore --packageRoot . --typescriptDts ./dist/firestore/src/index.d.ts --rollupDts ./dist/private.d.ts --untrimmedRollupDts ./dist/internal.d.ts --publicDts ./dist/index.d.ts", + "api-report:pipelines": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-pipelines --packageRoot . --typescriptDts ./dist/firestore/pipelines/pipelines.d.ts --rollupDts ./dist/private.pipelines.d.ts --untrimmedRollupDts ./dist/internal.pipelines.d.ts --publicDts ./dist/pipelines.d.ts --otherExportsPublicDtsFiles ./dist/index.d.ts", "api-report:lite": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-lite --packageRoot . --typescriptDts ./dist/firestore/lite/index.d.ts --rollupDts ./dist/lite/private.d.ts --untrimmedRollupDts ./dist/lite/internal.d.ts --publicDts ./dist/lite/index.d.ts", + "api-report:lite:pipelines": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-lite-pipelines --packageRoot . --typescriptDts ./dist/firestore/lite/pipelines/pipelines.d.ts --rollupDts ./dist/lite/private.pipelines.d.ts --untrimmedRollupDts ./dist/lite/internal.pipelines.d.ts --publicDts ./dist/lite/pipelines.d.ts --otherExportsPublicDtsFiles ./dist/lite/index.d.ts", "api-report:api-json": "rm -rf temp && api-extractor run --local --verbose", - "api-report": "run-s --npm-path npm api-report:main api-report:lite && yarn api-report:api-json", + "api-report": "run-s --npm-path npm api-report:main api-report:pipelines api-report:lite api-report:lite:pipelines && yarn api-report:api-json", "doc": "api-documenter markdown --input temp --output docs", "typings:public": "node ../../scripts/build/use_typings.js ./dist/index.d.ts", "assertion-id:check": "ts-node scripts/assertion-id-tool.ts --dir=src --check", @@ -82,11 +85,37 @@ }, "react-native": "./dist/lite/index.rn.esm.js", "browser": { - "require": "./dist/lite/index.cjs.js", + "require": "./dist/lite/index.browser.cjs.js", "import": "./dist/lite/index.browser.esm.js" }, "default": "./dist/lite/index.browser.esm.js" }, + "./lite/pipelines": { + "types": "./dist/lite/pipelines.d.ts", + "node": { + "require": "./dist/lite/pipelines.node.cjs.js", + "import": "./dist/lite/pipelines.node.mjs" + }, + "react-native": "./dist/lite/pipelines.rn.esm.js", + "browser": { + "require": "./dist/lite/pipelines.browser.cjs.js", + "import": "./dist/lite/pipelines.browser.esm.js" + }, + "default": "./dist/lite/pipelines.browser.esm.js" + }, + "./pipelines": { + "types": "./pipelines/pipelines.d.ts", + "node": { + "require": "./dist/pipelines.node.cjs.js", + "import": "./dist/pipelines.node.mjs" + }, + "react-native": "./dist/index.rn.js", + "browser": { + "require": "./dist/pipelines.cjs.js", + "import": "./dist/pipelines.esm.js" + }, + "default": "./dist/pipelines.esm.js" + }, "./package.json": "./package.json" }, "main": "dist/index.node.cjs.js", @@ -97,7 +126,11 @@ "license": "Apache-2.0", "files": [ "dist", - "lite/package.json" + "lite/package.json", + "pipelines/package.json", + "pipelines/pipelines.d.ts", + "lite/pipelines/package.json", + "lite/pipelines/pipelines.d.ts" ], "dependencies": { "@firebase/component": "0.7.0", diff --git a/packages/firestore/pipelines/package.json b/packages/firestore/pipelines/package.json new file mode 100644 index 0000000000..aaf410ce36 --- /dev/null +++ b/packages/firestore/pipelines/package.json @@ -0,0 +1,14 @@ +{ + "name": "@firebase/firestore-pipelines", + "description": "pipelines", + "main": "../dist/pipelines.node.cjs.js", + "main-esm": "../dist/pipelines.node.mjs", + "module": "../dist/pipelines.esm.js", + "browser": "../dist/pipelines.esm.js", + "react-native": "../dist/pipelines.rn.js", + "typings": "./pipelines.d.ts", + "private": true, + "engines": { + "node": ">=20.0.0" + } +} diff --git a/packages/firestore/pipelines/pipelines.d.ts b/packages/firestore/pipelines/pipelines.d.ts new file mode 100644 index 0000000000..90e2923975 --- /dev/null +++ b/packages/firestore/pipelines/pipelines.d.ts @@ -0,0 +1,28 @@ +/** + * @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. + */ +import { PipelineSource, Pipeline } from '../dist/pipelines'; + +// Augment the Firestore and Query classes with the pipeline() method. +// This is stripped from dist/lite/pipelines.d.ts during the build +// so it needs to be re-added here. +declare module '@firebase/firestore' { + interface Firestore { + pipeline(): PipelineSource; + } +} + +export * from '../dist/pipelines'; diff --git a/packages/firestore/pipelines/pipelines.node.ts b/packages/firestore/pipelines/pipelines.node.ts new file mode 100644 index 0000000000..42de68b39c --- /dev/null +++ b/packages/firestore/pipelines/pipelines.node.ts @@ -0,0 +1,18 @@ +/** + * @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. + */ + +export * from '../src/api_pipelines'; diff --git a/packages/firestore/pipelines/pipelines.rn.ts b/packages/firestore/pipelines/pipelines.rn.ts new file mode 100644 index 0000000000..42de68b39c --- /dev/null +++ b/packages/firestore/pipelines/pipelines.rn.ts @@ -0,0 +1,18 @@ +/** + * @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. + */ + +export * from '../src/api_pipelines'; diff --git a/packages/firestore/pipelines/pipelines.ts b/packages/firestore/pipelines/pipelines.ts new file mode 100644 index 0000000000..8996148263 --- /dev/null +++ b/packages/firestore/pipelines/pipelines.ts @@ -0,0 +1,51 @@ +/** + * Cloud Firestore + * + * @packageDocumentation + */ + +/** + * @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. + */ + +// External exports: ./api +// These external exports will be stripped from the dist/pipelines.d.ts file +// by the prune-dts script, in order to reduce type duplication. However, these +// types need to be exported here to ensure that api-extractor behaves +// correctly. If a type from api.ts is missing from this export, then +// api-extractor may rename it with a suffix `_#`, e.g. `YourType_2`. +export type { + Timestamp, + DocumentReference, + VectorValue, + GeoPoint, + FieldPath, + DocumentData, + Query, + Firestore, + FirestoreDataConverter, + WithFieldValue, + PartialWithFieldValue, + SetOptions, + QueryDocumentSnapshot, + SnapshotOptions, + Primitive, + FieldValue, + SnapshotMetadata, + Bytes +} from '../src/api'; + +export * from '../src/api_pipelines'; diff --git a/packages/firestore/rollup.config.js b/packages/firestore/rollup.config.js index 5fa616bca8..646ed038f0 100644 --- a/packages/firestore/rollup.config.js +++ b/packages/firestore/rollup.config.js @@ -26,6 +26,7 @@ import tmp from 'tmp'; import typescript from 'typescript'; import { generateBuildTargetReplaceConfig } from '../../scripts/build/rollup_replace_build_target'; +import { replaceDeclareModule } from '../../scripts/build/rollup_replace_declare_module'; import pkg from './package.json'; import tsconfig from './tsconfig.json'; @@ -64,9 +65,11 @@ const allBuilds = [ // this is an intermediate build used to generate the actual esm and cjs builds // which add build target reporting { - input: './src/index.node.ts', + input: ['./src/index.node.ts', './pipelines/pipelines.node.ts'], output: { - file: pkg['main-esm'], + dir: 'dist/intermediate', + entryFileNames: '[name].mjs', + chunkFileNames: 'common-[hash].node.mjs', format: 'es', sourcemap: true }, @@ -79,9 +82,14 @@ const allBuilds = [ }, // Node CJS build { - input: pkg['main-esm'], + input: [ + 'dist/intermediate/index.node.mjs', + 'dist/intermediate/pipelines.node.mjs' + ], output: { - file: pkg.main, + dir: 'dist/', + entryFileNames: '[name].cjs.js', + chunkFileNames: 'common-[hash].node.cjs.js', format: 'cjs', sourcemap: true }, @@ -106,9 +114,14 @@ const allBuilds = [ }, // Node ESM build with build target reporting { - input: pkg['main-esm'], + input: [ + 'dist/intermediate/index.node.mjs', + 'dist/intermediate/pipelines.node.mjs' + ], output: { - file: pkg['main-esm'], + dir: 'dist/', + entryFileNames: '[name].mjs', + chunkFileNames: 'common-[hash].node.mjs', format: 'es', sourcemap: true }, @@ -125,9 +138,11 @@ const allBuilds = [ // this is an intermediate build used to generate the actual esm and cjs builds // which add build target reporting { - input: './src/index.ts', + input: ['./src/index.ts', './pipelines/pipelines.ts'], output: { - file: pkg.browser, + dir: 'dist/intermediate', + entryFileNames: '[name].js', + chunkFileNames: 'common-[hash].js', format: 'es', sourcemap: true }, @@ -139,10 +154,12 @@ const allBuilds = [ }, // Convert es2020 build to cjs { - input: pkg['browser'], + input: ['dist/intermediate/index.js', 'dist/intermediate/pipelines.js'], output: [ { - file: './dist/index.cjs.js', + dir: 'dist/', + entryFileNames: '[name].cjs.js', + chunkFileNames: 'common-[hash].cjs.js', format: 'cjs', sourcemap: true } @@ -158,10 +175,12 @@ const allBuilds = [ }, // es2020 build with build target reporting { - input: pkg['browser'], + input: ['dist/intermediate/index.js', 'dist/intermediate/pipelines.js'], output: [ { - file: pkg['browser'], + dir: 'dist/', + entryFileNames: '[name].esm.js', + chunkFileNames: 'common-[hash].esm.js', format: 'es', sourcemap: true } @@ -177,9 +196,11 @@ const allBuilds = [ }, // RN build { - input: './src/index.rn.ts', + input: ['./src/index.rn.ts', './pipelines/pipelines.rn.ts'], output: { - file: pkg['react-native'], + dir: 'dist/', + entryFileNames: '[name].js', + chunkFileNames: 'common-[hash].rn.js', format: 'es', sourcemap: true }, @@ -194,7 +215,7 @@ const allBuilds = [ } }, { - input: 'dist/firestore/src/index.d.ts', + input: 'dist/firestore/src/global.d.ts', output: { file: 'dist/firestore/src/global_index.d.ts', format: 'es' @@ -202,7 +223,17 @@ const allBuilds = [ plugins: [ dts({ respectExternal: true - }) + }), + + // The global.d.ts input file will include + // a `declare module './database' { ... }` block. This block + // was not removed in the build, and the module + // './database' is not known in context of the global.d.ts file. + // Use the declareModuleReplacePlugin to replace: + // `declare module './database' { Y }` + // with the contents of the block: + // `Y` + replaceDeclareModule('global_index.d.ts', './database') ] } ]; diff --git a/packages/firestore/rollup.config.lite.js b/packages/firestore/rollup.config.lite.js index 5ea2225f36..6bf9297e4d 100644 --- a/packages/firestore/rollup.config.lite.js +++ b/packages/firestore/rollup.config.lite.js @@ -56,9 +56,11 @@ const allBuilds = [ // this is an intermediate build used to generate the actual esm and cjs builds // which add build target reporting { - input: './lite/index.ts', + input: ['./lite/index.ts', './lite/pipelines/pipelines.ts'], output: { - file: path.resolve('./lite', pkg['main-esm']), + dir: 'dist/intermediate/lite/', + entryFileNames: '[name].node.mjs', + chunkFileNames: 'common-[hash].node.mjs', format: 'es', sourcemap: true }, @@ -77,9 +79,14 @@ const allBuilds = [ }, // Node CJS build { - input: path.resolve('./lite', pkg['main-esm']), + input: [ + 'dist/intermediate/lite/index.node.mjs', + 'dist/intermediate/lite/pipelines.node.mjs' + ], output: { - file: path.resolve('./lite', pkg.main), + dir: 'dist/lite/', + entryFileNames: '[name].cjs.js', + chunkFileNames: 'common-[hash].node.cjs.js', format: 'cjs', sourcemap: true }, @@ -102,9 +109,14 @@ const allBuilds = [ }, // Node ESM build { - input: path.resolve('./lite', pkg['main-esm']), + input: [ + 'dist/intermediate/lite/index.node.mjs', + 'dist/intermediate/lite/pipelines.node.mjs' + ], output: { - file: path.resolve('./lite', pkg['main-esm']), + dir: 'dist/lite/', + entryFileNames: '[name].mjs', + chunkFileNames: 'common-[hash].node.mjs', format: 'es', sourcemap: true }, @@ -121,9 +133,11 @@ const allBuilds = [ // this is an intermediate build used to generate the actual esm and cjs builds // which add build target reporting { - input: './lite/index.ts', + input: ['./lite/index.ts', './lite/pipelines/pipelines.ts'], output: { - file: path.resolve('./lite', pkg.browser), + dir: 'dist/intermediate/lite/', + entryFileNames: '[name].browser.js', + chunkFileNames: 'common-[hash].browser.js', format: 'es', sourcemap: true }, @@ -142,10 +156,15 @@ const allBuilds = [ }, // Convert es2020 build to CJS { - input: path.resolve('./lite', pkg.browser), + input: [ + 'dist/intermediate/lite/index.browser.js', + 'dist/intermediate/lite/pipelines.browser.js' + ], output: [ { - file: './dist/lite/index.cjs.js', + dir: 'dist/lite/', + entryFileNames: '[name].cjs.js', + chunkFileNames: 'common-[hash].cjs.js', format: 'es', sourcemap: true } @@ -161,10 +180,15 @@ const allBuilds = [ }, // Browser es2020 build { - input: path.resolve('./lite', pkg.browser), + input: [ + 'dist/intermediate/lite/index.browser.js', + 'dist/intermediate/lite/pipelines.browser.js' + ], output: [ { - file: path.resolve('./lite', pkg.browser), + dir: 'dist/lite/', + entryFileNames: '[name].esm.js', + chunkFileNames: 'common-[hash].esm.js', format: 'es', sourcemap: true } @@ -180,9 +204,11 @@ const allBuilds = [ }, // RN build { - input: './lite/index.ts', + input: ['./lite/index.ts', './lite/pipelines/pipelines.ts'], output: { - file: path.resolve('./lite', pkg['react-native']), + dir: 'dist/lite/', + entryFileNames: '[name].rn.esm.js', + chunkFileNames: 'common-[hash].rn.esm.js', format: 'es', sourcemap: true }, diff --git a/packages/firestore/src/api/aggregate.ts b/packages/firestore/src/api/aggregate.ts index f0e2c1e1dc..453f9e0a84 100644 --- a/packages/firestore/src/api/aggregate.ts +++ b/packages/firestore/src/api/aggregate.ts @@ -15,17 +15,21 @@ * limitations under the License. */ -import { AggregateField, AggregateSpec, DocumentData, Query } from '../api'; import { AggregateImpl } from '../core/aggregate'; import { firestoreClientRunAggregateQuery } from '../core/firestore_client'; import { count } from '../lite-api/aggregate'; -import { AggregateQuerySnapshot } from '../lite-api/aggregate_types'; +import { + AggregateField, + AggregateQuerySnapshot, + AggregateSpec +} from '../lite-api/aggregate_types'; +import { DocumentData, Query } from '../lite-api/reference'; import { ApiClientObjectMap, Value } from '../protos/firestore_proto_api'; import { cast } from '../util/input_validation'; import { mapToArray } from '../util/obj'; import { ensureFirestoreConfigured, Firestore } from './database'; -import { ExpUserDataWriter } from './reference_impl'; +import { ExpUserDataWriter } from './user_data_writer'; export { aggregateQuerySnapshotEqual, diff --git a/packages/firestore/src/api/database.ts b/packages/firestore/src/api/database.ts index a2feb19507..f894ddce03 100644 --- a/packages/firestore/src/api/database.ts +++ b/packages/firestore/src/api/database.ts @@ -302,6 +302,7 @@ export function configureFirestore(firestore: Firestore): void { firestore._databaseId, firestore._app?.options.appId || '', firestore._persistenceKey, + firestore._app?.options.apiKey, settings ); if (!firestore._componentsProvider) { diff --git a/packages/firestore/src/api/parse_context.ts b/packages/firestore/src/api/parse_context.ts index ce3c221f66..2381bcff4c 100644 --- a/packages/firestore/src/api/parse_context.ts +++ b/packages/firestore/src/api/parse_context.ts @@ -16,8 +16,53 @@ */ import { DatabaseId } from '../core/database_info'; +import { UserDataSource } from '../lite-api/user_data_reader'; +import { DocumentKey } from '../model/document_key'; +import { FieldTransform } from '../model/mutation'; +import { FieldPath as InternalFieldPath } from '../model/path'; +import { JsonProtoSerializer } from '../remote/serializer'; +import { FirestoreError } from '../util/error'; + +/** Contains the settings that are mutated as we parse user data. */ +export interface ContextSettings { + /** Indicates what kind of API method this data came from. */ + readonly dataSource: UserDataSource; + /** The name of the method the user called to create the ParseContext. */ + readonly methodName: string; + /** The document the user is attempting to modify, if that applies. */ + readonly targetDoc?: DocumentKey; + /** + * A path within the object being parsed. This could be an empty path (in + * which case the context represents the root of the data being parsed), or a + * nonempty path (indicating the context represents a nested location within + * the data). + */ + readonly path?: InternalFieldPath; + /** + * Whether or not this context corresponds to an element of an array. + * If not set, elements are treated as if they were outside of arrays. + */ + readonly arrayElement?: boolean; + /** + * Whether or not a converter was specified in this context. If true, error + * messages will reference the converter when invalid data is provided. + */ + readonly hasConverter?: boolean; +} export interface ParseContext { + readonly settings: ContextSettings; readonly databaseId: DatabaseId; + readonly serializer: JsonProtoSerializer; readonly ignoreUndefinedProperties: boolean; + fieldTransforms: FieldTransform[]; + fieldMask: InternalFieldPath[]; + get path(): InternalFieldPath | undefined; + get dataSource(): UserDataSource; + contextWith(configuration: Partial): ParseContext; + childContextForField(field: string): ParseContext; + childContextForFieldPath(field: InternalFieldPath): ParseContext; + childContextForArray(index: number): ParseContext; + createError(reason: string): FirestoreError; + contains(fieldPath: InternalFieldPath): boolean; } diff --git a/packages/firestore/src/api/pipeline.ts b/packages/firestore/src/api/pipeline.ts new file mode 100644 index 0000000000..311c3a59c4 --- /dev/null +++ b/packages/firestore/src/api/pipeline.ts @@ -0,0 +1,47 @@ +/** + * @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. + */ + +import { Pipeline as LitePipeline } from '../lite-api/pipeline'; +import { Stage } from '../lite-api/stage'; +import { UserDataReader } from '../lite-api/user_data_reader'; +import { AbstractUserDataWriter } from '../lite-api/user_data_writer'; + +import { Firestore } from './database'; + +/** + * @beta + */ +export class Pipeline extends LitePipeline { + /** + * @internal + * @private + * @param db + * @param userDataReader + * @param userDataWriter + * @param stages + * @param converter + * @protected + */ + protected newPipeline( + db: Firestore, + userDataReader: UserDataReader, + userDataWriter: AbstractUserDataWriter, + stages: Stage[] + ): Pipeline { + return new Pipeline(db, userDataReader, userDataWriter, stages); + } +} diff --git a/packages/firestore/src/api/pipeline_impl.ts b/packages/firestore/src/api/pipeline_impl.ts new file mode 100644 index 0000000000..e5d650847d --- /dev/null +++ b/packages/firestore/src/api/pipeline_impl.ts @@ -0,0 +1,216 @@ +/** + * @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. + */ + +import { Pipeline } from '../api/pipeline'; +import { firestoreClientExecutePipeline } from '../core/firestore_client'; +import { + StructuredPipeline, + StructuredPipelineOptions +} from '../core/structured_pipeline'; +import { Pipeline as LitePipeline } from '../lite-api/pipeline'; +import { PipelineResult, PipelineSnapshot } from '../lite-api/pipeline-result'; +import { PipelineSource } from '../lite-api/pipeline-source'; +import { PipelineExecuteOptions } from '../lite-api/pipeline_options'; +import { Stage } from '../lite-api/stage'; +import { + newUserDataReader, + UserDataReader, + UserDataSource +} from '../lite-api/user_data_reader'; +import { cast } from '../util/input_validation'; + +import { ensureFirestoreConfigured, Firestore } from './database'; +import { DocumentReference } from './reference'; +import { ExpUserDataWriter } from './user_data_writer'; + +declare module './database' { + /** + * @beta + * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link Pipeline}. + * + * @example + * ``` + * let myPipeline: Pipeline = firestore.pipeline().collection('books'); + * ``` + */ + interface Firestore { + pipeline(): PipelineSource; + } +} + +/** + * @beta + * Executes a pipeline and returns a Promise to represent the asynchronous operation. + * + * The returned Promise can be used to track the progress of the pipeline execution + * and retrieve the results (or handle any errors) asynchronously. + * + * The pipeline results are returned as a {@link PipelineSnapshot} that contains + * a list of {@link PipelineResult} objects. Each {@link PipelineResult} typically + * represents a single key/value map that has passed through all the + * stages of the pipeline, however this might differ depending on the stages involved in the + * pipeline. For example: + * + *

    + *
  • If there are no stages or only transformation stages, each {@link PipelineResult} + * represents a single document.
  • + *
  • If there is an aggregation, only a single {@link PipelineResult} is returned, + * representing the aggregated results over the entire dataset .
  • + *
  • If there is an aggregation stage with grouping, each {@link PipelineResult} represents a + * distinct group and its associated aggregated values.
  • + *
+ * + *

Example: + * + * ```typescript + * const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") + * .where(gt(field("rating"), 4.5)) + * .select("title", "author", "rating")); + * + * const results: PipelineResults = snapshot.results; + * ``` + * + * @param pipeline The pipeline to execute. + * @return A Promise representing the asynchronous pipeline execution. + */ +export function execute(pipeline: LitePipeline): Promise; +/** + * @beta + * Executes a pipeline and returns a Promise to represent the asynchronous operation. + * + * The returned Promise can be used to track the progress of the pipeline execution + * and retrieve the results (or handle any errors) asynchronously. + * + * The pipeline results are returned as a {@link PipelineSnapshot} that contains + * a list of {@link PipelineResult} objects. Each {@link PipelineResult} typically + * represents a single key/value map that has passed through all the + * stages of the pipeline, however this might differ depending on the stages involved in the + * pipeline. For example: + * + *

    + *
  • If there are no stages or only transformation stages, each {@link PipelineResult} + * represents a single document.
  • + *
  • If there is an aggregation, only a single {@link PipelineResult} is returned, + * representing the aggregated results over the entire dataset .
  • + *
  • If there is an aggregation stage with grouping, each {@link PipelineResult} represents a + * distinct group and its associated aggregated values.
  • + *
+ * + *

Example: + * + * ```typescript + * const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") + * .where(gt(field("rating"), 4.5)) + * .select("title", "author", "rating")); + * + * const results: PipelineResults = snapshot.results; + * ``` + * + * @param options Specifies the pipeline to execute and other options for execute. + * @return A Promise representing the asynchronous pipeline execution. + */ +export function execute( + options: PipelineExecuteOptions +): Promise; +export function execute( + pipelineOrOptions: LitePipeline | PipelineExecuteOptions +): Promise { + const options: PipelineExecuteOptions = !( + pipelineOrOptions instanceof LitePipeline + ) + ? pipelineOrOptions + : { + pipeline: pipelineOrOptions + }; + + const { pipeline, rawOptions, ...rest } = options; + + const firestore = cast(pipeline._db, Firestore); + const client = ensureFirestoreConfigured(firestore); + + const udr = new UserDataReader( + firestore._databaseId, + /* ignoreUndefinedProperties */ true + ); + const context = udr.createContext(UserDataSource.Argument, 'execute'); + + const structuredPipelineOptions = new StructuredPipelineOptions( + rest, + rawOptions + ); + structuredPipelineOptions._readUserData(context); + + const structuredPipeline: StructuredPipeline = new StructuredPipeline( + pipeline, + structuredPipelineOptions + ); + + return firestoreClientExecutePipeline(client, structuredPipeline).then( + result => { + // Get the execution time from the first result. + // firestoreClientExecutePipeline returns at least one PipelineStreamElement + // even if the returned document set is empty. + const executionTime = + result.length > 0 ? result[0].executionTime?.toTimestamp() : undefined; + + const docs = result + // Currently ignore any response from ExecutePipeline that does + // not contain any document data in the `fields` property. + .filter(element => !!element.fields) + .map( + element => + new PipelineResult( + pipeline._userDataWriter, + element.fields!, + element.key?.path + ? new DocumentReference(firestore, null, element.key) + : undefined, + element.createTime?.toTimestamp(), + element.updateTime?.toTimestamp() + ) + ); + + return new PipelineSnapshot(pipeline, docs, executionTime); + } + ); +} + +/** + * @beta + * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link Pipeline}. + * + * @example + * ``` + * let myPipeline: Pipeline = firestore.pipeline().collection('books'); + * ``` + */ +// Augment the Firestore class with the pipeline() factory method +Firestore.prototype.pipeline = function (): PipelineSource { + const userDataReader = newUserDataReader(this); + return new PipelineSource( + this._databaseId, + userDataReader, + (stages: Stage[]) => { + return new Pipeline( + this, + userDataReader, + new ExpUserDataWriter(this), + stages + ); + } + ); +}; diff --git a/packages/firestore/src/api/reference_impl.ts b/packages/firestore/src/api/reference_impl.ts index 8fa21a13e6..4283453d81 100644 --- a/packages/firestore/src/api/reference_impl.ts +++ b/packages/firestore/src/api/reference_impl.ts @@ -37,7 +37,6 @@ import { } from '../core/firestore_client'; import { newQueryForPath, Query as InternalQuery } from '../core/query'; import { ViewSnapshot } from '../core/view_snapshot'; -import { Bytes } from '../lite-api/bytes'; import { FieldPath } from '../lite-api/field_path'; import { validateHasExplicitOrderByForLimitToLast } from '../lite-api/query'; import { @@ -59,11 +58,9 @@ import { parseUpdateData, parseUpdateVarargs } from '../lite-api/user_data_reader'; -import { AbstractUserDataWriter } from '../lite-api/user_data_writer'; import { DocumentKey } from '../model/document_key'; import { DeleteMutation, Mutation, Precondition } from '../model/mutation'; import { debugAssert } from '../util/assert'; -import { ByteString } from '../util/byte_string'; import { Code, FirestoreError } from '../util/error'; import { cast } from '../util/input_validation'; @@ -74,6 +71,7 @@ import { QuerySnapshot, SnapshotMetadata } from './snapshot'; +import { ExpUserDataWriter } from './user_data_writer'; /** * An options object that can be passed to {@link (onSnapshot:1)} and {@link @@ -130,21 +128,6 @@ export function getDoc( ).then(snapshot => convertToDocSnapshot(firestore, reference, snapshot)); } -export class ExpUserDataWriter extends AbstractUserDataWriter { - constructor(protected firestore: Firestore) { - super(); - } - - protected convertBytes(bytes: ByteString): Bytes { - return new Bytes(bytes); - } - - protected convertReference(name: string): DocumentReference { - const key = this.convertDocumentKey(name, this.firestore._databaseId); - return new DocumentReference(this.firestore, /* converter= */ null, key); - } -} - /** * Reads the document referred to by this `DocumentReference` from cache. * Returns an error if the document is not currently cached. diff --git a/packages/firestore/src/api/snapshot.ts b/packages/firestore/src/api/snapshot.ts index c82add0642..86e075a4ca 100644 --- a/packages/firestore/src/api/snapshot.ts +++ b/packages/firestore/src/api/snapshot.ts @@ -31,10 +31,12 @@ import { import { LiteUserDataWriter } from '../lite-api/reference_impl'; import { DocumentSnapshot as LiteDocumentSnapshot, - fieldPathFromArgument, FirestoreDataConverter as LiteFirestoreDataConverter } from '../lite-api/snapshot'; -import { UntypedFirestoreDataConverter } from '../lite-api/user_data_reader'; +import { + fieldPathFromArgument, + UntypedFirestoreDataConverter +} from '../lite-api/user_data_reader'; import { AbstractUserDataWriter } from '../lite-api/user_data_writer'; import { fromBundledQuery } from '../local/local_serializer'; import { documentKeySet } from '../model/collections'; diff --git a/packages/firestore/src/api/transaction.ts b/packages/firestore/src/api/transaction.ts index 955866f19b..8f83f52718 100644 --- a/packages/firestore/src/api/transaction.ts +++ b/packages/firestore/src/api/transaction.ts @@ -28,9 +28,9 @@ import { validateReference } from '../lite-api/write_batch'; import { cast } from '../util/input_validation'; import { ensureFirestoreConfigured, Firestore } from './database'; -import { ExpUserDataWriter } from './reference_impl'; import { DocumentSnapshot, SnapshotMetadata } from './snapshot'; import { TransactionOptions } from './transaction_options'; +import { ExpUserDataWriter } from './user_data_writer'; /** * A reference to a transaction. diff --git a/packages/firestore/src/api/user_data_writer.ts b/packages/firestore/src/api/user_data_writer.ts new file mode 100644 index 0000000000..3567f72cd9 --- /dev/null +++ b/packages/firestore/src/api/user_data_writer.ts @@ -0,0 +1,38 @@ +/** + * @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. + */ + +import { Bytes } from '../lite-api/bytes'; +import { DocumentReference } from '../lite-api/reference'; +import { AbstractUserDataWriter } from '../lite-api/user_data_writer'; +import { ByteString } from '../util/byte_string'; + +import { Firestore } from './database'; + +export class ExpUserDataWriter extends AbstractUserDataWriter { + constructor(protected firestore: Firestore) { + super(); + } + + protected convertBytes(bytes: ByteString): Bytes { + return new Bytes(bytes); + } + + protected convertReference(name: string): DocumentReference { + const key = this.convertDocumentKey(name, this.firestore._databaseId); + return new DocumentReference(this.firestore, /* converter= */ null, key); + } +} diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts new file mode 100644 index 0000000000..693b7f5468 --- /dev/null +++ b/packages/firestore/src/api_pipelines.ts @@ -0,0 +1,165 @@ +/** + * @license + * Copyright 2021 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. + */ + +export { PipelineSource } from './lite-api/pipeline-source'; + +export { OneOf } from './util/types'; + +export { + PipelineResult, + PipelineSnapshot, + pipelineResultEqual +} from './lite-api/pipeline-result'; + +export { Pipeline } from './api/pipeline'; + +export { execute } from './api/pipeline_impl'; + +export { PipelineExecuteOptions } from './lite-api/pipeline_options'; + +export { + StageOptions, + CollectionStageOptions, + CollectionGroupStageOptions, + DatabaseStageOptions, + DocumentsStageOptions, + AddFieldsStageOptions, + RemoveFieldsStageOptions, + SelectStageOptions, + WhereStageOptions, + OffsetStageOptions, + LimitStageOptions, + DistinctStageOptions, + AggregateStageOptions, + FindNearestStageOptions, + ReplaceWithStageOptions, + SampleStageOptions, + UnionStageOptions, + UnnestStageOptions, + SortStageOptions +} from './lite-api/stage_options'; + +export { + field, + constant, + add, + subtract, + multiply, + divide, + mod, + equal, + notEqual, + lessThan, + lessThanOrEqual, + greaterThan, + greaterThanOrEqual, + arrayConcat, + arrayContains, + arrayContainsAny, + arrayContainsAll, + arrayLength, + equalAny, + notEqualAny, + xor, + conditional, + not, + logicalMaximum, + logicalMinimum, + exists, + reverse, + byteLength, + charLength, + like, + regexContains, + regexMatch, + stringContains, + startsWith, + endsWith, + toLower, + toUpper, + trim, + stringConcat, + mapGet, + countAll, + count, + sum, + average, + and, + or, + minimum, + maximum, + cosineDistance, + dotProduct, + euclideanDistance, + vectorLength, + unixMicrosToTimestamp, + timestampToUnixMicros, + unixMillisToTimestamp, + timestampToUnixMillis, + unixSecondsToTimestamp, + timestampToUnixSeconds, + timestampAdd, + timestampSubtract, + ascending, + descending, + countIf, + array, + arrayGet, + isError, + ifError, + isAbsent, + map, + mapRemove, + mapMerge, + documentId, + substring, + countDistinct, + ceil, + floor, + exp, + pow, + round, + collectionId, + ln, + log, + sqrt, + stringReverse, + length, + abs, + concat, + currentTimestamp, + ifAbsent, + join, + log10, + arraySum, + timestampTruncate, + split, + type, + Expression, + AliasedExpression, + Field, + FunctionExpression, + Ordering, + BooleanExpression, + AggregateFunction, + ExpressionType, + AliasedAggregate, + Selectable, + TimeGranularity +} from './lite-api/expressions'; + +export { _internalPipelineToExecutePipelineRequestProto } from './remote/internal_serializer'; diff --git a/packages/firestore/src/core/database_info.ts b/packages/firestore/src/core/database_info.ts index a057516763..ec75ba2486 100644 --- a/packages/firestore/src/core/database_info.ts +++ b/packages/firestore/src/core/database_info.ts @@ -49,7 +49,8 @@ export class DatabaseInfo { readonly autoDetectLongPolling: boolean, readonly longPollingOptions: ExperimentalLongPollingOptions, readonly useFetchStreams: boolean, - readonly isUsingEmulator: boolean + readonly isUsingEmulator: boolean, + readonly apiKey: string | undefined ) {} } diff --git a/packages/firestore/src/core/firestore_client.ts b/packages/firestore/src/core/firestore_client.ts index 39bb8dd4eb..7535a87a60 100644 --- a/packages/firestore/src/core/firestore_client.ts +++ b/packages/firestore/src/core/firestore_client.ts @@ -38,11 +38,16 @@ import { Document } from '../model/document'; import { DocumentKey } from '../model/document_key'; import { FieldIndex } from '../model/field_index'; import { Mutation } from '../model/mutation'; +import { PipelineStreamElement } from '../model/pipeline_stream_element'; import { toByteStreamReader } from '../platform/byte_stream_reader'; import { newSerializer } from '../platform/serializer'; import { newTextEncoder } from '../platform/text_serializer'; import { ApiClientObjectMap, Value } from '../protos/firestore_proto_api'; -import { Datastore, invokeRunAggregationQueryRpc } from '../remote/datastore'; +import { + Datastore, + invokeExecutePipeline, + invokeRunAggregationQueryRpc +} from '../remote/datastore'; import { RemoteStore, remoteStoreDisableNetwork, @@ -82,6 +87,7 @@ import { removeSnapshotsInSyncListener } from './event_manager'; import { newQueryForPath, Query } from './query'; +import { StructuredPipeline } from './structured_pipeline'; import { SyncEngine } from './sync_engine'; import { syncEngineListen, @@ -140,7 +146,10 @@ export class FirestoreClient { * an async I/O to complete). */ public asyncQueue: AsyncQueue, - private databaseInfo: DatabaseInfo, + /** + * Exposed for testing + */ + public _databaseInfo: DatabaseInfo, componentProvider?: { _offline: OfflineComponentProvider; _online: OnlineComponentProvider; @@ -161,7 +170,7 @@ export class FirestoreClient { get configuration(): ComponentConfiguration { return { asyncQueue: this.asyncQueue, - databaseInfo: this.databaseInfo, + databaseInfo: this._databaseInfo, clientId: this.clientId, authCredentials: this.authCredentials, appCheckCredentials: this.appCheckCredentials, @@ -550,6 +559,23 @@ export function firestoreClientRunAggregateQuery( return deferred.promise; } +export function firestoreClientExecutePipeline( + client: FirestoreClient, + pipeline: StructuredPipeline +): Promise { + const deferred = new Deferred(); + + client.asyncQueue.enqueueAndForget(async () => { + try { + const datastore = await getDatastore(client); + deferred.resolve(invokeExecutePipeline(datastore, pipeline)); + } catch (e) { + deferred.reject(e as Error); + } + }); + return deferred.promise; +} + export function firestoreClientWrite( client: FirestoreClient, mutations: Mutation[] diff --git a/packages/firestore/src/core/options_util.ts b/packages/firestore/src/core/options_util.ts new file mode 100644 index 0000000000..f723385064 --- /dev/null +++ b/packages/firestore/src/core/options_util.ts @@ -0,0 +1,95 @@ +/** + * @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. + */ + +import { ParseContext } from '../api/parse_context'; +import { parseData } from '../lite-api/user_data_reader'; +import { ObjectValue } from '../model/object_value'; +import { FieldPath } from '../model/path'; +import { ApiClientObjectMap, Value } from '../protos/firestore_proto_api'; +import { isPlainObject } from '../util/input_validation'; +import { mapToArray } from '../util/obj'; +export type OptionsDefinitions = Record; +export interface OptionDefinition { + serverName: string; + nestedOptions?: OptionsDefinitions; +} + +export class OptionsUtil { + constructor(private optionDefinitions: OptionsDefinitions) {} + + private _getKnownOptions( + options: Record, + context: ParseContext + ): ObjectValue { + const knownOptions: ObjectValue = ObjectValue.empty(); + + // SERIALIZE KNOWN OPTIONS + for (const knownOptionKey in this.optionDefinitions) { + if (this.optionDefinitions.hasOwnProperty(knownOptionKey)) { + const optionDefinition: OptionDefinition = + this.optionDefinitions[knownOptionKey]; + + if (knownOptionKey in options) { + const optionValue: unknown = options[knownOptionKey]; + let protoValue: Value | undefined = undefined; + + if (optionDefinition.nestedOptions && isPlainObject(optionValue)) { + const nestedUtil = new OptionsUtil(optionDefinition.nestedOptions); + protoValue = { + mapValue: { + fields: nestedUtil.getOptionsProto(context, optionValue) + } + }; + } else if (optionValue) { + protoValue = parseData(optionValue, context) ?? undefined; + } + + if (protoValue) { + knownOptions.set( + FieldPath.fromServerFormat(optionDefinition.serverName), + protoValue + ); + } + } + } + } + + return knownOptions; + } + + getOptionsProto( + context: ParseContext, + knownOptions: Record, + optionsOverride?: Record + ): ApiClientObjectMap | undefined { + const result: ObjectValue = this._getKnownOptions(knownOptions, context); + + // APPLY OPTIONS OVERRIDES + if (optionsOverride) { + const optionsMap = new Map( + mapToArray(optionsOverride, (value, key) => [ + FieldPath.fromServerFormat(key), + value !== undefined ? parseData(value, context) : null + ]) + ); + result.setAll(optionsMap); + } + + // Return MapValue from `result` or empty map value + return result.value.mapValue.fields ?? {}; + } +} diff --git a/packages/firestore/src/core/pipeline-util.ts b/packages/firestore/src/core/pipeline-util.ts new file mode 100644 index 0000000000..b27babf695 --- /dev/null +++ b/packages/firestore/src/core/pipeline-util.ts @@ -0,0 +1,271 @@ +/** + * @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. + */ + +import { Firestore } from '../lite-api/database'; +import { + Constant, + BooleanExpression, + and, + or, + Ordering, + lessThan, + greaterThan, + field +} from '../lite-api/expressions'; +import { Pipeline } from '../lite-api/pipeline'; +import { doc } from '../lite-api/reference'; +import { fail } from '../util/assert'; + +import { Bound } from './bound'; +import { + CompositeFilter as CompositeFilterInternal, + CompositeOperator, + FieldFilter as FieldFilterInternal, + Filter as FilterInternal, + Operator +} from './filter'; +import { Direction } from './order_by'; +import { + isCollectionGroupQuery, + isDocumentQuery, + LimitType, + Query, + queryNormalizedOrderBy +} from './query'; + +/* eslint @typescript-eslint/no-explicit-any: 0 */ + +export function toPipelineBooleanExpr(f: FilterInternal): BooleanExpression { + if (f instanceof FieldFilterInternal) { + const fieldValue = field(f.field.toString()); + // Comparison filters + const value = f.value; + switch (f.op) { + case Operator.LESS_THAN: + return and( + fieldValue.exists(), + fieldValue.lessThan(Constant._fromProto(value)) + ); + case Operator.LESS_THAN_OR_EQUAL: + return and( + fieldValue.exists(), + fieldValue.lessThanOrEqual(Constant._fromProto(value)) + ); + case Operator.GREATER_THAN: + return and( + fieldValue.exists(), + fieldValue.greaterThan(Constant._fromProto(value)) + ); + case Operator.GREATER_THAN_OR_EQUAL: + return and( + fieldValue.exists(), + fieldValue.greaterThanOrEqual(Constant._fromProto(value)) + ); + case Operator.EQUAL: + return and( + fieldValue.exists(), + fieldValue.equal(Constant._fromProto(value)) + ); + case Operator.NOT_EQUAL: + return and( + fieldValue.exists(), + fieldValue.notEqual(Constant._fromProto(value)) + ); + case Operator.ARRAY_CONTAINS: + return and( + fieldValue.exists(), + fieldValue.arrayContains(Constant._fromProto(value)) + ); + case Operator.IN: { + const values = value?.arrayValue?.values?.map((val: any) => + Constant._fromProto(val) + ); + if (!values) { + return and(fieldValue.exists(), fieldValue.equalAny([])); + } else if (values.length === 1) { + return and(fieldValue.exists(), fieldValue.equal(values[0])); + } else { + return and(fieldValue.exists(), fieldValue.equalAny(values)); + } + } + case Operator.ARRAY_CONTAINS_ANY: { + const values = value?.arrayValue?.values?.map((val: any) => + Constant._fromProto(val) + ); + return and(fieldValue.exists(), fieldValue.arrayContainsAny(values!)); + } + case Operator.NOT_IN: { + const values = value?.arrayValue?.values?.map((val: any) => + Constant._fromProto(val) + ); + if (!values) { + return and(fieldValue.exists(), fieldValue.notEqualAny([])); + } else if (values.length === 1) { + return and(fieldValue.exists(), fieldValue.notEqual(values[0])); + } else { + return and(fieldValue.exists(), fieldValue.notEqualAny(values)); + } + } + default: + fail(0x9047, 'Unexpected operator'); + } + } else if (f instanceof CompositeFilterInternal) { + switch (f.op) { + case CompositeOperator.AND: { + const conditions = f.getFilters().map(f => toPipelineBooleanExpr(f)); + return and(conditions[0], conditions[1], ...conditions.slice(2)); + } + case CompositeOperator.OR: { + const conditions = f.getFilters().map(f => toPipelineBooleanExpr(f)); + return or(conditions[0], conditions[1], ...conditions.slice(2)); + } + default: + fail(0x89ea, 'Unexpected operator'); + } + } + + throw new Error(`Failed to convert filter to pipeline conditions: ${f}`); +} + +function reverseOrderings(orderings: Ordering[]): Ordering[] { + return orderings.map( + o => + new Ordering( + o.expr, + o.direction === 'ascending' ? 'descending' : 'ascending', + undefined + ) + ); +} + +export function toPipeline(query: Query, db: Firestore): Pipeline { + let pipeline: Pipeline; + if (isCollectionGroupQuery(query)) { + pipeline = db.pipeline().collectionGroup(query.collectionGroup!); + } else if (isDocumentQuery(query)) { + pipeline = db.pipeline().documents([doc(db, query.path.canonicalString())]); + } else { + pipeline = db.pipeline().collection(query.path.canonicalString()); + } + + // filters + for (const filter of query.filters) { + pipeline = pipeline.where(toPipelineBooleanExpr(filter)); + } + + // orders + const orders = queryNormalizedOrderBy(query); + const existsConditions = orders.map(order => + field(order.field.canonicalString()).exists() + ); + if (existsConditions.length > 1) { + pipeline = pipeline.where( + and( + existsConditions[0], + existsConditions[1], + ...existsConditions.slice(2) + ) + ); + } else { + pipeline = pipeline.where(existsConditions[0]); + } + + const orderings = orders.map(order => + order.dir === Direction.ASCENDING + ? field(order.field.canonicalString()).ascending() + : field(order.field.canonicalString()).descending() + ); + + if (orderings.length > 0) { + if (query.limitType === LimitType.Last) { + const actualOrderings = reverseOrderings(orderings); + pipeline = pipeline.sort(actualOrderings[0], ...actualOrderings.slice(1)); + // cursors + if (query.startAt !== null) { + pipeline = pipeline.where( + whereConditionsFromCursor(query.startAt, orderings, 'after') + ); + } + + if (query.endAt !== null) { + pipeline = pipeline.where( + whereConditionsFromCursor(query.endAt, orderings, 'before') + ); + } + + pipeline = pipeline.limit(query.limit!); + pipeline = pipeline.sort(orderings[0], ...orderings.slice(1)); + } else { + pipeline = pipeline.sort(orderings[0], ...orderings.slice(1)); + if (query.startAt !== null) { + pipeline = pipeline.where( + whereConditionsFromCursor(query.startAt, orderings, 'after') + ); + } + if (query.endAt !== null) { + pipeline = pipeline.where( + whereConditionsFromCursor(query.endAt, orderings, 'before') + ); + } + + if (query.limit !== null) { + pipeline = pipeline.limit(query.limit); + } + } + } + + return pipeline; +} + +function whereConditionsFromCursor( + bound: Bound, + orderings: Ordering[], + position: 'before' | 'after' +): BooleanExpression { + // The filterFunc is either greater than or less than + const filterFunc = position === 'before' ? lessThan : greaterThan; + const cursors = bound.position.map(value => Constant._fromProto(value)); + const size = cursors.length; + + let field = orderings[size - 1].expr; + let value = cursors[size - 1]; + + // Add condition for last bound + let condition: BooleanExpression = filterFunc(field, value); + if (bound.inclusive) { + // When the cursor bound is inclusive, then the last bound + // can be equal to the value, otherwise it's not equal + condition = or(condition, field.equal(value)); + } + + // Iterate backwards over the remaining bounds, adding + // a condition for each one + for (let i = size - 2; i >= 0; i--) { + field = orderings[i].expr; + value = cursors[i]; + + // For each field in the orderings, the condition is either + // a) lt|gt the cursor value, + // b) or equal the cursor value and lt|gt the cursor values for other fields + condition = or( + filterFunc(field, value), + and(field.equal(value), condition) + ); + } + + return condition; +} diff --git a/packages/firestore/src/core/structured_pipeline.ts b/packages/firestore/src/core/structured_pipeline.ts new file mode 100644 index 0000000000..ac8ee4284f --- /dev/null +++ b/packages/firestore/src/core/structured_pipeline.ts @@ -0,0 +1,67 @@ +/** + * @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. + */ + +import { ParseContext } from '../api/parse_context'; +import { UserData } from '../lite-api/user_data_reader'; +import { + ApiClientObjectMap, + firestoreV1ApiClientInterfaces, + Pipeline as PipelineProto, + StructuredPipeline as StructuredPipelineProto +} from '../protos/firestore_proto_api'; +import { JsonProtoSerializer, ProtoSerializable } from '../remote/serializer'; + +import { OptionsUtil } from './options_util'; + +export class StructuredPipelineOptions implements UserData { + proto: ApiClientObjectMap | undefined; + + readonly optionsUtil = new OptionsUtil({ + indexMode: { + serverName: 'index_mode' + } + }); + + constructor( + private _userOptions: Record = {}, + private _optionsOverride: Record = {} + ) {} + + _readUserData(context: ParseContext): void { + this.proto = this.optionsUtil.getOptionsProto( + context, + this._userOptions, + this._optionsOverride + ); + } +} + +export class StructuredPipeline + implements ProtoSerializable +{ + constructor( + private pipeline: ProtoSerializable, + private options: StructuredPipelineOptions + ) {} + + _toProto(serializer: JsonProtoSerializer): StructuredPipelineProto { + return { + pipeline: this.pipeline._toProto(serializer), + options: this.options.proto + }; + } +} diff --git a/packages/firestore/src/global.ts b/packages/firestore/src/global.ts new file mode 100644 index 0000000000..a04572dac0 --- /dev/null +++ b/packages/firestore/src/global.ts @@ -0,0 +1,29 @@ +/** + * @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. + */ + +// This file supports a special internal build that includes the entire +// Firestore classic and pipeline api surface in one bundle. + +import * as pipelines from './api_pipelines'; +export * from './api'; +export { pipelines }; + +// Console specific exports +export { + type firestoreV1ApiClientInterfaces, + type Timestamp as ProtoTimestamp +} from './protos/firestore_proto_api'; diff --git a/packages/firestore/src/lite-api/aggregate_types.ts b/packages/firestore/src/lite-api/aggregate_types.ts index a87b3ca695..292a2edd4f 100644 --- a/packages/firestore/src/lite-api/aggregate_types.ts +++ b/packages/firestore/src/lite-api/aggregate_types.ts @@ -16,8 +16,13 @@ */ import { AggregateType } from '../core/aggregate'; +import { ObjectValue } from '../model/object_value'; import { FieldPath as InternalFieldPath } from '../model/path'; -import { ApiClientObjectMap, Value } from '../protos/firestore_proto_api'; +import { + ApiClientObjectMap, + firestoreV1ApiClientInterfaces, + Value +} from '../protos/firestore_proto_api'; import { average, count, sum } from './aggregate'; import { DocumentData, Query } from './reference'; @@ -116,4 +121,22 @@ export class AggregateQuerySnapshot< this._data ) as AggregateSpecData; } + + /** + * @internal + * @private + * + * Retrieves all fields in the snapshot as a proto value. + * + * @returns An `Object` containing all fields in the snapshot. + */ + _fieldsProto(): { [key: string]: firestoreV1ApiClientInterfaces.Value } { + // Wrap data in an ObjectValue to clone it. + const dataClone = new ObjectValue({ + mapValue: { fields: this._data } + }).clone(); + + // Return the cloned value to prevent manipulation of the Snapshot's data + return dataClone.value.mapValue.fields!; + } } diff --git a/packages/firestore/src/lite-api/components.ts b/packages/firestore/src/lite-api/components.ts index 52c3b3729e..d956fcd31f 100644 --- a/packages/firestore/src/lite-api/components.ts +++ b/packages/firestore/src/lite-api/components.ts @@ -75,6 +75,7 @@ export function getDatastore(firestore: FirestoreService): Datastore { firestore._databaseId, firestore.app.options.appId || '', firestore._persistenceKey, + firestore.app.options.apiKey, firestore._freezeSettings() ); const connection = newConnection(databaseInfo); @@ -108,6 +109,7 @@ export function makeDatabaseInfo( databaseId: DatabaseId, appId: string, persistenceKey: string, + apiKey: string | undefined, settings: FirestoreSettingsImpl ): DatabaseInfo { return new DatabaseInfo( @@ -120,6 +122,7 @@ export function makeDatabaseInfo( settings.experimentalAutoDetectLongPolling, cloneLongPollingOptions(settings.experimentalLongPollingOptions), settings.useFetchStreams, - settings.isUsingEmulator + settings.isUsingEmulator, + apiKey ); } diff --git a/packages/firestore/src/lite-api/database_augmentation.ts b/packages/firestore/src/lite-api/database_augmentation.ts new file mode 100644 index 0000000000..bf25e9c59c --- /dev/null +++ b/packages/firestore/src/lite-api/database_augmentation.ts @@ -0,0 +1,16 @@ +/** + * @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. + */ diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts new file mode 100644 index 0000000000..7b236ea5c6 --- /dev/null +++ b/packages/firestore/src/lite-api/expressions.ts @@ -0,0 +1,8183 @@ +/** + * @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. + */ + +import { FirestoreError } from '../api'; +import { ParseContext } from '../api/parse_context'; +import { + DOCUMENT_KEY_NAME, + FieldPath as InternalFieldPath +} from '../model/path'; +import { Value as ProtoValue } from '../protos/firestore_proto_api'; +import { + JsonProtoSerializer, + ProtoValueSerializable, + toMapValue, + toStringValue +} from '../remote/serializer'; +import { hardAssert } from '../util/assert'; +import { isPlainObject } from '../util/input_validation'; +import { isFirestoreValue } from '../util/proto'; +import { isString } from '../util/types'; + +import { Bytes } from './bytes'; +import { documentId as documentIdFieldPath, FieldPath } from './field_path'; +import { vector } from './field_value_impl'; +import { GeoPoint } from './geo_point'; +import { DocumentReference } from './reference'; +import { Timestamp } from './timestamp'; +import { fieldPathFromArgument, parseData, UserData } from './user_data_reader'; +import { VectorValue } from './vector_value'; + +/** + * @beta + * + * An enumeration of the different types of expressions. + */ +export type ExpressionType = + | 'Field' + | 'Constant' + | 'Function' + | 'AggregateFunction' + | 'ListOfExpressions' + | 'AliasedExpression'; + +/** + * Converts a value to an Expr, Returning either a Constant, MapFunction, + * ArrayFunction, or the input itself (if it's already an expression). + * + * @private + * @internal + * @param value + */ +function valueToDefaultExpr(value: unknown): Expression { + let result: Expression | undefined; + if (value instanceof Expression) { + return value; + } else if (isPlainObject(value)) { + result = _map(value as Record, undefined); + } else if (value instanceof Array) { + result = array(value); + } else { + result = _constant(value, undefined); + } + + return result; +} + +/** + * Converts a value to an Expr, Returning either a Constant, MapFunction, + * ArrayFunction, or the input itself (if it's already an expression). + * + * @private + * @internal + * @param value + */ +function vectorToExpr(value: VectorValue | number[] | Expression): Expression { + if (value instanceof Expression) { + return value; + } else if (value instanceof VectorValue) { + return constant(value); + } else if (Array.isArray(value)) { + return constant(vector(value)); + } else { + throw new Error('Unsupported value: ' + typeof value); + } +} + +/** + * Converts a value to an Expr, 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(value: unknown): Expression { + if (isString(value)) { + const result = field(value); + return result; + } else { + return valueToDefaultExpr(value); + } +} + +/** + * @beta + * + * Represents an expression that can be evaluated to a value within the execution of a {@link + * 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 `Expr` class provides a fluent API for building expressions. You can chain together + * method calls to create complex expressions. + */ +export abstract class Expression implements ProtoValueSerializable, UserData { + abstract readonly expressionType: ExpressionType; + + abstract readonly _methodName?: string; + + /** + * @private + * @internal + */ + abstract _toProto(serializer: JsonProtoSerializer): ProtoValue; + _protoValueType = 'ProtoValue' as const; + + /** + * @private + * @internal + */ + abstract _readUserData(context: ParseContext): void; + + /** + * Creates an expression that adds this expression to another expression. + * + * ```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. + * @return A new `Expr` representing the addition operation. + */ + add(second: Expression | unknown): FunctionExpression { + return new FunctionExpression( + 'add', + [this, valueToDefaultExpr(second)], + 'add' + ); + } + + /** + * @beta + * Wraps the expression in a [BooleanExpression]. + * + * @return A [BooleanExpression] representing the same expression. + */ + asBoolean(): BooleanExpression { + 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 FirestoreError( + 'invalid-argument', + `Conversion of type ${typeof this} to BooleanExpression not supported.` + ); + } + } + + /** + * @beta + * Creates an expression that subtracts another expression from this expression. + * + * ```typescript + * // Subtract the 'discount' field from the 'price' field + * field("price").subtract(field("discount")); + * ``` + * + * @param subtrahend The expression to subtract from this expression. + * @return A new `Expr` representing the subtraction operation. + */ + subtract(subtrahend: Expression): FunctionExpression; + + /** + * @beta + * Creates an expression that subtracts a constant value from this expression. + * + * ```typescript + * // Subtract 20 from the value of the 'total' field + * field("total").subtract(20); + * ``` + * + * @param subtrahend The constant value to subtract. + * @return A new `Expr` representing the subtraction operation. + */ + subtract(subtrahend: number): FunctionExpression; + subtract(subtrahend: number | Expression): FunctionExpression { + return new FunctionExpression( + 'subtract', + [this, valueToDefaultExpr(subtrahend)], + 'subtract' + ); + } + + /** + * @beta + * Creates an expression that multiplies this expression by another expression. + * + * ```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. + * @return A new `Expr` representing the multiplication operation. + */ + multiply(second: Expression | number): FunctionExpression { + return new FunctionExpression( + 'multiply', + [this, valueToDefaultExpr(second)], + 'multiply' + ); + } + + /** + * @beta + * Creates an expression that divides this expression by another expression. + * + * ```typescript + * // Divide the 'total' field by the 'count' field + * field("total").divide(field("count")); + * ``` + * + * @param divisor The expression to divide by. + * @return A new `Expr` representing the division operation. + */ + divide(divisor: Expression): FunctionExpression; + + /** + * @beta + * Creates an expression that divides this expression by a constant value. + * + * ```typescript + * // Divide the 'value' field by 10 + * field("value").divide(10); + * ``` + * + * @param divisor The constant value to divide by. + * @return A new `Expr` representing the division operation. + */ + divide(divisor: number): FunctionExpression; + divide(divisor: number | Expression): FunctionExpression { + return new FunctionExpression( + 'divide', + [this, valueToDefaultExpr(divisor)], + 'divide' + ); + } + + /** + * @beta + * Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. + * + * ```typescript + * // Calculate the remainder of dividing the 'value' field by the 'divisor' field + * field("value").mod(field("divisor")); + * ``` + * + * @param expression The expression to divide by. + * @return A new `Expr` representing the modulo operation. + */ + mod(expression: Expression): FunctionExpression; + + /** + * @beta + * Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. + * + * ```typescript + * // Calculate the remainder of dividing the 'value' field by 10 + * field("value").mod(10); + * ``` + * + * @param value The constant value to divide by. + * @return A new `Expr` representing the modulo operation. + */ + mod(value: number): FunctionExpression; + mod(other: number | Expression): FunctionExpression { + return new FunctionExpression( + 'mod', + [this, valueToDefaultExpr(other)], + 'mod' + ); + } + + /** + * @beta + * Creates an expression that checks if this expression is equal to another expression. + * + * ```typescript + * // Check if the 'age' field is equal to 21 + * field("age").equal(21); + * ``` + * + * @param expression The expression to compare for equality. + * @return A new `Expr` representing the equality comparison. + */ + equal(expression: Expression): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if this expression is equal to a constant value. + * + * ```typescript + * // Check if the 'city' field is equal to "London" + * field("city").equal("London"); + * ``` + * + * @param value The constant value to compare for equality. + * @return A new `Expr` representing the equality comparison. + */ + equal(value: unknown): BooleanExpression; + equal(other: unknown): BooleanExpression { + return new FunctionExpression( + 'equal', + [this, valueToDefaultExpr(other)], + 'equal' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if this expression is not equal to another expression. + * + * ```typescript + * // Check if the 'status' field is not equal to "completed" + * field("status").notEqual("completed"); + * ``` + * + * @param expression The expression to compare for inequality. + * @return A new `Expr` representing the inequality comparison. + */ + notEqual(expression: Expression): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if this expression is not equal to a constant value. + * + * ```typescript + * // Check if the 'country' field is not equal to "USA" + * field("country").notEqual("USA"); + * ``` + * + * @param value The constant value to compare for inequality. + * @return A new `Expr` representing the inequality comparison. + */ + notEqual(value: unknown): BooleanExpression; + notEqual(other: unknown): BooleanExpression { + return new FunctionExpression( + 'not_equal', + [this, valueToDefaultExpr(other)], + 'notEqual' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if this expression is less than another expression. + * + * ```typescript + * // Check if the 'age' field is less than 'limit' + * field("age").lessThan(field('limit')); + * ``` + * + * @param experession The expression to compare for less than. + * @return A new `Expr` representing the less than comparison. + */ + lessThan(experession: Expression): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if this expression is less than a constant value. + * + * ```typescript + * // Check if the 'price' field is less than 50 + * field("price").lessThan(50); + * ``` + * + * @param value The constant value to compare for less than. + * @return A new `Expr` representing the less than comparison. + */ + lessThan(value: unknown): BooleanExpression; + lessThan(other: unknown): BooleanExpression { + return new FunctionExpression( + 'less_than', + [this, valueToDefaultExpr(other)], + 'lessThan' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if this expression is less than or equal to another + * expression. + * + * ```typescript + * // Check if the 'quantity' field is less than or equal to 20 + * field("quantity").lessThan(constant(20)); + * ``` + * + * @param expression The expression to compare for less than or equal to. + * @return A new `Expr` representing the less than or equal to comparison. + */ + lessThanOrEqual(expression: Expression): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if this expression is less than or equal to a constant value. + * + * ```typescript + * // Check if the 'score' field is less than or equal to 70 + * field("score").lessThan(70); + * ``` + * + * @param value The constant value to compare for less than or equal to. + * @return A new `Expr` representing the less than or equal to comparison. + */ + lessThanOrEqual(value: unknown): BooleanExpression; + lessThanOrEqual(other: unknown): BooleanExpression { + return new FunctionExpression( + 'less_than_or_equal', + [this, valueToDefaultExpr(other)], + 'lessThanOrEqual' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if this expression is greater than another expression. + * + * ```typescript + * // Check if the 'age' field is greater than the 'limit' field + * field("age").greaterThan(field("limit")); + * ``` + * + * @param expression The expression to compare for greater than. + * @return A new `Expr` representing the greater than comparison. + */ + greaterThan(expression: Expression): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if this expression is greater than a constant value. + * + * ```typescript + * // Check if the 'price' field is greater than 100 + * field("price").greaterThan(100); + * ``` + * + * @param value The constant value to compare for greater than. + * @return A new `Expr` representing the greater than comparison. + */ + greaterThan(value: unknown): BooleanExpression; + greaterThan(other: unknown): BooleanExpression { + return new FunctionExpression( + 'greater_than', + [this, valueToDefaultExpr(other)], + 'greaterThan' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if this expression is greater than or equal to another + * expression. + * + * ```typescript + * // Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1 + * field("quantity").greaterThanOrEqual(field('requirement').add(1)); + * ``` + * + * @param expression The expression to compare for greater than or equal to. + * @return A new `Expr` representing the greater than or equal to comparison. + */ + greaterThanOrEqual(expression: Expression): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if this expression is greater than or equal to a constant + * value. + * + * ```typescript + * // Check if the 'score' field is greater than or equal to 80 + * field("score").greaterThanOrEqual(80); + * ``` + * + * @param value The constant value to compare for greater than or equal to. + * @return A new `Expr` representing the greater than or equal to comparison. + */ + greaterThanOrEqual(value: unknown): BooleanExpression; + greaterThanOrEqual(other: unknown): BooleanExpression { + return new FunctionExpression( + 'greater_than_or_equal', + [this, valueToDefaultExpr(other)], + 'greaterThanOrEqual' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that concatenates an array expression with one or more other arrays. + * + * ```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. + * @return A new `Expr` representing the concatenated array. + */ + arrayConcat( + secondArray: Expression | unknown[], + ...otherArrays: Array + ): FunctionExpression { + const elements = [secondArray, ...otherArrays]; + const exprValues = elements.map(value => valueToDefaultExpr(value)); + return new FunctionExpression( + 'array_concat', + [this, ...exprValues], + 'arrayConcat' + ); + } + + /** + * @beta + * Creates an expression that checks if an array contains a specific element. + * + * ```typescript + * // Check if the 'sizes' array contains the value from the 'selectedSize' field + * field("sizes").arrayContains(field("selectedSize")); + * ``` + * + * @param expression The element to search for in the array. + * @return A new `Expr` representing the 'array_contains' comparison. + */ + arrayContains(expression: Expression): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if an array contains a specific value. + * + * ```typescript + * // Check if the 'colors' array contains "red" + * field("colors").arrayContains("red"); + * ``` + * + * @param value The element to search for in the array. + * @return A new `Expr` representing the 'array_contains' comparison. + */ + arrayContains(value: unknown): BooleanExpression; + arrayContains(element: unknown): BooleanExpression { + return new FunctionExpression( + 'array_contains', + [this, valueToDefaultExpr(element)], + 'arrayContains' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if an array contains all the specified elements. + * + * ```typescript + * // Check if the 'tags' array contains both the value in field "tag1" and the literal value "tag2" + * field("tags").arrayContainsAll([field("tag1"), "tag2"]); + * ``` + * + * @param values The elements to check for in the array. + * @return A new `Expr` representing the 'array_contains_all' comparison. + */ + arrayContainsAll(values: Array): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if an array contains all the specified elements. + * + * ```typescript + * // Check if the 'tags' array contains both of the values from field "tag1" and the literal value "tag2" + * field("tags").arrayContainsAll(array([field("tag1"), "tag2"])); + * ``` + * + * @param arrayExpression The elements to check for in the array. + * @return A new `Expr` representing the 'array_contains_all' comparison. + */ + arrayContainsAll(arrayExpression: Expression): BooleanExpression; + arrayContainsAll(values: unknown[] | Expression): BooleanExpression { + const normalizedExpr = Array.isArray(values) + ? new ListOfExprs(values.map(valueToDefaultExpr), 'arrayContainsAll') + : values; + return new FunctionExpression( + 'array_contains_all', + [this, normalizedExpr], + 'arrayContainsAll' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if an array contains any of the specified elements. + * + * ```typescript + * // Check if the 'categories' array contains either values from field "cate1" or "cate2" + * field("categories").arrayContainsAny([field("cate1"), field("cate2")]); + * ``` + * + * @param values The elements to check for in the array. + * @return A new `Expr` representing the 'array_contains_any' comparison. + */ + arrayContainsAny(values: Array): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if an array contains any of the specified elements. + * + * ```typescript + * // Check if the 'groups' array contains either the value from the 'userGroup' field + * // or the value "guest" + * field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); + * ``` + * + * @param arrayExpression The elements to check for in the array. + * @return A new `Expr` representing the 'array_contains_any' comparison. + */ + arrayContainsAny(arrayExpression: Expression): BooleanExpression; + arrayContainsAny( + values: Array | Expression + ): BooleanExpression { + const normalizedExpr = Array.isArray(values) + ? new ListOfExprs(values.map(valueToDefaultExpr), 'arrayContainsAny') + : values; + return new FunctionExpression( + 'array_contains_any', + [this, normalizedExpr], + 'arrayContainsAny' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that reverses an array. + * + * ```typescript + * // Reverse the value of the 'myArray' field. + * field("myArray").arrayReverse(); + * ``` + * + * @return A new {@code Expr} representing the reversed array. + */ + arrayReverse(): FunctionExpression { + return new FunctionExpression('array_reverse', [this]); + } + + /** + * @beta + * Creates an expression that calculates the length of an array. + * + * ```typescript + * // Get the number of items in the 'cart' array + * field("cart").arrayLength(); + * ``` + * + * @return A new `Expr` representing the length of the array. + */ + arrayLength(): FunctionExpression { + return new FunctionExpression('array_length', [this], 'arrayLength'); + } + + /** + * @beta + * Creates an expression that checks if this expression is equal to any of the provided values or + * expressions. + * + * ```typescript + * // Check if the 'category' field is either "Electronics" or value of field 'primaryType' + * field("category").equalAny("Electronics", field("primaryType")); + * ``` + * + * @param values The values or expressions to check against. + * @return A new `Expr` representing the 'IN' comparison. + */ + equalAny(values: Array): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if this expression is equal to any of the provided values or + * expressions. + * + * ```typescript + * // Check if the 'category' field is either "Electronics" or value of field 'primaryType' + * field("category").equalAny(array(["Electronics", field("primaryType")])); + * ``` + * + * @param arrayExpression An expression that evaluates to an array of values to check against. + * @return A new `Expr` representing the 'IN' comparison. + */ + equalAny(arrayExpression: Expression): BooleanExpression; + equalAny(others: unknown[] | Expression): BooleanExpression { + const exprOthers = Array.isArray(others) + ? new ListOfExprs(others.map(valueToDefaultExpr), 'equalAny') + : others; + return new FunctionExpression( + 'equal_any', + [this, exprOthers], + 'equalAny' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if this expression is not equal to any of the provided values or + * expressions. + * + * ```typescript + * // Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' + * field("status").notEqualAny(["pending", field("rejectedStatus")]); + * ``` + * + * @param values The values or expressions to check against. + * @return A new `Expr` representing the 'notEqualAny' comparison. + */ + notEqualAny(values: Array): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. + * + * ```typescript + * // Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' + * field("status").notEqualAny(field('rejectedStatuses')); + * ``` + * + * @param arrayExpression The values or expressions to check against. + * @return A new `Expr` representing the 'notEqualAny' comparison. + */ + notEqualAny(arrayExpression: Expression): BooleanExpression; + notEqualAny(others: unknown[] | Expression): BooleanExpression { + const exprOthers = Array.isArray(others) + ? new ListOfExprs(others.map(valueToDefaultExpr), '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. + * + * ```typescript + * // Check if the document has a field named "phoneNumber" + * field("phoneNumber").exists(); + * ``` + * + * @return A new `Expr` representing the 'exists' check. + */ + exists(): BooleanExpression { + return new FunctionExpression('exists', [this], 'exists').asBoolean(); + } + + /** + * @beta + * Creates an expression that calculates the character length of a string in UTF-8. + * + * ```typescript + * // Get the character length of the 'name' field in its UTF-8 form. + * field("name").charLength(); + * ``` + * + * @return A new `Expr` representing the length of the string. + */ + charLength(): FunctionExpression { + return new FunctionExpression('char_length', [this], 'charLength'); + } + + /** + * @beta + * Creates an expression that performs a case-sensitive string comparison. + * + * ```typescript + * // Check if the 'title' field contains the word "guide" (case-sensitive) + * field("title").like("%guide%"); + * ``` + * + * @param pattern The pattern to search for. You can use "%" as a wildcard character. + * @return A new `Expr` representing the 'like' comparison. + */ + like(pattern: string): BooleanExpression; + + /** + * @beta + * Creates an expression that performs a case-sensitive string comparison. + * + * ```typescript + * // Check if the 'title' field contains the word "guide" (case-sensitive) + * field("title").like("%guide%"); + * ``` + * + * @param pattern The pattern to search for. You can use "%" as a wildcard character. + * @return A new `Expr` representing the 'like' comparison. + */ + like(pattern: Expression): BooleanExpression; + like(stringOrExpr: string | Expression): BooleanExpression { + return new FunctionExpression( + 'like', + [this, valueToDefaultExpr(stringOrExpr)], + 'like' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if a string contains a specified regular expression as a + * substring. + * + * ```typescript + * // Check if the 'description' field contains "example" (case-insensitive) + * field("description").regexContains("(?i)example"); + * ``` + * + * @param pattern The regular expression to use for the search. + * @return A new `Expr` representing the 'contains' comparison. + */ + regexContains(pattern: string): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if a string contains a specified regular expression as a + * substring. + * + * ```typescript + * // Check if the 'description' field contains the regular expression stored in field 'regex' + * field("description").regexContains(field("regex")); + * ``` + * + * @param pattern The regular expression to use for the search. + * @return A new `Expr` representing the 'contains' comparison. + */ + regexContains(pattern: Expression): BooleanExpression; + regexContains(stringOrExpr: string | Expression): BooleanExpression { + return new FunctionExpression( + 'regex_contains', + [this, valueToDefaultExpr(stringOrExpr)], + 'regexContains' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if a string matches a specified regular expression. + * + * ```typescript + * // Check if the 'email' field matches a valid email pattern + * field("email").regexMatch("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + * ``` + * + * @param pattern The regular expression to use for the match. + * @return A new `Expr` representing the regular expression match. + */ + regexMatch(pattern: string): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if a string matches a specified regular expression. + * + * ```typescript + * // Check if the 'email' field matches a regular expression stored in field 'regex' + * field("email").regexMatch(field("regex")); + * ``` + * + * @param pattern The regular expression to use for the match. + * @return A new `Expr` representing the regular expression match. + */ + regexMatch(pattern: Expression): BooleanExpression; + regexMatch(stringOrExpr: string | Expression): BooleanExpression { + return new FunctionExpression( + 'regex_match', + [this, valueToDefaultExpr(stringOrExpr)], + 'regexMatch' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if a string contains a specified substring. + * + * ```typescript + * // Check if the 'description' field contains "example". + * field("description").stringContains("example"); + * ``` + * + * @param substring The substring to search for. + * @return A new `Expr` representing the 'contains' comparison. + */ + stringContains(substring: string): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if a string contains the string represented by another expression. + * + * ```typescript + * // Check if the 'description' field contains the value of the 'keyword' field. + * field("description").stringContains(field("keyword")); + * ``` + * + * @param expr The expression representing the substring to search for. + * @return A new `Expr` representing the 'contains' comparison. + */ + stringContains(expr: Expression): BooleanExpression; + stringContains(stringOrExpr: string | Expression): BooleanExpression { + return new FunctionExpression( + 'string_contains', + [this, valueToDefaultExpr(stringOrExpr)], + 'stringContains' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if a string starts with a given prefix. + * + * ```typescript + * // Check if the 'name' field starts with "Mr." + * field("name").startsWith("Mr."); + * ``` + * + * @param prefix The prefix to check for. + * @return A new `Expr` representing the 'starts with' comparison. + */ + startsWith(prefix: string): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if a string starts with a given prefix (represented as an + * expression). + * + * ```typescript + * // Check if the 'fullName' field starts with the value of the 'firstName' field + * field("fullName").startsWith(field("firstName")); + * ``` + * + * @param prefix The prefix expression to check for. + * @return A new `Expr` representing the 'starts with' comparison. + */ + startsWith(prefix: Expression): BooleanExpression; + startsWith(stringOrExpr: string | Expression): BooleanExpression { + return new FunctionExpression( + 'starts_with', + [this, valueToDefaultExpr(stringOrExpr)], + 'startsWith' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that checks if a string ends with a given postfix. + * + * ```typescript + * // Check if the 'filename' field ends with ".txt" + * field("filename").endsWith(".txt"); + * ``` + * + * @param suffix The postfix to check for. + * @return A new `Expr` representing the 'ends with' comparison. + */ + endsWith(suffix: string): BooleanExpression; + + /** + * @beta + * Creates an expression that checks if a string ends with a given postfix (represented as an + * expression). + * + * ```typescript + * // Check if the 'url' field ends with the value of the 'extension' field + * field("url").endsWith(field("extension")); + * ``` + * + * @param suffix The postfix expression to check for. + * @return A new `Expr` representing the 'ends with' comparison. + */ + endsWith(suffix: Expression): BooleanExpression; + endsWith(stringOrExpr: string | Expression): BooleanExpression { + return new FunctionExpression( + 'ends_with', + [this, valueToDefaultExpr(stringOrExpr)], + 'endsWith' + ).asBoolean(); + } + + /** + * @beta + * Creates an expression that converts a string to lowercase. + * + * ```typescript + * // Convert the 'name' field to lowercase + * field("name").toLower(); + * ``` + * + * @return A new `Expr` representing the lowercase string. + */ + toLower(): FunctionExpression { + return new FunctionExpression('to_lower', [this], 'toLower'); + } + + /** + * @beta + * Creates an expression that converts a string to uppercase. + * + * ```typescript + * // Convert the 'title' field to uppercase + * field("title").toUpper(); + * ``` + * + * @return A new `Expr` representing the uppercase string. + */ + toUpper(): FunctionExpression { + return new FunctionExpression('to_upper', [this], 'toUpper'); + } + + /** + * @beta + * Creates an expression that removes leading and trailing characters from a string or byte array. + * + * ```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. + * @return A new `Expr` representing the trimmed string or byte array. + */ + trim(valueToTrim?: string | Expression | Bytes): FunctionExpression { + const args: Expression[] = [this]; + if (valueToTrim) { + args.push(valueToDefaultExpr(valueToTrim)); + } + return new FunctionExpression('trim', args, 'trim'); + } + + /** + * @beta + * Creates an expression that concatenates string expressions together. + * + * ```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. + * @return A new `Expr` representing the concatenated string. + */ + stringConcat( + secondString: Expression | string, + ...otherStrings: Array + ): FunctionExpression { + const elements = [secondString, ...otherStrings]; + const exprs = elements.map(valueToDefaultExpr); + return new FunctionExpression( + 'string_concat', + [this, ...exprs], + 'stringConcat' + ); + } + + /** + * @beta + * Creates an expression that concatenates expression results together. + * + * ```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. + * @return A new `Expr` representing the concatenated value. + */ + concat( + second: Expression | unknown, + ...others: Array + ): FunctionExpression { + const elements = [second, ...others]; + const exprs = elements.map(valueToDefaultExpr); + return new FunctionExpression('concat', [this, ...exprs], 'concat'); + } + + /** + * @beta + * Creates an expression that reverses this string expression. + * + * ```typescript + * // Reverse the value of the 'myString' field. + * field("myString").reverse(); + * ``` + * + * @return A new {@code Expr} representing the reversed string. + */ + reverse(): FunctionExpression { + return new FunctionExpression('reverse', [this], 'reverse'); + } + + /** + * @beta + * Creates an expression that calculates the length of this string expression in bytes. + * + * ```typescript + * // Calculate the length of the 'myString' field in bytes. + * field("myString").byteLength(); + * ``` + * + * @return A new {@code Expr} representing the length of the string in bytes. + */ + byteLength(): FunctionExpression { + return new FunctionExpression('byte_length', [this], 'byteLength'); + } + + /** + * @beta + * Creates an expression that computes the ceiling of a numeric value. + * + * ```typescript + * // Compute the ceiling of the 'price' field. + * field("price").ceil(); + * ``` + * + * @return A new {@code Expr} representing the ceiling of the numeric value. + */ + ceil(): FunctionExpression { + return new FunctionExpression('ceil', [this]); + } + + /** + * @beta + * Creates an expression that computes the floor of a numeric value. + * + * ```typescript + * // Compute the floor of the 'price' field. + * field("price").floor(); + * ``` + * + * @return A new {@code Expr} representing the floor of the numeric value. + */ + floor(): FunctionExpression { + return new FunctionExpression('floor', [this]); + } + + /** + * @beta + * Creates an expression that computes the absolute value of a numeric value. + * + * ```typescript + * // Compute the absolute value of the 'price' field. + * field("price").abs(); + * ``` + * + * @return A new {@code Expr} representing the absolute value of the numeric value. + */ + abs(): FunctionExpression { + return new FunctionExpression('abs', [this]); + } + + /** + * @beta + * Creates an expression that computes e to the power of this expression. + * + * ```typescript + * // Compute e to the power of the 'value' field. + * field("value").exp(); + * ``` + * + * @return A new {@code Expr} representing the exp of the numeric value. + */ + exp(): FunctionExpression { + return new FunctionExpression('exp', [this]); + } + + /** + * @beta + * Accesses a value from a map (object) field using the provided key. + * + * ```typescript + * // Get the 'city' value from the 'address' map field + * field("address").mapGet("city"); + * ``` + * + * @param subfield The key to access in the map. + * @return A new `Expr` representing the value associated with the given key in the map. + */ + mapGet(subfield: string): FunctionExpression { + 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. + * + * ```typescript + * // Count the total number of products + * field("productId").count().as("totalProducts"); + * ``` + * + * @return A new `AggregateFunction` representing the 'count' aggregation. + */ + count(): AggregateFunction { + return AggregateFunction._create('count', [this], 'count'); + } + + /** + * @beta + * Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. + * + * ```typescript + * // Calculate the total revenue from a set of orders + * field("orderAmount").sum().as("totalRevenue"); + * ``` + * + * @return A new `AggregateFunction` representing the 'sum' aggregation. + */ + sum(): AggregateFunction { + return AggregateFunction._create('sum', [this], 'sum'); + } + + /** + * @beta + * Creates an aggregation that calculates the average (mean) of a numeric field across multiple + * stage inputs. + * + * ```typescript + * // Calculate the average age of users + * field("age").average().as("averageAge"); + * ``` + * + * @return A new `AggregateFunction` representing the 'average' aggregation. + */ + average(): AggregateFunction { + return AggregateFunction._create('average', [this], 'average'); + } + + /** + * @beta + * Creates an aggregation that finds the minimum value of a field across multiple stage inputs. + * + * ```typescript + * // Find the lowest price of all products + * field("price").minimum().as("lowestPrice"); + * ``` + * + * @return A new `AggregateFunction` representing the 'minimum' aggregation. + */ + minimum(): AggregateFunction { + return AggregateFunction._create('minimum', [this], 'minimum'); + } + + /** + * @beta + * Creates an aggregation that finds the maximum value of a field across multiple stage inputs. + * + * ```typescript + * // Find the highest score in a leaderboard + * field("score").maximum().as("highestScore"); + * ``` + * + * @return A new `AggregateFunction` representing the 'maximum' aggregation. + */ + maximum(): AggregateFunction { + return AggregateFunction._create('maximum', [this], 'maximum'); + } + + /** + * @beta + * Creates an aggregation that counts the number of distinct values of the expression or field. + * + * ```typescript + * // Count the distinct number of products + * field("productId").countDistinct().as("distinctProducts"); + * ``` + * + * @return A new `AggregateFunction` representing the 'count_distinct' aggregation. + */ + countDistinct(): AggregateFunction { + 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. + * + * ```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. + * @return A new {@code Expr} representing the logical maximum operation. + */ + logicalMaximum( + second: Expression | unknown, + ...others: Array + ): FunctionExpression { + const values = [second, ...others]; + return new FunctionExpression( + 'maximum', + [this, ...values.map(valueToDefaultExpr)], + 'logicalMaximum' + ); + } + + /** + * @beta + * Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. + * + * ```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. + * @return A new {@code Expr} representing the logical minimum operation. + */ + logicalMinimum( + second: Expression | unknown, + ...others: Array + ): FunctionExpression { + const values = [second, ...others]; + return new FunctionExpression( + 'minimum', + [this, ...values.map(valueToDefaultExpr)], + 'minimum' + ); + } + + /** + * @beta + * Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. + * + * ```typescript + * // Get the vector length (dimension) of the field 'embedding'. + * field("embedding").vectorLength(); + * ``` + * + * @return A new {@code Expr} representing the length of the vector. + */ + vectorLength(): FunctionExpression { + return new FunctionExpression('vector_length', [this], 'vectorLength'); + } + + /** + * @beta + * Calculates the cosine distance between two vectors. + * + * ```typescript + * // Calculate the cosine distance between the 'userVector' field and the 'itemVector' field + * field("userVector").cosineDistance(field("itemVector")); + * ``` + * + * @param vectorExpression The other vector (represented as an Expr) to compare against. + * @return A new `Expr` representing the cosine distance between the two vectors. + */ + cosineDistance(vectorExpression: Expression): FunctionExpression; + /** + * @beta + * Calculates the Cosine distance between two vectors. + * + * ```typescript + * // Calculate the Cosine distance between the 'location' field and a target location + * field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); + * ``` + * + * @param vector The other vector (as a VectorValue) to compare against. + * @return A new `Expr` representing the Cosine* distance between the two vectors. + */ + cosineDistance(vector: VectorValue | number[]): FunctionExpression; + cosineDistance( + other: Expression | VectorValue | number[] + ): FunctionExpression { + return new FunctionExpression( + 'cosine_distance', + [this, vectorToExpr(other)], + 'cosineDistance' + ); + } + + /** + * @beta + * Calculates the dot product between two vectors. + * + * ```typescript + * // Calculate the dot product between a feature vector and a target vector + * field("features").dotProduct([0.5, 0.8, 0.2]); + * ``` + * + * @param vectorExpression The other vector (as an array of numbers) to calculate with. + * @return A new `Expr` representing the dot product between the two vectors. + */ + dotProduct(vectorExpression: Expression): FunctionExpression; + + /** + * @beta + * Calculates the dot product between two vectors. + * + * ```typescript + * // Calculate the dot product between a feature vector and a target vector + * field("features").dotProduct(new VectorValue([0.5, 0.8, 0.2])); + * ``` + * + * @param vector The other vector (as an array of numbers) to calculate with. + * @return A new `Expr` representing the dot product between the two vectors. + */ + dotProduct(vector: VectorValue | number[]): FunctionExpression; + dotProduct(other: Expression | VectorValue | number[]): FunctionExpression { + return new FunctionExpression( + 'dot_product', + [this, vectorToExpr(other)], + 'dotProduct' + ); + } + + /** + * @beta + * Calculates the Euclidean distance between two vectors. + * + * ```typescript + * // Calculate the Euclidean distance between the 'location' field and a target location + * field("location").euclideanDistance([37.7749, -122.4194]); + * ``` + * + * @param vectorExpression The other vector (as an array of numbers) to calculate with. + * @return A new `Expr` representing the Euclidean distance between the two vectors. + */ + euclideanDistance(vectorExpression: Expression): FunctionExpression; + + /** + * @beta + * Calculates the Euclidean distance between two vectors. + * + * ```typescript + * // Calculate the Euclidean distance between the 'location' field and a target location + * field("location").euclideanDistance(new VectorValue([37.7749, -122.4194])); + * ``` + * + * @param vector The other vector (as a VectorValue) to compare against. + * @return A new `Expr` representing the Euclidean distance between the two vectors. + */ + euclideanDistance(vector: VectorValue | number[]): FunctionExpression; + euclideanDistance( + other: Expression | VectorValue | number[] + ): FunctionExpression { + return new FunctionExpression( + 'euclidean_distance', + [this, vectorToExpr(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. + * + * ```typescript + * // Interpret the 'microseconds' field as microseconds since epoch. + * field("microseconds").unixMicrosToTimestamp(); + * ``` + * + * @return A new {@code Expr} representing the timestamp. + */ + unixMicrosToTimestamp(): FunctionExpression { + 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). + * + * ```typescript + * // Convert the 'timestamp' field to microseconds since epoch. + * field("timestamp").timestampToUnixMicros(); + * ``` + * + * @return A new {@code Expr} representing the number of microseconds since epoch. + */ + timestampToUnixMicros(): FunctionExpression { + 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. + * + * ```typescript + * // Interpret the 'milliseconds' field as milliseconds since epoch. + * field("milliseconds").unixMillisToTimestamp(); + * ``` + * + * @return A new {@code Expr} representing the timestamp. + */ + unixMillisToTimestamp(): FunctionExpression { + 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). + * + * ```typescript + * // Convert the 'timestamp' field to milliseconds since epoch. + * field("timestamp").timestampToUnixMillis(); + * ``` + * + * @return A new {@code Expr} representing the number of milliseconds since epoch. + */ + timestampToUnixMillis(): FunctionExpression { + 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. + * + * ```typescript + * // Interpret the 'seconds' field as seconds since epoch. + * field("seconds").unixSecondsToTimestamp(); + * ``` + * + * @return A new {@code Expr} representing the timestamp. + */ + unixSecondsToTimestamp(): FunctionExpression { + 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). + * + * ```typescript + * // Convert the 'timestamp' field to seconds since epoch. + * field("timestamp").timestampToUnixSeconds(); + * ``` + * + * @return A new {@code Expr} representing the number of seconds since epoch. + */ + timestampToUnixSeconds(): FunctionExpression { + return new FunctionExpression( + 'timestamp_to_unix_seconds', + [this], + 'timestampToUnixSeconds' + ); + } + + /** + * @beta + * Creates an expression that adds a specified amount of time to this timestamp expression. + * + * ```typescript + * // Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. + * field("timestamp").timestampAdd(field("unit"), field("amount")); + * ``` + * + * @param unit The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. + * @param amount The expression evaluates to amount of the unit. + * @return A new {@code Expr} representing the resulting timestamp. + */ + timestampAdd(unit: Expression, amount: Expression): FunctionExpression; + + /** + * @beta + * Creates an expression that adds a specified amount of time to this timestamp expression. + * + * ```typescript + * // Add 1 day to the 'timestamp' field. + * field("timestamp").timestampAdd("day", 1); + * ``` + * + * @param unit The unit of time to add (e.g., "day", "hour"). + * @param amount The amount of time to add. + * @return A new {@code Expr} representing the resulting timestamp. + */ + timestampAdd( + unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', + amount: number + ): FunctionExpression; + timestampAdd( + unit: + | Expression + | 'microsecond' + | 'millisecond' + | 'second' + | 'minute' + | 'hour' + | 'day', + amount: Expression | number + ): FunctionExpression { + return new FunctionExpression( + 'timestamp_add', + [this, valueToDefaultExpr(unit), valueToDefaultExpr(amount)], + 'timestampAdd' + ); + } + + /** + * @beta + * Creates an expression that subtracts a specified amount of time from this timestamp expression. + * + * ```typescript + * // Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. + * field("timestamp").timestampSubtract(field("unit"), field("amount")); + * ``` + * + * @param unit The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. + * @param amount The expression evaluates to amount of the unit. + * @return A new {@code Expr} representing the resulting timestamp. + */ + timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; + + /** + * @beta + * Creates an expression that subtracts a specified amount of time from this timestamp expression. + * + * ```typescript + * // Subtract 1 day from the 'timestamp' field. + * field("timestamp").timestampSubtract("day", 1); + * ``` + * + * @param unit The unit of time to subtract (e.g., "day", "hour"). + * @param amount The amount of time to subtract. + * @return A new {@code Expr} representing the resulting timestamp. + */ + timestampSubtract( + unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', + amount: number + ): FunctionExpression; + timestampSubtract( + unit: + | Expression + | 'microsecond' + | 'millisecond' + | 'second' + | 'minute' + | 'hour' + | 'day', + amount: Expression | number + ): FunctionExpression { + return new FunctionExpression( + 'timestamp_subtract', + [this, valueToDefaultExpr(unit), valueToDefaultExpr(amount)], + 'timestampSubtract' + ); + } + + /** + * @beta + * + * Creates an expression that returns the document ID from a path. + * + * ```typescript + * // Get the document ID from a path. + * field("__path__").documentId(); + * ``` + * + * @return A new {@code Expr} representing the documentId operation. + */ + documentId(): FunctionExpression { + return new FunctionExpression('document_id', [this], 'documentId'); + } + + /** + * @beta + * + * Creates an expression that returns a substring of the results of this expression. + * + * @param position Index of the first character of the substring. + * @param length Length of the substring. If not provided, the substring will + * end at the end of the input. + */ + substring(position: number, length?: number): FunctionExpression; + + /** + * @beta + * + * Creates an expression that returns a substring of the results of this expression. + * + * @param position An expression returning the index of the first character of the substring. + * @param length An expression returning the length of the substring. If not provided the + * substring will end at the end of the input. + */ + substring(position: Expression, length?: Expression): FunctionExpression; + substring( + position: Expression | number, + length?: Expression | number + ): FunctionExpression { + const positionExpr = valueToDefaultExpr(position); + if (length === undefined) { + return new FunctionExpression( + 'substring', + [this, positionExpr], + 'substring' + ); + } else { + return new FunctionExpression( + 'substring', + [this, positionExpr, valueToDefaultExpr(length)], + 'substring' + ); + } + } + + /** + * @beta + * Creates an expression that indexes into an array from the beginning or end + * and returns the element. If the offset exceeds the array length, an error is + * returned. A negative offset, starts from the end. + * + * ```typescript + * // Return the value in the 'tags' field array at index `1`. + * field('tags').arrayGet(1); + * ``` + * + * @param offset The index of the element to return. + * @return A new Expr representing the 'arrayGet' operation. + */ + arrayGet(offset: number): FunctionExpression; + + /** + * @beta + * Creates an expression that indexes into an array from the beginning or end + * and returns the element. If the offset exceeds the array length, an error is + * returned. A negative offset, starts from the end. + * + * ```typescript + * // Return the value in the tags field array at index specified by field + * // 'favoriteTag'. + * field('tags').arrayGet(field('favoriteTag')); + * ``` + * + * @param offsetExpr An Expr evaluating to the index of the element to return. + * @return A new Expr representing the 'arrayGet' operation. + */ + arrayGet(offsetExpr: Expression): FunctionExpression; + arrayGet(offset: Expression | number): FunctionExpression { + return new FunctionExpression( + 'array_get', + [this, valueToDefaultExpr(offset)], + 'arrayGet' + ); + } + + /** + * @beta + * + * Creates an expression that checks if a given expression produces an error. + * + * ```typescript + * // Check if the result of a calculation is an error + * field("title").arrayContains(1).isError(); + * ``` + * + * @return A new {@code BooleanExpr} representing the 'isError' check. + */ + isError(): BooleanExpression { + return new FunctionExpression('is_error', [this], 'isError').asBoolean(); + } + + /** + * @beta + * + * Creates an expression that returns the result of the `catchExpr` argument + * if there is an error, else return the result of this expression. + * + * ```typescript + * // Returns the first item in the title field arrays, or returns + * // the entire title field if the array is empty or the field is another type. + * field("title").arrayGet(0).ifError(field("title")); + * ``` + * + * @param catchExpr The catch expression that will be evaluated and + * returned if this expression produces an error. + * @return A new {@code Expr} representing the 'ifError' operation. + */ + ifError(catchExpr: Expression): FunctionExpression; + + /** + * @beta + * + * Creates an expression that returns the `catch` argument if there is an + * error, else return the result of this expression. + * + * ```typescript + * // Returns the first item in the title field arrays, or returns + * // "Default Title" + * field("title").arrayGet(0).ifError("Default Title"); + * ``` + * + * @param catchValue The value that will be returned if this expression + * produces an error. + * @return A new {@code Expr} representing the 'ifError' operation. + */ + ifError(catchValue: unknown): FunctionExpression; + ifError(catchValue: unknown): FunctionExpression | BooleanExpression { + const result = new FunctionExpression( + 'if_error', + [this, valueToDefaultExpr(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`. + * + * ```typescript + * // Check if the field `value` is absent. + * field("value").isAbsent(); + * ``` + * + * @return A new {@code BooleanExpr} representing the 'isAbsent' check. + */ + isAbsent(): BooleanExpression { + return new FunctionExpression('is_absent', [this], 'isAbsent').asBoolean(); + } + + /** + * @beta + * + * Creates an expression that removes a key from the map produced by evaluating this expression. + * + * ``` + * // Removes the key 'baz' from the input map. + * map({foo: 'bar', baz: true}).mapRemove('baz'); + * ``` + * + * @param key The name of the key to remove from the input map. + * @returns A new {@code FirestoreFunction} representing the 'mapRemove' operation. + */ + mapRemove(key: string): FunctionExpression; + /** + * @beta + * + * Creates an expression that removes a key from the map produced by evaluating this expression. + * + * ``` + * // Removes the key 'baz' from the input map. + * map({foo: 'bar', baz: true}).mapRemove(constant('baz')); + * ``` + * + * @param keyExpr An expression that produces the name of the key to remove from the input map. + * @returns A new {@code FirestoreFunction} representing the 'mapRemove' operation. + */ + mapRemove(keyExpr: Expression): FunctionExpression; + mapRemove(stringExpr: Expression | string): FunctionExpression { + return new FunctionExpression( + 'map_remove', + [this, valueToDefaultExpr(stringExpr)], + 'mapRemove' + ); + } + + /** + * @beta + * + * Creates an expression that merges multiple map values. + * + * ``` + * // 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 {@code FirestoreFunction} representing the 'mapMerge' operation. + */ + mapMerge( + secondMap: Record | Expression, + ...otherMaps: Array | Expression> + ): FunctionExpression { + const secondMapExpr = valueToDefaultExpr(secondMap); + const otherMapExprs = otherMaps.map(valueToDefaultExpr); + return new FunctionExpression( + 'map_merge', + [this, secondMapExpr, ...otherMapExprs], + 'mapMerge' + ); + } + + /** + * @beta + * Creates an expression that returns the value of this expression raised to the power of another expression. + * + * ```typescript + * // Raise the value of the 'base' field to the power of the 'exponent' field. + * field("base").pow(field("exponent")); + * ``` + * + * @param exponent The expression to raise this expression to the power of. + * @return A new `Expr` representing the power operation. + */ + pow(exponent: Expression): FunctionExpression; + + /** + * @beta + * Creates an expression that returns the value of this expression raised to the power of a constant value. + * + * ```typescript + * // Raise the value of the 'base' field to the power of 2. + * field("base").pow(2); + * ``` + * + * @param exponent The constant value to raise this expression to the power of. + * @return A new `Expr` representing the power operation. + */ + pow(exponent: number): FunctionExpression; + pow(exponent: number | Expression): FunctionExpression { + return new FunctionExpression('pow', [this, valueToDefaultExpr(exponent)]); + } + + /** + * @beta + * Creates an expression that rounds a numeric value to the nearest whole number. + * + * ```typescript + * // Round the value of the 'price' field. + * field("price").round(); + * ``` + * + * @return A new `Expr` representing the rounded value. + */ + round(): FunctionExpression; + /** + * @beta + * Creates an expression that rounds a numeric value to the specified number of decimal places. + * + * ```typescript + * // Round the value of the 'price' field to two decimal places. + * field("price").round(2); + * ``` + * + * @param decimalPlaces A constant specifying the rounding precision in decimal places. + * + * @return A new `Expr` representing the rounded value. + */ + round(decimalPlaces: number): FunctionExpression; + /** + * @beta + * Creates an expression that rounds a numeric value to the specified number of decimal places. + * + * ```typescript + * // Round the value of the 'price' field to two decimal places. + * field("price").round(constant(2)); + * ``` + * + * @param decimalPlaces An expression specifying the rounding precision in decimal places. + * + * @return A new `Expr` representing the rounded value. + */ + round(decimalPlaces: Expression): FunctionExpression; + round(decimalPlaces?: number | Expression): FunctionExpression { + if (decimalPlaces === undefined) { + return new FunctionExpression('round', [this]); + } else { + return new FunctionExpression( + 'round', + [this, valueToDefaultExpr(decimalPlaces)], + 'round' + ); + } + } + + /** + * @beta + * Creates an expression that returns the collection ID from a path. + * + * ```typescript + * // Get the collection ID from a path. + * field("__path__").collectionId(); + * ``` + * + * @return A new {@code Expr} representing the collectionId operation. + */ + collectionId(): FunctionExpression { + return new FunctionExpression('collection_id', [this]); + } + + /** + * @beta + * Creates an expression that calculates the length of a string, array, map, vector, or bytes. + * + * ```typescript + * // Get the length of the 'name' field. + * field("name").length(); + * + * // Get the number of items in the 'cart' array. + * field("cart").length(); + * ``` + * + * @return A new `Expr` representing the length of the string, array, map, vector, or bytes. + */ + length(): FunctionExpression { + return new FunctionExpression('length', [this]); + } + + /** + * @beta + * Creates an expression that computes the natural logarithm of a numeric value. + * + * ```typescript + * // Compute the natural logarithm of the 'value' field. + * field("value").ln(); + * ``` + * + * @return A new {@code Expr} representing the natural logarithm of the numeric value. + */ + ln(): FunctionExpression { + return new FunctionExpression('ln', [this]); + } + + /** + * @beta + * Creates an expression that computes the square root of a numeric value. + * + * ```typescript + * // Compute the square root of the 'value' field. + * field("value").sqrt(); + * ``` + * + * @return A new {@code Expr} representing the square root of the numeric value. + */ + sqrt(): FunctionExpression { + return new FunctionExpression('sqrt', [this]); + } + + /** + * @beta + * Creates an expression that reverses a string. + * + * ```typescript + * // Reverse the value of the 'myString' field. + * field("myString").stringReverse(); + * ``` + * + * @return A new {@code Expr} representing the reversed string. + */ + stringReverse(): FunctionExpression { + return new FunctionExpression('string_reverse', [this]); + } + + /** + * @beta + * Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else + * return the result of the this expression evaluation. + * + * ```typescript + * // Returns the value of the optional field 'optional_field', or returns 'default_value' + * // if the field is absent. + * field("optional_field").ifAbsent("default_value") + * ``` + * + * @param elseValue The value that will be returned if this Expression evaluates to an absent value. + * @return A new [Expression] representing the ifAbsent operation. + */ + ifAbsent(elseValue: unknown): Expression; + + /** + * @beta + * Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else + * return the result of this expression evaluation. + * + * ```typescript + * // Returns the value of the optional field 'optional_field', or if that is + * // absent, then returns the value of the field ` + * field("optional_field").ifAbsent(field('default_field')) + * ``` + * + * @param elseExpression The Expression that will be evaluated if this Expression evaluates to an absent value. + * @return A new [Expression] representing the ifAbsent operation. + */ + ifAbsent(elseExpression: unknown): Expression; + + ifAbsent(elseValueOrExpression: Expression | unknown): Expression { + return new FunctionExpression( + 'if_absent', + [this, valueToDefaultExpr(elseValueOrExpression)], + 'ifAbsent' + ); + } + + /** + * @beta + * Creates an expression that joins the elements of an array into a string. + * + * ```typescript + * // Join the elements of the 'tags' field with the delimiter from the 'separator' field. + * field("tags").join(field("separator")) + * ``` + * + * @param delimiterExpression The expression that evaluates to the delimiter string. + * @return A new Expression representing the join operation. + */ + join(delimiterExpression: Expression): Expression; + + /** + * @beta + * Creates an expression that joins the elements of an array field into a string. + * + * ```typescript + * // Join the elements of the 'tags' field with a comma and space. + * field("tags").join(", ") + * ``` + * + * @param delimiter The string to use as a delimiter. + * @return A new Expression representing the join operation. + */ + join(delimiter: string): Expression; + + join(delimeterValueOrExpression: string | Expression): Expression { + return new FunctionExpression( + 'join', + [this, valueToDefaultExpr(delimeterValueOrExpression)], + 'join' + ); + } + + /** + * @beta + * Creates an expression that computes the base-10 logarithm of a numeric value. + * + * ```typescript + * // Compute the base-10 logarithm of the 'value' field. + * field("value").log10(); + * ``` + * + * @return A new {@code Expr} representing the base-10 logarithm of the numeric value. + */ + log10(): FunctionExpression { + return new FunctionExpression('log10', [this]); + } + + /** + * @beta + * Creates an expression that computes the sum of the elements in an array. + * + * ```typescript + * // Compute the sum of the elements in the 'scores' field. + * field("scores").arraySum(); + * ``` + * + * @return A new {@code Expr} representing the sum of the elements in the array. + */ + arraySum(): FunctionExpression { + return new FunctionExpression('sum', [this]); + } + + /** + * @beta + * Creates an expression that splits the result of this expression into an + * array of substrings based on the provided delimiter. + * + * @example + * ```typescript + * // Split the 'scoresCsv' field on delimiter ',' + * field('scoresCsv').split(',') + * ``` + * + * @return A new {@code Expression} representing the split function. + */ + split(delimiter: string): FunctionExpression; + + /** + * @beta + * Creates an expression that splits the result of this expression into an + * array of substrings based on the provided delimiter. + * + * @example + * ```typescript + * // Split the 'scores' field on delimiter ',' or ':' depending on the stored format + * field('scores').split(conditional(field('format').equal('csv'), constant(','), constant(':')) + * ``` + * + * @return A new {@code Expression} representing the split function. + */ + split(delimiter: Expression): FunctionExpression; + split(delimiter: string | Expression): FunctionExpression { + return new FunctionExpression('split', [ + this, + valueToDefaultExpr(delimiter) + ]); + } + + /** + * Creates an expression that truncates a timestamp to a specified granularity. + * + * @example + * ```typescript + * // Truncate the 'createdAt' timestamp to the beginning of the day. + * field('createdAt').timestampTruncate('day') + * ``` + * + * @param granularity The granularity to truncate to. + * @param timezone The timezone to use for truncation. Valid values are from + * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". + * @return A new {Expression} representing the truncated timestamp. + */ + timestampTruncate( + granularity: TimeGranularity, + timezone?: string | Expression + ): FunctionExpression; + + /** + * Creates an expression that truncates a timestamp to a specified granularity. + * + * @example + * ```typescript + * // Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. + * field('createdAt').timestampTruncate(field('granularity')) + * ``` + * + * @param granularity The granularity to truncate to. + * @param timezone The timezone to use for truncation. Valid values are from + * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". + * @return A new {Expression} representing the truncated timestamp. + */ + timestampTruncate( + granularity: Expression, + timezone?: string | Expression + ): FunctionExpression; + timestampTruncate( + granularity: TimeGranularity | Expression, + timezone?: string | Expression + ): FunctionExpression { + const internalGranularity = isString(granularity) + ? granularity.toLowerCase() + : granularity; + + const args = [this, valueToDefaultExpr(internalGranularity)]; + if (timezone) { + args.push(valueToDefaultExpr(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() + * ``` + * + * @return A new {Expression} representing the data type. + */ + type(): FunctionExpression { + return new FunctionExpression('type', [this]); + } + + // TODO(new-expression): Add new expression method definitions above this line + + /** + * @beta + * Creates an {@link Ordering} that sorts documents in ascending order based on this expression. + * + * ```typescript + * // Sort documents by the 'name' field in ascending order + * pipeline().collection("users") + * .sort(field("name").ascending()); + * ``` + * + * @return A new `Ordering` for ascending sorting. + */ + ascending(): Ordering { + return ascending(this); + } + + /** + * @beta + * Creates an {@link Ordering} that sorts documents in descending order based on this expression. + * + * ```typescript + * // Sort documents by the 'createdAt' field in descending order + * firestore.pipeline().collection("users") + * .sort(field("createdAt").descending()); + * ``` + * + * @return A new `Ordering` for descending sorting. + */ + descending(): Ordering { + 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. + * + * ```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. + * @return A new {@link AliasedExpression} that wraps this + * expression and associates it with the provided alias. + */ + as(name: string): AliasedExpression { + return new AliasedExpression(this, name, 'as'); + } +} + +/** + * @beta + * Specify time granularity for expressions. + */ +export type TimeGranularity = + | 'microsecond' + | 'millisecond' + | 'second' + | 'minute' + | 'hour' + | 'day' + | 'week' + | 'week(monday)' + | 'week(tuesday)' + | 'week(wednesday)' + | 'week(thursday)' + | 'week(friday)' + | 'week(saturday)' + | 'week(sunday)' + | 'isoWeek' + | 'month' + | 'quarter' + | 'year' + | 'isoYear'; + +/** + * @beta + * + * An interface that represents a selectable expression. + */ +export interface Selectable { + selectable: true; + /** + * @private + * @internal + */ + readonly alias: string; + /** + * @private + * @internal + */ + readonly expr: Expression; +} + +/** + * @beta + * + * A class that represents an aggregate function. + */ +export class AggregateFunction implements ProtoValueSerializable, UserData { + exprType: ExpressionType = 'AggregateFunction'; + + /** + * @internal + */ + _methodName?: string; + + constructor(private name: string, private params: Expression[]) {} + + /** + * @internal + * @private + */ + static _create( + name: string, + params: Expression[], + methodName: string + ): AggregateFunction { + 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. + * + * ```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. + * @return A new {@link AliasedAggregate} that wraps this + * AggregateFunction and associates it with the provided alias. + */ + as(name: string): AliasedAggregate { + return new AliasedAggregate(this, name, 'as'); + } + + /** + * @private + * @internal + */ + _toProto(serializer: JsonProtoSerializer): ProtoValue { + return { + functionValue: { + name: this.name, + args: this.params.map(p => p._toProto(serializer)) + } + }; + } + + _protoValueType = 'ProtoValue' as const; + + /** + * @private + * @internal + */ + _readUserData(context: ParseContext): void { + context = this._methodName + ? context.contextWith({ methodName: this._methodName }) + : context; + this.params.forEach(expr => { + return expr._readUserData(context); + }); + } +} + +/** + * @beta + * + * An AggregateFunction with alias. + */ +export class AliasedAggregate implements UserData { + constructor( + readonly aggregate: AggregateFunction, + readonly alias: string, + readonly _methodName: string | undefined + ) {} + + /** + * @private + * @internal + */ + _readUserData(context: ParseContext): void { + this.aggregate._readUserData(context); + } +} + +/** + * @beta + */ +export class AliasedExpression implements Selectable, UserData { + exprType: ExpressionType = 'AliasedExpression'; + selectable = true as const; + + constructor( + readonly expr: Expression, + readonly alias: string, + readonly _methodName: string | undefined + ) {} + + /** + * @private + * @internal + */ + _readUserData(context: ParseContext): void { + this.expr._readUserData(context); + } +} + +/** + * @internal + */ +class ListOfExprs extends Expression implements UserData { + expressionType: ExpressionType = 'ListOfExpressions'; + + constructor( + private exprs: Expression[], + readonly _methodName: string | undefined + ) { + super(); + } + + /** + * @private + * @internal + */ + _toProto(serializer: JsonProtoSerializer): ProtoValue { + return { + arrayValue: { + values: this.exprs.map(p => p._toProto(serializer)!) + } + }; + } + + /** + * @private + * @internal + */ + _readUserData(context: ParseContext): void { + this.exprs.forEach((expr: Expression) => expr._readUserData(context)); + } +} + +/** + * @beta + * + * Represents a reference to a field in a Firestore document, or outputs of a {@link Pipeline} stage. + * + *

Field references are used to access document field values in expressions and to specify fields + * for sorting, filtering, and projecting data in Firestore pipelines. + * + *

You can create a `Field` instance using the static {@link #of} method: + * + * ```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"); + * ``` + */ +export class Field extends Expression implements Selectable { + readonly expressionType: ExpressionType = 'Field'; + selectable = true as const; + + /** + * @internal + * @private + * @hideconstructor + * @param fieldPath + */ + constructor( + private fieldPath: InternalFieldPath, + readonly _methodName: string | undefined + ) { + super(); + } + + get fieldName(): string { + return this.fieldPath.canonicalString(); + } + + get alias(): string { + return this.fieldName; + } + + get expr(): Expression { + return this; + } + + /** + * @private + * @internal + */ + _toProto(serializer: JsonProtoSerializer): ProtoValue { + return { + fieldReferenceValue: this.fieldPath.canonicalString() + }; + } + + /** + * @private + * @internal + */ + _readUserData(context: ParseContext): void {} +} + +/** + * @beta + * Creates a {@code Field} instance representing the field at the given path. + * + * The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field + * (e.g., "address.city"). + * + * ```typescript + * // Create a Field instance for the 'title' field + * const titleField = field("title"); + * + * // Create a Field instance for a nested field 'author.firstName' + * const authorFirstNameField = field("author.firstName"); + * ``` + * + * @param name The path to the field. + * @return A new {@code Field} instance representing the specified field. + */ +export function field(name: string): Field; + +/** + * @beta + * Creates a {@code Field} instance representing the field at the given path. + * + * @param path A FieldPath specifying the field. + * @return A new {@code Field} instance representing the specified field. + */ +export function field(path: FieldPath): Field; +export function field(nameOrPath: string | FieldPath): Field { + return _field(nameOrPath, 'field'); +} + +export function _field( + nameOrPath: string | FieldPath, + methodName: string | undefined +): Field { + if (typeof nameOrPath === 'string') { + if (DOCUMENT_KEY_NAME === nameOrPath) { + return new Field(documentIdFieldPath()._internalPath, methodName); + } + return new Field(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 #of} method: + * + * ```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"); + * ``` + */ +export class Constant extends Expression { + readonly expressionType: ExpressionType = 'Constant'; + + private _protoValue?: ProtoValue; + + /** + * @private + * @internal + * @hideconstructor + * @param value The value of the constant. + */ + constructor( + private value: unknown, + readonly _methodName: string | undefined + ) { + super(); + } + + /** + * @private + * @internal + */ + static _fromProto(value: ProtoValue): Constant { + const result = new Constant(value, undefined); + result._protoValue = value; + return result; + } + + /** + * @private + * @internal + */ + _toProto(_: JsonProtoSerializer): ProtoValue { + hardAssert( + this._protoValue !== undefined, + 0x00ed, + 'Value of this constant has not been serialized to proto value' + ); + return this._protoValue; + } + + /** + * @private + * @internal + */ + _readUserData(context: ParseContext): void { + context = this._methodName + ? context.contextWith({ methodName: this._methodName }) + : context; + if (isFirestoreValue(this._protoValue)) { + return; + } else { + this._protoValue = parseData(this.value, context)!; + } + } +} + +/** + * @beta + * Creates a `Constant` instance for a number value. + * + * @param value The number value. + * @return A new `Constant` instance. + */ +export function constant(value: number): Expression; + +/** + * @beta + * Creates a `Constant` instance for a string value. + * + * @param value The string value. + * @return A new `Constant` instance. + */ +export function constant(value: string): Expression; + +/** + * @beta + * Creates a `BooleanExpression` instance for a boolean value. + * + * @param value The boolean value. + * @return A new `Constant` instance. + */ +export function constant(value: boolean): BooleanExpression; + +/** + * @beta + * Creates a `Constant` instance for a null value. + * + * @param value The null value. + * @return A new `Constant` instance. + */ +export function constant(value: null): Expression; + +/** + * @beta + * Creates a `Constant` instance for a GeoPoint value. + * + * @param value The GeoPoint value. + * @return A new `Constant` instance. + */ +export function constant(value: GeoPoint): Expression; + +/** + * @beta + * Creates a `Constant` instance for a Timestamp value. + * + * @param value The Timestamp value. + * @return A new `Constant` instance. + */ +export function constant(value: Timestamp): Expression; + +/** + * @beta + * Creates a `Constant` instance for a Date value. + * + * @param value The Date value. + * @return A new `Constant` instance. + */ +export function constant(value: Date): Expression; + +/** + * @beta + * Creates a `Constant` instance for a Bytes value. + * + * @param value The Bytes value. + * @return A new `Constant` instance. + */ +export function constant(value: Bytes): Expression; + +/** + * @beta + * Creates a `Constant` instance for a DocumentReference value. + * + * @param value The DocumentReference value. + * @return A new `Constant` instance. + */ +export function constant(value: DocumentReference): Expression; + +/** + * Creates a `Constant` instance for a Firestore proto value. + * For internal use only. + * @private + * @internal + * @param value The Firestore proto value. + * @return A new `Constant` instance. + */ +export function constant(value: ProtoValue): Expression; + +/** + * @beta + * Creates a `Constant` instance for a VectorValue value. + * + * @param value The VectorValue value. + * @return A new `Constant` instance. + */ +export function constant(value: VectorValue): Expression; + +export function constant(value: unknown): Expression | BooleanExpression { + return _constant(value, 'constant'); +} + +/** + * @internal + * @private + * @param value + * @param methodName + */ +export function _constant( + value: unknown, + methodName: string | undefined +): Constant | BooleanExpression { + const c = new Constant(value, methodName); + if (typeof value === 'boolean') { + return new BooleanConstant(c); + } else { + return c; + } +} + +/** + * Internal only + * @internal + * @private + */ +export class MapValue extends Expression { + constructor( + private plainObject: Map, + readonly _methodName: string | undefined + ) { + super(); + } + + expressionType: ExpressionType = 'Constant'; + + _readUserData(context: ParseContext): void { + context = this._methodName + ? context.contextWith({ methodName: this._methodName }) + : context; + this.plainObject.forEach(expr => { + expr._readUserData(context); + }); + } + + _toProto(serializer: JsonProtoSerializer): ProtoValue { + return toMapValue(serializer, this.plainObject); + } +} + +/** + * @beta + * + * This class defines the base class for Firestore {@link Pipeline} functions, which can be evaluated within pipeline + * execution. + * + * Typically, you would not use this class or its children directly. Use either the functions like {@link and}, {@link equal}, + * or the methods on {@link Expression} ({@link Expression#equal}, {@link Expression#lessThan}, etc.) to construct new Function instances. + */ +export class FunctionExpression extends Expression { + readonly expressionType: ExpressionType = 'Function'; + + constructor(name: string, params: Expression[]); + constructor( + name: string, + params: Expression[], + _methodName: string | undefined + ); + constructor( + private name: string, + private params: Expression[], + readonly _methodName?: string + ) { + super(); + } + + /** + * @private + * @internal + */ + _toProto(serializer: JsonProtoSerializer): ProtoValue { + return { + functionValue: { + name: this.name, + args: this.params.map(p => p._toProto(serializer)) + } + }; + } + + /** + * @private + * @internal + */ + _readUserData(context: ParseContext): void { + context = this._methodName + ? context.contextWith({ methodName: this._methodName }) + : context; + this.params.forEach(expr => { + return expr._readUserData(context); + }); + } +} + +/** + * @beta + * + * An interface that represents a filter condition. + */ +export abstract class BooleanExpression extends Expression { + abstract get _expr(): Expression; + + get _methodName(): string | undefined { + return this._expr._methodName; + } + + /** + * @beta + * Creates an aggregation that finds the count of input documents satisfying + * this boolean expression. + * + * ```typescript + * // Find the count of documents with a score greater than 90 + * field("score").greaterThan(90).countIf().as("highestScore"); + * ``` + * + * @return A new `AggregateFunction` representing the 'countIf' aggregation. + */ + countIf(): AggregateFunction { + return AggregateFunction._create('count_if', [this], 'countIf'); + } + + /** + * @beta + * Creates an expression that negates this boolean expression. + * + * ```typescript + * // Find documents where the 'tags' field does not contain 'completed' + * field("tags").arrayContains("completed").not(); + * ``` + * + * @return A new {@code Expr} representing the negated filter condition. + */ + not(): BooleanExpression { + return new FunctionExpression('not', [this], 'not').asBoolean(); + } + + /** + * @beta + * Creates a conditional expression that evaluates to the 'then' expression + * if `this` expression evaluates to `true`, + * or evaluates to the 'else' expression if `this` expressions evaluates `false`. + * + * ```typescript + * // If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". + * field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor")); + * ``` + * + * @param thenExpr The expression to evaluate if the condition is true. + * @param elseExpr The expression to evaluate if the condition is false. + * @return A new {@code Expr} representing the conditional expression. + */ + conditional(thenExpr: Expression, elseExpr: Expression): FunctionExpression { + return new FunctionExpression( + 'conditional', + [this, thenExpr, elseExpr], + 'conditional' + ); + } + + /** + * @beta + * + * Creates an expression that returns the `catch` argument if there is an + * error, else return the result of this expression. + * + * ```typescript + * // Create an expression that protects against a divide by zero error + * // but always returns a boolean expression. + * constant(50).divide('length').gt(1).ifError(constant(false)); + * ``` + * + * @param catchValue The value that will be returned if this expression + * produces an error. + * @return A new {@code Expr} representing the 'ifError' operation. + */ + ifError(catchValue: BooleanExpression): BooleanExpression; + + /** + * @beta + * + * Creates an expression that returns the `catch` argument if there is an + * error, else return the result of this expression. + * + * ```typescript + * // Create an expression that protects against a divide by zero error + * // but always returns a boolean expression. + * constant(50).divide('length').gt(1).ifError(false); + * ``` + * + * @param catchValue The value that will be returned if this expression + * produces an error. + * @return A new {@code Expr} representing the 'ifError' operation. + */ + ifError(catchValue: boolean): BooleanExpression; + + /** + * @beta + * + * Creates an expression that returns the `catch` argument if there is an + * error, else return the result of this expression. + * + * ```typescript + * // Create an expression that protects against a divide by zero error. + * constant(50).divide('length').gt(1).ifError(constant(0)); + * ``` + * + * @param catchValue The value that will be returned if this expression + * produces an error. + * @return A new {@code Expr} representing the 'ifError' operation. + */ + ifError(catchValue: Expression): FunctionExpression; + + /** + * @beta + * + * Creates an expression that returns the `catch` argument if there is an + * error, else return the result of this expression. + * + * ```typescript + * // Create an expression that protects against a divide by zero error. + * constant(50).divide('length').gt(1).ifError(0); + * ``` + * + * @param catchValue The value that will be returned if this expression + * produces an error. + * @return A new {@code Expr} representing the 'ifError' operation. + */ + ifError(catchValue: unknown): FunctionExpression; + ifError(catchValue: unknown): unknown { + const normalizedCatchValue = valueToDefaultExpr(catchValue); + const expr = new FunctionExpression( + 'if_error', + [this, normalizedCatchValue], + 'ifError' + ); + + return normalizedCatchValue instanceof BooleanExpression + ? expr.asBoolean() + : expr; + } + + /** + * @private + * @internal + */ + _toProto(serializer: JsonProtoSerializer): ProtoValue { + return this._expr._toProto(serializer); + } + + /** + * @private + * @internal + */ + _readUserData(context: ParseContext): void { + this._expr._readUserData(context); + } +} + +export class BooleanFunctionExpression extends BooleanExpression { + readonly expressionType: ExpressionType = 'Function'; + constructor(readonly _expr: FunctionExpression) { + super(); + } +} + +export class BooleanConstant extends BooleanExpression { + readonly expressionType: ExpressionType = 'Constant'; + constructor(readonly _expr: Constant) { + super(); + } +} + +export class BooleanField extends BooleanExpression { + readonly expressionType: ExpressionType = 'Field'; + constructor(readonly _expr: Field) { + super(); + } +} + +/** + * @beta + * Creates an aggregation that counts the number of stage inputs where the provided + * boolean expression evaluates to true. + * + * ```typescript + * // Count the number of documents where 'is_active' field equals true + * countIf(field("is_active").equal(true)).as("numActiveDocuments"); + * ``` + * + * @param booleanExpr - The boolean expression to evaluate on each input. + * @returns A new `AggregateFunction` representing the 'countIf' aggregation. + */ +export function countIf(booleanExpr: BooleanExpression): AggregateFunction { + return booleanExpr.countIf(); +} + +/** + * @beta + * Creates an expression that indexes into an array from the beginning or end + * and return the element. If the offset exceeds the array length, an error is + * returned. A negative offset, starts from the end. + * + * ```typescript + * // Return the value in the tags field array at index 1. + * arrayGet('tags', 1); + * ``` + * + * @param arrayField The name of the array field. + * @param offset The index of the element to return. + * @return A new Expr representing the 'arrayGet' operation. + */ +export function arrayGet( + arrayField: string, + offset: number +): FunctionExpression; + +/** + * @beta + * Creates an expression that indexes into an array from the beginning or end + * and return the element. If the offset exceeds the array length, an error is + * returned. A negative offset, starts from the end. + * + * ```typescript + * // Return the value in the tags field array at index specified by field + * // 'favoriteTag'. + * arrayGet('tags', field('favoriteTag')); + * ``` + * + * @param arrayField The name of the array field. + * @param offsetExpr An Expr evaluating to the index of the element to return. + * @return A new Expr representing the 'arrayGet' operation. + */ +export function arrayGet( + arrayField: string, + offsetExpr: Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that indexes into an array from the beginning or end + * and return the element. If the offset exceeds the array length, an error is + * returned. A negative offset, starts from the end. + * + * ```typescript + * // Return the value in the tags field array at index 1. + * arrayGet(field('tags'), 1); + * ``` + * + * @param arrayExpression An Expr evaluating to an array. + * @param offset The index of the element to return. + * @return A new Expr representing the 'arrayGet' operation. + */ +export function arrayGet( + arrayExpression: Expression, + offset: number +): FunctionExpression; + +/** + * @beta + * Creates an expression that indexes into an array from the beginning or end + * and return the element. If the offset exceeds the array length, an error is + * returned. A negative offset, starts from the end. + * + * ```typescript + * // Return the value in the tags field array at index specified by field + * // 'favoriteTag'. + * arrayGet(field('tags'), field('favoriteTag')); + * ``` + * + * @param arrayExpression An Expr evaluating to an array. + * @param offsetExpr An Expr evaluating to the index of the element to return. + * @return A new Expr representing the 'arrayGet' operation. + */ +export function arrayGet( + arrayExpression: Expression, + offsetExpr: Expression +): FunctionExpression; +export function arrayGet( + array: Expression | string, + offset: Expression | number +): FunctionExpression { + return fieldOrExpression(array).arrayGet(valueToDefaultExpr(offset)); +} + +/** + * @beta + * + * Creates an expression that checks if a given expression produces an error. + * + * ```typescript + * // Check if the result of a calculation is an error + * isError(field("title").arrayContains(1)); + * ``` + * + * @param value The expression to check. + * @return A new {@code Expr} representing the 'isError' check. + */ +export function isError(value: Expression): BooleanExpression { + return value.isError().asBoolean(); +} + +/** + * @beta + * + * Creates an expression that returns the `catch` argument if there is an + * error, else return the result of the `try` argument evaluation. + * + * This overload is useful when a BooleanExpression is required. + * + * ```typescript + * // Create an expression that protects against a divide by zero error + * // but always returns a boolean expression. + * ifError(constant(50).divide('length').gt(1), constant(false)); + * ``` + * + * @param tryExpr The try expression. + * @param catchExpr The catch expression that will be evaluated and + * returned if the tryExpr produces an error. + * @return A new {@code Expr} representing the 'ifError' operation. + */ +export function ifError( + tryExpr: BooleanExpression, + catchExpr: BooleanExpression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that returns the `catch` argument if there is an + * error, else return the result of the `try` argument evaluation. + * + * ```typescript + * // Returns the first item in the title field arrays, or returns + * // the entire title field if the array is empty or the field is another type. + * ifError(field("title").arrayGet(0), field("title")); + * ``` + * + * @param tryExpr The try expression. + * @param catchExpr The catch expression that will be evaluated and + * returned if the tryExpr produces an error. + * @return A new {@code Expr} representing the 'ifError' operation. + */ +export function ifError( + tryExpr: Expression, + catchExpr: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the `catch` argument if there is an + * error, else return the result of the `try` argument evaluation. + * + * ```typescript + * // Returns the first item in the title field arrays, or returns + * // "Default Title" + * ifError(field("title").arrayGet(0), "Default Title"); + * ``` + * + * @param tryExpr The try expression. + * @param catchValue The value that will be returned if the tryExpr produces an + * error. + * @return A new {@code Expr} representing the 'ifError' operation. + */ +export function ifError( + tryExpr: Expression, + catchValue: unknown +): FunctionExpression; + +export function ifError( + tryExpr: Expression, + catchValue: unknown +): FunctionExpression | BooleanExpression { + if ( + tryExpr instanceof BooleanExpression && + catchValue instanceof BooleanExpression + ) { + return tryExpr.ifError(catchValue).asBoolean(); + } else { + return tryExpr.ifError(valueToDefaultExpr(catchValue)); + } +} + +/** + * @beta + * + * Creates an expression that returns `true` if a value is absent. Otherwise, + * returns `false` even if the value is `null`. + * + * ```typescript + * // Check if the field `value` is absent. + * isAbsent(field("value")); + * ``` + * + * @param value The expression to check. + * @return A new {@code Expr} representing the 'isAbsent' check. + */ +export function isAbsent(value: Expression): BooleanExpression; + +/** + * @beta + * + * Creates an expression that returns `true` if a field is absent. Otherwise, + * returns `false` even if the field value is `null`. + * + * ```typescript + * // Check if the field `value` is absent. + * isAbsent("value"); + * ``` + * + * @param field The field to check. + * @return A new {@code Expr} representing the 'isAbsent' check. + */ +export function isAbsent(field: string): BooleanExpression; +export function isAbsent(value: Expression | string): BooleanExpression { + return fieldOrExpression(value).isAbsent(); +} + +/** + * @beta + * + * Creates an expression that removes a key from the map at the specified field name. + * + * ``` + * // Removes the key 'city' field from the map in the address field of the input document. + * mapRemove('address', 'city'); + * ``` + * + * @param mapField The name of a field containing a map value. + * @param key The name of the key to remove from the input map. + */ +export function mapRemove(mapField: string, key: string): FunctionExpression; +/** + * @beta + * + * Creates an expression that removes a key from the map produced by evaluating an expression. + * + * ``` + * // Removes the key 'baz' from the input map. + * mapRemove(map({foo: 'bar', baz: true}), 'baz'); + * ``` + * + * @param mapExpr An expression return a map value. + * @param key The name of the key to remove from the input map. + */ +export function mapRemove(mapExpr: Expression, key: string): FunctionExpression; +/** + * @beta + * + * Creates an expression that removes a key from the map at the specified field name. + * + * ``` + * // Removes the key 'city' field from the map in the address field of the input document. + * mapRemove('address', constant('city')); + * ``` + * + * @param mapField The name of a field containing a map value. + * @param keyExpr An expression that produces the name of the key to remove from the input map. + */ +export function mapRemove( + mapField: string, + keyExpr: Expression +): FunctionExpression; +/** + * @beta + * + * Creates an expression that removes a key from the map produced by evaluating an expression. + * + * ``` + * // Removes the key 'baz' from the input map. + * mapRemove(map({foo: 'bar', baz: true}), constant('baz')); + * ``` + * + * @param mapExpr An expression return a map value. + * @param keyExpr An expression that produces the name of the key to remove from the input map. + */ +export function mapRemove( + mapExpr: Expression, + keyExpr: Expression +): FunctionExpression; + +export function mapRemove( + mapExpr: Expression | string, + stringExpr: Expression | string +): FunctionExpression { + return fieldOrExpression(mapExpr).mapRemove(valueToDefaultExpr(stringExpr)); +} + +/** + * @beta + * + * Creates an expression that merges multiple map values. + * + * ``` + * // Merges the map in the settings field with, a map literal, and a map in + * // that is conditionally returned by another expression + * mapMerge('settings', { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) + * ``` + * + * @param mapField Name of a field containing a map value that will be merged. + * @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. + */ +export function mapMerge( + mapField: string, + secondMap: Record | Expression, + ...otherMaps: Array | Expression> +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that merges multiple map values. + * + * ``` + * // Merges the map in the settings field with, a map literal, and a map in + * // that is conditionally returned by another expression + * mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) + * ``` + * + * @param firstMap An expression or literal map value that will be merged. + * @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. + */ +export function mapMerge( + firstMap: Record | Expression, + secondMap: Record | Expression, + ...otherMaps: Array | Expression> +): FunctionExpression; + +export function mapMerge( + firstMap: string | Record | Expression, + secondMap: Record | Expression, + ...otherMaps: Array | Expression> +): FunctionExpression { + const secondMapExpr = valueToDefaultExpr(secondMap); + const otherMapExprs = otherMaps.map(valueToDefaultExpr); + return fieldOrExpression(firstMap).mapMerge(secondMapExpr, ...otherMapExprs); +} + +/** + * @beta + * + * Creates an expression that returns the document ID from a path. + * + * ```typescript + * // Get the document ID from a path. + * documentId(myDocumentReference); + * ``` + * + * @return A new {@code Expr} representing the documentId operation. + */ +export function documentId( + documentPath: string | DocumentReference +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the document ID from a path. + * + * ```typescript + * // Get the document ID from a path. + * documentId(field("__path__")); + * ``` + * + * @return A new {@code Expr} representing the documentId operation. + */ +export function documentId(documentPathExpr: Expression): FunctionExpression; + +export function documentId( + documentPath: Expression | string | DocumentReference +): FunctionExpression { + // @ts-ignore + const documentPathExpr = valueToDefaultExpr(documentPath); + return documentPathExpr.documentId(); +} + +/** + * @beta + * + * Creates an expression that returns a substring of a string or byte array. + * + * @param field The name of a field containing a string or byte array to compute the substring from. + * @param position Index of the first character of the substring. + * @param length Length of the substring. + */ +export function substring( + field: string, + position: number, + length?: number +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns a substring of a string or byte array. + * + * @param input An expression returning a string or byte array to compute the substring from. + * @param position Index of the first character of the substring. + * @param length Length of the substring. + */ +export function substring( + input: Expression, + position: number, + length?: number +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns a substring of a string or byte array. + * + * @param field The name of a field containing a string or byte array to compute the substring from. + * @param position An expression that returns the index of the first character of the substring. + * @param length An expression that returns the length of the substring. + */ +export function substring( + field: string, + position: Expression, + length?: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns a substring of a string or byte array. + * + * @param input An expression returning a string or byte array to compute the substring from. + * @param position An expression that returns the index of the first character of the substring. + * @param length An expression that returns the length of the substring. + */ +export function substring( + input: Expression, + position: Expression, + length?: Expression +): FunctionExpression; + +export function substring( + field: Expression | string, + position: Expression | number, + length?: Expression | number +): FunctionExpression { + const fieldExpr = fieldOrExpression(field); + const positionExpr = valueToDefaultExpr(position); + const lengthExpr = + length === undefined ? undefined : valueToDefaultExpr(length); + return fieldExpr.substring(positionExpr, lengthExpr); +} + +/** + * @beta + * + * Creates an expression that adds two expressions together. + * + * ```typescript + * // Add the value of the 'quantity' field and the 'reserve' field. + * add(field("quantity"), field("reserve")); + * ``` + * + * @param first The first expression to add. + * @param second The second expression or literal to add. + * @param others Optional other expressions or literals to add. + * @return A new {@code Expr} representing the addition operation. + */ +export function add( + first: Expression, + second: Expression | unknown +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that adds a field's value to an expression. + * + * ```typescript + * // Add the value of the 'quantity' field and the 'reserve' field. + * add("quantity", field("reserve")); + * ``` + * + * @param fieldName The name of the field containing the value to add. + * @param second The second expression or literal to add. + * @param others Optional other expressions or literals to add. + * @return A new {@code Expr} representing the addition operation. + */ +export function add( + fieldName: string, + second: Expression | unknown +): FunctionExpression; + +export function add( + first: Expression | string, + second: Expression | unknown +): FunctionExpression { + return fieldOrExpression(first).add(valueToDefaultExpr(second)); +} + +/** + * @beta + * + * Creates an expression that subtracts two expressions. + * + * ```typescript + * // Subtract the 'discount' field from the 'price' field + * subtract(field("price"), field("discount")); + * ``` + * + * @param left The expression to subtract from. + * @param right The expression to subtract. + * @return A new {@code Expr} representing the subtraction operation. + */ +export function subtract( + left: Expression, + right: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that subtracts a constant value from an expression. + * + * ```typescript + * // Subtract the constant value 2 from the 'value' field + * subtract(field("value"), 2); + * ``` + * + * @param expression The expression to subtract from. + * @param value The constant value to subtract. + * @return A new {@code Expr} representing the subtraction operation. + */ +export function subtract( + expression: Expression, + value: unknown +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that subtracts an expression from a field's value. + * + * ```typescript + * // Subtract the 'discount' field from the 'price' field + * subtract("price", field("discount")); + * ``` + * + * @param fieldName The field name to subtract from. + * @param expression The expression to subtract. + * @return A new {@code Expr} representing the subtraction operation. + */ +export function subtract( + fieldName: string, + expression: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that subtracts a constant value from a field's value. + * + * ```typescript + * // Subtract 20 from the value of the 'total' field + * subtract("total", 20); + * ``` + * + * @param fieldName The field name to subtract from. + * @param value The constant value to subtract. + * @return A new {@code Expr} representing the subtraction operation. + */ +export function subtract(fieldName: string, value: unknown): FunctionExpression; +export function subtract( + left: Expression | string, + right: Expression | unknown +): FunctionExpression { + const normalizedLeft = typeof left === 'string' ? field(left) : left; + const normalizedRight = valueToDefaultExpr(right); + return normalizedLeft.subtract(normalizedRight); +} + +/** + * @beta + * + * Creates an expression that multiplies two expressions together. + * + * ```typescript + * // Multiply the 'quantity' field by the 'price' field + * multiply(field("quantity"), field("price")); + * ``` + * + * @param first The first expression to multiply. + * @param second The second expression or literal to multiply. + * @param others Optional additional expressions or literals to multiply. + * @return A new {@code Expr} representing the multiplication operation. + */ +export function multiply( + first: Expression, + second: Expression | unknown +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that multiplies a field's value by an expression. + * + * ```typescript + * // Multiply the 'quantity' field by the 'price' field + * multiply("quantity", field("price")); + * ``` + * + * @param fieldName The name of the field containing the value to add. + * @param second The second expression or literal to add. + * @param others Optional other expressions or literals to add. + * @return A new {@code Expr} representing the multiplication operation. + */ +export function multiply( + fieldName: string, + second: Expression | unknown +): FunctionExpression; + +export function multiply( + first: Expression | string, + second: Expression | unknown +): FunctionExpression { + return fieldOrExpression(first).multiply(valueToDefaultExpr(second)); +} + +/** + * @beta + * + * Creates an expression that divides two expressions. + * + * ```typescript + * // Divide the 'total' field by the 'count' field + * divide(field("total"), field("count")); + * ``` + * + * @param left The expression to be divided. + * @param right The expression to divide by. + * @return A new {@code Expr} representing the division operation. + */ +export function divide(left: Expression, right: Expression): FunctionExpression; + +/** + * @beta + * + * Creates an expression that divides an expression by a constant value. + * + * ```typescript + * // Divide the 'value' field by 10 + * divide(field("value"), 10); + * ``` + * + * @param expression The expression to be divided. + * @param value The constant value to divide by. + * @return A new {@code Expr} representing the division operation. + */ +export function divide( + expression: Expression, + value: unknown +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that divides a field's value by an expression. + * + * ```typescript + * // Divide the 'total' field by the 'count' field + * divide("total", field("count")); + * ``` + * + * @param fieldName The field name to be divided. + * @param expressions The expression to divide by. + * @return A new {@code Expr} representing the division operation. + */ +export function divide( + fieldName: string, + expressions: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that divides a field's value by a constant value. + * + * ```typescript + * // Divide the 'value' field by 10 + * divide("value", 10); + * ``` + * + * @param fieldName The field name to be divided. + * @param value The constant value to divide by. + * @return A new {@code Expr} representing the division operation. + */ +export function divide(fieldName: string, value: unknown): FunctionExpression; +export function divide( + left: Expression | string, + right: Expression | unknown +): FunctionExpression { + const normalizedLeft = typeof left === 'string' ? field(left) : left; + const normalizedRight = valueToDefaultExpr(right); + return normalizedLeft.divide(normalizedRight); +} + +/** + * @beta + * + * Creates an expression that calculates the modulo (remainder) of dividing two expressions. + * + * ```typescript + * // Calculate the remainder of dividing 'field1' by 'field2'. + * mod(field("field1"), field("field2")); + * ``` + * + * @param left The dividend expression. + * @param right The divisor expression. + * @return A new {@code Expr} representing the modulo operation. + */ +export function mod(left: Expression, right: Expression): FunctionExpression; + +/** + * @beta + * + * Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. + * + * ```typescript + * // Calculate the remainder of dividing 'field1' by 5. + * mod(field("field1"), 5); + * ``` + * + * @param expression The dividend expression. + * @param value The divisor constant. + * @return A new {@code Expr} representing the modulo operation. + */ +export function mod(expression: Expression, value: unknown): FunctionExpression; + +/** + * @beta + * + * Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. + * + * ```typescript + * // Calculate the remainder of dividing 'field1' by 'field2'. + * mod("field1", field("field2")); + * ``` + * + * @param fieldName The dividend field name. + * @param expression The divisor expression. + * @return A new {@code Expr} representing the modulo operation. + */ +export function mod( + fieldName: string, + expression: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. + * + * ```typescript + * // Calculate the remainder of dividing 'field1' by 5. + * mod("field1", 5); + * ``` + * + * @param fieldName The dividend field name. + * @param value The divisor constant. + * @return A new {@code Expr} representing the modulo operation. + */ +export function mod(fieldName: string, value: unknown): FunctionExpression; +export function mod( + left: Expression | string, + right: Expression | unknown +): FunctionExpression { + const normalizedLeft = typeof left === 'string' ? field(left) : left; + const normalizedRight = valueToDefaultExpr(right); + return normalizedLeft.mod(normalizedRight); +} + +/** + * @beta + * + * Creates an expression that creates a Firestore map value from an input object. + * + * ```typescript + * // Create a map from the input object and reference the 'baz' field value from the input document. + * map({foo: 'bar', baz: Field.of('baz')}).as('data'); + * ``` + * + * @param elements The input map to evaluate in the expression. + * @return A new {@code Expr} representing the map function. + */ +export function map(elements: Record): FunctionExpression { + return _map(elements, 'map'); +} +export function _map( + elements: Record, + methodName: string | undefined +): FunctionExpression { + const result: Expression[] = []; + for (const key in elements) { + if (Object.prototype.hasOwnProperty.call(elements, key)) { + const value = elements[key]; + result.push(constant(key)); + result.push(valueToDefaultExpr(value)); + } + } + return new FunctionExpression('map', result, 'map'); +} + +/** + * Internal use only + * Converts a plainObject to a mapValue in the proto representation, + * rather than a functionValue+map that is the result of the map(...) function. + * This behaves different from constant(plainObject) because it + * traverses the input object, converts values in the object to expressions, + * and calls _readUserData on each of these expressions. + * @private + * @internal + * @param plainObject + */ +export function _mapValue(plainObject: Record): MapValue { + const result: Map = new Map(); + for (const key in plainObject) { + if (Object.prototype.hasOwnProperty.call(plainObject, key)) { + const value = plainObject[key]; + result.set(key, valueToDefaultExpr(value)); + } + } + return new MapValue(result, undefined); +} + +/** + * @beta + * + * Creates an expression that creates a Firestore array value from an input array. + * + * ```typescript + * // Create an array value from the input array and reference the 'baz' field value from the input document. + * array(['bar', Field.of('baz')]).as('foo'); + * ``` + * + * @param elements The input array to evaluate in the expression. + * @return A new {@code Expr} representing the array function. + */ +export function array(elements: unknown[]): FunctionExpression { + return _array(elements, 'array'); +} +export function _array( + elements: unknown[], + methodName: string | undefined +): FunctionExpression { + return new FunctionExpression( + 'array', + elements.map(element => valueToDefaultExpr(element)), + methodName + ); +} + +/** + * @beta + * + * Creates an expression that checks if two expressions are equal. + * + * ```typescript + * // Check if the 'age' field is equal to an expression + * equal(field("age"), field("minAge").add(10)); + * ``` + * + * @param left The first expression to compare. + * @param right The second expression to compare. + * @return A new `Expr` representing the equality comparison. + */ +export function equal(left: Expression, right: Expression): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if an expression is equal to a constant value. + * + * ```typescript + * // Check if the 'age' field is equal to 21 + * equal(field("age"), 21); + * ``` + * + * @param expression The expression to compare. + * @param value The constant value to compare to. + * @return A new `Expr` representing the equality comparison. + */ +export function equal( + expression: Expression, + value: unknown +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is equal to an expression. + * + * ```typescript + * // Check if the 'age' field is equal to the 'limit' field + * equal("age", field("limit")); + * ``` + * + * @param fieldName The field name to compare. + * @param expression The expression to compare to. + * @return A new `Expr` representing the equality comparison. + */ +export function equal( + fieldName: string, + expression: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is equal to a constant value. + * + * ```typescript + * // Check if the 'city' field is equal to string constant "London" + * equal("city", "London"); + * ``` + * + * @param fieldName The field name to compare. + * @param value The constant value to compare to. + * @return A new `Expr` representing the equality comparison. + */ +export function equal(fieldName: string, value: unknown): BooleanExpression; +export function equal( + left: Expression | string, + right: unknown +): BooleanExpression { + const leftExpr = left instanceof Expression ? left : field(left); + const rightExpr = valueToDefaultExpr(right); + return leftExpr.equal(rightExpr); +} + +/** + * @beta + * + * Creates an expression that checks if two expressions are not equal. + * + * ```typescript + * // Check if the 'status' field is not equal to field 'finalState' + * notEqual(field("status"), field("finalState")); + * ``` + * + * @param left The first expression to compare. + * @param right The second expression to compare. + * @return A new `Expr` representing the inequality comparison. + */ +export function notEqual( + left: Expression, + right: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if an expression is not equal to a constant value. + * + * ```typescript + * // Check if the 'status' field is not equal to "completed" + * notEqual(field("status"), "completed"); + * ``` + * + * @param expression The expression to compare. + * @param value The constant value to compare to. + * @return A new `Expr` representing the inequality comparison. + */ +export function notEqual( + expression: Expression, + value: unknown +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is not equal to an expression. + * + * ```typescript + * // Check if the 'status' field is not equal to the value of 'expectedStatus' + * notEqual("status", field("expectedStatus")); + * ``` + * + * @param fieldName The field name to compare. + * @param expression The expression to compare to. + * @return A new `Expr` representing the inequality comparison. + */ +export function notEqual( + fieldName: string, + expression: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is not equal to a constant value. + * + * ```typescript + * // Check if the 'country' field is not equal to "USA" + * notEqual("country", "USA"); + * ``` + * + * @param fieldName The field name to compare. + * @param value The constant value to compare to. + * @return A new `Expr` representing the inequality comparison. + */ +export function notEqual(fieldName: string, value: unknown): BooleanExpression; +export function notEqual( + left: Expression | string, + right: unknown +): BooleanExpression { + const leftExpr = left instanceof Expression ? left : field(left); + const rightExpr = valueToDefaultExpr(right); + return leftExpr.notEqual(rightExpr); +} + +/** + * @beta + * + * Creates an expression that checks if the first expression is less than the second expression. + * + * ```typescript + * // Check if the 'age' field is less than 30 + * lessThan(field("age"), field("limit")); + * ``` + * + * @param left The first expression to compare. + * @param right The second expression to compare. + * @return A new `Expr` representing the less than comparison. + */ +export function lessThan( + left: Expression, + right: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if an expression is less than a constant value. + * + * ```typescript + * // Check if the 'age' field is less than 30 + * lessThan(field("age"), 30); + * ``` + * + * @param expression The expression to compare. + * @param value The constant value to compare to. + * @return A new `Expr` representing the less than comparison. + */ +export function lessThan( + expression: Expression, + value: unknown +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is less than an expression. + * + * ```typescript + * // Check if the 'age' field is less than the 'limit' field + * lessThan("age", field("limit")); + * ``` + * + * @param fieldName The field name to compare. + * @param expression The expression to compare to. + * @return A new `Expr` representing the less than comparison. + */ +export function lessThan( + fieldName: string, + expression: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is less than a constant value. + * + * ```typescript + * // Check if the 'price' field is less than 50 + * lessThan("price", 50); + * ``` + * + * @param fieldName The field name to compare. + * @param value The constant value to compare to. + * @return A new `Expr` representing the less than comparison. + */ +export function lessThan(fieldName: string, value: unknown): BooleanExpression; +export function lessThan( + left: Expression | string, + right: unknown +): BooleanExpression { + const leftExpr = left instanceof Expression ? left : field(left); + const rightExpr = valueToDefaultExpr(right); + return leftExpr.lessThan(rightExpr); +} + +/** + * @beta + * + * Creates an expression that checks if the first expression is less than or equal to the second + * expression. + * + * ```typescript + * // Check if the 'quantity' field is less than or equal to 20 + * lessThan(field("quantity"), field("limit")); + * ``` + * + * @param left The first expression to compare. + * @param right The second expression to compare. + * @return A new `Expr` representing the less than or equal to comparison. + */ +export function lessThanOrEqual( + left: Expression, + right: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if an expression is less than or equal to a constant value. + * + * ```typescript + * // Check if the 'quantity' field is less than or equal to 20 + * lessThan(field("quantity"), 20); + * ``` + * + * @param expression The expression to compare. + * @param value The constant value to compare to. + * @return A new `Expr` representing the less than or equal to comparison. + */ +export function lessThanOrEqual( + expression: Expression, + value: unknown +): BooleanExpression; + +/** + * @beta + * Creates an expression that checks if a field's value is less than or equal to an expression. + * + * ```typescript + * // Check if the 'quantity' field is less than or equal to the 'limit' field + * lessThan("quantity", field("limit")); + * ``` + * + * @param fieldName The field name to compare. + * @param expression The expression to compare to. + * @return A new `Expr` representing the less than or equal to comparison. + */ +export function lessThanOrEqual( + fieldName: string, + expression: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is less than or equal to a constant value. + * + * ```typescript + * // Check if the 'score' field is less than or equal to 70 + * lessThan("score", 70); + * ``` + * + * @param fieldName The field name to compare. + * @param value The constant value to compare to. + * @return A new `Expr` representing the less than or equal to comparison. + */ +export function lessThanOrEqual( + fieldName: string, + value: unknown +): BooleanExpression; +export function lessThanOrEqual( + left: Expression | string, + right: unknown +): BooleanExpression { + const leftExpr = left instanceof Expression ? left : field(left); + const rightExpr = valueToDefaultExpr(right); + return leftExpr.lessThanOrEqual(rightExpr); +} + +/** + * @beta + * + * Creates an expression that checks if the first expression is greater than the second + * expression. + * + * ```typescript + * // Check if the 'age' field is greater than 18 + * greaterThan(field("age"), Constant(9).add(9)); + * ``` + * + * @param left The first expression to compare. + * @param right The second expression to compare. + * @return A new `Expr` representing the greater than comparison. + */ +export function greaterThan( + left: Expression, + right: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if an expression is greater than a constant value. + * + * ```typescript + * // Check if the 'age' field is greater than 18 + * greaterThan(field("age"), 18); + * ``` + * + * @param expression The expression to compare. + * @param value The constant value to compare to. + * @return A new `Expr` representing the greater than comparison. + */ +export function greaterThan( + expression: Expression, + value: unknown +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is greater than an expression. + * + * ```typescript + * // Check if the value of field 'age' is greater than the value of field 'limit' + * greaterThan("age", field("limit")); + * ``` + * + * @param fieldName The field name to compare. + * @param expression The expression to compare to. + * @return A new `Expr` representing the greater than comparison. + */ +export function greaterThan( + fieldName: string, + expression: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is greater than a constant value. + * + * ```typescript + * // Check if the 'price' field is greater than 100 + * greaterThan("price", 100); + * ``` + * + * @param fieldName The field name to compare. + * @param value The constant value to compare to. + * @return A new `Expr` representing the greater than comparison. + */ +export function greaterThan( + fieldName: string, + value: unknown +): BooleanExpression; +export function greaterThan( + left: Expression | string, + right: unknown +): BooleanExpression { + const leftExpr = left instanceof Expression ? left : field(left); + const rightExpr = valueToDefaultExpr(right); + return leftExpr.greaterThan(rightExpr); +} + +/** + * @beta + * + * Creates an expression that checks if the first expression is greater than or equal to the + * second expression. + * + * ```typescript + * // Check if the 'quantity' field is greater than or equal to the field "threshold" + * greaterThanOrEqual(field("quantity"), field("threshold")); + * ``` + * + * @param left The first expression to compare. + * @param right The second expression to compare. + * @return A new `Expr` representing the greater than or equal to comparison. + */ +export function greaterThanOrEqual( + left: Expression, + right: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if an expression is greater than or equal to a constant + * value. + * + * ```typescript + * // Check if the 'quantity' field is greater than or equal to 10 + * greaterThanOrEqual(field("quantity"), 10); + * ``` + * + * @param expression The expression to compare. + * @param value The constant value to compare to. + * @return A new `Expr` representing the greater than or equal to comparison. + */ +export function greaterThanOrEqual( + expression: Expression, + value: unknown +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is greater than or equal to an expression. + * + * ```typescript + * // Check if the value of field 'age' is greater than or equal to the value of field 'limit' + * greaterThanOrEqual("age", field("limit")); + * ``` + * + * @param fieldName The field name to compare. + * @param value The expression to compare to. + * @return A new `Expr` representing the greater than or equal to comparison. + */ +export function greaterThanOrEqual( + fieldName: string, + value: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is greater than or equal to a constant + * value. + * + * ```typescript + * // Check if the 'score' field is greater than or equal to 80 + * greaterThanOrEqual("score", 80); + * ``` + * + * @param fieldName The field name to compare. + * @param value The constant value to compare to. + * @return A new `Expr` representing the greater than or equal to comparison. + */ +export function greaterThanOrEqual( + fieldName: string, + value: unknown +): BooleanExpression; +export function greaterThanOrEqual( + left: Expression | string, + right: unknown +): BooleanExpression { + const leftExpr = left instanceof Expression ? left : field(left); + const rightExpr = valueToDefaultExpr(right); + return leftExpr.greaterThanOrEqual(rightExpr); +} + +/** + * @beta + * + * Creates an expression that concatenates an array expression with other arrays. + * + * ```typescript + * // Combine the 'items' array with two new item arrays + * arrayConcat(field("items"), [field("newItems"), field("otherItems")]); + * ``` + * + * @param firstArray The first array expression to concatenate to. + * @param secondArray The second array expression or array literal to concatenate to. + * @param otherArrays Optional additional array expressions or array literals to concatenate. + * @return A new {@code Expr} representing the concatenated array. + */ +export function arrayConcat( + firstArray: Expression, + secondArray: Expression | unknown[], + ...otherArrays: Array +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that concatenates a field's array value with other arrays. + * + * ```typescript + * // Combine the 'items' array with two new item arrays + * arrayConcat("items", [field("newItems"), field("otherItems")]); + * ``` + * + * @param firstArrayField The first array to concatenate to. + * @param secondArray The second array expression or array literal to concatenate to. + * @param otherArrays Optional additional array expressions or array literals to concatenate. + * @return A new {@code Expr} representing the concatenated array. + */ +export function arrayConcat( + firstArrayField: string, + secondArray: Expression | unknown[], + ...otherArrays: Array +): FunctionExpression; + +export function arrayConcat( + firstArray: Expression | string, + secondArray: Expression | unknown[], + ...otherArrays: Array +): FunctionExpression { + const exprValues = otherArrays.map(element => valueToDefaultExpr(element)); + return fieldOrExpression(firstArray).arrayConcat( + fieldOrExpression(secondArray), + ...exprValues + ); +} + +/** + * @beta + * + * Creates an expression that checks if an array expression contains a specific element. + * + * ```typescript + * // Check if the 'colors' array contains the value of field 'selectedColor' + * arrayContains(field("colors"), field("selectedColor")); + * ``` + * + * @param array The array expression to check. + * @param element The element to search for in the array. + * @return A new {@code Expr} representing the 'array_contains' comparison. + */ +export function arrayContains( + array: Expression, + element: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if an array expression contains a specific element. + * + * ```typescript + * // Check if the 'colors' array contains "red" + * arrayContains(field("colors"), "red"); + * ``` + * + * @param array The array expression to check. + * @param element The element to search for in the array. + * @return A new {@code Expr} representing the 'array_contains' comparison. + */ +export function arrayContains( + array: Expression, + element: unknown +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's array value contains a specific element. + * + * ```typescript + * // Check if the 'colors' array contains the value of field 'selectedColor' + * arrayContains("colors", field("selectedColor")); + * ``` + * + * @param fieldName The field name to check. + * @param element The element to search for in the array. + * @return A new {@code Expr} representing the 'array_contains' comparison. + */ +export function arrayContains( + fieldName: string, + element: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's array value contains a specific value. + * + * ```typescript + * // Check if the 'colors' array contains "red" + * arrayContains("colors", "red"); + * ``` + * + * @param fieldName The field name to check. + * @param element The element to search for in the array. + * @return A new {@code Expr} representing the 'array_contains' comparison. + */ +export function arrayContains( + fieldName: string, + element: unknown +): BooleanExpression; +export function arrayContains( + array: Expression | string, + element: unknown +): BooleanExpression { + const arrayExpr = fieldOrExpression(array); + const elementExpr = valueToDefaultExpr(element); + return arrayExpr.arrayContains(elementExpr); +} + +/** + * @beta + * + * Creates an expression that checks if an array expression contains any of the specified + * elements. + * + * ```typescript + * // Check if the 'categories' array contains either values from field "cate1" or "Science" + * arrayContainsAny(field("categories"), [field("cate1"), "Science"]); + * ``` + * + * @param array The array expression to check. + * @param values The elements to check for in the array. + * @return A new {@code Expr} representing the 'array_contains_any' comparison. + */ +export function arrayContainsAny( + array: Expression, + values: Array +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's array value contains any of the specified + * elements. + * + * ```typescript + * // Check if the 'groups' array contains either the value from the 'userGroup' field + * // or the value "guest" + * arrayContainsAny("categories", [field("cate1"), "Science"]); + * ``` + * + * @param fieldName The field name to check. + * @param values The elements to check for in the array. + * @return A new {@code Expr} representing the 'array_contains_any' comparison. + */ +export function arrayContainsAny( + fieldName: string, + values: Array +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if an array expression contains any of the specified + * elements. + * + * ```typescript + * // Check if the 'categories' array contains either values from field "cate1" or "Science" + * arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); + * ``` + * + * @param array The array expression to check. + * @param values An expression that evaluates to an array, whose elements to check for in the array. + * @return A new {@code Expr} representing the 'array_contains_any' comparison. + */ +export function arrayContainsAny( + array: Expression, + values: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's array value contains any of the specified + * elements. + * + * ```typescript + * // Check if the 'groups' array contains either the value from the 'userGroup' field + * // or the value "guest" + * arrayContainsAny("categories", array([field("cate1"), "Science"])); + * ``` + * + * @param fieldName The field name to check. + * @param values An expression that evaluates to an array, whose elements to check for in the array field. + * @return A new {@code Expr} representing the 'array_contains_any' comparison. + */ +export function arrayContainsAny( + fieldName: string, + values: Expression +): BooleanExpression; +export function arrayContainsAny( + array: Expression | string, + values: unknown[] | Expression +): BooleanExpression { + // @ts-ignore implementation accepts both types + return fieldOrExpression(array).arrayContainsAny(values); +} + +/** + * @beta + * + * Creates an expression that checks if an array expression contains all the specified elements. + * + * ```typescript + * // Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" + * arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); + * ``` + * + * @param array The array expression to check. + * @param values The elements to check for in the array. + * @return A new {@code Expr} representing the 'array_contains_all' comparison. + */ +export function arrayContainsAll( + array: Expression, + values: Array +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's array value contains all the specified values or + * expressions. + * + * ```typescript + * // Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" + * arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); + * ``` + * + * @param fieldName The field name to check. + * @param values The elements to check for in the array. + * @return A new {@code Expr} representing the 'array_contains_all' comparison. + */ +export function arrayContainsAll( + fieldName: string, + values: Array +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if an array expression contains all the specified elements. + * + * ```typescript + * // Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" + * arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); + * ``` + * + * @param array The array expression to check. + * @param arrayExpression The elements to check for in the array. + * @return A new {@code Expr} representing the 'array_contains_all' comparison. + */ +export function arrayContainsAll( + array: Expression, + arrayExpression: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's array value contains all the specified values or + * expressions. + * + * ```typescript + * // Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" + * arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); + * ``` + * + * @param fieldName The field name to check. + * @param arrayExpression The elements to check for in the array. + * @return A new {@code Expr} representing the 'array_contains_all' comparison. + */ +export function arrayContainsAll( + fieldName: string, + arrayExpression: Expression +): BooleanExpression; +export function arrayContainsAll( + array: Expression | string, + values: unknown[] | Expression +): BooleanExpression { + // @ts-ignore implementation accepts both types + return fieldOrExpression(array).arrayContainsAll(values); +} + +/** + * @beta + * + * Creates an expression that calculates the length of an array in a specified field. + * + * ```typescript + * // Get the number of items in field 'cart' + * arrayLength('cart'); + * ``` + * + * @param fieldName The name of the field containing an array to calculate the length of. + * @return A new {@code Expr} representing the length of the array. + */ +export function arrayLength(fieldName: string): FunctionExpression; + +/** + * @beta + * + * Creates an expression that calculates the length of an array expression. + * + * ```typescript + * // Get the number of items in the 'cart' array + * arrayLength(field("cart")); + * ``` + * + * @param array The array expression to calculate the length of. + * @return A new {@code Expr} representing the length of the array. + */ +export function arrayLength(array: Expression): FunctionExpression; +export function arrayLength(array: Expression | string): FunctionExpression { + return fieldOrExpression(array).arrayLength(); +} + +/** + * @beta + * + * Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or + * expressions. + * + * ```typescript + * // Check if the 'category' field is either "Electronics" or value of field 'primaryType' + * equalAny(field("category"), [constant("Electronics"), field("primaryType")]); + * ``` + * + * @param expression The expression whose results to compare. + * @param values The values to check against. + * @return A new {@code Expr} representing the 'IN' comparison. + */ +export function equalAny( + expression: Expression, + values: Array +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if an expression is equal to any of the provided values. + * + * ```typescript + * // Check if the 'category' field is set to a value in the disabledCategories field + * equalAny(field("category"), field('disabledCategories')); + * ``` + * + * @param expression The expression whose results to compare. + * @param arrayExpression An expression that evaluates to an array, whose elements to check for equality to the input. + * @return A new {@code Expr} representing the 'IN' comparison. + */ +export function equalAny( + expression: Expression, + arrayExpression: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is equal to any of the provided values or + * expressions. + * + * ```typescript + * // Check if the 'category' field is either "Electronics" or value of field 'primaryType' + * equalAny("category", [constant("Electronics"), field("primaryType")]); + * ``` + * + * @param fieldName The field to compare. + * @param values The values to check against. + * @return A new {@code Expr} representing the 'IN' comparison. + */ +export function equalAny( + fieldName: string, + values: Array +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is equal to any of the provided values or + * expressions. + * + * ```typescript + * // Check if the 'category' field is either "Electronics" or value of field 'primaryType' + * equalAny("category", ["Electronics", field("primaryType")]); + * ``` + * + * @param fieldName The field to compare. + * @param arrayExpression An expression that evaluates to an array, whose elements to check for equality to the input field. + * @return A new {@code Expr} representing the 'IN' comparison. + */ +export function equalAny( + fieldName: string, + arrayExpression: Expression +): BooleanExpression; +export function equalAny( + element: Expression | string, + values: unknown[] | Expression +): BooleanExpression { + // @ts-ignore implementation accepts both types + return fieldOrExpression(element).equalAny(values); +} + +/** + * @beta + * + * Creates an expression that checks if an expression is not equal to any of the provided values + * or expressions. + * + * ```typescript + * // Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' + * notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + * ``` + * + * @param element The expression to compare. + * @param values The values to check against. + * @return A new {@code Expr} representing the 'NOT IN' comparison. + */ +export function notEqualAny( + element: Expression, + values: Array +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is not equal to any of the provided values + * or expressions. + * + * ```typescript + * // Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' + * notEqualAny("status", [constant("pending"), field("rejectedStatus")]); + * ``` + * + * @param fieldName The field name to compare. + * @param values The values to check against. + * @return A new {@code Expr} representing the 'NOT IN' comparison. + */ +export function notEqualAny( + fieldName: string, + values: Array +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if an expression is not equal to any of the provided values + * or expressions. + * + * ```typescript + * // Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' + * notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + * ``` + * + * @param element The expression to compare. + * @param arrayExpression The values to check against. + * @return A new {@code Expr} representing the 'NOT IN' comparison. + */ +export function notEqualAny( + element: Expression, + arrayExpression: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. + * + * ```typescript + * // Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' + * notEqualAny("status", field("rejectedStatuses")); + * ``` + * + * @param fieldName The field name to compare. + * @param arrayExpression The values to check against. + * @return A new {@code Expr} representing the 'NOT IN' comparison. + */ +export function notEqualAny( + fieldName: string, + arrayExpression: Expression +): BooleanExpression; + +export function notEqualAny( + element: Expression | string, + values: unknown[] | Expression +): BooleanExpression { + // @ts-ignore implementation accepts both types + return fieldOrExpression(element).notEqualAny(values); +} + +/** + * @beta + * + * Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. + * + * ```typescript + * // Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London", + * // or 'status' is "active". + * const condition = xor( + * greaterThan("age", 18), + * equal("city", "London"), + * equal("status", "active")); + * ``` + * + * @param first The first condition. + * @param second The second condition. + * @param additionalConditions Additional conditions to 'XOR' together. + * @return A new {@code Expr} representing the logical 'XOR' operation. + */ +export function xor( + first: BooleanExpression, + second: BooleanExpression, + ...additionalConditions: BooleanExpression[] +): BooleanExpression { + return new FunctionExpression( + 'xor', + [first, second, ...additionalConditions], + 'xor' + ).asBoolean(); +} + +/** + * @beta + * + * Creates a conditional expression that evaluates to a 'then' expression if a condition is true + * and an 'else' expression if the condition is false. + * + * ```typescript + * // If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". + * conditional( + * greaterThan("age", 18), constant("Adult"), constant("Minor")); + * ``` + * + * @param condition The condition to evaluate. + * @param thenExpr The expression to evaluate if the condition is true. + * @param elseExpr The expression to evaluate if the condition is false. + * @return A new {@code Expr} representing the conditional expression. + */ +export function conditional( + condition: BooleanExpression, + thenExpr: Expression, + elseExpr: Expression +): FunctionExpression { + return new FunctionExpression( + 'conditional', + [condition, thenExpr, elseExpr], + 'conditional' + ); +} + +/** + * @beta + * + * Creates an expression that negates a filter condition. + * + * ```typescript + * // Find documents where the 'completed' field is NOT true + * not(equal("completed", true)); + * ``` + * + * @param booleanExpr The filter condition to negate. + * @return A new {@code Expr} representing the negated filter condition. + */ +export function not(booleanExpr: BooleanExpression): BooleanExpression { + return booleanExpr.not(); +} + +/** + * @beta + * + * Creates an expression that returns the largest value between multiple input + * expressions or literal values. Based on Firestore's value type ordering. + * + * ```typescript + * // Returns the largest value between the 'field1' field, the 'field2' field, + * // and 1000 + * logicalMaximum(field("field1"), field("field2"), 1000); + * ``` + * + * @param first The first operand expression. + * @param second The second expression or literal. + * @param others Optional additional expressions or literals. + * @return A new {@code Expr} representing the logical maximum operation. + */ +export function logicalMaximum( + first: Expression, + second: Expression | unknown, + ...others: Array +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the largest value between multiple input + * expressions or literal values. Based on Firestore's value type ordering. + * + * ```typescript + * // Returns the largest value between the 'field1' field, the 'field2' field, + * // and 1000. + * logicalMaximum("field1", field("field2"), 1000); + * ``` + * + * @param fieldName The first operand field name. + * @param second The second expression or literal. + * @param others Optional additional expressions or literals. + * @return A new {@code Expr} representing the logical maximum operation. + */ +export function logicalMaximum( + fieldName: string, + second: Expression | unknown, + ...others: Array +): FunctionExpression; + +export function logicalMaximum( + first: Expression | string, + second: Expression | unknown, + ...others: Array +): FunctionExpression { + return fieldOrExpression(first).logicalMaximum( + valueToDefaultExpr(second), + ...others.map(value => valueToDefaultExpr(value)) + ); +} + +/** + * @beta + * + * Creates an expression that returns the smallest value between multiple input + * expressions and literal values. Based on Firestore's value type ordering. + * + * ```typescript + * // Returns the smallest value between the 'field1' field, the 'field2' field, + * // and 1000. + * logicalMinimum(field("field1"), field("field2"), 1000); + * ``` + * + * @param first The first operand expression. + * @param second The second expression or literal. + * @param others Optional additional expressions or literals. + * @return A new {@code Expr} representing the logical minimum operation. + */ +export function logicalMinimum( + first: Expression, + second: Expression | unknown, + ...others: Array +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the smallest value between a field's value + * and other input expressions or literal values. + * Based on Firestore's value type ordering. + * + * ```typescript + * // Returns the smallest value between the 'field1' field, the 'field2' field, + * // and 1000. + * logicalMinimum("field1", field("field2"), 1000); + * ``` + * + * @param fieldName The first operand field name. + * @param second The second expression or literal. + * @param others Optional additional expressions or literals. + * @return A new {@code Expr} representing the logical minimum operation. + */ +export function logicalMinimum( + fieldName: string, + second: Expression | unknown, + ...others: Array +): FunctionExpression; + +export function logicalMinimum( + first: Expression | string, + second: Expression | unknown, + ...others: Array +): FunctionExpression { + return fieldOrExpression(first).logicalMinimum( + valueToDefaultExpr(second), + ...others.map(value => valueToDefaultExpr(value)) + ); +} + +/** + * @beta + * + * Creates an expression that checks if a field exists. + * + * ```typescript + * // Check if the document has a field named "phoneNumber" + * exists(field("phoneNumber")); + * ``` + * + * @param value An expression evaluates to the name of the field to check. + * @return A new {@code Expr} representing the 'exists' check. + */ +export function exists(value: Expression): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field exists. + * + * ```typescript + * // Check if the document has a field named "phoneNumber" + * exists("phoneNumber"); + * ``` + * + * @param fieldName The field name to check. + * @return A new {@code Expr} representing the 'exists' check. + */ +export function exists(fieldName: string): BooleanExpression; +export function exists(valueOrField: Expression | string): BooleanExpression { + return fieldOrExpression(valueOrField).exists(); +} + +/** + * @beta + * + * Creates an expression that reverses a string. + * + * ```typescript + * // Reverse the value of the 'myString' field. + * reverse(field("myString")); + * ``` + * + * @param stringExpression An expression evaluating to a string value, which will be reversed. + * @return A new {@code Expr} representing the reversed string. + */ +export function reverse(stringExpression: Expression): FunctionExpression; + +/** + * @beta + * + * Creates an expression that reverses a string value in the specified field. + * + * ```typescript + * // Reverse the value of the 'myString' field. + * reverse("myString"); + * ``` + * + * @param field The name of the field representing the string to reverse. + * @return A new {@code Expr} representing the reversed string. + */ +export function reverse(field: string): FunctionExpression; +export function reverse(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).reverse(); +} + +/** + * @beta + * + * Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. + * + * ```typescript + * // Calculate the length of the 'myString' field in bytes. + * byteLength(field("myString")); + * ``` + * + * @param expr The expression representing the string. + * @return A new {@code Expr} representing the length of the string in bytes. + */ +export function byteLength(expr: Expression): FunctionExpression; + +/** + * @beta + * + * Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. + * + * ```typescript + * // Calculate the length of the 'myString' field in bytes. + * byteLength("myString"); + * ``` + * + * @param fieldName The name of the field containing the string. + * @return A new {@code Expr} representing the length of the string in bytes. + */ +export function byteLength(fieldName: string): FunctionExpression; +export function byteLength(expr: Expression | string): FunctionExpression { + const normalizedExpr = fieldOrExpression(expr); + return normalizedExpr.byteLength(); +} + +/** + * @beta + * Creates an expression that reverses an array. + * + * ```typescript + * // Reverse the value of the 'myArray' field. + * arrayReverse("myArray"); + * ``` + * + * @param fieldName The name of the field to reverse. + * @return A new {@code Expr} representing the reversed array. + */ +export function arrayReverse(fieldName: string): FunctionExpression; + +/** + * @beta + * Creates an expression that reverses an array. + * + * ```typescript + * // Reverse the value of the 'myArray' field. + * arrayReverse(field("myArray")); + * ``` + * + * @param arrayExpression An expression evaluating to an array value, which will be reversed. + * @return A new {@code Expr} representing the reversed array. + */ +export function arrayReverse(arrayExpression: Expression): FunctionExpression; +export function arrayReverse(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).arrayReverse(); +} + +/** + * @beta + * Creates an expression that computes e to the power of the expression's result. + * + * ```typescript + * // Compute e to the power of 2. + * exp(constant(2)); + * ``` + * + * @return A new {@code Expr} representing the exp of the numeric value. + */ +export function exp(expression: Expression): FunctionExpression; + +/** + * @beta + * Creates an expression that computes e to the power of the expression's result. + * + * ```typescript + * // Compute e to the power of the 'value' field. + * exp('value'); + * ``` + * + * @return A new {@code Expr} representing the exp of the numeric value. + */ +export function exp(fieldName: string): FunctionExpression; + +export function exp( + expressionOrFieldName: Expression | string +): FunctionExpression { + return fieldOrExpression(expressionOrFieldName).exp(); +} + +/** + * @beta + * Creates an expression that computes the ceiling of a numeric value. + * + * ```typescript + * // Compute the ceiling of the 'price' field. + * ceil("price"); + * ``` + * + * @param fieldName The name of the field to compute the ceiling of. + * @return A new {@code Expr} representing the ceiling of the numeric value. + */ +export function ceil(fieldName: string): FunctionExpression; + +/** + * @beta + * Creates an expression that computes the ceiling of a numeric value. + * + * ```typescript + * // Compute the ceiling of the 'price' field. + * ceil(field("price")); + * ``` + * + * @param expression An expression evaluating to a numeric value, which the ceiling will be computed for. + * @return A new {@code Expr} representing the ceiling of the numeric value. + */ +export function ceil(expression: Expression): FunctionExpression; +export function ceil(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).ceil(); +} + +/** + * @beta + * Creates an expression that computes the floor of a numeric value. + * + * @param expr The expression to compute the floor of. + * @return A new {@code Expr} representing the floor of the numeric value. + */ +export function floor(expr: Expression): FunctionExpression; + +/** + * @beta + * Creates an expression that computes the floor of a numeric value. + * + * @param fieldName The name of the field to compute the floor of. + * @return A new {@code Expr} representing the floor of the numeric value. + */ +export function floor(fieldName: string): FunctionExpression; +export function floor(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).floor(); +} + +/** + * @beta + * Creates an aggregation that counts the number of distinct values of a field. + * + * @param expr The expression or field to count distinct values of. + * @return A new `AggregateFunction` representing the 'count_distinct' aggregation. + */ +export function countDistinct(expr: Expression | string): AggregateFunction { + return fieldOrExpression(expr).countDistinct(); +} + +/** + * @beta + * + * Creates an expression that calculates the character length of a string field in UTF8. + * + * ```typescript + * // Get the character length of the 'name' field in UTF-8. + * strLength("name"); + * ``` + * + * @param fieldName The name of the field containing the string. + * @return A new {@code Expr} representing the length of the string. + */ +export function charLength(fieldName: string): FunctionExpression; + +/** + * @beta + * + * Creates an expression that calculates the character length of a string expression in UTF-8. + * + * ```typescript + * // Get the character length of the 'name' field in UTF-8. + * strLength(field("name")); + * ``` + * + * @param stringExpression The expression representing the string to calculate the length of. + * @return A new {@code Expr} representing the length of the string. + */ +export function charLength(stringExpression: Expression): FunctionExpression; +export function charLength(value: Expression | string): FunctionExpression { + const valueExpr = fieldOrExpression(value); + return valueExpr.charLength(); +} + +/** + * @beta + * + * Creates an expression that performs a case-sensitive wildcard string comparison against a + * field. + * + * ```typescript + * // Check if the 'title' field contains the string "guide" + * like("title", "%guide%"); + * ``` + * + * @param fieldName The name of the field containing the string. + * @param pattern The pattern to search for. You can use "%" as a wildcard character. + * @return A new {@code Expr} representing the 'like' comparison. + */ +export function like(fieldName: string, pattern: string): BooleanExpression; + +/** + * @beta + * + * Creates an expression that performs a case-sensitive wildcard string comparison against a + * field. + * + * ```typescript + * // Check if the 'title' field contains the string "guide" + * like("title", field("pattern")); + * ``` + * + * @param fieldName The name of the field containing the string. + * @param pattern The pattern to search for. You can use "%" as a wildcard character. + * @return A new {@code Expr} representing the 'like' comparison. + */ +export function like(fieldName: string, pattern: Expression): BooleanExpression; + +/** + * @beta + * + * Creates an expression that performs a case-sensitive wildcard string comparison. + * + * ```typescript + * // Check if the 'title' field contains the string "guide" + * like(field("title"), "%guide%"); + * ``` + * + * @param stringExpression The expression representing the string to perform the comparison on. + * @param pattern The pattern to search for. You can use "%" as a wildcard character. + * @return A new {@code Expr} representing the 'like' comparison. + */ +export function like( + stringExpression: Expression, + pattern: string +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that performs a case-sensitive wildcard string comparison. + * + * ```typescript + * // Check if the 'title' field contains the string "guide" + * like(field("title"), field("pattern")); + * ``` + * + * @param stringExpression The expression representing the string to perform the comparison on. + * @param pattern The pattern to search for. You can use "%" as a wildcard character. + * @return A new {@code Expr} representing the 'like' comparison. + */ +export function like( + stringExpression: Expression, + pattern: Expression +): BooleanExpression; +export function like( + left: Expression | string, + pattern: Expression | string +): BooleanExpression { + const leftExpr = fieldOrExpression(left); + const patternExpr = valueToDefaultExpr(pattern); + return leftExpr.like(patternExpr); +} + +/** + * @beta + * + * Creates an expression that checks if a string field contains a specified regular expression as + * a substring. + * + * ```typescript + * // Check if the 'description' field contains "example" (case-insensitive) + * regexContains("description", "(?i)example"); + * ``` + * + * @param fieldName The name of the field containing the string. + * @param pattern The regular expression to use for the search. + * @return A new {@code Expr} representing the 'contains' comparison. + */ +export function regexContains( + fieldName: string, + pattern: string +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string field contains a specified regular expression as + * a substring. + * + * ```typescript + * // Check if the 'description' field contains "example" (case-insensitive) + * regexContains("description", field("pattern")); + * ``` + * + * @param fieldName The name of the field containing the string. + * @param pattern The regular expression to use for the search. + * @return A new {@code Expr} representing the 'contains' comparison. + */ +export function regexContains( + fieldName: string, + pattern: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string expression contains a specified regular + * expression as a substring. + * + * ```typescript + * // Check if the 'description' field contains "example" (case-insensitive) + * regexContains(field("description"), "(?i)example"); + * ``` + * + * @param stringExpression The expression representing the string to perform the comparison on. + * @param pattern The regular expression to use for the search. + * @return A new {@code Expr} representing the 'contains' comparison. + */ +export function regexContains( + stringExpression: Expression, + pattern: string +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string expression contains a specified regular + * expression as a substring. + * + * ```typescript + * // Check if the 'description' field contains "example" (case-insensitive) + * regexContains(field("description"), field("pattern")); + * ``` + * + * @param stringExpression The expression representing the string to perform the comparison on. + * @param pattern The regular expression to use for the search. + * @return A new {@code Expr} representing the 'contains' comparison. + */ +export function regexContains( + stringExpression: Expression, + pattern: Expression +): BooleanExpression; +export function regexContains( + left: Expression | string, + pattern: Expression | string +): BooleanExpression { + const leftExpr = fieldOrExpression(left); + const patternExpr = valueToDefaultExpr(pattern); + return leftExpr.regexContains(patternExpr); +} + +/** + * @beta + * + * Creates an expression that checks if a string field matches a specified regular expression. + * + * ```typescript + * // Check if the 'email' field matches a valid email pattern + * regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + * ``` + * + * @param fieldName The name of the field containing the string. + * @param pattern The regular expression to use for the match. + * @return A new {@code Expr} representing the regular expression match. + */ +export function regexMatch( + fieldName: string, + pattern: string +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string field matches a specified regular expression. + * + * ```typescript + * // Check if the 'email' field matches a valid email pattern + * regexMatch("email", field("pattern")); + * ``` + * + * @param fieldName The name of the field containing the string. + * @param pattern The regular expression to use for the match. + * @return A new {@code Expr} representing the regular expression match. + */ +export function regexMatch( + fieldName: string, + pattern: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string expression matches a specified regular + * expression. + * + * ```typescript + * // Check if the 'email' field matches a valid email pattern + * regexMatch(field("email"), "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); + * ``` + * + * @param stringExpression The expression representing the string to match against. + * @param pattern The regular expression to use for the match. + * @return A new {@code Expr} representing the regular expression match. + */ +export function regexMatch( + stringExpression: Expression, + pattern: string +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string expression matches a specified regular + * expression. + * + * ```typescript + * // Check if the 'email' field matches a valid email pattern + * regexMatch(field("email"), field("pattern")); + * ``` + * + * @param stringExpression The expression representing the string to match against. + * @param pattern The regular expression to use for the match. + * @return A new {@code Expr} representing the regular expression match. + */ +export function regexMatch( + stringExpression: Expression, + pattern: Expression +): BooleanExpression; +export function regexMatch( + left: Expression | string, + pattern: Expression | string +): BooleanExpression { + const leftExpr = fieldOrExpression(left); + const patternExpr = valueToDefaultExpr(pattern); + return leftExpr.regexMatch(patternExpr); +} + +/** + * @beta + * + * Creates an expression that checks if a string field contains a specified substring. + * + * ```typescript + * // Check if the 'description' field contains "example". + * stringContains("description", "example"); + * ``` + * + * @param fieldName The name of the field containing the string. + * @param substring The substring to search for. + * @return A new {@code Expr} representing the 'contains' comparison. + */ +export function stringContains( + fieldName: string, + substring: string +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string field contains a substring specified by an expression. + * + * ```typescript + * // Check if the 'description' field contains the value of the 'keyword' field. + * stringContains("description", field("keyword")); + * ``` + * + * @param fieldName The name of the field containing the string. + * @param substring The expression representing the substring to search for. + * @return A new {@code Expr} representing the 'contains' comparison. + */ +export function stringContains( + fieldName: string, + substring: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string expression contains a specified substring. + * + * ```typescript + * // Check if the 'description' field contains "example". + * stringContains(field("description"), "example"); + * ``` + * + * @param stringExpression The expression representing the string to perform the comparison on. + * @param substring The substring to search for. + * @return A new {@code Expr} representing the 'contains' comparison. + */ +export function stringContains( + stringExpression: Expression, + substring: string +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string expression contains a substring specified by another expression. + * + * ```typescript + * // Check if the 'description' field contains the value of the 'keyword' field. + * stringContains(field("description"), field("keyword")); + * ``` + * + * @param stringExpression The expression representing the string to perform the comparison on. + * @param substring The expression representing the substring to search for. + * @return A new {@code Expr} representing the 'contains' comparison. + */ +export function stringContains( + stringExpression: Expression, + substring: Expression +): BooleanExpression; +export function stringContains( + left: Expression | string, + substring: Expression | string +): BooleanExpression { + const leftExpr = fieldOrExpression(left); + const substringExpr = valueToDefaultExpr(substring); + return leftExpr.stringContains(substringExpr); +} + +/** + * @beta + * + * Creates an expression that checks if a field's value starts with a given prefix. + * + * ```typescript + * // Check if the 'name' field starts with "Mr." + * startsWith("name", "Mr."); + * ``` + * + * @param fieldName The field name to check. + * @param prefix The prefix to check for. + * @return A new {@code Expr} representing the 'starts with' comparison. + */ +export function startsWith( + fieldName: string, + prefix: string +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value starts with a given prefix. + * + * ```typescript + * // Check if the 'fullName' field starts with the value of the 'firstName' field + * startsWith("fullName", field("firstName")); + * ``` + * + * @param fieldName The field name to check. + * @param prefix The expression representing the prefix. + * @return A new {@code Expr} representing the 'starts with' comparison. + */ +export function startsWith( + fieldName: string, + prefix: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string expression starts with a given prefix. + * + * ```typescript + * // Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." + * startsWith(field("fullName"), "Mr."); + * ``` + * + * @param stringExpression The expression to check. + * @param prefix The prefix to check for. + * @return A new {@code Expr} representing the 'starts with' comparison. + */ +export function startsWith( + stringExpression: Expression, + prefix: string +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string expression starts with a given prefix. + * + * ```typescript + * // Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." + * startsWith(field("fullName"), field("prefix")); + * ``` + * + * @param stringExpression The expression to check. + * @param prefix The prefix to check for. + * @return A new {@code Expr} representing the 'starts with' comparison. + */ +export function startsWith( + stringExpression: Expression, + prefix: Expression +): BooleanExpression; +export function startsWith( + expr: Expression | string, + prefix: Expression | string +): BooleanExpression { + return fieldOrExpression(expr).startsWith(valueToDefaultExpr(prefix)); +} + +/** + * @beta + * + * Creates an expression that checks if a field's value ends with a given postfix. + * + * ```typescript + * // Check if the 'filename' field ends with ".txt" + * endsWith("filename", ".txt"); + * ``` + * + * @param fieldName The field name to check. + * @param suffix The postfix to check for. + * @return A new {@code Expr} representing the 'ends with' comparison. + */ +export function endsWith(fieldName: string, suffix: string): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a field's value ends with a given postfix. + * + * ```typescript + * // Check if the 'url' field ends with the value of the 'extension' field + * endsWith("url", field("extension")); + * ``` + * + * @param fieldName The field name to check. + * @param suffix The expression representing the postfix. + * @return A new {@code Expr} representing the 'ends with' comparison. + */ +export function endsWith( + fieldName: string, + suffix: Expression +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string expression ends with a given postfix. + * + * ```typescript + * // Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." + * endsWith(field("fullName"), "Jr."); + * ``` + * + * @param stringExpression The expression to check. + * @param suffix The postfix to check for. + * @return A new {@code Expr} representing the 'ends with' comparison. + */ +export function endsWith( + stringExpression: Expression, + suffix: string +): BooleanExpression; + +/** + * @beta + * + * Creates an expression that checks if a string expression ends with a given postfix. + * + * ```typescript + * // Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." + * endsWith(field("fullName"), constant("Jr.")); + * ``` + * + * @param stringExpression The expression to check. + * @param suffix The postfix to check for. + * @return A new {@code Expr} representing the 'ends with' comparison. + */ +export function endsWith( + stringExpression: Expression, + suffix: Expression +): BooleanExpression; +export function endsWith( + expr: Expression | string, + suffix: Expression | string +): BooleanExpression { + return fieldOrExpression(expr).endsWith(valueToDefaultExpr(suffix)); +} + +/** + * @beta + * + * Creates an expression that converts a string field to lowercase. + * + * ```typescript + * // Convert the 'name' field to lowercase + * toLower("name"); + * ``` + * + * @param fieldName The name of the field containing the string. + * @return A new {@code Expr} representing the lowercase string. + */ +export function toLower(fieldName: string): FunctionExpression; + +/** + * @beta + * + * Creates an expression that converts a string expression to lowercase. + * + * ```typescript + * // Convert the 'name' field to lowercase + * toLower(field("name")); + * ``` + * + * @param stringExpression The expression representing the string to convert to lowercase. + * @return A new {@code Expr} representing the lowercase string. + */ +export function toLower(stringExpression: Expression): FunctionExpression; +export function toLower(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).toLower(); +} + +/** + * @beta + * + * Creates an expression that converts a string field to uppercase. + * + * ```typescript + * // Convert the 'title' field to uppercase + * toUpper("title"); + * ``` + * + * @param fieldName The name of the field containing the string. + * @return A new {@code Expr} representing the uppercase string. + */ +export function toUpper(fieldName: string): FunctionExpression; + +/** + * @beta + * + * Creates an expression that converts a string expression to uppercase. + * + * ```typescript + * // Convert the 'title' field to uppercase + * toUppercase(field("title")); + * ``` + * + * @param stringExpression The expression representing the string to convert to uppercase. + * @return A new {@code Expr} representing the uppercase string. + */ +export function toUpper(stringExpression: Expression): FunctionExpression; +export function toUpper(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).toUpper(); +} + +/** + * @beta + * + * Creates an expression that removes leading and trailing whitespace from a string or byte array. + * + * ```typescript + * // Trim whitespace from the 'userInput' field + * trim("userInput"); + * + * // Trim quotes from the 'userInput' field + * trim("userInput", '"'); + * ``` + * + * @param fieldName The name of the field containing the string or byte array. + * @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. + * @return A new {@code Expr} representing the trimmed string. + */ +export function trim( + fieldName: string, + valueToTrim?: string | Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that removes leading and trailing characters from a string or byte array expression. + * + * ```typescript + * // Trim whitespace from the 'userInput' field + * trim(field("userInput")); + * + * // Trim quotes from the 'userInput' field + * trim(field("userInput"), '"'); + * ``` + * + * @param stringExpression The expression representing the string or byte array to 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. + * @return A new {@code Expr} representing the trimmed string or byte array. + */ +export function trim( + stringExpression: Expression, + valueToTrim?: string | Expression +): FunctionExpression; +export function trim( + expr: Expression | string, + valueToTrim?: string | Expression +): FunctionExpression { + return fieldOrExpression(expr).trim(valueToTrim); +} + +/** + * @beta + * + * Creates an expression that concatenates string functions, fields or constants together. + * + * ```typescript + * // Combine the 'firstName', " ", and 'lastName' fields into a single string + * stringConcat("firstName", " ", field("lastName")); + * ``` + * + * @param fieldName The field name containing the initial string value. + * @param secondString An expression or string literal to concatenate. + * @param otherStrings Optional additional expressions or literals (typically strings) to concatenate. + * @return A new {@code Expr} representing the concatenated string. + */ +export function stringConcat( + fieldName: string, + secondString: Expression | string, + ...otherStrings: Array +): FunctionExpression; + +/** + * @beta + * Creates an expression that concatenates string expressions together. + * + * ```typescript + * // Combine the 'firstName', " ", and 'lastName' fields into a single string + * stringConcat(field("firstName"), " ", field("lastName")); + * ``` + * + * @param firstString The initial string expression to concatenate to. + * @param secondString An expression or string literal to concatenate. + * @param otherStrings Optional additional expressions or literals (typically strings) to concatenate. + * @return A new {@code Expr} representing the concatenated string. + */ +export function stringConcat( + firstString: Expression, + secondString: Expression | string, + ...otherStrings: Array +): FunctionExpression; +export function stringConcat( + first: string | Expression, + second: string | Expression, + ...elements: Array +): FunctionExpression { + return fieldOrExpression(first).stringConcat( + valueToDefaultExpr(second), + ...elements.map(valueToDefaultExpr) + ); +} + +/** + * @beta + * + * Accesses a value from a map (object) field using the provided key. + * + * ```typescript + * // Get the 'city' value from the 'address' map field + * mapGet("address", "city"); + * ``` + * + * @param fieldName The field name of the map field. + * @param subField The key to access in the map. + * @return A new {@code Expr} representing the value associated with the given key in the map. + */ +export function mapGet(fieldName: string, subField: string): FunctionExpression; + +/** + * @beta + * + * Accesses a value from a map (object) expression using the provided key. + * + * ```typescript + * // Get the 'city' value from the 'address' map field + * mapGet(field("address"), "city"); + * ``` + * + * @param mapExpression The expression representing the map. + * @param subField The key to access in the map. + * @return A new {@code Expr} representing the value associated with the given key in the map. + */ +export function mapGet( + mapExpression: Expression, + subField: string +): FunctionExpression; +export function mapGet( + fieldOrExpr: string | Expression, + subField: string +): FunctionExpression { + return fieldOrExpression(fieldOrExpr).mapGet(subField); +} + +/** + * @beta + * + * Creates an aggregation that counts the total number of stage inputs. + * + * ```typescript + * // Count the total number of input documents + * countAll().as("totalDocument"); + * ``` + * + * @return A new {@code AggregateFunction} representing the 'countAll' aggregation. + */ +export function countAll(): AggregateFunction { + return AggregateFunction._create('count', [], 'count'); +} + +/** + * @beta + * + * Creates an aggregation that counts the number of stage inputs with valid evaluations of the + * provided expression. + * + * ```typescript + * // Count the number of items where the price is greater than 10 + * count(field("price").greaterThan(10)).as("expensiveItemCount"); + * ``` + * + * @param expression The expression to count. + * @return A new {@code AggregateFunction} representing the 'count' aggregation. + */ +export function count(expression: Expression): AggregateFunction; + +/** + * @beta + * Creates an aggregation that counts the number of stage inputs where the input field exists. + * + * ```typescript + * // Count the total number of products + * count("productId").as("totalProducts"); + * ``` + * + * @param fieldName The name of the field to count. + * @return A new {@code AggregateFunction} representing the 'count' aggregation. + */ +export function count(fieldName: string): AggregateFunction; +export function count(value: Expression | string): AggregateFunction { + return fieldOrExpression(value).count(); +} + +/** + * @beta + * + * Creates an aggregation that calculates the sum of values from an expression across multiple + * stage inputs. + * + * ```typescript + * // Calculate the total revenue from a set of orders + * sum(field("orderAmount")).as("totalRevenue"); + * ``` + * + * @param expression The expression to sum up. + * @return A new {@code AggregateFunction} representing the 'sum' aggregation. + */ +export function sum(expression: Expression): AggregateFunction; + +/** + * @beta + * + * Creates an aggregation that calculates the sum of a field's values across multiple stage + * inputs. + * + * ```typescript + * // Calculate the total revenue from a set of orders + * sum("orderAmount").as("totalRevenue"); + * ``` + * + * @param fieldName The name of the field containing numeric values to sum up. + * @return A new {@code AggregateFunction} representing the 'sum' aggregation. + */ +export function sum(fieldName: string): AggregateFunction; +export function sum(value: Expression | string): AggregateFunction { + return fieldOrExpression(value).sum(); +} + +/** + * @beta + * + * Creates an aggregation that calculates the average (mean) of values from an expression across + * multiple stage inputs. + * + * ```typescript + * // Calculate the average age of users + * average(field("age")).as("averageAge"); + * ``` + * + * @param expression The expression representing the values to average. + * @return A new {@code AggregateFunction} representing the 'average' aggregation. + */ +export function average(expression: Expression): AggregateFunction; + +/** + * @beta + * + * Creates an aggregation that calculates the average (mean) of a field's values across multiple + * stage inputs. + * + * ```typescript + * // Calculate the average age of users + * average("age").as("averageAge"); + * ``` + * + * @param fieldName The name of the field containing numeric values to average. + * @return A new {@code AggregateFunction} representing the 'average' aggregation. + */ +export function average(fieldName: string): AggregateFunction; +export function average(value: Expression | string): AggregateFunction { + return fieldOrExpression(value).average(); +} + +/** + * @beta + * + * Creates an aggregation that finds the minimum value of an expression across multiple stage + * inputs. + * + * ```typescript + * // Find the lowest price of all products + * minimum(field("price")).as("lowestPrice"); + * ``` + * + * @param expression The expression to find the minimum value of. + * @return A new {@code AggregateFunction} representing the 'minimum' aggregation. + */ +export function minimum(expression: Expression): AggregateFunction; + +/** + * @beta + * + * Creates an aggregation that finds the minimum value of a field across multiple stage inputs. + * + * ```typescript + * // Find the lowest price of all products + * minimum("price").as("lowestPrice"); + * ``` + * + * @param fieldName The name of the field to find the minimum value of. + * @return A new {@code AggregateFunction} representing the 'minimum' aggregation. + */ +export function minimum(fieldName: string): AggregateFunction; +export function minimum(value: Expression | string): AggregateFunction { + return fieldOrExpression(value).minimum(); +} + +/** + * @beta + * + * Creates an aggregation that finds the maximum value of an expression across multiple stage + * inputs. + * + * ```typescript + * // Find the highest score in a leaderboard + * maximum(field("score")).as("highestScore"); + * ``` + * + * @param expression The expression to find the maximum value of. + * @return A new {@code AggregateFunction} representing the 'maximum' aggregation. + */ +export function maximum(expression: Expression): AggregateFunction; + +/** + * @beta + * + * Creates an aggregation that finds the maximum value of a field across multiple stage inputs. + * + * ```typescript + * // Find the highest score in a leaderboard + * maximum("score").as("highestScore"); + * ``` + * + * @param fieldName The name of the field to find the maximum value of. + * @return A new {@code AggregateFunction} representing the 'maximum' aggregation. + */ +export function maximum(fieldName: string): AggregateFunction; +export function maximum(value: Expression | string): AggregateFunction { + return fieldOrExpression(value).maximum(); +} + +/** + * @beta + * + * Calculates the Cosine distance between a field's vector value and a literal vector value. + * + * ```typescript + * // Calculate the Cosine distance between the 'location' field and a target location + * cosineDistance("location", [37.7749, -122.4194]); + * ``` + * + * @param fieldName The name of the field containing the first vector. + * @param vector The other vector (as an array of doubles) or {@link VectorValue} to compare against. + * @return A new {@code Expr} representing the Cosine distance between the two vectors. + */ +export function cosineDistance( + fieldName: string, + vector: number[] | VectorValue +): FunctionExpression; + +/** + * @beta + * + * Calculates the Cosine distance between a field's vector value and a vector expression. + * + * ```typescript + * // Calculate the cosine distance between the 'userVector' field and the 'itemVector' field + * cosineDistance("userVector", field("itemVector")); + * ``` + * + * @param fieldName The name of the field containing the first vector. + * @param vectorExpression The other vector (represented as an Expr) to compare against. + * @return A new {@code Expr} representing the cosine distance between the two vectors. + */ +export function cosineDistance( + fieldName: string, + vectorExpression: Expression +): FunctionExpression; + +/** + * @beta + * + * Calculates the Cosine distance between a vector expression and a vector literal. + * + * ```typescript + * // Calculate the cosine distance between the 'location' field and a target location + * cosineDistance(field("location"), [37.7749, -122.4194]); + * ``` + * + * @param vectorExpression The first vector (represented as an Expr) to compare against. + * @param vector The other vector (as an array of doubles or VectorValue) to compare against. + * @return A new {@code Expr} representing the cosine distance between the two vectors. + */ +export function cosineDistance( + vectorExpression: Expression, + vector: number[] | VectorValue +): FunctionExpression; + +/** + * @beta + * + * Calculates the Cosine distance between two vector expressions. + * + * ```typescript + * // Calculate the cosine distance between the 'userVector' field and the 'itemVector' field + * cosineDistance(field("userVector"), field("itemVector")); + * ``` + * + * @param vectorExpression The first vector (represented as an Expr) to compare against. + * @param otherVectorExpression The other vector (represented as an Expr) to compare against. + * @return A new {@code Expr} representing the cosine distance between the two vectors. + */ +export function cosineDistance( + vectorExpression: Expression, + otherVectorExpression: Expression +): FunctionExpression; +export function cosineDistance( + expr: Expression | string, + other: Expression | number[] | VectorValue +): FunctionExpression { + const expr1 = fieldOrExpression(expr); + const expr2 = vectorToExpr(other); + return expr1.cosineDistance(expr2); +} + +/** + * @beta + * + * Calculates the dot product between a field's vector value and a double array. + * + * ```typescript + * // Calculate the dot product distance between a feature vector and a target vector + * dotProduct("features", [0.5, 0.8, 0.2]); + * ``` + * + * @param fieldName The name of the field containing the first vector. + * @param vector The other vector (as an array of doubles or VectorValue) to calculate with. + * @return A new {@code Expr} representing the dot product between the two vectors. + */ +export function dotProduct( + fieldName: string, + vector: number[] | VectorValue +): FunctionExpression; + +/** + * @beta + * + * Calculates the dot product between a field's vector value and a vector expression. + * + * ```typescript + * // Calculate the dot product distance between two document vectors: 'docVector1' and 'docVector2' + * dotProduct("docVector1", field("docVector2")); + * ``` + * + * @param fieldName The name of the field containing the first vector. + * @param vectorExpression The other vector (represented as an Expr) to calculate with. + * @return A new {@code Expr} representing the dot product between the two vectors. + */ +export function dotProduct( + fieldName: string, + vectorExpression: Expression +): FunctionExpression; + +/** + * @beta + * + * Calculates the dot product between a vector expression and a double array. + * + * ```typescript + * // Calculate the dot product between a feature vector and a target vector + * dotProduct(field("features"), [0.5, 0.8, 0.2]); + * ``` + * + * @param vectorExpression The first vector (represented as an Expr) to calculate with. + * @param vector The other vector (as an array of doubles or VectorValue) to calculate with. + * @return A new {@code Expr} representing the dot product between the two vectors. + */ +export function dotProduct( + vectorExpression: Expression, + vector: number[] | VectorValue +): FunctionExpression; + +/** + * @beta + * + * Calculates the dot product between two vector expressions. + * + * ```typescript + * // Calculate the dot product between two document vectors: 'docVector1' and 'docVector2' + * dotProduct(field("docVector1"), field("docVector2")); + * ``` + * + * @param vectorExpression The first vector (represented as an Expr) to calculate with. + * @param otherVectorExpression The other vector (represented as an Expr) to calculate with. + * @return A new {@code Expr} representing the dot product between the two vectors. + */ +export function dotProduct( + vectorExpression: Expression, + otherVectorExpression: Expression +): FunctionExpression; +export function dotProduct( + expr: Expression | string, + other: Expression | number[] | VectorValue +): FunctionExpression { + const expr1 = fieldOrExpression(expr); + const expr2 = vectorToExpr(other); + return expr1.dotProduct(expr2); +} + +/** + * @beta + * + * Calculates the Euclidean distance between a field's vector value and a double array. + * + * ```typescript + * // Calculate the Euclidean distance between the 'location' field and a target location + * euclideanDistance("location", [37.7749, -122.4194]); + * ``` + * + * @param fieldName The name of the field containing the first vector. + * @param vector The other vector (as an array of doubles or VectorValue) to compare against. + * @return A new {@code Expr} representing the Euclidean distance between the two vectors. + */ +export function euclideanDistance( + fieldName: string, + vector: number[] | VectorValue +): FunctionExpression; + +/** + * @beta + * + * Calculates the Euclidean distance between a field's vector value and a vector expression. + * + * ```typescript + * // Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' + * euclideanDistance("pointA", field("pointB")); + * ``` + * + * @param fieldName The name of the field containing the first vector. + * @param vectorExpression The other vector (represented as an Expr) to compare against. + * @return A new {@code Expr} representing the Euclidean distance between the two vectors. + */ +export function euclideanDistance( + fieldName: string, + vectorExpression: Expression +): FunctionExpression; + +/** + * @beta + * + * Calculates the Euclidean distance between a vector expression and a double array. + * + * ```typescript + * // Calculate the Euclidean distance between the 'location' field and a target location + * + * euclideanDistance(field("location"), [37.7749, -122.4194]); + * ``` + * + * @param vectorExpression The first vector (represented as an Expr) to compare against. + * @param vector The other vector (as an array of doubles or VectorValue) to compare against. + * @return A new {@code Expr} representing the Euclidean distance between the two vectors. + */ +export function euclideanDistance( + vectorExpression: Expression, + vector: number[] | VectorValue +): FunctionExpression; + +/** + * @beta + * + * Calculates the Euclidean distance between two vector expressions. + * + * ```typescript + * // Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' + * euclideanDistance(field("pointA"), field("pointB")); + * ``` + * + * @param vectorExpression The first vector (represented as an Expr) to compare against. + * @param otherVectorExpression The other vector (represented as an Expr) to compare against. + * @return A new {@code Expr} representing the Euclidean distance between the two vectors. + */ +export function euclideanDistance( + vectorExpression: Expression, + otherVectorExpression: Expression +): FunctionExpression; +export function euclideanDistance( + expr: Expression | string, + other: Expression | number[] | VectorValue +): FunctionExpression { + const expr1 = fieldOrExpression(expr); + const expr2 = vectorToExpr(other); + return expr1.euclideanDistance(expr2); +} + +/** + * @beta + * + * Creates an expression that calculates the length of a Firestore Vector. + * + * ```typescript + * // Get the vector length (dimension) of the field 'embedding'. + * vectorLength(field("embedding")); + * ``` + * + * @param vectorExpression The expression representing the Firestore Vector. + * @return A new {@code Expr} representing the length of the array. + */ +export function vectorLength(vectorExpression: Expression): FunctionExpression; + +/** + * @beta + * + * Creates an expression that calculates the length of a Firestore Vector represented by a field. + * + * ```typescript + * // Get the vector length (dimension) of the field 'embedding'. + * vectorLength("embedding"); + * ``` + * + * @param fieldName The name of the field representing the Firestore Vector. + * @return A new {@code Expr} representing the length of the array. + */ +export function vectorLength(fieldName: string): FunctionExpression; +export function vectorLength(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).vectorLength(); +} + +/** + * @beta + * + * Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) + * and returns a timestamp. + * + * ```typescript + * // Interpret the 'microseconds' field as microseconds since epoch. + * unixMicrosToTimestamp(field("microseconds")); + * ``` + * + * @param expr The expression representing the number of microseconds since epoch. + * @return A new {@code Expr} representing the timestamp. + */ +export function unixMicrosToTimestamp(expr: Expression): FunctionExpression; + +/** + * @beta + * + * Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) + * and returns a timestamp. + * + * ```typescript + * // Interpret the 'microseconds' field as microseconds since epoch. + * unixMicrosToTimestamp("microseconds"); + * ``` + * + * @param fieldName The name of the field representing the number of microseconds since epoch. + * @return A new {@code Expr} representing the timestamp. + */ +export function unixMicrosToTimestamp(fieldName: string): FunctionExpression; +export function unixMicrosToTimestamp( + expr: Expression | string +): FunctionExpression { + return fieldOrExpression(expr).unixMicrosToTimestamp(); +} + +/** + * @beta + * + * Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + * + * ```typescript + * // Convert the 'timestamp' field to microseconds since epoch. + * timestampToUnixMicros(field("timestamp")); + * ``` + * + * @param expr The expression representing the timestamp. + * @return A new {@code Expr} representing the number of microseconds since epoch. + */ +export function timestampToUnixMicros(expr: Expression): FunctionExpression; + +/** + * @beta + * + * Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + * + * ```typescript + * // Convert the 'timestamp' field to microseconds since epoch. + * timestampToUnixMicros("timestamp"); + * ``` + * + * @param fieldName The name of the field representing the timestamp. + * @return A new {@code Expr} representing the number of microseconds since epoch. + */ +export function timestampToUnixMicros(fieldName: string): FunctionExpression; +export function timestampToUnixMicros( + expr: Expression | string +): FunctionExpression { + return fieldOrExpression(expr).timestampToUnixMicros(); +} + +/** + * @beta + * + * Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) + * and returns a timestamp. + * + * ```typescript + * // Interpret the 'milliseconds' field as milliseconds since epoch. + * unixMillisToTimestamp(field("milliseconds")); + * ``` + * + * @param expr The expression representing the number of milliseconds since epoch. + * @return A new {@code Expr} representing the timestamp. + */ +export function unixMillisToTimestamp(expr: Expression): FunctionExpression; + +/** + * @beta + * + * Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) + * and returns a timestamp. + * + * ```typescript + * // Interpret the 'milliseconds' field as milliseconds since epoch. + * unixMillisToTimestamp("milliseconds"); + * ``` + * + * @param fieldName The name of the field representing the number of milliseconds since epoch. + * @return A new {@code Expr} representing the timestamp. + */ +export function unixMillisToTimestamp(fieldName: string): FunctionExpression; +export function unixMillisToTimestamp( + expr: Expression | string +): FunctionExpression { + const normalizedExpr = fieldOrExpression(expr); + return normalizedExpr.unixMillisToTimestamp(); +} + +/** + * @beta + * + * Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + * + * ```typescript + * // Convert the 'timestamp' field to milliseconds since epoch. + * timestampToUnixMillis(field("timestamp")); + * ``` + * + * @param expr The expression representing the timestamp. + * @return A new {@code Expr} representing the number of milliseconds since epoch. + */ +export function timestampToUnixMillis(expr: Expression): FunctionExpression; + +/** + * @beta + * + * Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + * + * ```typescript + * // Convert the 'timestamp' field to milliseconds since epoch. + * timestampToUnixMillis("timestamp"); + * ``` + * + * @param fieldName The name of the field representing the timestamp. + * @return A new {@code Expr} representing the number of milliseconds since epoch. + */ +export function timestampToUnixMillis(fieldName: string): FunctionExpression; +export function timestampToUnixMillis( + expr: Expression | string +): FunctionExpression { + const normalizedExpr = fieldOrExpression(expr); + return normalizedExpr.timestampToUnixMillis(); +} + +/** + * @beta + * + * Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) + * and returns a timestamp. + * + * ```typescript + * // Interpret the 'seconds' field as seconds since epoch. + * unixSecondsToTimestamp(field("seconds")); + * ``` + * + * @param expr The expression representing the number of seconds since epoch. + * @return A new {@code Expr} representing the timestamp. + */ +export function unixSecondsToTimestamp(expr: Expression): FunctionExpression; + +/** + * @beta + * + * Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) + * and returns a timestamp. + * + * ```typescript + * // Interpret the 'seconds' field as seconds since epoch. + * unixSecondsToTimestamp("seconds"); + * ``` + * + * @param fieldName The name of the field representing the number of seconds since epoch. + * @return A new {@code Expr} representing the timestamp. + */ +export function unixSecondsToTimestamp(fieldName: string): FunctionExpression; +export function unixSecondsToTimestamp( + expr: Expression | string +): FunctionExpression { + const normalizedExpr = fieldOrExpression(expr); + return normalizedExpr.unixSecondsToTimestamp(); +} + +/** + * @beta + * + * Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + * + * ```typescript + * // Convert the 'timestamp' field to seconds since epoch. + * timestampToUnixSeconds(field("timestamp")); + * ``` + * + * @param expr The expression representing the timestamp. + * @return A new {@code Expr} representing the number of seconds since epoch. + */ +export function timestampToUnixSeconds(expr: Expression): FunctionExpression; + +/** + * @beta + * + * Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + * + * ```typescript + * // Convert the 'timestamp' field to seconds since epoch. + * timestampToUnixSeconds("timestamp"); + * ``` + * + * @param fieldName The name of the field representing the timestamp. + * @return A new {@code Expr} representing the number of seconds since epoch. + */ +export function timestampToUnixSeconds(fieldName: string): FunctionExpression; +export function timestampToUnixSeconds( + expr: Expression | string +): FunctionExpression { + const normalizedExpr = fieldOrExpression(expr); + return normalizedExpr.timestampToUnixSeconds(); +} + +/** + * @beta + * + * Creates an expression that adds a specified amount of time to a timestamp. + * + * ```typescript + * // Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. + * timestampAdd(field("timestamp"), field("unit"), field("amount")); + * ``` + * + * @param timestamp The expression representing the timestamp. + * @param unit The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. + * @param amount The expression evaluates to amount of the unit. + * @return A new {@code Expr} representing the resulting timestamp. + */ +export function timestampAdd( + timestamp: Expression, + unit: Expression, + amount: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that adds a specified amount of time to a timestamp. + * + * ```typescript + * // Add 1 day to the 'timestamp' field. + * timestampAdd(field("timestamp"), "day", 1); + * ``` + * + * @param timestamp The expression representing the timestamp. + * @param unit The unit of time to add (e.g., "day", "hour"). + * @param amount The amount of time to add. + * @return A new {@code Expr} representing the resulting timestamp. + */ +export function timestampAdd( + timestamp: Expression, + unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', + amount: number +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that adds a specified amount of time to a timestamp represented by a field. + * + * ```typescript + * // Add 1 day to the 'timestamp' field. + * timestampAdd("timestamp", "day", 1); + * ``` + * + * @param fieldName The name of the field representing the timestamp. + * @param unit The unit of time to add (e.g., "day", "hour"). + * @param amount The amount of time to add. + * @return A new {@code Expr} representing the resulting timestamp. + */ +export function timestampAdd( + fieldName: string, + unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', + amount: number +): FunctionExpression; +export function timestampAdd( + timestamp: Expression | string, + unit: + | Expression + | 'microsecond' + | 'millisecond' + | 'second' + | 'minute' + | 'hour' + | 'day', + amount: Expression | number +): FunctionExpression { + const normalizedTimestamp = fieldOrExpression(timestamp); + const normalizedUnit = valueToDefaultExpr(unit); + const normalizedAmount = valueToDefaultExpr(amount); + return normalizedTimestamp.timestampAdd(normalizedUnit, normalizedAmount); +} + +/** + * @beta + * + * Creates an expression that subtracts a specified amount of time from a timestamp. + * + * ```typescript + * // Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. + * timestampSubtract(field("timestamp"), field("unit"), field("amount")); + * ``` + * + * @param timestamp The expression representing the timestamp. + * @param unit The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. + * @param amount The expression evaluates to amount of the unit. + * @return A new {@code Expr} representing the resulting timestamp. + */ +export function timestampSubtract( + timestamp: Expression, + unit: Expression, + amount: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that subtracts a specified amount of time from a timestamp. + * + * ```typescript + * // Subtract 1 day from the 'timestamp' field. + * timestampSubtract(field("timestamp"), "day", 1); + * ``` + * + * @param timestamp The expression representing the timestamp. + * @param unit The unit of time to subtract (e.g., "day", "hour"). + * @param amount The amount of time to subtract. + * @return A new {@code Expr} representing the resulting timestamp. + */ +export function timestampSubtract( + timestamp: Expression, + unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', + amount: number +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. + * + * ```typescript + * // Subtract 1 day from the 'timestamp' field. + * timestampSubtract("timestamp", "day", 1); + * ``` + * + * @param fieldName The name of the field representing the timestamp. + * @param unit The unit of time to subtract (e.g., "day", "hour"). + * @param amount The amount of time to subtract. + * @return A new {@code Expr} representing the resulting timestamp. + */ +export function timestampSubtract( + fieldName: string, + unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', + amount: number +): FunctionExpression; +export function timestampSubtract( + timestamp: Expression | string, + unit: + | Expression + | 'microsecond' + | 'millisecond' + | 'second' + | 'minute' + | 'hour' + | 'day', + amount: Expression | number +): FunctionExpression { + const normalizedTimestamp = fieldOrExpression(timestamp); + const normalizedUnit = valueToDefaultExpr(unit); + const normalizedAmount = valueToDefaultExpr(amount); + return normalizedTimestamp.timestampSubtract( + normalizedUnit, + normalizedAmount + ); +} + +/** + * @beta + * + * Creates an expression that evaluates to the current server timestamp. + * + * ```typescript + * // Get the current server timestamp + * currentTimestamp() + * ``` + * + * @return A new Expression representing the current server timestamp. + */ +export function currentTimestamp(): FunctionExpression { + return new FunctionExpression('current_timestamp', [], 'currentTimestamp'); +} + +/** + * @beta + * + * Creates an expression that performs a logical 'AND' operation on multiple filter conditions. + * + * ```typescript + * // Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND + * // the 'status' field is "active" + * const condition = and(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); + * ``` + * + * @param first The first filter condition. + * @param second The second filter condition. + * @param more Additional filter conditions to 'AND' together. + * @return A new {@code Expr} representing the logical 'AND' operation. + */ +export function and( + first: BooleanExpression, + second: BooleanExpression, + ...more: BooleanExpression[] +): BooleanExpression { + return new FunctionExpression( + 'and', + [first, second, ...more], + 'and' + ).asBoolean(); +} + +/** + * @beta + * + * Creates an expression that performs a logical 'OR' operation on multiple filter conditions. + * + * ```typescript + * // Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR + * // the 'status' field is "active" + * const condition = or(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); + * ``` + * + * @param first The first filter condition. + * @param second The second filter condition. + * @param more Additional filter conditions to 'OR' together. + * @return A new {@code Expr} representing the logical 'OR' operation. + */ +export function or( + first: BooleanExpression, + second: BooleanExpression, + ...more: BooleanExpression[] +): BooleanExpression { + return new FunctionExpression( + 'or', + [first, second, ...more], + 'xor' + ).asBoolean(); +} + +/** + * @beta + * Creates an expression that returns the value of the base expression raised to the power of the exponent expression. + * + * ```typescript + * // Raise the value of the 'base' field to the power of the 'exponent' field. + * pow(field("base"), field("exponent")); + * ``` + * + * @param base The expression to raise to the power of the exponent. + * @param exponent The expression to raise the base to the power of. + * @return A new `Expr` representing the power operation. + */ +export function pow(base: Expression, exponent: Expression): FunctionExpression; + +/** + * @beta + * Creates an expression that returns the value of the base expression raised to the power of the exponent. + * + * ```typescript + * // Raise the value of the 'base' field to the power of 2. + * pow(field("base"), 2); + * ``` + * + * @param base The expression to raise to the power of the exponent. + * @param exponent The constant value to raise the base to the power of. + * @return A new `Expr` representing the power operation. + */ +export function pow(base: Expression, exponent: number): FunctionExpression; + +/** + * @beta + * Creates an expression that returns the value of the base field raised to the power of the exponent expression. + * + * ```typescript + * // Raise the value of the 'base' field to the power of the 'exponent' field. + * pow("base", field("exponent")); + * ``` + * + * @param base The name of the field to raise to the power of the exponent. + * @param exponent The expression to raise the base to the power of. + * @return A new `Expr` representing the power operation. + */ +export function pow(base: string, exponent: Expression): FunctionExpression; + +/** + * @beta + * Creates an expression that returns the value of the base field raised to the power of the exponent. + * + * ```typescript + * // Raise the value of the 'base' field to the power of 2. + * pow("base", 2); + * ``` + * + * @param base The name of the field to raise to the power of the exponent. + * @param exponent The constant value to raise the base to the power of. + * @return A new `Expr` representing the power operation. + */ +export function pow(base: string, exponent: number): FunctionExpression; +export function pow( + base: Expression | string, + exponent: Expression | number +): FunctionExpression { + return fieldOrExpression(base).pow(exponent as number); +} + +/** + * @beta + * Creates an expression that rounds a numeric value to the nearest whole number. + * + * ```typescript + * // Round the value of the 'price' field. + * round("price"); + * ``` + * + * @param fieldName The name of the field to round. + * @return A new `Expr` representing the rounded value. + */ +export function round(fieldName: string): FunctionExpression; + +/** + * @beta + * Creates an expression that rounds a numeric value to the nearest whole number. + * + * ```typescript + * // Round the value of the 'price' field. + * round(field("price")); + * ``` + * + * @param expression An expression evaluating to a numeric value, which will be rounded. + * @return A new `Expr` representing the rounded value. + */ +export function round(expression: Expression): FunctionExpression; + +/** + * @beta + * Creates an expression that rounds a numeric value to the specified number of decimal places. + * + * ```typescript + * // Round the value of the 'price' field to two decimal places. + * round("price", 2); + * ``` + * + * @param fieldName The name of the field to round. + * @param decimalPlaces A constant or expression specifying the rounding precision in decimal places. + * @return A new `Expr` representing the rounded value. + */ +export function round( + fieldName: string, + decimalPlaces: number | Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that rounds a numeric value to the specified number of decimal places. + * + * ```typescript + * // Round the value of the 'price' field to two decimal places. + * round(field("price"), constant(2)); + * ``` + * + * @param expression An expression evaluating to a numeric value, which will be rounded. + * @param decimalPlaces A constant or expression specifying the rounding precision in decimal places. + * @return A new `Expr` representing the rounded value. + */ +export function round( + expression: Expression, + decimalPlaces: number | Expression +): FunctionExpression; +export function round( + expr: Expression | string, + decimalPlaces?: number | Expression +): FunctionExpression { + if (decimalPlaces === undefined) { + return fieldOrExpression(expr).round(); + } else { + return fieldOrExpression(expr).round(valueToDefaultExpr(decimalPlaces)); + } +} + +/** + * @beta + * Creates an expression that returns the collection ID from a path. + * + * ```typescript + * // Get the collection ID from a path. + * collectionId("__name__"); + * ``` + * + * @param fieldName The name of the field to get the collection ID from. + * @return A new {@code Expr} representing the collectionId operation. + */ +export function collectionId(fieldName: string): FunctionExpression; + +/** + * @beta + * Creates an expression that returns the collection ID from a path. + * + * ```typescript + * // Get the collection ID from a path. + * collectionId(field("__name__")); + * ``` + * + * @param expression An expression evaluating to a path, which the collection ID will be extracted from. + * @return A new {@code Expr} representing the collectionId operation. + */ +export function collectionId(expression: Expression): FunctionExpression; +export function collectionId(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).collectionId(); +} + +/** + * @beta + * Creates an expression that calculates the length of a string, array, map, vector, or bytes. + * + * ```typescript + * // Get the length of the 'name' field. + * length("name"); + * + * // Get the number of items in the 'cart' array. + * length("cart"); + * ``` + * + * @param fieldName The name of the field to calculate the length of. + * @return A new `Expr` representing the length of the string, array, map, vector, or bytes. + */ +export function length(fieldName: string): FunctionExpression; + +/** + * @beta + * Creates an expression that calculates the length of a string, array, map, vector, or bytes. + * + * ```typescript + * // Get the length of the 'name' field. + * length(field("name")); + * + * // Get the number of items in the 'cart' array. + * length(field("cart")); + * ``` + * + * @param expression An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. + * @return A new `Expr` representing the length of the string, array, map, vector, or bytes. + */ +export function length(expression: Expression): FunctionExpression; +export function length(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).length(); +} + +/** + * @beta + * Creates an expression that computes the natural logarithm of a numeric value. + * + * ```typescript + * // Compute the natural logarithm of the 'value' field. + * ln("value"); + * ``` + * + * @param fieldName The name of the field to compute the natural logarithm of. + * @return A new `Expr` representing the natural logarithm of the numeric value. + */ +export function ln(fieldName: string): FunctionExpression; + +/** + * @beta + * Creates an expression that computes the natural logarithm of a numeric value. + * + * ```typescript + * // Compute the natural logarithm of the 'value' field. + * ln(field("value")); + * ``` + * + * @param expression An expression evaluating to a numeric value, which the natural logarithm will be computed for. + * @return A new `Expr` representing the natural logarithm of the numeric value. + */ +export function ln(expression: Expression): FunctionExpression; +export function ln(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).ln(); +} + +/** + * @beta + * Creates an expression that computes the logarithm of an expression to a given base. + * + * ```typescript + * // Compute the logarithm of the 'value' field with base 10. + * log(field("value"), 10); + * ``` + * + * @param expression An expression evaluating to a numeric value, which the logarithm will be computed for. + * @param base The base of the logarithm. + * @return A new {@code Expr} representing the logarithm of the numeric value. + */ +export function log(expression: Expression, base: number): FunctionExpression; +/** + * @beta + * Creates an expression that computes the logarithm of an expression to a given base. + * + * ```typescript + * // Compute the logarithm of the 'value' field with the base in the 'base' field. + * log(field("value"), field("base")); + * ``` + * + * @param expression An expression evaluating to a numeric value, which the logarithm will be computed for. + * @param base The base of the logarithm. + * @return A new {@code Expr} representing the logarithm of the numeric value. + */ +export function log( + expression: Expression, + base: Expression +): FunctionExpression; +/** + * @beta + * Creates an expression that computes the logarithm of a field to a given base. + * + * ```typescript + * // Compute the logarithm of the 'value' field with base 10. + * log("value", 10); + * ``` + * + * @param fieldName The name of the field to compute the logarithm of. + * @param base The base of the logarithm. + * @return A new {@code Expr} representing the logarithm of the numeric value. + */ +export function log(fieldName: string, base: number): FunctionExpression; +/** + * @beta + * Creates an expression that computes the logarithm of a field to a given base. + * + * ```typescript + * // Compute the logarithm of the 'value' field with the base in the 'base' field. + * log("value", field("base")); + * ``` + * + * @param fieldName The name of the field to compute the logarithm of. + * @param base The base of the logarithm. + * @return A new {@code Expr} representing the logarithm of the numeric value. + */ +export function log(fieldName: string, base: Expression): FunctionExpression; +export function log( + expr: Expression | string, + base: number | Expression +): FunctionExpression { + return new FunctionExpression('log', [ + fieldOrExpression(expr), + valueToDefaultExpr(base) + ]); +} + +/** + * @beta + * Creates an expression that computes the square root of a numeric value. + * + * ```typescript + * // Compute the square root of the 'value' field. + * sqrt(field("value")); + * ``` + * + * @param expression An expression evaluating to a numeric value, which the square root will be computed for. + * @return A new {@code Expr} representing the square root of the numeric value. + */ +export function sqrt(expression: Expression): FunctionExpression; +/** + * @beta + * Creates an expression that computes the square root of a numeric value. + * + * ```typescript + * // Compute the square root of the 'value' field. + * sqrt("value"); + * ``` + * + * @param fieldName The name of the field to compute the square root of. + * @return A new {@code Expr} representing the square root of the numeric value. + */ +export function sqrt(fieldName: string): FunctionExpression; +export function sqrt(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).sqrt(); +} + +/** + * @beta + * Creates an expression that reverses a string. + * + * ```typescript + * // Reverse the value of the 'myString' field. + * strReverse(field("myString")); + * ``` + * + * @param stringExpression An expression evaluating to a string value, which will be reversed. + * @return A new {@code Expr} representing the reversed string. + */ +export function stringReverse(stringExpression: Expression): FunctionExpression; + +/** + * @beta + * Creates an expression that reverses a string value in the specified field. + * + * ```typescript + * // Reverse the value of the 'myString' field. + * strReverse("myString"); + * ``` + * + * @param field The name of the field representing the string to reverse. + * @return A new {@code Expr} representing the reversed string. + */ +export function stringReverse(field: string): FunctionExpression; +export function stringReverse(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).stringReverse(); +} + +/** + * @beta + * Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. + * + * ```typescript + * // Concatenate the 'firstName' and 'lastName' fields with a space in between. + * concat(field("firstName"), " ", field("lastName")) + * ``` + * + * @param first The first expressions to concatenate. + * @param second The second literal or expression to concatenate. + * @param others Additional literals or expressions to concatenate. + * @return A new `Expression` representing the concatenation. + */ +export function concat( + first: Expression, + second: Expression | unknown, + ...others: Array +): FunctionExpression; + +/** + * @beta + * Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. + * + * ```typescript + * // Concatenate a field with a literal string. + * concat(field("firstName"), "Doe") + * ``` + * + * @param fieldName The name of a field to concatenate. + * @param second The second literal or expression to concatenate. + * @param others Additional literal or expressions to concatenate. + * @return A new `Expression` representing the concatenation. + */ +export function concat( + fieldName: string, + second: Expression | unknown, + ...others: Array +): FunctionExpression; + +export function concat( + fieldNameOrExpression: string | Expression, + second: Expression | unknown, + ...others: Array +): FunctionExpression { + return new FunctionExpression('concat', [ + fieldOrExpression(fieldNameOrExpression), + valueToDefaultExpr(second), + ...others.map(valueToDefaultExpr) + ]); +} + +/** + * @beta + * Creates an expression that computes the absolute value of a numeric value. + * + * @param expr The expression to compute the absolute value of. + * @return A new {@code Expr} representing the absolute value of the numeric value. + */ +export function abs(expr: Expression): FunctionExpression; + +/** + * @beta + * Creates an expression that computes the absolute value of a numeric value. + * + * @param fieldName The field to compute the absolute value of. + * @return A new {@code Expr} representing the absolute value of the numeric value. + */ +export function abs(fieldName: string): FunctionExpression; +export function abs(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).abs(); +} + +/** + * @beta + * Creates an expression that returns the `elseExpr` argument if `ifExpr` is absent, else return + * the result of the `ifExpr` argument evaluation. + * + * ```typescript + * // Returns the value of the optional field 'optional_field', or returns 'default_value' + * // if the field is absent. + * ifAbsent(field("optional_field"), constant("default_value")) + * ``` + * + * @param ifExpr The expression to check for absence. + * @param elseExpr The expression that will be evaluated and returned if [ifExpr] is absent. + * @return A new Expression representing the ifAbsent operation. + */ +export function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expression; + +/** + * @beta + * Creates an expression that returns the `elseValue` argument if `ifExpr` is absent, else + * return the result of the `ifExpr` argument evaluation. + * + * ```typescript + * // Returns the value of the optional field 'optional_field', or returns 'default_value' + * // if the field is absent. + * ifAbsent(field("optional_field"), "default_value") + * ``` + * + * @param ifExpr The expression to check for absence. + * @param elseValue The value that will be returned if `ifExpr` evaluates to an absent value. + * @return A new [Expression] representing the ifAbsent operation. + */ +export function ifAbsent(ifExpr: Expression, elseValue: unknown): Expression; + +/** + * @beta + * Creates an expression that returns the `elseExpr` argument if `ifFieldName` is absent, else + * return the value of the field. + * + * ```typescript + * // Returns the value of the optional field 'optional_field', or returns the value of + * // 'default_field' if 'optional_field' is absent. + * ifAbsent("optional_field", field("default_field")) + * ``` + * + * @param ifFieldName The field to check for absence. + * @param elseExpr The expression that will be evaluated and returned if `ifFieldName` is + * absent. + * @return A new Expression representing the ifAbsent operation. + */ +export function ifAbsent(ifFieldName: string, elseExpr: Expression): Expression; + +/** + * @beta + * Creates an expression that returns the `elseValue` argument if `ifFieldName` is absent, else + * return the value of the field. + * + * ```typescript + * // Returns the value of the optional field 'optional_field', or returns 'default_value' + * // if the field is absent. + * ifAbsent("optional_field", "default_value") + * ``` + * + * @param ifFieldName The field to check for absence. + * @param elseValue The value that will be returned if [ifFieldName] is absent. + * @return A new Expression representing the ifAbsent operation. + */ +export function ifAbsent( + ifFieldName: string | Expression, + elseValue: Expression | unknown +): Expression; +export function ifAbsent( + fieldNameOrExpression: string | Expression, + elseValue: Expression | unknown +): Expression { + return fieldOrExpression(fieldNameOrExpression).ifAbsent( + valueToDefaultExpr(elseValue) + ); +} + +/** + * @beta + * Creates an expression that joins the elements of an array into a string. + * + * ```typescript + * // Join the elements of the 'tags' field with a comma and space. + * join("tags", ", ") + * ``` + * + * @param arrayFieldName The name of the field containing the array. + * @param delimiter The string to use as a delimiter. + * @return A new Expression representing the join operation. + */ +export function join(arrayFieldName: string, delimiter: string): Expression; + +/** + * @beta + * Creates an expression that joins the elements of an array into a string. + * + * ```typescript + * // Join an array of string using the delimiter from the 'separator' field. + * join(array(['foo', 'bar']), field("separator")) + * ``` + * + * @param arrayExpression An expression that evaluates to an array. + * @param delimiterExpression The expression that evaluates to the delimiter string. + * @return A new Expression representing the join operation. + */ +export function join( + arrayExpression: Expression, + delimiterExpression: Expression +): Expression; + +/** + * @beta + * Creates an expression that joins the elements of an array into a string. + * + * ```typescript + * // Join the elements of the 'tags' field with a comma and space. + * join(field("tags"), ", ") + * ``` + * + * @param arrayExpression An expression that evaluates to an array. + * @param delimiter The string to use as a delimiter. + * @return A new Expression representing the join operation. + */ +export function join( + arrayExpression: Expression, + delimiter: string +): Expression; + +/** + * @beta + * Creates an expression that joins the elements of an array into a string. + * + * ```typescript + * // Join the elements of the 'tags' field with the delimiter from the 'separator' field. + * join('tags', field("separator")) + * ``` + * + * @param arrayFieldName The name of the field containing the array. + * @param delimiterExpression The expression that evaluates to the delimiter string. + * @return A new Expression representing the join operation. + */ +export function join( + arrayFieldName: string, + delimiterExpression: Expression +): Expression; +export function join( + fieldNameOrExpression: string | Expression, + delimiterValueOrExpression: Expression | string +): Expression { + return fieldOrExpression(fieldNameOrExpression).join( + valueToDefaultExpr(delimiterValueOrExpression) + ); +} + +/** + * @beta + * Creates an expression that computes the base-10 logarithm of a numeric value. + * + * ```typescript + * // Compute the base-10 logarithm of the 'value' field. + * log10("value"); + * ``` + * + * @param fieldName The name of the field to compute the base-10 logarithm of. + * @return A new `Expr` representing the base-10 logarithm of the numeric value. + */ +export function log10(fieldName: string): FunctionExpression; + +/** + * @beta + * Creates an expression that computes the base-10 logarithm of a numeric value. + * + * ```typescript + * // Compute the base-10 logarithm of the 'value' field. + * log10(field("value")); + * ``` + * + * @param expression An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. + * @return A new `Expr` representing the base-10 logarithm of the numeric value. + */ +export function log10(expression: Expression): FunctionExpression; +export function log10(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).log10(); +} + +/** + * @beta + * Creates an expression that computes the sum of the elements in an array. + * + * ```typescript + * // Compute the sum of the elements in the 'scores' field. + * arraySum("scores"); + * ``` + * + * @param fieldName The name of the field to compute the sum of. + * @return A new `Expr` representing the sum of the elements in the array. + */ +export function arraySum(fieldName: string): FunctionExpression; + +/** + * @beta + * Creates an expression that computes the sum of the elements in an array. + * + * ```typescript + * // Compute the sum of the elements in the 'scores' field. + * arraySum(field("scores")); + * ``` + * + * @param expression An expression evaluating to a numeric array, which the sum will be computed for. + * @return A new `Expr` representing the sum of the elements in the array. + */ +export function arraySum(expression: Expression): FunctionExpression; +export function arraySum(expr: Expression | string): FunctionExpression { + return fieldOrExpression(expr).arraySum(); +} + +/** + * @beta + * Creates an expression that splits the value of a field on the provided delimiter. + * + * @example + * ```typescript + * // Split the 'scoresCsv' field on delimiter ',' + * split('scoresCsv', ',') + * ``` + * + * @param fieldName Split the value in this field. + * @param delimiter Split on this delimiter. + * + * @return A new {@code Expression} representing the split function. + */ +export function split(fieldName: string, delimiter: string): FunctionExpression; + +/** + * @beta + * Creates an expression that splits the value of a field on the provided delimiter. + * + * @example + * ```typescript + * // Split the 'scores' field on delimiter ',' or ':' depending on the stored format + * split('scores', conditional(field('format').equal('csv'), constant(','), constant(':')) + * ``` + * + * @param fieldName Split the value in this field. + * @param delimiter Split on this delimiter returned by evaluating this expression. + * + * @return A new {@code Expression} representing the split function. + */ +export function split( + fieldName: string, + delimiter: Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that splits a string into an array of substrings based on the provided delimiter. + * + * @example + * ```typescript + * // Split the 'scoresCsv' field on delimiter ',' + * split(field('scoresCsv'), ',') + * ``` + * + * @param expression Split the result of this expression. + * @param delimiter Split on this delimiter. + * + * @return A new {@code Expression} representing the split function. + */ +export function split( + expression: Expression, + delimiter: string +): FunctionExpression; + +/** + * @beta + * Creates an expression that splits a string into an array of substrings based on the provided delimiter. + * + * @example + * ```typescript + * // Split the 'scores' field on delimiter ',' or ':' depending on the stored format + * split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':')) + * ``` + * + * @param expression Split the result of this expression. + * @param delimiter Split on this delimiter returned by evaluating this expression. + * + * @return A new {@code Expression} representing the split function. + */ +export function split( + expression: Expression, + delimiter: Expression +): FunctionExpression; +export function split( + fieldNameOrExpression: string | Expression, + delimiter: string | Expression +): FunctionExpression { + return fieldOrExpression(fieldNameOrExpression).split( + valueToDefaultExpr(delimiter) + ); +} + +/** + * @beta + * Creates an expression that truncates a timestamp to a specified granularity. + * + * @example + * ```typescript + * // Truncate the 'createdAt' timestamp to the beginning of the day. + * field('createdAt').timestampTruncate('day') + * ``` + * + * @param fieldName Truncate the timestamp value contained in this field. + * @param granularity The granularity to truncate to. + * @param timezone The timezone to use for truncation. Valid values are from + * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". + * @return A new {Expression} representing the truncated timestamp. + */ +export function timestampTruncate( + fieldName: string, + granularity: TimeGranularity, + timezone?: string | Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that truncates a timestamp to a specified granularity. + * + * @example + * ```typescript + * // Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. + * field('createdAt').timestampTruncate(field('granularity')) + * ``` + * + * @param fieldName Truncate the timestamp value contained in this field. + * @param granularity The granularity to truncate to. + * @param timezone The timezone to use for truncation. Valid values are from + * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". + * @return A new {Expression} representing the truncated timestamp. + */ +export function timestampTruncate( + fieldName: string, + granularity: Expression, + timezone?: string | Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that truncates a timestamp to a specified granularity. + * + * @example + * ```typescript + * // Truncate the 'createdAt' timestamp to the beginning of the day. + * field('createdAt').timestampTruncate('day') + * ``` + * + * @param timestampExpression Truncate the timestamp value that is returned by this expression. + * @param granularity The granularity to truncate to. + * @param timezone The timezone to use for truncation. Valid values are from + * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". + * @return A new {Expression} representing the truncated timestamp. + */ +export function timestampTruncate( + timestampExpression: Expression, + granularity: TimeGranularity, + timezone?: string | Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that truncates a timestamp to a specified granularity. + * + * @example + * ```typescript + * // Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. + * field('createdAt').timestampTruncate(field('granularity')) + * ``` + * + * @param timestampExpression Truncate the timestamp value that is returned by this expression. + * @param granularity The granularity to truncate to. + * @param timezone The timezone to use for truncation. Valid values are from + * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". + * @return A new {Expression} representing the truncated timestamp. + */ +export function timestampTruncate( + timestampExpression: Expression, + granularity: Expression, + timezone?: string | Expression +): FunctionExpression; +export function timestampTruncate( + fieldNameOrExpression: string | Expression, + granularity: TimeGranularity | Expression, + timezone?: string | Expression +): FunctionExpression { + const internalGranularity = isString(granularity) + ? valueToDefaultExpr(granularity.toLowerCase()) + : granularity; + return fieldOrExpression(fieldNameOrExpression).timestampTruncate( + internalGranularity, + timezone + ); +} + +/** + * @beta + * Creates an expression that returns the data type of the data in the specified field. + * + * @example + * ```typescript + * // Get the data type of the value in field 'title' + * type('title') + * ``` + * + * @return A new {Expression} representing the data type. + */ +export function type(fieldName: string): FunctionExpression; +/** + * @beta + * Creates an expression that returns the data type of an expression's result. + * + * @example + * ```typescript + * // Get the data type of a conditional expression + * type(conditional(exists('foo'), constant(1), constant(true))) + * ``` + * + * @return A new {Expression} representing the data type. + */ +export function type(expression: Expression): FunctionExpression; +export function type( + fieldNameOrExpression: string | Expression +): FunctionExpression { + return fieldOrExpression(fieldNameOrExpression).type(); +} + +// TODO(new-expression): Add new top-level expression function definitions above this line + +/** + * @beta + * + * Creates an {@link Ordering} that sorts documents in ascending order based on an expression. + * + * ```typescript + * // Sort documents by the 'name' field in lowercase in ascending order + * firestore.pipeline().collection("users") + * .sort(ascending(field("name").toLower())); + * ``` + * + * @param expr The expression to create an ascending ordering for. + * @return A new `Ordering` for ascending sorting. + */ +export function ascending(expr: Expression): Ordering; + +/** + * @beta + * + * Creates an {@link Ordering} that sorts documents in ascending order based on a field. + * + * ```typescript + * // Sort documents by the 'name' field in ascending order + * firestore.pipeline().collection("users") + * .sort(ascending("name")); + * ``` + * + * @param fieldName The field to create an ascending ordering for. + * @return A new `Ordering` for ascending sorting. + */ +export function ascending(fieldName: string): Ordering; +export function ascending(field: Expression | string): Ordering { + return new Ordering(fieldOrExpression(field), 'ascending', 'ascending'); +} + +/** + * @beta + * + * Creates an {@link Ordering} that sorts documents in descending order based on an expression. + * + * ```typescript + * // Sort documents by the 'name' field in lowercase in descending order + * firestore.pipeline().collection("users") + * .sort(descending(field("name").toLower())); + * ``` + * + * @param expr The expression to create a descending ordering for. + * @return A new `Ordering` for descending sorting. + */ +export function descending(expr: Expression): Ordering; + +/** + * @beta + * + * Creates an {@link Ordering} that sorts documents in descending order based on a field. + * + * ```typescript + * // Sort documents by the 'name' field in descending order + * firestore.pipeline().collection("users") + * .sort(descending("name")); + * ``` + * + * @param fieldName The field to create a descending ordering for. + * @return A new `Ordering` for descending sorting. + */ +export function descending(fieldName: string): Ordering; +export function descending(field: Expression | string): Ordering { + return new Ordering(fieldOrExpression(field), 'descending', 'descending'); +} + +/** + * @beta + * + * Represents an ordering criterion for sorting documents in a Firestore pipeline. + * + * You create `Ordering` instances using the `ascending` and `descending` helper functions. + */ +export class Ordering implements ProtoValueSerializable, UserData { + constructor( + public readonly expr: Expression, + public readonly direction: 'ascending' | 'descending', + readonly _methodName: string | undefined + ) {} + + /** + * @private + * @internal + */ + _toProto(serializer: JsonProtoSerializer): ProtoValue { + return { + mapValue: { + fields: { + direction: toStringValue(this.direction), + expression: this.expr._toProto(serializer) + } + } + }; + } + + /** + * @private + * @internal + */ + _readUserData(context: ParseContext): void { + this.expr._readUserData(context); + } + + _protoValueType: 'ProtoValue' = 'ProtoValue'; +} + +export function isSelectable(val: unknown): val is Selectable { + const candidate = val as Selectable; + return ( + candidate.selectable && isString(candidate.alias) && isExpr(candidate.expr) + ); +} + +export function isOrdering(val: unknown): val is Ordering { + const candidate = val as Ordering; + return ( + isExpr(candidate.expr) && + (candidate.direction === 'ascending' || + candidate.direction === 'descending') + ); +} + +export function isAliasedAggregate(val: unknown): val is AliasedAggregate { + const candidate = val as AliasedAggregate; + return ( + isString(candidate.alias) && + candidate.aggregate instanceof AggregateFunction + ); +} + +export function isExpr(val: unknown): val is Expression { + return val instanceof Expression; +} + +export function isBooleanExpr(val: unknown): val is BooleanExpression { + return val instanceof BooleanExpression; +} + +export function isField(val: unknown): val is Field { + return val instanceof Field; +} + +export function toField(value: string | Field): Field { + if (isString(value)) { + const result = field(value); + return result; + } else { + return value as Field; + } +} diff --git a/packages/firestore/src/lite-api/pipeline-result.ts b/packages/firestore/src/lite-api/pipeline-result.ts new file mode 100644 index 0000000000..a853a65299 --- /dev/null +++ b/packages/firestore/src/lite-api/pipeline-result.ts @@ -0,0 +1,278 @@ +/** + * @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. + */ + +import { ObjectValue } from '../model/object_value'; +import { firestoreV1ApiClientInterfaces } from '../protos/firestore_proto_api'; +import { isOptionalEqual } from '../util/misc'; + +import { Field, isField } from './expressions'; +import { FieldPath } from './field_path'; +import { Pipeline } from './pipeline'; +import { DocumentData, DocumentReference, refEqual } from './reference'; +import { Timestamp } from './timestamp'; +import { fieldPathFromArgument } from './user_data_reader'; +import { AbstractUserDataWriter } from './user_data_writer'; + +/** + * @beta + * Represents the results of a Firestore pipeline execution. + * + * A `PipelineSnapshot` contains zero or more {@link PipelineResult} objects + * representing the documents returned by a pipeline query. It provides methods + * to iterate over the documents and access metadata about the query results. + * + * @example + * ```typescript + * const snapshot: PipelineSnapshot = await firestore + * .pipeline() + * .collection('myCollection') + * .where(field('value').greaterThan(10)) + * .execute(); + * + * snapshot.results.forEach(doc => { + * console.log(doc.id, '=>', doc.data()); + * }); + * ``` + */ +export class PipelineSnapshot { + private readonly _pipeline: Pipeline; + private readonly _executionTime: Timestamp | undefined; + private readonly _results: PipelineResult[]; + constructor( + pipeline: Pipeline, + results: PipelineResult[], + executionTime?: Timestamp + ) { + this._pipeline = pipeline; + this._executionTime = executionTime; + this._results = results; + } + + /** + * @beta An array of all the results in the `PipelineSnapshot`. + */ + get results(): PipelineResult[] { + return this._results; + } + + /** + * @beta + * The time at which the pipeline producing this result is executed. + * + * @type {Timestamp} + * @readonly + * + */ + get executionTime(): Timestamp { + if (this._executionTime === undefined) { + throw new Error( + "'executionTime' is expected to exist, but it is undefined" + ); + } + return this._executionTime; + } +} + +/** + * @beta + * + * A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the + * {@link #data()} or {@link #get(String)} methods. + * + *

If the PipelineResult represents a non-document result, `ref` will return a undefined + * value. + */ +export class PipelineResult { + private readonly _userDataWriter: AbstractUserDataWriter; + + private readonly _createTime: Timestamp | undefined; + private readonly _updateTime: Timestamp | undefined; + + /** + * @internal + * @private + */ + readonly _ref: DocumentReference | undefined; + + /** + * @internal + * @private + */ + readonly _fields: ObjectValue; + + /** + * @private + * @internal + * + * @param userDataWriter The serializer used to encode/decode protobuf. + * @param ref The reference to the document. + * @param fields The fields of the Firestore `Document` Protobuf backing + * this document. + * @param createTime The time when the document was created if the result is a document, undefined otherwise. + * @param updateTime The time when the document was last updated if the result is a document, undefined otherwise. + */ + constructor( + userDataWriter: AbstractUserDataWriter, + fields: ObjectValue, + ref?: DocumentReference, + createTime?: Timestamp, + updateTime?: Timestamp + ) { + this._ref = ref; + this._userDataWriter = userDataWriter; + this._createTime = createTime; + this._updateTime = updateTime; + this._fields = fields; + } + + /** + * @beta + * The reference of the document, if it is a document; otherwise `undefined`. + */ + get ref(): DocumentReference | undefined { + return this._ref; + } + + /** + * @beta + * The ID of the document for which this PipelineResult contains data, if it is a document; otherwise `undefined`. + * + * @type {string} + * @readonly + * + */ + get id(): string | undefined { + return this._ref?.id; + } + + /** + * @beta + * The time the document was created. Undefined if this result is not a document. + * + * @type {Timestamp|undefined} + * @readonly + */ + get createTime(): Timestamp | undefined { + return this._createTime; + } + + /** + * @beta + * The time the document was last updated (at the time the snapshot was + * generated). Undefined if this result is not a document. + * + * @type {Timestamp|undefined} + * @readonly + */ + get updateTime(): Timestamp | undefined { + return this._updateTime; + } + + /** + * @beta + * Retrieves all fields in the result as an object. + * + * @returns {T} An object containing all fields in the document or + * 'undefined' if the document doesn't exist. + * + * @example + * ``` + * let p = firestore.pipeline().collection('col'); + * + * p.execute().then(results => { + * let data = results[0].data(); + * console.log(`Retrieved data: ${JSON.stringify(data)}`); + * }); + * ``` + */ + data(): AppModelType { + return this._userDataWriter.convertValue( + this._fields.value + ) as AppModelType; + } + + /** + * @internal + * @private + * + * Retrieves all fields in the result as a proto value. + * + * @returns An `Object` containing all fields in the result. + */ + _fieldsProto(): { [key: string]: firestoreV1ApiClientInterfaces.Value } { + // Return a cloned value to prevent manipulation of the Snapshot's data + return this._fields.clone().value.mapValue.fields!; + } + + /** + * @beta + * Retrieves the field specified by `field`. + * + * @param {string|FieldPath|Field} field The field path + * (e.g. 'foo' or 'foo.bar') to a specific field. + * @returns {*} The data at the specified field location or undefined if no + * such field exists. + * + * @example + * ``` + * let p = firestore.pipeline().collection('col'); + * + * p.execute().then(results => { + * let field = results[0].get('a.b'); + * console.log(`Retrieved field value: ${field}`); + * }); + * ``` + */ + // We deliberately use `any` in the external API to not impose type-checking + // on end users. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + get(fieldPath: string | FieldPath | Field): any { + if (this._fields === undefined) { + return undefined; + } + if (isField(fieldPath)) { + fieldPath = fieldPath.fieldName; + } + + const value = this._fields.field( + fieldPathFromArgument('DocumentSnapshot.get', fieldPath) + ); + if (value !== null) { + return this._userDataWriter.convertValue(value); + } + } +} + +/** + * @beta + * Test equality of two PipelineResults. + * @param left + * @param right + */ +export function pipelineResultEqual( + left: PipelineResult, + right: PipelineResult +): boolean { + if (left === right) { + return true; + } + + return ( + isOptionalEqual(left._ref, right._ref, refEqual) && + isOptionalEqual(left._fields, right._fields, (l, r) => l.isEqual(r)) + ); +} diff --git a/packages/firestore/src/lite-api/pipeline-source.ts b/packages/firestore/src/lite-api/pipeline-source.ts new file mode 100644 index 0000000000..0186ca3526 --- /dev/null +++ b/packages/firestore/src/lite-api/pipeline-source.ts @@ -0,0 +1,278 @@ +/** + * @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. + */ + +import { DatabaseId } from '../core/database_info'; +import { toPipeline } from '../core/pipeline-util'; +import { Code, FirestoreError } from '../util/error'; +import { isString } from '../util/types'; + +import { Pipeline } from './pipeline'; +import { + CollectionReference, + DocumentReference, + isCollectionReference, + Query +} from './reference'; +import { + CollectionGroupSource, + CollectionSource, + DatabaseSource, + DocumentsSource, + Stage +} from './stage'; +import { + CollectionGroupStageOptions, + CollectionStageOptions, + DatabaseStageOptions, + DocumentsStageOptions +} from './stage_options'; +import { UserDataReader, UserDataSource } from './user_data_reader'; + +/** + * @beta + * Provides the entry point for defining the data source of a Firestore {@link Pipeline}. + * + * Use the methods of this class (e.g., {@link PipelineSource#collection}, {@link PipelineSource#collectionGroup}, + * {@link PipelineSource#database}, or {@link PipelineSource#documents}) to specify the initial data + * for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. + */ +export class PipelineSource { + /** + * @internal + * @private + * @param databaseId + * @param userDataReader + * @param _createPipeline + */ + constructor( + private databaseId: DatabaseId, + private userDataReader: UserDataReader, + /** + * @internal + * @private + */ + public _createPipeline: (stages: Stage[]) => PipelineType + ) {} + + /** + * @beta + * Returns all documents from the entire collection. The collection can be nested. + * @param collection - Name or reference to the collection that will be used as the Pipeline source. + */ + collection(collection: string | CollectionReference): PipelineType; + /** + * @beta + * Returns all documents from the entire collection. The collection can be nested. + * @param options - Options defining how this CollectionStage is evaluated. + */ + collection(options: CollectionStageOptions): PipelineType; + collection( + collectionOrOptions: string | CollectionReference | CollectionStageOptions + ): PipelineType { + // Process argument union(s) from method overloads + const options = + isString(collectionOrOptions) || + isCollectionReference(collectionOrOptions) + ? {} + : collectionOrOptions; + const collectionRefOrString = + isString(collectionOrOptions) || + isCollectionReference(collectionOrOptions) + ? collectionOrOptions + : collectionOrOptions.collection; + + // Validate that a user provided reference is for the same Firestore DB + if (isCollectionReference(collectionRefOrString)) { + this._validateReference(collectionRefOrString); + } + + // Convert user land convenience types to internal types + const normalizedCollection = isString(collectionRefOrString) + ? (collectionRefOrString as string) + : collectionRefOrString.path; + + // Create stage object + const stage = new CollectionSource(normalizedCollection, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'collection' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._createPipeline([stage]); + } + + /** + * @beta + * Returns all documents from a collection ID regardless of the parent. + * @param collectionId - ID of the collection group to use as the Pipeline source. + */ + collectionGroup(collectionId: string): PipelineType; + /** + * @beta + * Returns all documents from a collection ID regardless of the parent. + * @param options - Options defining how this CollectionGroupStage is evaluated. + */ + collectionGroup(options: CollectionGroupStageOptions): PipelineType; + collectionGroup( + collectionIdOrOptions: string | CollectionGroupStageOptions + ): PipelineType { + // Process argument union(s) from method overloads + let collectionId: string; + let options: {}; + if (isString(collectionIdOrOptions)) { + collectionId = collectionIdOrOptions; + options = {}; + } else { + ({ collectionId, ...options } = collectionIdOrOptions); + } + + // Create stage object + const stage = new CollectionGroupSource(collectionId, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'collectionGroup' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._createPipeline([stage]); + } + + /** + * @beta + * Returns all documents from the entire database. + */ + database(): PipelineType; + /** + * @beta + * Returns all documents from the entire database. + * @param options - Options defining how a DatabaseStage is evaluated. + */ + database(options: DatabaseStageOptions): PipelineType; + database(options?: DatabaseStageOptions): PipelineType { + // Process argument union(s) from method overloads + options = options ?? {}; + + // Create stage object + const stage = new DatabaseSource(options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'database' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._createPipeline([stage]); + } + + /** + * @beta + * Set the pipeline's source to the documents specified by the given paths and DocumentReferences. + * + * @param docs An array of paths and DocumentReferences specifying the individual documents that will be the source of this pipeline. + * The converters for these DocumentReferences will be ignored and not have an effect on this pipeline. + * + * @throws {@FirestoreError} Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. + */ + documents(docs: Array): PipelineType; + + /** + * @beta + * Set the pipeline's source to the documents specified by the given paths and DocumentReferences. + * + * @param options - Options defining how this DocumentsStage is evaluated. + * + * @throws {@FirestoreError} Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. + */ + documents(options: DocumentsStageOptions): PipelineType; + documents( + docsOrOptions: Array | DocumentsStageOptions + ): PipelineType { + // Process argument union(s) from method overloads + let options: {}; + let docs: Array; + if (Array.isArray(docsOrOptions)) { + docs = docsOrOptions; + options = {}; + } else { + ({ docs, ...options } = docsOrOptions); + } + + // Validate that all user provided references are for the same Firestore DB + docs + .filter(v => v instanceof DocumentReference) + .forEach(dr => this._validateReference(dr as DocumentReference)); + + // Convert user land convenience types to internal types + const normalizedDocs: string[] = docs.map(doc => + isString(doc) ? doc : doc.path + ); + + // Create stage object + const stage = new DocumentsSource(normalizedDocs, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'documents' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._createPipeline([stage]); + } + + /** + * @beta + * Convert the given Query into an equivalent Pipeline. + * + * @param query A Query to be converted into a Pipeline. + * + * @throws {@FirestoreError} Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. + */ + createFrom(query: Query): Pipeline { + return toPipeline(query._query, query.firestore); + } + + _validateReference(reference: CollectionReference | DocumentReference): void { + const refDbId = reference.firestore._databaseId; + if (!refDbId.isEqual(this.databaseId)) { + throw new FirestoreError( + Code.INVALID_ARGUMENT, + `Invalid ${ + reference instanceof CollectionReference + ? 'CollectionReference' + : 'DocumentReference' + }. ` + + `The project ID ("${refDbId.projectId}") or the database ("${refDbId.database}") does not match ` + + `the project ID ("${this.databaseId.projectId}") and database ("${this.databaseId.database}") of the target database of this Pipeline.` + ); + } + } +} diff --git a/packages/firestore/src/lite-api/pipeline.ts b/packages/firestore/src/lite-api/pipeline.ts new file mode 100644 index 0000000000..4352e30f4c --- /dev/null +++ b/packages/firestore/src/lite-api/pipeline.ts @@ -0,0 +1,1478 @@ +/** + * @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. + */ + +import { + Pipeline as ProtoPipeline, + Stage as ProtoStage +} from '../protos/firestore_proto_api'; +import { JsonProtoSerializer, ProtoSerializable } from '../remote/serializer'; +import { isPlainObject } from '../util/input_validation'; +import { + aliasedAggregateToMap, + fieldOrExpression, + selectablesToMap, + vectorToExpr +} from '../util/pipeline_util'; +import { isNumber, isString } from '../util/types'; + +import { Firestore } from './database'; +import { + _mapValue, + AggregateFunction, + AliasedAggregate, + BooleanExpression, + _constant, + Expression, + Field, + field, + Ordering, + Selectable, + _field, + isSelectable, + isField, + isBooleanExpr, + isAliasedAggregate, + toField, + isOrdering, + isExpr +} from './expressions'; +import { + AddFields, + Aggregate, + Distinct, + FindNearest, + RawStage, + Limit, + Offset, + RemoveFields, + Replace, + Sample, + Select, + Sort, + Stage, + Union, + Unnest, + Where +} from './stage'; +import { + AddFieldsStageOptions, + AggregateStageOptions, + DistinctStageOptions, + FindNearestStageOptions, + LimitStageOptions, + OffsetStageOptions, + RemoveFieldsStageOptions, + ReplaceWithStageOptions, + SampleStageOptions, + SelectStageOptions, + SortStageOptions, + StageOptions, + UnionStageOptions, + UnnestStageOptions, + WhereStageOptions +} from './stage_options'; +import { UserDataReader, UserDataSource } from './user_data_reader'; +import { AbstractUserDataWriter } from './user_data_writer'; + +/** + * @beta + * + * The Pipeline class provides a flexible and expressive framework for building complex data + * transformation and query pipelines for Firestore. + * + * A pipeline takes data sources, such as Firestore collections or collection groups, and applies + * a series of stages that are chained together. Each stage takes the output from the previous stage + * (or the data source) and produces an output for the next stage (or as the final output of the + * pipeline). + * + * Expressions can be used within each stage to filter and transform data through the stage. + * + * NOTE: The chained stages do not prescribe exactly how Firestore will execute the pipeline. + * Instead, Firestore only guarantees that the result is the same as if the chained stages were + * executed in order. + * + * Usage Examples: + * + * ```typescript + * const db: Firestore; // Assumes a valid firestore instance. + * + * // Example 1: Select specific fields and rename 'rating' to 'bookRating' + * const results1 = await execute(db.pipeline() + * .collection("books") + * .select("title", "author", field("rating").as("bookRating"))); + * + * // Example 2: Filter documents where 'genre' is "Science Fiction" and 'published' is after 1950 + * const results2 = await execute(db.pipeline() + * .collection("books") + * .where(and(field("genre").eq("Science Fiction"), field("published").gt(1950)))); + * + * // Example 3: Calculate the average rating of books published after 1980 + * const results3 = await execute(db.pipeline() + * .collection("books") + * .where(field("published").gt(1980)) + * .aggregate(avg(field("rating")).as("averageRating"))); + * ``` + */ +export class Pipeline implements ProtoSerializable { + /** + * @internal + * @private + * @param _db + * @param userDataReader + * @param _userDataWriter + * @param stages + */ + constructor( + /** + * @internal + * @private + */ + public _db: Firestore, + /** + * @internal + * @private + */ + private userDataReader: UserDataReader, + /** + * @internal + * @private + */ + public _userDataWriter: AbstractUserDataWriter, + /** + * @internal + * @private + */ + private stages: Stage[] + ) {} + + /** + * @beta + * Adds new fields to outputs from previous stages. + * + * This stage allows you to compute values on-the-fly based on existing data from previous + * stages or constants. You can use this to create new fields or overwrite existing ones (if there + * is name overlaps). + * + * The added fields are defined using {@link Selectable}s, which can be: + * + * - {@link Field}: References an existing document field. + * - {@link Expression}: Either a literal value (see {@link Constant}) or a computed value + * (see {@FunctionExpr}) with an assigned alias using {@link Expression#as}. + * + * Example: + * + * ```typescript + * firestore.pipeline().collection("books") + * .addFields( + * field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' + * add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' + * ); + * ``` + * + * @param field The first field to add to the documents, specified as a {@link Selectable}. + * @param additionalFields Optional additional fields to add to the documents, specified as {@link Selectable}s. + * @return A new Pipeline object with this stage appended to the stage list. + */ + addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; + /** + * @beta + * Adds new fields to outputs from previous stages. + * + * This stage allows you to compute values on-the-fly based on existing data from previous + * stages or constants. You can use this to create new fields or overwrite existing ones (if there + * is name overlaps). + * + * The added fields are defined using {@link Selectable}s, which can be: + * + * - {@link Field}: References an existing document field. + * - {@link Expression}: Either a literal value (see {@link Constant}) or a computed value + * (see {@FunctionExpr}) with an assigned alias using {@link Expression#as}. + * + * Example: + * + * ```typescript + * firestore.pipeline().collection("books") + * .addFields( + * field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' + * add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' + * ); + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new Pipeline object with this stage appended to the stage list. + */ + addFields(options: AddFieldsStageOptions): Pipeline; + addFields( + fieldOrOptions: Selectable | AddFieldsStageOptions, + ...additionalFields: Selectable[] + ): Pipeline { + // Process argument union(s) from method overloads + let fields: Selectable[]; + let options: {}; + if (isSelectable(fieldOrOptions)) { + fields = [fieldOrOptions, ...additionalFields]; + options = {}; + } else { + ({ fields, ...options } = fieldOrOptions); + } + + // Convert user land convenience types to internal types + const normalizedFields: Map = selectablesToMap(fields); + + // Create stage object + const stage = new AddFields(normalizedFields, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'addFields' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Remove fields from outputs of previous stages. + * + * Example: + * + * ```typescript + * firestore.pipeline().collection('books') + * // removes field 'rating' and 'cost' from the previous stage outputs. + * .removeFields( + * field('rating'), + * 'cost' + * ); + * ``` + * + * @param fieldValue The first field to remove. + * @param additionalFields Optional additional fields to remove. + * @return A new Pipeline object with this stage appended to the stage list. + */ + removeFields( + fieldValue: Field | string, + ...additionalFields: Array + ): Pipeline; + /** + * @beta + * Remove fields from outputs of previous stages. + * + * Example: + * + * ```typescript + * firestore.pipeline().collection('books') + * // removes field 'rating' and 'cost' from the previous stage outputs. + * .removeFields( + * field('rating'), + * 'cost' + * ); + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new Pipeline object with this stage appended to the stage list. + */ + removeFields(options: RemoveFieldsStageOptions): Pipeline; + removeFields( + fieldValueOrOptions: Field | string | RemoveFieldsStageOptions, + ...additionalFields: Array + ): Pipeline { + // Process argument union(s) from method overloads + const options = + isField(fieldValueOrOptions) || isString(fieldValueOrOptions) + ? {} + : fieldValueOrOptions; + const fields: Array = + isField(fieldValueOrOptions) || isString(fieldValueOrOptions) + ? [fieldValueOrOptions, ...additionalFields] + : fieldValueOrOptions.fields; + + // Convert user land convenience types to internal types + const convertedFields: Field[] = fields.map(f => + isString(f) ? field(f) : (f as Field) + ); + + // Create stage object + const stage = new RemoveFields(convertedFields, options); + + // User data must be read in the context of the API method to + // provide contextual errors + stage._readUserData( + this.userDataReader.createContext(UserDataSource.Argument, 'removeFields') + ); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Selects or creates a set of fields from the outputs of previous stages. + * + *

The selected fields are defined using {@link Selectable} expressions, which can be: + * + *

    + *
  • {@code string}: Name of an existing field
  • + *
  • {@link Field}: References an existing field.
  • + *
  • {@link Function}: Represents the result of a function with an assigned alias name using + * {@link Expression#as}
  • + *
+ * + *

If no selections are provided, the output of this stage is empty. Use {@link + * Pipeline#addFields} instead if only additions are + * desired. + * + *

Example: + * + * ```typescript + * db.pipeline().collection("books") + * .select( + * "firstName", + * field("lastName"), + * field("address").toUppercase().as("upperAddress"), + * ); + * ``` + * + * @param selection The first field to include in the output documents, specified as {@link + * Selectable} expression or string value representing the field name. + * @param additionalSelections Optional additional fields to include in the output documents, specified as {@link + * Selectable} expressions or {@code string} values representing field names. + * @return A new Pipeline object with this stage appended to the stage list. + */ + select( + selection: Selectable | string, + ...additionalSelections: Array + ): Pipeline; + /** + * @beta + * Selects or creates a set of fields from the outputs of previous stages. + * + *

The selected fields are defined using {@link Selectable} expressions, which can be: + * + *

    + *
  • {@code string}: Name of an existing field
  • + *
  • {@link Field}: References an existing field.
  • + *
  • {@link Function}: Represents the result of a function with an assigned alias name using + * {@link Expression#as}
  • + *
+ * + *

If no selections are provided, the output of this stage is empty. Use {@link + * Pipeline#addFields} instead if only additions are + * desired. + * + *

Example: + * + * ```typescript + * db.pipeline().collection("books") + * .select( + * "firstName", + * field("lastName"), + * field("address").toUppercase().as("upperAddress"), + * ); + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new Pipeline object with this stage appended to the stage list. + */ + select(options: SelectStageOptions): Pipeline; + select( + selectionOrOptions: Selectable | string | SelectStageOptions, + ...additionalSelections: Array + ): Pipeline { + // Process argument union(s) from method overloads + const options = + isSelectable(selectionOrOptions) || isString(selectionOrOptions) + ? {} + : selectionOrOptions; + + const selections: Array = + isSelectable(selectionOrOptions) || isString(selectionOrOptions) + ? [selectionOrOptions, ...additionalSelections] + : selectionOrOptions.selections; + + // Convert user land convenience types to internal types + const normalizedSelections: Map = + selectablesToMap(selections); + + // Create stage object + const stage = new Select(normalizedSelections, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'select' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Filters the documents from previous stages to only include those matching the specified {@link + * BooleanExpression}. + * + *

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. + * You can filter documents based on their field values, using implementations of {@link + * BooleanExpression}, typically including but not limited to: + * + *

    + *
  • field comparators: {@link Function#eq}, {@link Function#lt} (less than), {@link + * Function#gt} (greater than), etc.
  • + *
  • logical operators: {@link Function#and}, {@link Function#or}, {@link Function#not}, etc.
  • + *
  • advanced functions: {@link Function#regexMatch}, {@link + * Function#arrayContains}, etc.
  • + *
+ * + *

Example: + * + * ```typescript + * firestore.pipeline().collection("books") + * .where( + * and( + * gt(field("rating"), 4.0), // Filter for ratings greater than 4.0 + * field("genre").eq("Science Fiction") // Equivalent to gt("genre", "Science Fiction") + * ) + * ); + * ``` + * + * @param condition The {@link BooleanExpression} to apply. + * @return A new Pipeline object with this stage appended to the stage list. + */ + where(condition: BooleanExpression): Pipeline; + /** + * @beta + * Filters the documents from previous stages to only include those matching the specified {@link + * BooleanExpression}. + * + *

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. + * You can filter documents based on their field values, using implementations of {@link + * BooleanExpression}, typically including but not limited to: + * + *

    + *
  • field comparators: {@link Function#eq}, {@link Function#lt} (less than), {@link + * Function#gt} (greater than), etc.
  • + *
  • logical operators: {@link Function#and}, {@link Function#or}, {@link Function#not}, etc.
  • + *
  • advanced functions: {@link Function#regexMatch}, {@link + * Function#arrayContains}, etc.
  • + *
+ * + *

Example: + * + * ```typescript + * firestore.pipeline().collection("books") + * .where( + * and( + * gt(field("rating"), 4.0), // Filter for ratings greater than 4.0 + * field("genre").eq("Science Fiction") // Equivalent to gt("genre", "Science Fiction") + * ) + * ); + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new Pipeline object with this stage appended to the stage list. + */ + where(options: WhereStageOptions): Pipeline; + where(conditionOrOptions: BooleanExpression | WhereStageOptions): Pipeline { + // Process argument union(s) from method overloads + const options = isBooleanExpr(conditionOrOptions) ? {} : conditionOrOptions; + const condition: BooleanExpression = isBooleanExpr(conditionOrOptions) + ? conditionOrOptions + : conditionOrOptions.condition; + + // Create stage object + const stage = new Where(condition, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'where' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Skips the first `offset` number of documents from the results of previous stages. + * + *

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve + * results in chunks. It is typically used in conjunction with {@link #limit} to control the + * size of each page. + * + *

Example: + * + * ```typescript + * // Retrieve the second page of 20 results + * firestore.pipeline().collection('books') + * .sort(field('published').descending()) + * .offset(20) // Skip the first 20 results + * .limit(20); // Take the next 20 results + * ``` + * + * @param offset The number of documents to skip. + * @return A new Pipeline object with this stage appended to the stage list. + */ + offset(offset: number): Pipeline; + /** + * @beta + * Skips the first `offset` number of documents from the results of previous stages. + * + *

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve + * results in chunks. It is typically used in conjunction with {@link #limit} to control the + * size of each page. + * + *

Example: + * + * ```typescript + * // Retrieve the second page of 20 results + * firestore.pipeline().collection('books') + * .sort(field('published').descending()) + * .offset(20) // Skip the first 20 results + * .limit(20); // Take the next 20 results + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new Pipeline object with this stage appended to the stage list. + */ + offset(options: OffsetStageOptions): Pipeline; + offset(offsetOrOptions: number | OffsetStageOptions): Pipeline { + // Process argument union(s) from method overloads + let options: {}; + let offset: number; + if (isNumber(offsetOrOptions)) { + options = {}; + offset = offsetOrOptions; + } else { + options = offsetOrOptions; + offset = offsetOrOptions.offset; + } + + // Create stage object + const stage = new Offset(offset, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'offset' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Limits the maximum number of documents returned by previous stages to `limit`. + * + *

This stage is particularly useful when you want to retrieve a controlled subset of data from + * a potentially large result set. It's often used for: + * + *

    + *
  • **Pagination:** In combination with {@link #offset} to retrieve specific pages of + * results.
  • + *
  • **Limiting Data Retrieval:** To prevent excessive data transfer and improve performance, + * especially when dealing with large collections.
  • + *
+ * + *

Example: + * + * ```typescript + * // Limit the results to the top 10 highest-rated books + * firestore.pipeline().collection('books') + * .sort(field('rating').descending()) + * .limit(10); + * ``` + * + * @param limit The maximum number of documents to return. + * @return A new Pipeline object with this stage appended to the stage list. + */ + limit(limit: number): Pipeline; + /** + * @beta + * Limits the maximum number of documents returned by previous stages to `limit`. + * + *

This stage is particularly useful when you want to retrieve a controlled subset of data from + * a potentially large result set. It's often used for: + * + *

    + *
  • **Pagination:** In combination with {@link #offset} to retrieve specific pages of + * results.
  • + *
  • **Limiting Data Retrieval:** To prevent excessive data transfer and improve performance, + * especially when dealing with large collections.
  • + *
+ * + *

Example: + * + * ```typescript + * // Limit the results to the top 10 highest-rated books + * firestore.pipeline().collection('books') + * .sort(field('rating').descending()) + * .limit(10); + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new Pipeline object with this stage appended to the stage list. + */ + limit(options: LimitStageOptions): Pipeline; + limit(limitOrOptions: number | LimitStageOptions): Pipeline { + // Process argument union(s) from method overloads + const options = isNumber(limitOrOptions) ? {} : limitOrOptions; + const limit: number = isNumber(limitOrOptions) + ? limitOrOptions + : limitOrOptions.limit; + + // Create stage object + const stage = new Limit(limit, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'limit' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Returns a set of distinct values from the inputs to this stage. + * + * This stage runs through the results from previous stages to include only results with + * unique combinations of {@link Expression} values ({@link Field}, {@link Function}, etc). + * + * The parameters to this stage are defined using {@link Selectable} expressions or strings: + * + * - {@code string}: Name of an existing field + * - {@link Field}: References an existing document field. + * - {@link AliasedExpr}: Represents the result of a function with an assigned alias name + * using {@link Expression#as}. + * + * Example: + * + * ```typescript + * // Get a list of unique author names in uppercase and genre combinations. + * firestore.pipeline().collection("books") + * .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") + * .select("authorName"); + * ``` + * + * @param group The {@link Selectable} expression or field name to consider when determining + * distinct value combinations. + * @param additionalGroups Optional additional {@link Selectable} expressions to consider when determining distinct + * value combinations or strings representing field names. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + distinct( + group: string | Selectable, + ...additionalGroups: Array + ): Pipeline; + /** + * @beta + * Returns a set of distinct values from the inputs to this stage. + * + * This stage runs through the results from previous stages to include only results with + * unique combinations of {@link Expression} values ({@link Field}, {@link Function}, etc). + * + * The parameters to this stage are defined using {@link Selectable} expressions or strings: + * + * - {@code string}: Name of an existing field + * - {@link Field}: References an existing document field. + * - {@link AliasedExpr}: Represents the result of a function with an assigned alias name + * using {@link Expression#as}. + * + * Example: + * + * ```typescript + * // Get a list of unique author names in uppercase and genre combinations. + * firestore.pipeline().collection("books") + * .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") + * .select("authorName"); + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + distinct(options: DistinctStageOptions): Pipeline; + distinct( + groupOrOptions: string | Selectable | DistinctStageOptions, + ...additionalGroups: Array + ): Pipeline { + // Process argument union(s) from method overloads + const options = + isString(groupOrOptions) || isSelectable(groupOrOptions) + ? {} + : groupOrOptions; + const groups: Array = + isString(groupOrOptions) || isSelectable(groupOrOptions) + ? [groupOrOptions, ...additionalGroups] + : groupOrOptions.groups; + + // Convert user land convenience types to internal types + const convertedGroups: Map = selectablesToMap(groups); + + // Create stage object + const stage = new Distinct(convertedGroups, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'distinct' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Performs aggregation operations on the documents from previous stages. + * + *

This stage allows you to calculate aggregate values over a set of documents. You define the + * aggregations to perform using {@link AliasedAggregate} expressions which are typically results of + * calling {@link Expression#as} on {@link AggregateFunction} instances. + * + *

Example: + * + * ```typescript + * // Calculate the average rating and the total number of books + * firestore.pipeline().collection("books") + * .aggregate( + * field("rating").avg().as("averageRating"), + * countAll().as("totalBooks") + * ); + * ``` + * + * @param accumulator The first {@link AliasedAggregate}, wrapping an {@link AggregateFunction} + * and providing a name for the accumulated results. + * @param additionalAccumulators Optional additional {@link AliasedAggregate}, each wrapping an {@link AggregateFunction} + * and providing a name for the accumulated results. + * @return A new Pipeline object with this stage appended to the stage list. + */ + aggregate( + accumulator: AliasedAggregate, + ...additionalAccumulators: AliasedAggregate[] + ): Pipeline; + /** + * @beta + * Performs optionally grouped aggregation operations on the documents from previous stages. + * + *

This stage allows you to calculate aggregate values over a set of documents, optionally + * grouped by one or more fields or functions. You can specify: + * + *

    + *
  • **Grouping Fields or Functions:** One or more fields or functions to group the documents + * by. For each distinct combination of values in these fields, a separate group is created. + * If no grouping fields are provided, a single group containing all documents is used. Not + * specifying groups is the same as putting the entire inputs into one group.
  • + *
  • **Accumulators:** One or more accumulation operations to perform within each group. These + * are defined using {@link AliasedAggregate} expressions, which are typically created by + * calling {@link Expression#as} on {@link AggregateFunction} instances. Each aggregation + * calculates a value (e.g., sum, average, count) based on the documents within its group.
  • + *
+ * + *

Example: + * + * ```typescript + * // Calculate the average rating for each genre. + * firestore.pipeline().collection("books") + * .aggregate({ + * accumulators: [avg(field("rating")).as("avg_rating")] + * groups: ["genre"] + * }); + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new {@code Pipeline} object with this stage appended to the stage + * list. + */ + aggregate(options: AggregateStageOptions): Pipeline; + aggregate( + targetOrOptions: AliasedAggregate | AggregateStageOptions, + ...rest: AliasedAggregate[] + ): Pipeline { + // Process argument union(s) from method overloads + const options = isAliasedAggregate(targetOrOptions) ? {} : targetOrOptions; + const accumulators: AliasedAggregate[] = isAliasedAggregate(targetOrOptions) + ? [targetOrOptions, ...rest] + : targetOrOptions.accumulators; + const groups: Array = isAliasedAggregate( + targetOrOptions + ) + ? [] + : targetOrOptions.groups ?? []; + + // Convert user land convenience types to internal types + const convertedAccumulators: Map = + aliasedAggregateToMap(accumulators); + const convertedGroups: Map = selectablesToMap(groups); + + // Create stage object + const stage = new Aggregate( + convertedGroups, + convertedAccumulators, + options + ); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'aggregate' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Performs a vector proximity search on the documents from the previous stage, returning the + * K-nearest documents based on the specified query `vectorValue` and `distanceMeasure`. The + * returned documents will be sorted in order from nearest to furthest from the query `vectorValue`. + * + *

Example: + * + * ```typescript + * // Find the 10 most similar books based on the book description. + * const bookDescription = "Lorem ipsum..."; + * const queryVector: number[] = ...; // compute embedding of `bookDescription` + * + * firestore.pipeline().collection("books") + * .findNearest({ + * field: 'embedding', + * vectorValue: queryVector, + * distanceMeasure: 'euclidean', + * limit: 10, // optional + * distanceField: 'computedDistance' // optional + * }); + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + findNearest(options: FindNearestStageOptions): Pipeline { + // Convert user land convenience types to internal types + const field = toField(options.field); + const vectorValue = vectorToExpr(options.vectorValue); + const distanceField = options.distanceField + ? toField(options.distanceField) + : undefined; + const internalOptions = { + distanceField, + limit: options.limit, + rawOptions: options.rawOptions + }; + + // Create stage object + const stage = new FindNearest( + vectorValue, + field, + options.distanceMeasure, + internalOptions + ); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'addFields' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Sorts the documents from previous stages based on one or more {@link Ordering} criteria. + * + *

This stage allows you to order the results of your pipeline. You can specify multiple {@link + * Ordering} instances to sort by multiple fields in ascending or descending order. If documents + * have the same value for a field used for sorting, the next specified ordering will be used. If + * all orderings result in equal comparison, the documents are considered equal and the order is + * unspecified. + * + *

Example: + * + * ```typescript + * // Sort books by rating in descending order, and then by title in ascending order for books + * // with the same rating + * firestore.pipeline().collection("books") + * .sort( + * Ordering.of(field("rating")).descending(), + * Ordering.of(field("title")) // Ascending order is the default + * ); + * ``` + * + * @param ordering The first {@link Ordering} instance specifying the sorting criteria. + * @param additionalOrderings Optional additional {@link Ordering} instances specifying the additional sorting criteria. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; + /** + * @beta + * Sorts the documents from previous stages based on one or more {@link Ordering} criteria. + * + *

This stage allows you to order the results of your pipeline. You can specify multiple {@link + * Ordering} instances to sort by multiple fields in ascending or descending order. If documents + * have the same value for a field used for sorting, the next specified ordering will be used. If + * all orderings result in equal comparison, the documents are considered equal and the order is + * unspecified. + * + *

Example: + * + * ```typescript + * // Sort books by rating in descending order, and then by title in ascending order for books + * // with the same rating + * firestore.pipeline().collection("books") + * .sort( + * Ordering.of(field("rating")).descending(), + * Ordering.of(field("title")) // Ascending order is the default + * ); + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + sort(options: SortStageOptions): Pipeline; + sort( + orderingOrOptions: Ordering | SortStageOptions, + ...additionalOrderings: Ordering[] + ): Pipeline { + // Process argument union(s) from method overloads + const options = isOrdering(orderingOrOptions) ? {} : orderingOrOptions; + const orderings: Ordering[] = isOrdering(orderingOrOptions) + ? [orderingOrOptions, ...additionalOrderings] + : orderingOrOptions.orderings; + + // Create stage object + const stage = new Sort(orderings, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'sort' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Fully overwrites all fields in a document with those coming from a nested map. + * + *

This stage allows you to emit a map value as a document. Each key of the map becomes a field + * on the document that contains the corresponding value. + * + *

Example: + * + * ```typescript + * // Input. + * // { + * // 'name': 'John Doe Jr.', + * // 'parents': { + * // 'father': 'John Doe Sr.', + * // 'mother': 'Jane Doe' + * // } + * // } + * + * // Emit parents as document. + * firestore.pipeline().collection('people').replaceWith('parents'); + * + * // Output + * // { + * // 'father': 'John Doe Sr.', + * // 'mother': 'Jane Doe' + * // } + * ``` + * + * @param fieldName The {@link Field} field containing the nested map. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + replaceWith(fieldName: string): Pipeline; + /** + * @beta + * Fully overwrites all fields in a document with those coming from a map. + * + *

This stage allows you to emit a map value as a document. Each key of the map becomes a field + * on the document that contains the corresponding value. + * + *

Example: + * + * ```typescript + * // Input. + * // { + * // 'name': 'John Doe Jr.', + * // 'parents': { + * // 'father': 'John Doe Sr.', + * // 'mother': 'Jane Doe' + * // } + * // } + * + * // Emit parents as document. + * firestore.pipeline().collection('people').replaceWith(map({ + * foo: 'bar', + * info: { + * name: field('name') + * } + * })); + * + * // Output + * // { + * // 'father': 'John Doe Sr.', + * // 'mother': 'Jane Doe' + * // } + * ``` + * + * @param expr An {@link Expression} that when returned evaluates to a map. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + replaceWith(expr: Expression): Pipeline; + /** + * @beta + * Fully overwrites all fields in a document with those coming from a map. + * + *

This stage allows you to emit a map value as a document. Each key of the map becomes a field + * on the document that contains the corresponding value. + * + *

Example: + * + * ```typescript + * // Input. + * // { + * // 'name': 'John Doe Jr.', + * // 'parents': { + * // 'father': 'John Doe Sr.', + * // 'mother': 'Jane Doe' + * // } + * // } + * + * // Emit parents as document. + * firestore.pipeline().collection('people').replaceWith(map({ + * foo: 'bar', + * info: { + * name: field('name') + * } + * })); + * + * // Output + * // { + * // 'father': 'John Doe Sr.', + * // 'mother': 'Jane Doe' + * // } + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + replaceWith(options: ReplaceWithStageOptions): Pipeline; + replaceWith( + valueOrOptions: Expression | string | ReplaceWithStageOptions + ): Pipeline { + // Process argument union(s) from method overloads + const options = + isString(valueOrOptions) || isExpr(valueOrOptions) ? {} : valueOrOptions; + const fieldNameOrExpr: string | Expression = + isString(valueOrOptions) || isExpr(valueOrOptions) + ? valueOrOptions + : valueOrOptions.map; + + // Convert user land convenience types to internal types + const mapExpr = fieldOrExpression(fieldNameOrExpr); + + // Create stage object + const stage = new Replace(mapExpr, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'replaceWith' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Performs a pseudo-random sampling of the documents from the previous stage. + * + *

This stage will filter documents pseudo-randomly. The parameter specifies how number of + * documents to be returned. + * + *

Examples: + * + * ```typescript + * // Sample 25 books, if available. + * firestore.pipeline().collection('books') + * .sample(25); + * ``` + * + * @param documents The number of documents to sample. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + sample(documents: number): Pipeline; + + /** + * @beta + * Performs a pseudo-random sampling of the documents from the previous stage. + * + *

This stage will filter documents pseudo-randomly. The 'options' parameter specifies how + * sampling will be performed. See {@code SampleOptions} for more information. + * + *

Examples: + * + * // Sample 10 books, if available. + * firestore.pipeline().collection("books") + * .sample({ documents: 10 }); + * + * // Sample 50% of books. + * firestore.pipeline().collection("books") + * .sample({ percentage: 0.5 }); + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + sample(options: SampleStageOptions): Pipeline; + sample(documentsOrOptions: number | SampleStageOptions): Pipeline { + // Process argument union(s) from method overloads + const options = isNumber(documentsOrOptions) ? {} : documentsOrOptions; + let rate: number; + let mode: 'documents' | 'percent'; + if (isNumber(documentsOrOptions)) { + rate = documentsOrOptions; + mode = 'documents'; + } else if (isNumber(documentsOrOptions.documents)) { + rate = documentsOrOptions.documents; + mode = 'documents'; + } else { + rate = documentsOrOptions.percentage!; + mode = 'percent'; + } + + // Create stage object + const stage = new Sample(rate, mode, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'sample' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Performs union of all documents from two pipelines, including duplicates. + * + *

This stage will pass through documents from previous stage, and also pass through documents + * from previous stage of the `other` {@code Pipeline} given in parameter. The order of documents + * emitted from this stage is undefined. + * + *

Example: + * + * ```typescript + * // Emit documents from books collection and magazines collection. + * firestore.pipeline().collection('books') + * .union(firestore.pipeline().collection('magazines')); + * ``` + * + * @param other The other {@code Pipeline} that is part of union. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + union(other: Pipeline): Pipeline; + /** + * @beta + * Performs union of all documents from two pipelines, including duplicates. + * + *

This stage will pass through documents from previous stage, and also pass through documents + * from previous stage of the `other` {@code Pipeline} given in parameter. The order of documents + * emitted from this stage is undefined. + * + *

Example: + * + * ```typescript + * // Emit documents from books collection and magazines collection. + * firestore.pipeline().collection('books') + * .union(firestore.pipeline().collection('magazines')); + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + union(options: UnionStageOptions): Pipeline; + union(otherOrOptions: Pipeline | UnionStageOptions): Pipeline { + // Process argument union(s) from method overloads + let options: {}; + let otherPipeline: Pipeline; + if (isPipeline(otherOrOptions)) { + options = {}; + otherPipeline = otherOrOptions; + } else { + ({ other: otherPipeline, ...options } = otherOrOptions); + } + + // Create stage object + const stage = new Union(otherPipeline, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'union' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Produces a document for each element in an input array. + * + * For each previous stage document, this stage will emit zero or more augmented documents. The + * input array specified by the `selectable` parameter, will emit an augmented document for each input array element. The input array element will + * augment the previous stage document by setting the `alias` field with the array element value. + * + * When `selectable` evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for + * the current input document, returning it as is with the `alias` field absent. + * + * No documents are emitted when `selectable` evaluates to an empty array. + * + * Example: + * + * ```typescript + * // Input: + * // { "title": "The Hitchhiker's Guide to the Galaxy", "tags": [ "comedy", "space", "adventure" ], ... } + * + * // Emit a book document for each tag of the book. + * firestore.pipeline().collection("books") + * .unnest(field("tags").as('tag'), 'tagIndex'); + * + * // Output: + * // { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "comedy", "tagIndex": 0, ... } + * // { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "space", "tagIndex": 1, ... } + * // { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "adventure", "tagIndex": 2, ... } + * ``` + * + * @param selectable A selectable expression defining the field to unnest and the alias to use for each un-nested element in the output documents. + * @param indexField An optional string value specifying the field path to write the offset (starting at zero) into the array the un-nested element is from + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + unnest(selectable: Selectable, indexField?: string): Pipeline; + /** + * @beta + * Produces a document for each element in an input array. + * + * For each previous stage document, this stage will emit zero or more augmented documents. The + * input array specified by the `selectable` parameter, will emit an augmented document for each input array element. The input array element will + * augment the previous stage document by setting the `alias` field with the array element value. + * + * When `selectable` evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for + * the current input document, returning it as is with the `alias` field absent. + * + * No documents are emitted when `selectable` evaluates to an empty array. + * + * Example: + * + * ```typescript + * // Input: + * // { "title": "The Hitchhiker's Guide to the Galaxy", "tags": [ "comedy", "space", "adventure" ], ... } + * + * // Emit a book document for each tag of the book. + * firestore.pipeline().collection("books") + * .unnest(field("tags").as('tag'), 'tagIndex'); + * + * // Output: + * // { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "comedy", "tagIndex": 0, ... } + * // { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "space", "tagIndex": 1, ... } + * // { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "adventure", "tagIndex": 2, ... } + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + unnest(options: UnnestStageOptions): Pipeline; + unnest( + selectableOrOptions: Selectable | UnnestStageOptions, + indexField?: string + ): Pipeline { + // Process argument union(s) from method overloads + let options: { indexField?: Field } & StageOptions; + let selectable: Selectable; + let indexFieldName: string | undefined; + if (isSelectable(selectableOrOptions)) { + options = {}; + selectable = selectableOrOptions; + indexFieldName = indexField; + } else { + ({ + selectable, + indexField: indexFieldName, + ...options + } = selectableOrOptions); + } + + // Convert user land convenience types to internal types + const alias = selectable.alias; + const expr = selectable.expr as Expression; + if (isString(indexFieldName)) { + options.indexField = _field(indexFieldName, 'unnest'); + } + + // Create stage object + const stage = new Unnest(alias, expr, options); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'unnest' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @beta + * Adds a raw stage to the pipeline. + * + *

This method provides a flexible way to extend the pipeline's functionality by adding custom + * stages. Each raw stage is defined by a unique `name` and a set of `params` that control its + * behavior. + * + *

Example (Assuming there is no 'where' stage available in SDK): + * + * ```typescript + * // Assume we don't have a built-in 'where' stage + * firestore.pipeline().collection('books') + * .rawStage('where', [field('published').lt(1900)]) // Custom 'where' stage + * .select('title', 'author'); + * ``` + * + * @param name - The unique name of the raw stage to add. + * @param params - A list of parameters to configure the raw stage's behavior. + * @param options - An object of key value pairs that specifies optional parameters for the stage. + * @return A new {@code Pipeline} object with this stage appended to the stage list. + */ + rawStage( + name: string, + params: unknown[], + options?: { [key: string]: Expression | unknown } + ): Pipeline { + // Convert user land convenience types to internal types + const expressionParams = params.map((value: unknown) => { + if (value instanceof Expression) { + return value; + } else if (value instanceof AggregateFunction) { + return value; + } else if (isPlainObject(value)) { + return _mapValue(value as Record); + } else { + return _constant(value, 'rawStage'); + } + }); + + // Create stage object + const stage = new RawStage(name, expressionParams, options ?? {}); + + // User data must be read in the context of the API method to + // provide contextual errors + const parseContext = this.userDataReader.createContext( + UserDataSource.Argument, + 'rawStage' + ); + stage._readUserData(parseContext); + + // Add stage to the pipeline + return this._addStage(stage); + } + + /** + * @internal + * @private + */ + _toProto(jsonProtoSerializer: JsonProtoSerializer): ProtoPipeline { + const stages: ProtoStage[] = this.stages.map(stage => + stage._toProto(jsonProtoSerializer) + ); + return { stages }; + } + + private _addStage(stage: Stage): Pipeline { + const copy = this.stages.map(s => s); + copy.push(stage); + return this.newPipeline( + this._db, + this.userDataReader, + this._userDataWriter, + copy + ); + } + + /** + * @internal + * @private + * @param db + * @param userDataReader + * @param userDataWriter + * @param stages + * @protected + */ + protected newPipeline( + db: Firestore, + userDataReader: UserDataReader, + userDataWriter: AbstractUserDataWriter, + stages: Stage[] + ): Pipeline { + return new Pipeline(db, userDataReader, userDataWriter, stages); + } +} + +export function isPipeline(val: unknown): val is Pipeline { + return val instanceof Pipeline; +} diff --git a/packages/firestore/src/lite-api/pipeline_impl.ts b/packages/firestore/src/lite-api/pipeline_impl.ts new file mode 100644 index 0000000000..dbfe96a099 --- /dev/null +++ b/packages/firestore/src/lite-api/pipeline_impl.ts @@ -0,0 +1,152 @@ +/** + * @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. + */ + +import { + StructuredPipeline, + StructuredPipelineOptions +} from '../core/structured_pipeline'; +import { invokeExecutePipeline } from '../remote/datastore'; + +import { getDatastore } from './components'; +import { Firestore } from './database'; +import { Pipeline } from './pipeline'; +import { PipelineResult, PipelineSnapshot } from './pipeline-result'; +import { PipelineSource } from './pipeline-source'; +import { DocumentReference } from './reference'; +import { LiteUserDataWriter } from './reference_impl'; +import { Stage } from './stage'; +import { + newUserDataReader, + UserDataReader, + UserDataSource +} from './user_data_reader'; + +declare module './database' { + interface Firestore { + /** + * @beta + * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link Pipeline}. + * + * @example + * ``` + * let myPipeline: Pipeline = firestore.pipeline().collection('books'); + * ``` + */ + pipeline(): PipelineSource; + } +} + +/** + * @beta + * Executes this pipeline and returns a Promise to represent the asynchronous operation. + * + * The returned Promise can be used to track the progress of the pipeline execution + * and retrieve the results (or handle any errors) asynchronously. + * + * The pipeline results are returned as a {@link PipelineSnapshot} that contains + * a list of {@link PipelineResult} objects. Each {@link PipelineResult} typically + * represents a single key/value map that has passed through all the + * stages of the pipeline, however this might differ depending on the stages involved in the + * pipeline. For example: + * + *

    + *
  • If there are no stages or only transformation stages, each {@link PipelineResult} + * represents a single document.
  • + *
  • If there is an aggregation, only a single {@link PipelineResult} is returned, + * representing the aggregated results over the entire dataset .
  • + *
  • If there is an aggregation stage with grouping, each {@link PipelineResult} represents a + * distinct group and its associated aggregated values.
  • + *
+ * + *

Example: + * + * ```typescript + * const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") + * .where(gt(field("rating"), 4.5)) + * .select("title", "author", "rating")); + * + * const results: PipelineResults = snapshot.results; + * ``` + * + * @param pipeline The pipeline to execute. + * @return A Promise representing the asynchronous pipeline execution. + */ +export function execute(pipeline: Pipeline): Promise { + const datastore = getDatastore(pipeline._db); + + const udr = new UserDataReader( + pipeline._db._databaseId, + /* ignoreUndefinedProperties */ true + ); + const context = udr.createContext(UserDataSource.Argument, 'execute'); + + const structuredPipelineOptions = new StructuredPipelineOptions({}, {}); + structuredPipelineOptions._readUserData(context); + + const structuredPipeline: StructuredPipeline = new StructuredPipeline( + pipeline, + structuredPipelineOptions + ); + + return invokeExecutePipeline(datastore, structuredPipeline).then(result => { + // Get the execution time from the first result. + // firestoreClientExecutePipeline returns at least one PipelineStreamElement + // even if the returned document set is empty. + const executionTime = + result.length > 0 ? result[0].executionTime?.toTimestamp() : undefined; + + const docs = result + // Currently ignore any response from ExecutePipeline that does + // not contain any document data in the `fields` property. + .filter(element => !!element.fields) + .map( + element => + new PipelineResult( + pipeline._userDataWriter, + element.fields!, + element.key?.path + ? new DocumentReference(pipeline._db, null, element.key) + : undefined, + element.createTime?.toTimestamp(), + element.updateTime?.toTimestamp() + ) + ); + + return new PipelineSnapshot(pipeline, docs, executionTime); + }); +} + +/** + * @beta + * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link Pipeline}. + * + * @example + * ``` + * let myPipeline: Pipeline = firestore.pipeline().collection('books'); + * ``` + */ +Firestore.prototype.pipeline = function (): PipelineSource { + const userDataWriter = new LiteUserDataWriter(this); + const userDataReader = newUserDataReader(this); + return new PipelineSource( + this._databaseId, + userDataReader, + (stages: Stage[]) => { + return new Pipeline(this, userDataReader, userDataWriter, stages); + } + ); +}; diff --git a/packages/firestore/src/lite-api/pipeline_options.ts b/packages/firestore/src/lite-api/pipeline_options.ts new file mode 100644 index 0000000000..c46f42c856 --- /dev/null +++ b/packages/firestore/src/lite-api/pipeline_options.ts @@ -0,0 +1,83 @@ +/** + * @beta + * @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. + */ + +import type { Pipeline } from './pipeline'; + +/** + * @beta + * Options defining Pipeline execution. + */ +export interface PipelineExecuteOptions { + /** + * @beta + * Pipeline to be evaluated. + */ + pipeline: Pipeline; + + /** + * @beta + * Specify the index mode. + */ + indexMode?: 'recommended'; + + /** + * @beta + * An escape hatch to set options not known at SDK build time. These values + * will be passed directly to the Firestore backend and not used by the SDK. + * + * The option name will be used as provided. And must match the name + * format used by the backend (hint: use a snake_case_name). + * + * Custom option values can be any type supported + * by Firestore (for example: string, boolean, number, map, …). Value types + * not known to the SDK will be rejected. + * + * Values specified in rawOptions will take precedence over any options + * with the same name set by the SDK. + * + * Override the `example_option`: + * ``` + * execute({ + * pipeline: myPipeline, + * rawOptions: { + * // Override `example_option`. This will not + * // merge with the existing `example_option` object. + * "example_option": { + * foo: "bar" + * } + * } + * } + * ``` + * + * `rawOptions` supports dot notation, if you want to override + * a nested option. + * ``` + * execute({ + * pipeline: myPipeline, + * rawOptions: { + * // Override `example_option.foo` and do not override + * // any other properties of `example_option`. + * "example_option.foo": "bar" + * } + * } + * ``` + */ + rawOptions?: { + [name: string]: unknown; + }; +} diff --git a/packages/firestore/src/lite-api/query.ts b/packages/firestore/src/lite-api/query.ts index f0a357b828..f019f0d093 100644 --- a/packages/firestore/src/lite-api/query.ts +++ b/packages/firestore/src/lite-api/query.ts @@ -52,8 +52,9 @@ import { import { FieldPath } from './field_path'; import { DocumentData, DocumentReference, Query } from './reference'; -import { DocumentSnapshot, fieldPathFromArgument } from './snapshot'; +import { DocumentSnapshot } from './snapshot'; import { + fieldPathFromArgument, newUserDataReader, parseQueryValue, UserDataReader diff --git a/packages/firestore/src/lite-api/reference.ts b/packages/firestore/src/lite-api/reference.ts index e6c5fd7b05..43eedecf8b 100644 --- a/packages/firestore/src/lite-api/reference.ts +++ b/packages/firestore/src/lite-api/reference.ts @@ -440,6 +440,12 @@ export class CollectionReference< } } +export function isCollectionReference( + val: unknown +): val is CollectionReference { + return val instanceof CollectionReference; +} + /** * Gets a `CollectionReference` instance that refers to the collection at * the specified absolute path. diff --git a/packages/firestore/src/lite-api/snapshot.ts b/packages/firestore/src/lite-api/snapshot.ts index 3024e2e9db..99474bda5f 100644 --- a/packages/firestore/src/lite-api/snapshot.ts +++ b/packages/firestore/src/lite-api/snapshot.ts @@ -15,11 +15,11 @@ * limitations under the License. */ -import { Compat, getModularInstance } from '@firebase/util'; +import { getModularInstance } from '@firebase/util'; import { Document } from '../model/document'; import { DocumentKey } from '../model/document_key'; -import { FieldPath as InternalFieldPath } from '../model/path'; +import { firestoreV1ApiClientInterfaces } from '../protos/firestore_proto_api'; import { arrayEquals } from '../util/misc'; import { Firestore } from './database'; @@ -34,7 +34,7 @@ import { WithFieldValue } from './reference'; import { - fieldPathFromDotSeparatedString, + fieldPathFromArgument, UntypedFirestoreDataConverter } from './user_data_reader'; import { AbstractUserDataWriter } from './user_data_writer'; @@ -366,6 +366,23 @@ export class DocumentSnapshot< } } + /** + * @internal + * @private + * + * Retrieves all fields in the document as a proto Value. Returns `undefined` if + * the document doesn't exist. + * + * @returns An `Object` containing all fields in the document or `undefined` + * if the document doesn't exist. + */ + _fieldsProto(): + | { [key: string]: firestoreV1ApiClientInterfaces.Value } + | undefined { + // Return a cloned value to prevent manipulation of the Snapshot's data + return this._document?.data.clone().value.mapValue.fields ?? undefined; + } + /** * Retrieves the field specified by `fieldPath`. Returns `undefined` if the * document or field doesn't exist. @@ -509,19 +526,3 @@ export function snapshotEqual( return false; } - -/** - * Helper that calls `fromDotSeparatedString()` but wraps any error thrown. - */ -export function fieldPathFromArgument( - methodName: string, - arg: string | FieldPath | Compat -): InternalFieldPath { - if (typeof arg === 'string') { - return fieldPathFromDotSeparatedString(methodName, arg); - } else if (arg instanceof FieldPath) { - return arg._internalPath; - } else { - return arg._delegate._internalPath; - } -} diff --git a/packages/firestore/src/lite-api/stage.ts b/packages/firestore/src/lite-api/stage.ts new file mode 100644 index 0000000000..5dd30eedba --- /dev/null +++ b/packages/firestore/src/lite-api/stage.ts @@ -0,0 +1,764 @@ +/** + * @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. + */ + +import { ParseContext } from '../api/parse_context'; +import { OptionsUtil } from '../core/options_util'; +import { + ApiClientObjectMap, + firestoreV1ApiClientInterfaces, + Stage as ProtoStage +} from '../protos/firestore_proto_api'; +import { toNumber } from '../remote/number_serializer'; +import { + JsonProtoSerializer, + ProtoSerializable, + toMapValue, + toPipelineValue, + toStringValue +} from '../remote/serializer'; +import { hardAssert } from '../util/assert'; + +import { + AggregateFunction, + BooleanExpression, + Expression, + Field, + field, + Ordering +} from './expressions'; +import { Pipeline } from './pipeline'; +import { StageOptions } from './stage_options'; +import { isUserData, UserData } from './user_data_reader'; + +/** + * @beta + */ +export abstract class Stage implements ProtoSerializable, UserData { + /** + * Store optionsProto parsed by _readUserData. + * @private + * @internal + * @protected + */ + protected optionsProto: + | ApiClientObjectMap + | undefined = undefined; + protected knownOptions: Record; + protected rawOptions?: Record; + + constructor(options: StageOptions) { + ({ rawOptions: this.rawOptions, ...this.knownOptions } = options); + } + + _readUserData(context: ParseContext): void { + this.optionsProto = this._optionsUtil.getOptionsProto( + context, + this.knownOptions, + this.rawOptions + ); + } + + _toProto(_: JsonProtoSerializer): ProtoStage { + return { + name: this._name, + options: this.optionsProto + }; + } + + abstract get _optionsUtil(): OptionsUtil; + abstract get _name(): string; +} + +/** + * @beta + */ +export class AddFields extends Stage { + get _name(): string { + return 'add_fields'; + } + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor(private fields: Map, options: StageOptions) { + super(options); + } + + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [toMapValue(serializer, this.fields)] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + readUserDataHelper(this.fields, context); + } +} + +/** + * @beta + */ +export class RemoveFields extends Stage { + get _name(): string { + return 'remove_fields'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor(private fields: Field[], options: StageOptions) { + super(options); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: this.fields.map(f => f._toProto(serializer)) + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + readUserDataHelper(this.fields, context); + } +} + +/** + * @beta + */ +export class Aggregate extends Stage { + get _name(): string { + return 'aggregate'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor( + private groups: Map, + private accumulators: Map, + options: StageOptions + ) { + super(options); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [ + toMapValue(serializer, this.accumulators), + toMapValue(serializer, this.groups) + ] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + readUserDataHelper(this.groups, context); + readUserDataHelper(this.accumulators, context); + } +} + +/** + * @beta + */ +export class Distinct extends Stage { + get _name(): string { + return 'distinct'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor(private groups: Map, options: StageOptions) { + super(options); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [toMapValue(serializer, this.groups)] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + readUserDataHelper(this.groups, context); + } +} + +/** + * @beta + */ +export class CollectionSource extends Stage { + get _name(): string { + return 'collection'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({ + forceIndex: { + serverName: 'force_index' + } + }); + } + + private formattedCollectionPath: string; + + constructor(collection: string, options: StageOptions) { + super(options); + + // prepend slash to collection string + this.formattedCollectionPath = collection.startsWith('/') + ? collection + : '/' + collection; + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [{ referenceValue: this.formattedCollectionPath }] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + } +} + +/** + * @beta + */ +export class CollectionGroupSource extends Stage { + get _name(): string { + return 'collection_group'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({ + forceIndex: { + serverName: 'force_index' + } + }); + } + + constructor(private collectionId: string, options: StageOptions) { + super(options); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [{ referenceValue: '' }, { stringValue: this.collectionId }] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + } +} + +/** + * @beta + */ +export class DatabaseSource extends Stage { + get _name(): string { + return 'database'; + } + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer) + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + } +} + +/** + * @beta + */ +export class DocumentsSource extends Stage { + get _name(): string { + return 'documents'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + private formattedPaths: string[]; + + constructor(docPaths: string[], options: StageOptions) { + super(options); + this.formattedPaths = docPaths.map(path => + path.startsWith('/') ? path : '/' + path + ); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: this.formattedPaths.map(p => { + return { referenceValue: p }; + }) + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + } +} + +/** + * @beta + */ +export class Where extends Stage { + get _name(): string { + return 'where'; + } + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor(private condition: BooleanExpression, options: StageOptions) { + super(options); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [this.condition._toProto(serializer)] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + readUserDataHelper(this.condition, context); + } +} + +/** + * @beta + */ +export class FindNearest extends Stage { + get _name(): string { + return 'find_nearest'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({ + limit: { + serverName: 'limit' + }, + distanceField: { + serverName: 'distance_field' + } + }); + } + + constructor( + private vectorValue: Expression, + private field: Field, + private distanceMeasure: 'euclidean' | 'cosine' | 'dot_product', + options: StageOptions + ) { + super(options); + } + + /** + * @private + * @internal + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [ + this.field._toProto(serializer), + this.vectorValue._toProto(serializer), + toStringValue(this.distanceMeasure) + ] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + readUserDataHelper(this.vectorValue, context); + readUserDataHelper(this.field, context); + } +} + +/** + * @beta + */ +export class Limit extends Stage { + get _name(): string { + return 'limit'; + } + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor(private limit: number, options: StageOptions) { + hardAssert( + !isNaN(limit) && limit !== Infinity && limit !== -Infinity, + 0x882c, + 'Invalid limit value' + ); + super(options); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [toNumber(serializer, this.limit)] + }; + } +} + +/** + * @beta + */ +export class Offset extends Stage { + get _name(): string { + return 'offset'; + } + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor(private offset: number, options: StageOptions) { + super(options); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [toNumber(serializer, this.offset)] + }; + } +} + +/** + * @beta + */ +export class Select extends Stage { + get _name(): string { + return 'select'; + } + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor( + private selections: Map, + options: StageOptions + ) { + super(options); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [toMapValue(serializer, this.selections)] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + readUserDataHelper(this.selections, context); + } +} + +/** + * @beta + */ +export class Sort extends Stage { + get _name(): string { + return 'sort'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor(private orderings: Ordering[], options: StageOptions) { + super(options); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: this.orderings.map(o => o._toProto(serializer)) + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + readUserDataHelper(this.orderings, context); + } +} + +/** + * @beta + */ +export class Sample extends Stage { + get _name(): string { + return 'sample'; + } + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor( + private rate: number, + private mode: 'percent' | 'documents', + options: StageOptions + ) { + super(options); + } + + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [toNumber(serializer, this.rate)!, toStringValue(this.mode)!] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + } +} + +/** + * @beta + */ +export class Union extends Stage { + get _name(): string { + return 'union'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor(private other: Pipeline, options: StageOptions) { + super(options); + } + + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [toPipelineValue(this.other._toProto(serializer))] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + } +} + +/** + * @beta + */ +export class Unnest extends Stage { + get _name(): string { + return 'unnest'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({ + indexField: { + serverName: 'index_field' + } + }); + } + + constructor( + private alias: string, + private expr: Expression, + options: StageOptions + ) { + super(options); + } + + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [ + this.expr._toProto(serializer), + field(this.alias)._toProto(serializer) + ] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + readUserDataHelper(this.expr, context); + } +} + +/** + * @beta + */ +export class Replace extends Stage { + static readonly MODE = 'full_replace'; + + get _name(): string { + return 'replace_with'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor(private map: Expression, options: StageOptions) { + super(options); + } + + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [this.map._toProto(serializer), toStringValue(Replace.MODE)] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + readUserDataHelper(this.map, context); + } +} + +/** + * @beta + */ +export class RawStage extends Stage { + /** + * @private + * @internal + */ + constructor( + private name: string, + private params: Array, + rawOptions: Record + ) { + super({ rawOptions }); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + name: this.name, + args: this.params.map(o => o._toProto(serializer)), + options: this.optionsProto + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + readUserDataHelper(this.params, context); + } + + get _name(): string { + return this.name; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } +} + +/** + * Helper to read user data across a number of different formats. + * @param name Name of the calling function. Used for error messages when invalid user data is encountered. + * @param expressionMap + * @return the expressionMap argument. + * @private + */ +function readUserDataHelper< + T extends Map | UserData[] | UserData +>(expressionMap: T, context: ParseContext): T { + if (isUserData(expressionMap)) { + expressionMap._readUserData(context); + } else if (Array.isArray(expressionMap)) { + expressionMap.forEach(readableData => readableData._readUserData(context)); + } else { + expressionMap.forEach(expr => expr._readUserData(context)); + } + return expressionMap; +} diff --git a/packages/firestore/src/lite-api/stage_options.ts b/packages/firestore/src/lite-api/stage_options.ts new file mode 100644 index 0000000000..ea9ff08823 --- /dev/null +++ b/packages/firestore/src/lite-api/stage_options.ts @@ -0,0 +1,345 @@ +/** + * @beta + * @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. + */ + +import { OneOf } from '../util/types'; + +import { + AliasedAggregate, + BooleanExpression, + Expression, + Field, + Ordering, + Selectable +} from './expressions'; +import { Pipeline } from './pipeline'; +import { CollectionReference, DocumentReference } from './reference'; +import { VectorValue } from './vector_value'; + +/** + * @beta + * Options defining how a Stage is evaluated. + */ +export interface StageOptions { + /** + * @beta + * An escape hatch to set options not known at SDK build time. These values + * will be passed directly to the Firestore backend and not used by the SDK. + * + * The option name will be used as provided. And must match the name + * format used by the backend (hint: use a snake_case_name). + * + * Raw option values can be any type supported + * by Firestore (for example: string, boolean, number, map, …). Value types + * not known to the SDK will be rejected. + * + * Values specified in rawOptions will take precedence over any options + * with the same name set by the SDK. + * + * `rawOptions` supports dot notation, if you want to override + * a nested option. + */ + rawOptions?: { + [name: string]: unknown; + }; +} +/** + * @beta + * Options defining how a CollectionStage is evaluated. See {@link PipelineSource.collection}. + */ +export type CollectionStageOptions = StageOptions & { + /** + * @beta + * Name or reference to the collection that will be used as the Pipeline source. + */ + collection: string | CollectionReference; + + /** + * @beta + * Specifies the name of an index to be used for a query, overriding the query optimizer's default choice. + * This can be useful for performance tuning in specific scenarios where the default index selection + * does not yield optimal performance. + * + * @remarks This property is optional. When provided, it should be the exact name of the index to force. + */ + forceIndex?: string; +}; + +/** + * @beta + * Defines the configuration options for a {@link CollectionGroupStage} within a pipeline. + * This type extends {@link StageOptions} and provides specific settings for how a collection group + * is identified and processed during pipeline execution. + * + * @see {@link PipelineSource.collectionGroup} to create a collection group stage. + */ +export type CollectionGroupStageOptions = StageOptions & { + /** + * @beta + * ID of the collection group to use as the Pipeline source. + */ + collectionId: string; + + /** + * @beta + * Specifies the name of an index to be used for a query, overriding the query optimizer's default choice. + * This can be useful for performance tuning in specific scenarios where the default index selection + * does not yield optimal performance. + * + * @remarks This property is optional. When provided, it should be the exact name of the index to force. + */ + forceIndex?: string; +}; +/** + * @beta + * Options defining how a DatabaseStage is evaluated. See {@link PipelineSource.database}. + */ +export type DatabaseStageOptions = StageOptions & {}; +/** + * @beta + * Options defining how a DocumentsStage is evaluated. See {@link PipelineSource.documents}. + */ +export type DocumentsStageOptions = StageOptions & { + /** + * @beta + * An array of paths and DocumentReferences specifying the individual documents that will be the source of this pipeline. + * The converters for these DocumentReferences will be ignored and not have an effect on this pipeline. + * There must be at least one document specified in the array. + */ + docs: Array; +}; +/** + * @beta + * Options defining how an AddFieldsStage is evaluated. See {@link Pipeline.addFields}. + */ +export type AddFieldsStageOptions = StageOptions & { + /** + * @beta + * The fields to add to each document, specified as a {@link Selectable}. + * At least one field is required. + */ + fields: Selectable[]; +}; +/** + * @beta + * Options defining how a RemoveFieldsStage is evaluated. See {@link Pipeline.removeFields}. + */ +export type RemoveFieldsStageOptions = StageOptions & { + /** + * @beta + * The fields to remove from each document. + */ + fields: Array; +}; +/** + * @beta + * Options defining how a SelectStage is evaluated. See {@link Pipeline.select}. + */ +export type SelectStageOptions = StageOptions & { + /** + * @beta + * The fields to include in the output documents, specified as {@link Selectable} expression + * or as a string value indicating the field name. + */ + selections: Array; +}; +/** + * @beta + * Options defining how a WhereStage is evaluated. See {@link Pipeline.where}. + */ +export type WhereStageOptions = StageOptions & { + /** + * @beta + * The {@link BooleanExpression} to apply as a filter for each input document to this stage. + */ + condition: BooleanExpression; +}; +/** + * @beta + * Options defining how an OffsetStage is evaluated. See {@link Pipeline.offset}. + */ +export type OffsetStageOptions = StageOptions & { + /** + * @beta + * The number of documents to skip. + */ + offset: number; +}; +/** + * @beta + * Options defining how a LimitStage is evaluated. See {@link Pipeline.limit}. + */ +export type LimitStageOptions = StageOptions & { + /** + * @beta + * The maximum number of documents to return. + */ + limit: number; +}; +/** + * @beta + * Options defining how a DistinctStage is evaluated. See {@link Pipeline.distinct}. + */ +export type DistinctStageOptions = StageOptions & { + /** + * @beta + * The {@link Selectable} expressions or field names to consider when determining + * distinct value combinations (groups). + */ + groups: Array; +}; + +/** + * @beta + * Options defining how an AggregateStage is evaluated. See {@link Pipeline.aggregate}. + */ +export type AggregateStageOptions = StageOptions & { + /** + * @beta + * The {@link AliasedAggregate} values specifying aggregate operations to + * perform on the input documents. + */ + accumulators: AliasedAggregate[]; + /** + * @beta + * The {@link Selectable} expressions or field names to consider when determining + * distinct value combinations (groups), which will be aggregated over. + */ + groups?: Array; +}; +/** + * @beta + * Options defining how a FindNearestStage is evaluated. See {@link Pipeline.findNearest}. + */ +export type FindNearestStageOptions = StageOptions & { + /** + * @beta + * Specifies the field to be used. This can be a string representing the field path + * (e.g., 'fieldName', 'nested.fieldName') or an object of type {@link Field} + * representing a more complex field expression. + */ + field: Field | string; + /** + * @beta + * Specifies the query vector value, to which the vector distance will be computed. + */ + vectorValue: VectorValue | number[]; + /** + * @beta + * Specifies the method used to compute the distance between vectors. + * + * Possible values are: + * - `'euclidean'`: Euclidean distance. + * - `'cosine'`: Cosine similarity. + * - `'dot_product'`: Dot product. + */ + distanceMeasure: 'euclidean' | 'cosine' | 'dot_product'; + /** + * @beta + * The maximum number of documents to return from the FindNearest stage. + */ + limit?: number; + /** + * @beta + * If set, specifies the field on the output documents that will contain + * the computed vector distance for the document. If not set, the computed + * vector distance will not be returned. + */ + distanceField?: string; +}; +/** + * @beta + * Options defining how a ReplaceWithStage is evaluated. See {@link Pipeline.replaceWith}. + */ +export type ReplaceWithStageOptions = StageOptions & { + /** + * @beta + * The name of a field that contains a map or an {@link Expression} that + * evaluates to a map. + */ + map: Expression | string; +}; +/** + * @beta + * Defines the options for evaluating a sample stage within a pipeline. + * This type combines common {@link StageOptions} with a specific configuration + * where only one of the defined sampling methods can be applied. + * + * See {@link Pipeline.sample} to create a sample stage.. + */ +export type SampleStageOptions = StageOptions & + OneOf<{ + /** + * @beta + * If set, specifies the sample rate as a percentage of the + * input documents. + * + * Cannot be set when `documents: number` is set. + */ + percentage: number; + /** + * @beta + * If set, specifies the sample rate as a total number of + * documents to sample from the input documents. + * + * Cannot be set when `percentage: number` is set. + */ + documents: number; + }>; +/** + * @beta + * Options defining how a UnionStage is evaluated. See {@link Pipeline.union}. + */ +export type UnionStageOptions = StageOptions & { + /** + * @beta + * Specifies the other Pipeline to union with. + */ + other: Pipeline; +}; + +/** + * @beta + * Represents the specific options available for configuring an `UnnestStage` within a pipeline. + */ +export type UnnestStageOptions = StageOptions & { + /** + * @beta + * A `Selectable` object that defines an array expression to be un-nested + * and the alias for the un-nested field. + */ + selectable: Selectable; + /** + * @beta + * If set, specifies the field on the output documents that will contain the + * offset (starting at zero) that the element is from the original array. + */ + indexField?: string; +}; +/** + * @beta + * @beta + * Options defining how a SortStage is evaluated. See {@link Pipeline.sort}. + */ +export type SortStageOptions = StageOptions & { + /** + * @beta + * Orderings specify how the input documents are sorted. + * One or more ordering are required. + */ + orderings: Ordering[]; +}; diff --git a/packages/firestore/src/lite-api/user_data_reader.ts b/packages/firestore/src/lite-api/user_data_reader.ts index a3022be627..8ea2728b3a 100644 --- a/packages/firestore/src/lite-api/user_data_reader.ts +++ b/packages/firestore/src/lite-api/user_data_reader.ts @@ -22,7 +22,7 @@ import { } from '@firebase/firestore-types'; import { Compat, deepEqual, getModularInstance } from '@firebase/util'; -import { ParseContext } from '../api/parse_context'; +import { ContextSettings, ParseContext } from '../api/parse_context'; import { DatabaseId } from '../core/database_info'; import { DocumentKey } from '../model/document_key'; import { FieldMask } from '../model/field_mask'; @@ -56,7 +56,8 @@ import { JsonProtoSerializer, toBytes, toResourceName, - toTimestamp + toTimestamp, + isProtoValueSerializable } from '../remote/serializer'; import { debugAssert, fail } from '../util/assert'; import { Code, FirestoreError } from '../util/error'; @@ -181,33 +182,6 @@ function isWrite(dataSource: UserDataSource): boolean { } } -/** Contains the settings that are mutated as we parse user data. */ -interface ContextSettings { - /** Indicates what kind of API method this data came from. */ - readonly dataSource: UserDataSource; - /** The name of the method the user called to create the ParseContext. */ - readonly methodName: string; - /** The document the user is attempting to modify, if that applies. */ - readonly targetDoc?: DocumentKey; - /** - * A path within the object being parsed. This could be an empty path (in - * which case the context represents the root of the data being parsed), or a - * nonempty path (indicating the context represents a nested location within - * the data). - */ - readonly path?: InternalFieldPath; - /** - * Whether or not this context corresponds to an element of an array. - * If not set, elements are treated as if they were outside of arrays. - */ - readonly arrayElement?: boolean; - /** - * Whether or not a converter was specified in this context. If true, error - * messages will reference the converter when invalid data is provided. - */ - readonly hasConverter?: boolean; -} - /** A "context" object passed around while parsing user data. */ class ParseContextImpl implements ParseContext { readonly fieldTransforms: FieldTransform[]; @@ -731,7 +705,7 @@ export function parseQueryValue( */ export function parseData( input: unknown, - context: ParseContextImpl + context: ParseContext ): ProtoValue | null { // Unwrap the API type from the Compat SDK. This will return the API type // from firestore-exp. @@ -782,7 +756,7 @@ export function parseData( export function parseObject( obj: Dict, - context: ParseContextImpl + context: ParseContext ): { mapValue: ProtoMapValue } { const fields: Dict = {}; @@ -804,7 +778,7 @@ export function parseObject( return { mapValue: { fields } }; } -function parseArray(array: unknown[], context: ParseContextImpl): ProtoValue { +function parseArray(array: unknown[], context: ParseContext): ProtoValue { const values: ProtoValue[] = []; let entryIndex = 0; for (const entry of array) { @@ -829,7 +803,7 @@ function parseArray(array: unknown[], context: ParseContextImpl): ProtoValue { */ function parseSentinelFieldValue( value: FieldValue, - context: ParseContextImpl + context: ParseContext ): void { // Sentinels are only supported with writes, and not within arrays. if (!isWrite(context.dataSource)) { @@ -854,9 +828,9 @@ function parseSentinelFieldValue( * * @returns The parsed value */ -function parseScalarValue( +export function parseScalarValue( value: unknown, - context: ParseContextImpl + context: ParseContext ): ProtoValue | null { value = getModularInstance(value); @@ -911,6 +885,8 @@ function parseScalarValue( }; } else if (value instanceof VectorValue) { return parseVectorValue(value, context); + } else if (isProtoValueSerializable(value)) { + return value._toProto(context.serializer); } else { throw context.createError( `Unsupported field value: ${valueDescription(value)}` @@ -922,9 +898,10 @@ function parseScalarValue( * Creates a new VectorValue proto value (using the internal format). */ export function parseVectorValue( - value: VectorValue, - context: ParseContextImpl -): ProtoValue { + value: VectorValue | number[], + context: ParseContext +): { mapValue: ProtoMapValue } { + const values = value instanceof VectorValue ? value.toArray() : value; const mapValue: ProtoMapValue = { fields: { [TYPE_KEY]: { @@ -932,7 +909,7 @@ export function parseVectorValue( }, [VECTOR_MAP_VECTORS_KEY]: { arrayValue: { - values: value.toArray().map(value => { + values: values.map(value => { if (typeof value !== 'number') { throw context.createError( 'VectorValues must only contain numeric values.' @@ -956,7 +933,7 @@ export function parseVectorValue( * GeoPoints, etc. are not considered to look like JSON objects since they map * to specific FieldValue types other than ObjectValue. */ -function looksLikeJsonObject(input: unknown): boolean { +export function looksLikeJsonObject(input: unknown): boolean { return ( typeof input === 'object' && input !== null && @@ -967,13 +944,14 @@ function looksLikeJsonObject(input: unknown): boolean { !(input instanceof Bytes) && !(input instanceof DocumentReference) && !(input instanceof FieldValue) && - !(input instanceof VectorValue) + !(input instanceof VectorValue) && + !isProtoValueSerializable(input) ); } function validatePlainObject( message: string, - context: ParseContextImpl, + context: ParseContext, input: unknown ): asserts input is Dict { if (!looksLikeJsonObject(input) || !isPlainObject(input)) { @@ -1101,3 +1079,11 @@ function fieldMaskContains( ): boolean { return haystack.some(v => v.isEqual(needle)); } + +export interface UserData { + _readUserData(context: ParseContext): void; +} + +export function isUserData(value: unknown): value is UserData { + return typeof (value as UserData)._readUserData === 'function'; +} diff --git a/packages/firestore/src/model/pipeline_stream_element.ts b/packages/firestore/src/model/pipeline_stream_element.ts new file mode 100644 index 0000000000..efa27e2cc4 --- /dev/null +++ b/packages/firestore/src/model/pipeline_stream_element.ts @@ -0,0 +1,30 @@ +/** + * @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. + */ + +import { SnapshotVersion } from '../core/snapshot_version'; + +import { DocumentKey } from './document_key'; +import { ObjectValue } from './object_value'; + +export interface PipelineStreamElement { + transaction?: string; + key?: DocumentKey; + executionTime?: SnapshotVersion; + createTime?: SnapshotVersion; + updateTime?: SnapshotVersion; + fields?: ObjectValue; +} diff --git a/packages/firestore/src/platform/browser/webchannel_connection.ts b/packages/firestore/src/platform/browser/webchannel_connection.ts index 56f57aa959..b3fdd53340 100644 --- a/packages/firestore/src/platform/browser/webchannel_connection.ts +++ b/packages/firestore/src/platform/browser/webchannel_connection.ts @@ -16,7 +16,7 @@ */ import { - createWebChannelTransport, + createWebChannelTransport as internalCreateWebChannelTransport, ErrorCode, EventType, WebChannel, @@ -27,7 +27,8 @@ import { EventTarget, StatEvent, Event, - Stat + Stat, + WebChannelTransport } from '@firebase/webchannel-wrapper/webchannel-blob'; import { Token } from '../../api/credentials'; @@ -53,6 +54,28 @@ const RPC_STREAM_SERVICE = 'google.firestore.v1.Firestore'; const XHR_TIMEOUT_SECS = 15; +// Closure events are guarded and exceptions are swallowed, so catch any +// exception and rethrow using a setTimeout so they become visible again. +// Note that eventually this function could go away if we are confident +// enough the code is exception free. +const unguardedEventListen = ( + target: EventTarget, + type: string | number, + fn: (param: T) => void +): void => { + // TODO(dimond): closure typing seems broken because WebChannel does + // not implement goog.events.Listenable + target.listen(type, (param: unknown) => { + try { + fn(param as T); + } catch (e) { + setTimeout(() => { + throw e; + }, 0); + } + }); +}; + export class WebChannelConnection extends RestConnection { private readonly forceLongPolling: boolean; private readonly autoDetectLongPolling: boolean; @@ -70,6 +93,29 @@ export class WebChannelConnection extends RestConnection { this.longPollingOptions = info.longPollingOptions; } + /** + * Track if the STAT_EVENT listener has been initialized. + */ + static statEventListenerInitialized: boolean = false; + + /** + * Initialize STAT_EVENT listener once. Subsequent calls are a no-op. + * getStatEventTarget() returns the same target every time. + */ + static ensureStatEventListenerInitialized(): void { + if (!WebChannelConnection.statEventListenerInitialized) { + const requestStats = getStatEventTarget(); + unguardedEventListen(requestStats, Event.STAT_EVENT, event => { + if (event.stat === Stat.PROXY) { + logDebug(LOG_TAG, `STAT_EVENT: detected buffering proxy`); + } else if (event.stat === Stat.NOPROXY) { + logDebug(LOG_TAG, `STAT_EVENT: detected no buffering proxy`); + } + }); + WebChannelConnection.statEventListenerInitialized = true; + } + } + protected performRPCRequest( rpcName: string, url: string, @@ -181,8 +227,7 @@ export class WebChannelConnection extends RestConnection { rpcName, '/channel' ]; - const webchannelTransport = createWebChannelTransport(); - const requestStats = getStatEventTarget(); + const webchannelTransport = this.createWebChannelTransport(); const request: WebChannelOptions = { // Required for backend stickiness, routing behavior is based on this // parameter. @@ -285,28 +330,6 @@ export class WebChannelConnection extends RestConnection { closeFn: () => channel.close() }); - // Closure events are guarded and exceptions are swallowed, so catch any - // exception and rethrow using a setTimeout so they become visible again. - // Note that eventually this function could go away if we are confident - // enough the code is exception free. - const unguardedEventListen = ( - target: EventTarget, - type: string | number, - fn: (param: T) => void - ): void => { - // TODO(dimond): closure typing seems broken because WebChannel does - // not implement goog.events.Listenable - target.listen(type, (param: unknown) => { - try { - fn(param as T); - } catch (e) { - setTimeout(() => { - throw e; - }, 0); - } - }); - }; - unguardedEventListen(channel, WebChannel.EventType.OPEN, () => { if (!closed) { logDebug( @@ -409,19 +432,8 @@ export class WebChannelConnection extends RestConnection { } ); - unguardedEventListen(requestStats, Event.STAT_EVENT, event => { - if (event.stat === Stat.PROXY) { - logDebug( - LOG_TAG, - `RPC '${rpcName}' stream ${streamId} detected buffering proxy` - ); - } else if (event.stat === Stat.NOPROXY) { - logDebug( - LOG_TAG, - `RPC '${rpcName}' stream ${streamId} detected no buffering proxy` - ); - } - }); + // Ensure that event listeners are configured for STAT_EVENTs. + WebChannelConnection.ensureStatEventListenerInitialized(); setTimeout(() => { // Technically we could/should wait for the WebChannel opened event, @@ -460,4 +472,29 @@ export class WebChannelConnection extends RestConnection { instance => instance === webChannel ); } + + /** + * Modifies the headers for a request, adding the api key if present, + * and then calling super.modifyHeadersForRequest + */ + protected modifyHeadersForRequest( + headers: StringMap, + authToken: Token | null, + appCheckToken: Token | null + ): void { + super.modifyHeadersForRequest(headers, authToken, appCheckToken); + + // For web channel streams, we want to send the api key in the headers. + if (this.databaseInfo.apiKey) { + headers['x-goog-api-key'] = this.databaseInfo.apiKey; + } + } + + /** + * Wrapped for mocking. + * @protected + */ + protected createWebChannelTransport(): WebChannelTransport { + return internalCreateWebChannelTransport(); + } } diff --git a/packages/firestore/src/platform/node/grpc_connection.ts b/packages/firestore/src/platform/node/grpc_connection.ts index d50a314941..79ccb3ddf3 100644 --- a/packages/firestore/src/platform/node/grpc_connection.ts +++ b/packages/firestore/src/platform/node/grpc_connection.ts @@ -44,7 +44,8 @@ function createMetadata( databasePath: string, authToken: Token | null, appCheckToken: Token | null, - appId: string + appId: string, + apiKey: string | undefined ): grpc.Metadata { hardAssert( authToken === null || authToken.type === 'OAuth', @@ -69,6 +70,9 @@ function createMetadata( // 11 from Google3. metadata.set('Google-Cloud-Resource-Prefix', databasePath); metadata.set('x-goog-request-params', databasePath); + if (apiKey) { + metadata.set('X-Goog-Api-Key', apiKey); + } return metadata; } @@ -100,7 +104,8 @@ export class GrpcConnection implements Connection { this.databasePath = `projects/${databaseInfo.databaseId.projectId}/databases/${databaseInfo.databaseId.database}`; } - private ensureActiveStub(): GeneratedGrpcStub { + /** made protected for testing */ + protected ensureActiveStub(): GeneratedGrpcStub { if (!this.cachedStub) { logDebug(LOG_TAG, 'Creating Firestore stub.'); const credentials = this.databaseInfo.ssl @@ -127,7 +132,8 @@ export class GrpcConnection implements Connection { this.databasePath, authToken, appCheckToken, - this.databaseInfo.appId + this.databaseInfo.appId, + this.databaseInfo.apiKey ); const jsonRequest = { database: this.databasePath, ...request }; @@ -187,7 +193,8 @@ export class GrpcConnection implements Connection { this.databasePath, authToken, appCheckToken, - this.databaseInfo.appId + this.databaseInfo.appId, + this.databaseInfo.apiKey ); const jsonRequest = { ...request, database: this.databasePath }; const stream = stub[rpcName](jsonRequest, metadata); @@ -239,7 +246,8 @@ export class GrpcConnection implements Connection { this.databasePath, authToken, appCheckToken, - this.databaseInfo.appId + this.databaseInfo.appId, + this.databaseInfo.apiKey ); const grpcStream = stub[rpcName](metadata); diff --git a/packages/firestore/src/platform/rn_lite/snapshot_to_json.ts b/packages/firestore/src/platform/rn_lite/snapshot_to_json.ts index 709509c8a4..0ccebd779f 100644 --- a/packages/firestore/src/platform/rn_lite/snapshot_to_json.ts +++ b/packages/firestore/src/platform/rn_lite/snapshot_to_json.ts @@ -16,3 +16,10 @@ */ export { toByteStreamReader } from '../browser/byte_stream_reader'; + +// This is not included in the RN lite-bundle, but the rollup build +// will fail if these exports are not defined. +export { + buildDocumentSnapshotJsonBundle, + buildQuerySnapshotJsonBundle +} from '../browser/snapshot_to_json'; diff --git a/packages/firestore/src/protos/compile.sh b/packages/firestore/src/protos/compile.sh index 26c46d1a40..9f9fb4b321 100755 --- a/packages/firestore/src/protos/compile.sh +++ b/packages/firestore/src/protos/compile.sh @@ -18,10 +18,17 @@ set -euo pipefail # Variables PROTOS_DIR="." -PBJS="$(npm bin)/pbjs" +PBJS="../../node_modules/.bin/pbjs" +PBTS="../../node_modules/.bin/pbts" -"${PBJS}" --proto_path=. --target=json -o protos.json \ - -r firestore_v1 \ - "${PROTOS_DIR}/google/firestore/v1/*.proto" \ +"${PBJS}" --path=. --target=json -o protos.json \ + -r firestore/v1 "${PROTOS_DIR}/google/firestore/v1/*.proto" \ "${PROTOS_DIR}/google/protobuf/*.proto" "${PROTOS_DIR}/google/type/*.proto" \ "${PROTOS_DIR}/google/rpc/*.proto" "${PROTOS_DIR}/google/api/*.proto" + +"${PBJS}" --path="${PROTOS_DIR}" --target=static -o temp.js \ + -r firestore/v1 "${PROTOS_DIR}/google/firestore/v1/*.proto" \ + "${PROTOS_DIR}/google/protobuf/*.proto" "${PROTOS_DIR}/google/type/*.proto" \ + "${PROTOS_DIR}/google/rpc/*.proto" "${PROTOS_DIR}/google/api/*.proto" + +"${PBTS}" -o temp.d.ts --no-comments temp.js diff --git a/packages/firestore/src/protos/firestore_proto_api.ts b/packages/firestore/src/protos/firestore_proto_api.ts index 9618d71b86..cc1c57259f 100644 --- a/packages/firestore/src/protos/firestore_proto_api.ts +++ b/packages/firestore/src/protos/firestore_proto_api.ts @@ -145,9 +145,21 @@ export interface IValueNullValueEnum { } export declare const ValueNullValueEnum: IValueNullValueEnum; export declare namespace firestoreV1ApiClientInterfaces { + interface Aggregation { + count?: Count; + sum?: Sum; + avg?: Avg; + alias?: string; + } + interface AggregationResult { + aggregateFields?: ApiClientObjectMap; + } interface ArrayValue { values?: Value[]; } + interface Avg { + field?: FieldReference; + } interface BatchGetDocumentsRequest { database?: string; documents?: string[]; @@ -168,6 +180,14 @@ export declare namespace firestoreV1ApiClientInterfaces { interface BeginTransactionResponse { transaction?: string; } + interface BitSequence { + bitmap?: string | Uint8Array; + padding?: number; + } + interface BloomFilter { + bits?: BitSequence; + hashCount?: number; + } interface CollectionSelector { collectionId?: string; allDescendants?: boolean; @@ -185,6 +205,9 @@ export declare namespace firestoreV1ApiClientInterfaces { op?: CompositeFilterOp; filters?: Filter[]; } + interface Count { + upTo?: number; + } interface Cursor { values?: Value[]; before?: boolean; @@ -221,19 +244,23 @@ export declare namespace firestoreV1ApiClientInterfaces { documents?: string[]; } interface Empty {} + interface ExecutePipelineRequest { + database?: string; + structuredPipeline?: StructuredPipeline; + transaction?: string; + newTransaction?: TransactionOptions; + readTime?: string; + } + interface ExecutePipelineResponse { + transaction?: string; + results?: Document[]; + executionTime?: string; + } interface ExistenceFilter { targetId?: number; count?: number; unchangedNames?: BloomFilter; } - interface BloomFilter { - bits?: BitSequence; - hashCount?: number; - } - interface BitSequence { - bitmap?: string | Uint8Array; - padding?: number; - } interface FieldFilter { field?: FieldReference; op?: FieldFilterOp; @@ -254,6 +281,11 @@ export declare namespace firestoreV1ApiClientInterfaces { fieldFilter?: FieldFilter; unaryFilter?: UnaryFilter; } + interface Function { + name?: string; + args?: Value[]; + options?: ApiClientObjectMap; + } interface Index { name?: string; collectionId?: string; @@ -310,6 +342,9 @@ export declare namespace firestoreV1ApiClientInterfaces { field?: FieldReference; direction?: OrderDirection; } + interface Pipeline { + stages?: Stage[]; + } interface Precondition { exists?: boolean; updateTime?: Timestamp; @@ -355,33 +390,24 @@ export declare namespace firestoreV1ApiClientInterfaces { transaction?: string; readTime?: string; } - interface AggregationResult { - aggregateFields?: ApiClientObjectMap; - } interface StructuredAggregationQuery { structuredQuery?: StructuredQuery; aggregations?: Aggregation[]; } - interface Aggregation { - count?: Count; - sum?: Sum; - avg?: Avg; - alias?: string; - } - interface Count { - upTo?: number; - } - interface Sum { - field?: FieldReference; - } - interface Avg { - field?: FieldReference; + interface Stage { + name?: string; + args?: Value[]; + options?: ApiClientObjectMap; } interface Status { code?: number; message?: string; details?: Array>; } + interface StructuredPipeline { + pipeline?: Pipeline; + options?: ApiClientObjectMap; + } interface StructuredQuery { select?: Projection; from?: CollectionSelector[]; @@ -392,6 +418,9 @@ export declare namespace firestoreV1ApiClientInterfaces { offset?: number; limit?: number | { value: number }; } + interface Sum { + field?: FieldReference; + } interface Target { query?: QueryTarget; documents?: DocumentsTarget; @@ -428,6 +457,10 @@ export declare namespace firestoreV1ApiClientInterfaces { geoPointValue?: LatLng; arrayValue?: ArrayValue; mapValue?: MapValue; + fieldReferenceValue?: string; + // eslint-disable-next-line @typescript-eslint/ban-types + functionValue?: Function; + pipelineValue?: Pipeline; } interface Write { update?: Document; @@ -489,12 +522,17 @@ export declare type DocumentsTarget = export declare type Empty = firestoreV1ApiClientInterfaces.Empty; export declare type ExistenceFilter = firestoreV1ApiClientInterfaces.ExistenceFilter; +export declare type ExecutePipelineRequest = + firestoreV1ApiClientInterfaces.ExecutePipelineRequest; +export declare type ExecutePipelineResponse = + firestoreV1ApiClientInterfaces.ExecutePipelineResponse; export declare type FieldFilter = firestoreV1ApiClientInterfaces.FieldFilter; export declare type FieldReference = firestoreV1ApiClientInterfaces.FieldReference; export declare type FieldTransform = firestoreV1ApiClientInterfaces.FieldTransform; export declare type Filter = firestoreV1ApiClientInterfaces.Filter; +export declare type Function = firestoreV1ApiClientInterfaces.Function; export declare type Index = firestoreV1ApiClientInterfaces.Index; export declare type IndexField = firestoreV1ApiClientInterfaces.IndexField; export declare type LatLng = firestoreV1ApiClientInterfaces.LatLng; @@ -513,6 +551,7 @@ export declare type ListenResponse = export declare type MapValue = firestoreV1ApiClientInterfaces.MapValue; export declare type Operation = firestoreV1ApiClientInterfaces.Operation; export declare type Order = firestoreV1ApiClientInterfaces.Order; +export declare type Pipeline = firestoreV1ApiClientInterfaces.Pipeline; export declare type Precondition = firestoreV1ApiClientInterfaces.Precondition; export declare type Projection = firestoreV1ApiClientInterfaces.Projection; export declare type QueryTarget = firestoreV1ApiClientInterfaces.QueryTarget; @@ -529,9 +568,12 @@ export declare type RunAggregationQueryRequest = export declare type Aggregation = firestoreV1ApiClientInterfaces.Aggregation; export declare type RunAggregationQueryResponse = firestoreV1ApiClientInterfaces.RunAggregationQueryResponse; +export declare type Stage = firestoreV1ApiClientInterfaces.Stage; export declare type Status = firestoreV1ApiClientInterfaces.Status; export declare type StructuredQuery = firestoreV1ApiClientInterfaces.StructuredQuery; +export declare type StructuredPipeline = + firestoreV1ApiClientInterfaces.StructuredPipeline; export declare type Target = firestoreV1ApiClientInterfaces.Target; export declare type TargetChange = firestoreV1ApiClientInterfaces.TargetChange; export declare type TransactionOptions = diff --git a/packages/firestore/src/protos/google/firestore/v1/document.proto b/packages/firestore/src/protos/google/firestore/v1/document.proto index 5238a943ce..f760575050 100644 --- a/packages/firestore/src/protos/google/firestore/v1/document.proto +++ b/packages/firestore/src/protos/google/firestore/v1/document.proto @@ -129,6 +129,48 @@ message Value { // A map value. MapValue map_value = 6; + // Value which references a field. + // + // This is considered relative (vs absolute) since it only refers to a field + // and not a field within a particular document. + // + // **Requires:** + // + // * Must follow [field reference][FieldReference.field_path] limitations. + // + // * Not allowed to be used when writing documents. + // + // (-- NOTE(batchik): long term, there is no reason this type should not be + // allowed to be used on the write path. --) + string field_reference_value = 19; + + // A value that represents an unevaluated expression. + // + // **Requires:** + // + // * Not allowed to be used when writing documents. + // + // (-- NOTE(batchik): similar to above, there is no reason to not allow + // storing expressions into the database, just no plan to support in + // the near term. + // + // This would actually be an interesting way to represent user-defined + // functions or more expressive rules-based systems. --) + Function function_value = 20; + + // A value that represents an unevaluated pipeline. + // + // **Requires:** + // + // * Not allowed to be used when writing documents. + // + // (-- NOTE(batchik): similar to above, there is no reason to not allow + // storing expressions into the database, just no plan to support in + // the near term. + // + // This would actually be an interesting way to represent user-defined + // functions or more expressive rules-based systems. --) + Pipeline pipeline_value = 21; } } @@ -148,3 +190,73 @@ message MapValue { // not exceed 1,500 bytes and cannot be empty. map fields = 1; } + + +// Represents an unevaluated scalar expression. +// +// For example, the expression `like(user_name, "%alice%")` is represented as: +// +// ``` +// name: "like" +// args { field_reference: "user_name" } +// args { string_value: "%alice%" } +// ``` +// +// (-- api-linter: core::0123::resource-annotation=disabled +// aip.dev/not-precedent: this is not a One Platform API resource. --) +message Function { + // The name of the function to evaluate. + // + // **Requires:** + // + // * must be in snake case (lower case with underscore separator). + // + string name = 1; + + // Ordered list of arguments the given function expects. + repeated Value args = 2; + + // Optional named arguments that certain functions may support. + map options = 3; +} + +// A Firestore query represented as an ordered list of operations / stages. +message Pipeline { + // A single operation within a pipeline. + // + // A stage is made up of a unique name, and a list of arguments. The exact + // number of arguments & types is dependent on the stage type. + // + // To give an example, the stage `filter(state = "MD")` would be encoded as: + // + // ``` + // name: "filter" + // args { + // function_value { + // name: "eq" + // args { field_reference_value: "state" } + // args { string_value: "MD" } + // } + // } + // ``` + // + // See public documentation for the full list. + message Stage { + // The name of the stage to evaluate. + // + // **Requires:** + // + // * must be in snake case (lower case with underscore separator). + // + string name = 1; + + // Ordered list of arguments the given stage expects. + repeated Value args = 2; + + // Optional named arguments that certain functions may support. + map options = 3; + } + + // Ordered list of stages to evaluate. + repeated Stage stages = 1; +} diff --git a/packages/firestore/src/protos/google/firestore/v1/firestore.proto b/packages/firestore/src/protos/google/firestore/v1/firestore.proto index a8fc0d54b5..3e7b62e060 100644 --- a/packages/firestore/src/protos/google/firestore/v1/firestore.proto +++ b/packages/firestore/src/protos/google/firestore/v1/firestore.proto @@ -22,6 +22,7 @@ import "google/api/field_behavior.proto"; import "google/firestore/v1/aggregation_result.proto"; import "google/firestore/v1/common.proto"; import "google/firestore/v1/document.proto"; +import "google/firestore/v1/pipeline.proto"; import "google/firestore/v1/query.proto"; import "google/firestore/v1/write.proto"; import "google/protobuf/empty.proto"; @@ -135,6 +136,15 @@ service Firestore { }; } + // Executes a pipeline query. + rpc ExecutePipeline(ExecutePipelineRequest) + returns (stream ExecutePipelineResponse) { + option (google.api.http) = { + post: "/v1/{database=projects/*/databases/*}/documents:executePipeline" + body: "*" + }; + } + // Runs an aggregation query. // // Rather than producing [Document][google.firestore.v1.Document] results like [Firestore.RunQuery][google.firestore.v1.Firestore.RunQuery], @@ -157,7 +167,7 @@ service Firestore { } }; } - + // Partitions a query by returning partition cursors that can be used to run // the query in parallel. The returned partition cursors are split points that // can be used by RunQuery as starting/end points for the query results. @@ -547,6 +557,82 @@ message RunQueryResponse { int32 skipped_results = 4; } +// The request for [Firestore.ExecutePipeline][]. +message ExecutePipelineRequest { + // Database identifier, in the form `projects/{project}/databases/{database}`. + string database = 1 [ + (google.api.field_behavior) = REQUIRED + ]; + + oneof pipeline_type { + // A pipelined operation. + StructuredPipeline structured_pipeline = 2; + } + + // Optional consistency arguments, defaults to strong consistency. + oneof consistency_selector { + // Run the query within an already active transaction. + // + // The value here is the opaque transaction ID to execute the query in. + bytes transaction = 5; + + // Execute the pipeline in a new transaction. + // + // The identifier of the newly created transaction will be returned in the + // first response on the stream. This defaults to a read-only transaction. + TransactionOptions new_transaction = 6; + + // Execute the pipeline in a snapshot transaction at the given time. + // + // This must be a microsecond precision timestamp within the past one hour, + // or if Point-in-Time Recovery is enabled, can additionally be a whole + // minute timestamp within the past 7 days. + google.protobuf.Timestamp read_time = 7; + } + + // Explain / analyze options for the pipeline. + // ExplainOptions explain_options = 8 [(google.api.field_behavior) = OPTIONAL]; +} + +// The response for [Firestore.Execute][]. +message ExecutePipelineResponse { + // Newly created transaction identifier. + // + // This field is only specified on the first response from the server when + // the request specified [ExecuteRequest.new_transaction][]. + bytes transaction = 1; + + // An ordered batch of results returned executing a pipeline. + // + // The batch size is variable, and can even be zero for when only a partial + // progress message is returned. + // + // The fields present in the returned documents are only those that were + // explicitly requested in the pipeline, this include those like + // [`__name__`][Document.name] & [`__update_time__`][Document.update_time]. + // This is explicitly a divergence from `Firestore.RunQuery` / + // `Firestore.GetDocument` RPCs which always return such fields even when they + // are not specified in the [`mask`][DocumentMask]. + repeated Document results = 2; + + // The time at which the document(s) were read. + // + // This may be monotonically increasing; in this case, the previous documents + // in the result stream are guaranteed not to have changed between their + // `execution_time` and this one. + // + // If the query returns no results, a response with `execution_time` and no + // `results` will be sent, and this represents the time at which the operation + // was run. + google.protobuf.Timestamp execution_time = 3; + + // Query explain metrics. + // + // Set on the last response when [ExecutePipelineRequest.explain_options][] + // was specified on the request. + // ExplainMetrics explain_metrics = 4; +} + // The request for [Firestore.RunAggregationQuery][google.firestore.v1.Firestore.RunAggregationQuery]. message RunAggregationQueryRequest { // Required. The parent resource name. In the format: diff --git a/packages/firestore/src/protos/google/firestore/v1/pipeline.proto b/packages/firestore/src/protos/google/firestore/v1/pipeline.proto new file mode 100644 index 0000000000..ea5b230933 --- /dev/null +++ b/packages/firestore/src/protos/google/firestore/v1/pipeline.proto @@ -0,0 +1,41 @@ +/*! + * 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. + */ + +syntax = "proto3"; +package google.firestore.v1; +import "google/firestore/v1/document.proto"; +option csharp_namespace = "Google.Cloud.Firestore.V1"; +option php_namespace = "Google\\Cloud\\Firestore\\V1"; +option ruby_package = "Google::Cloud::Firestore::V1"; +option java_multiple_files = true; +option java_package = "com.google.firestore.v1"; +option java_outer_classname = "PipelineProto"; +option objc_class_prefix = "GCFS"; +// A Firestore query represented as an ordered list of operations / stages. +// +// This is considered the top-level function which plans & executes a query. +// It is logically equivalent to `query(stages, options)`, but prevents the +// client from having to build a function wrapper. +message StructuredPipeline { + // The pipeline query to execute. + Pipeline pipeline = 1; + // Optional query-level arguments. + // + // (-- Think query statement hints. --) + // + // (-- TODO(batchik): define the api contract of using an unsupported hint --) + map options = 2; +} diff --git a/packages/firestore/src/protos/google/firestore/v1/query_profile.proto b/packages/firestore/src/protos/google/firestore/v1/query_profile.proto new file mode 100644 index 0000000000..de27144a03 --- /dev/null +++ b/packages/firestore/src/protos/google/firestore/v1/query_profile.proto @@ -0,0 +1,92 @@ +// 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. + +syntax = "proto3"; + +package google.firestore.v1; + +import "google/api/field_behavior.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; + +option csharp_namespace = "Google.Cloud.Firestore.V1"; +option go_package = "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb"; +option java_multiple_files = true; +option java_outer_classname = "QueryProfileProto"; +option java_package = "com.google.firestore.v1"; +option objc_class_prefix = "GCFS"; +option php_namespace = "Google\\Cloud\\Firestore\\V1"; +option ruby_package = "Google::Cloud::Firestore::V1"; + +// Specification of the Firestore Query Profile fields. + +// Explain options for the query. +message ExplainOptions { + // Optional. Whether to execute this query. + // + // When false (the default), the query will be planned, returning only + // metrics from the planning stages. + // + // When true, the query will be planned and executed, returning the full + // query results along with both planning and execution stage metrics. + bool analyze = 1 [(google.api.field_behavior) = OPTIONAL]; +} + +// Explain metrics for the query. +message ExplainMetrics { + // Planning phase information for the query. + PlanSummary plan_summary = 1; + + // Aggregated stats from the execution of the query. Only present when + // [ExplainOptions.analyze][google.firestore.v1.ExplainOptions.analyze] is set + // to true. + ExecutionStats execution_stats = 2; +} + +// Planning phase information for the query. +message PlanSummary { + // The indexes selected for the query. For example: + // [ + // {"query_scope": "Collection", "properties": "(foo ASC, __name__ ASC)"}, + // {"query_scope": "Collection", "properties": "(bar ASC, __name__ ASC)"} + // ] + repeated google.protobuf.Struct indexes_used = 1; +} + +// Execution statistics for the query. +message ExecutionStats { + // Total number of results returned, including documents, projections, + // aggregation results, keys. + int64 results_returned = 1; + + // Total time to execute the query in the backend. + google.protobuf.Duration execution_duration = 3; + + // Total billable read operations. + int64 read_operations = 4; + + // Debugging statistics from the execution of the query. Note that the + // debugging stats are subject to change as Firestore evolves. It could + // include: + // { + // "indexes_entries_scanned": "1000", + // "documents_scanned": "20", + // "billing_details" : { + // "documents_billable": "20", + // "index_entries_billable": "1000", + // "min_query_cost": "0" + // } + // } + google.protobuf.Struct debug_stats = 5; +} diff --git a/packages/firestore/src/protos/protos.json b/packages/firestore/src/protos/protos.json index b2c50ccaee..5b73c4647f 100644 --- a/packages/firestore/src/protos/protos.json +++ b/packages/firestore/src/protos/protos.json @@ -4,16 +4,78 @@ "nested": { "protobuf": { "options": { - "csharp_namespace": "Google.Protobuf.WellKnownTypes", - "go_package": "github.com/golang/protobuf/ptypes/wrappers", + "go_package": "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor", "java_package": "com.google.protobuf", - "java_outer_classname": "WrappersProto", - "java_multiple_files": true, + "java_outer_classname": "DescriptorProtos", + "csharp_namespace": "Google.Protobuf.Reflection", "objc_class_prefix": "GPB", "cc_enable_arenas": true, "optimize_for": "SPEED" }, "nested": { + "Struct": { + "fields": { + "fields": { + "keyType": "string", + "type": "Value", + "id": 1 + } + } + }, + "Value": { + "oneofs": { + "kind": { + "oneof": [ + "nullValue", + "numberValue", + "stringValue", + "boolValue", + "structValue", + "listValue" + ] + } + }, + "fields": { + "nullValue": { + "type": "NullValue", + "id": 1 + }, + "numberValue": { + "type": "double", + "id": 2 + }, + "stringValue": { + "type": "string", + "id": 3 + }, + "boolValue": { + "type": "bool", + "id": 4 + }, + "structValue": { + "type": "Struct", + "id": 5 + }, + "listValue": { + "type": "ListValue", + "id": 6 + } + } + }, + "NullValue": { + "values": { + "NULL_VALUE": 0 + } + }, + "ListValue": { + "fields": { + "values": { + "rule": "repeated", + "type": "Value", + "id": 1 + } + } + }, "Timestamp": { "fields": { "seconds": { @@ -161,6 +223,10 @@ "end": { "type": "int32", "id": 2 + }, + "options": { + "type": "ExtensionRangeOptions", + "id": 3 } } }, @@ -178,6 +244,21 @@ } } }, + "ExtensionRangeOptions": { + "fields": { + "uninterpretedOption": { + "rule": "repeated", + "type": "UninterpretedOption", + "id": 999 + } + }, + "extensions": [ + [ + 1000, + 536870911 + ] + ] + }, "FieldDescriptorProto": { "fields": { "name": { @@ -279,6 +360,30 @@ "options": { "type": "EnumOptions", "id": 3 + }, + "reservedRange": { + "rule": "repeated", + "type": "EnumReservedRange", + "id": 4 + }, + "reservedName": { + "rule": "repeated", + "type": "string", + "id": 5 + } + }, + "nested": { + "EnumReservedRange": { + "fields": { + "start": { + "type": "int32", + "id": 1 + }, + "end": { + "type": "int32", + "id": 2 + } + } } } }, @@ -335,11 +440,17 @@ }, "clientStreaming": { "type": "bool", - "id": 5 + "id": 5, + "options": { + "default": false + } }, "serverStreaming": { "type": "bool", - "id": 6 + "id": 6, + "options": { + "default": false + } } } }, @@ -355,7 +466,10 @@ }, "javaMultipleFiles": { "type": "bool", - "id": 10 + "id": 10, + "options": { + "default": false + } }, "javaGenerateEqualsAndHash": { "type": "bool", @@ -366,7 +480,10 @@ }, "javaStringCheckUtf8": { "type": "bool", - "id": 27 + "id": 27, + "options": { + "default": false + } }, "optimizeFor": { "type": "OptimizeMode", @@ -381,23 +498,45 @@ }, "ccGenericServices": { "type": "bool", - "id": 16 + "id": 16, + "options": { + "default": false + } }, "javaGenericServices": { "type": "bool", - "id": 17 + "id": 17, + "options": { + "default": false + } }, "pyGenericServices": { "type": "bool", - "id": 18 + "id": 18, + "options": { + "default": false + } + }, + "phpGenericServices": { + "type": "bool", + "id": 42, + "options": { + "default": false + } }, "deprecated": { "type": "bool", - "id": 23 + "id": 23, + "options": { + "default": false + } }, "ccEnableArenas": { "type": "bool", - "id": 31 + "id": 31, + "options": { + "default": false + } }, "objcClassPrefix": { "type": "string", @@ -407,6 +546,26 @@ "type": "string", "id": 37 }, + "swiftPrefix": { + "type": "string", + "id": 39 + }, + "phpClassPrefix": { + "type": "string", + "id": 40 + }, + "phpNamespace": { + "type": "string", + "id": 41 + }, + "phpMetadataNamespace": { + "type": "string", + "id": 44 + }, + "rubyPackage": { + "type": "string", + "id": 45 + }, "uninterpretedOption": { "rule": "repeated", "type": "UninterpretedOption", @@ -439,15 +598,24 @@ "fields": { "messageSetWireFormat": { "type": "bool", - "id": 1 + "id": 1, + "options": { + "default": false + } }, "noStandardDescriptorAccessor": { "type": "bool", - "id": 2 + "id": 2, + "options": { + "default": false + } }, "deprecated": { "type": "bool", - "id": 3 + "id": 3, + "options": { + "default": false + } }, "mapEntry": { "type": "bool", @@ -469,6 +637,10 @@ [ 8, 8 + ], + [ + 9, + 9 ] ] }, @@ -494,15 +666,24 @@ }, "lazy": { "type": "bool", - "id": 5 + "id": 5, + "options": { + "default": false + } }, "deprecated": { "type": "bool", - "id": 3 + "id": 3, + "options": { + "default": false + } }, "weak": { "type": "bool", - "id": 10 + "id": 10, + "options": { + "default": false + } }, "uninterpretedOption": { "rule": "repeated", @@ -562,7 +743,10 @@ }, "deprecated": { "type": "bool", - "id": 3 + "id": 3, + "options": { + "default": false + } }, "uninterpretedOption": { "rule": "repeated", @@ -575,13 +759,22 @@ 1000, 536870911 ] + ], + "reserved": [ + [ + 5, + 5 + ] ] }, "EnumValueOptions": { "fields": { "deprecated": { "type": "bool", - "id": 1 + "id": 1, + "options": { + "default": false + } }, "uninterpretedOption": { "rule": "repeated", @@ -600,7 +793,10 @@ "fields": { "deprecated": { "type": "bool", - "id": 33 + "id": 33, + "options": { + "default": false + } }, "uninterpretedOption": { "rule": "repeated", @@ -619,7 +815,17 @@ "fields": { "deprecated": { "type": "bool", - "id": 33 + "id": 33, + "options": { + "default": false + } + }, + "idempotencyLevel": { + "type": "IdempotencyLevel", + "id": 34, + "options": { + "default": "IDEMPOTENCY_UNKNOWN" + } }, "uninterpretedOption": { "rule": "repeated", @@ -632,7 +838,16 @@ 1000, 536870911 ] - ] + ], + "nested": { + "IdempotencyLevel": { + "values": { + "IDEMPOTENCY_UNKNOWN": 0, + "NO_SIDE_EFFECTS": 1, + "IDEMPOTENT": 2 + } + } + } }, "UninterpretedOption": { "fields": { @@ -753,72 +968,6 @@ } } }, - "Struct": { - "fields": { - "fields": { - "keyType": "string", - "type": "Value", - "id": 1 - } - } - }, - "Value": { - "oneofs": { - "kind": { - "oneof": [ - "nullValue", - "numberValue", - "stringValue", - "boolValue", - "structValue", - "listValue" - ] - } - }, - "fields": { - "nullValue": { - "type": "NullValue", - "id": 1 - }, - "numberValue": { - "type": "double", - "id": 2 - }, - "stringValue": { - "type": "string", - "id": 3 - }, - "boolValue": { - "type": "bool", - "id": 4 - }, - "structValue": { - "type": "Struct", - "id": 5 - }, - "listValue": { - "type": "ListValue", - "id": 6 - } - } - }, - "NullValue": { - "values": { - "NULL_VALUE": 0 - } - }, - "ListValue": { - "fields": { - "values": { - "rule": "repeated", - "type": "Value", - "id": 1 - } - } - }, - "Empty": { - "fields": {} - }, "DoubleValue": { "fields": { "value": { @@ -891,9 +1040,12 @@ } } }, + "Empty": { + "fields": {} + }, "Any": { "fields": { - "typeUrl": { + "type_url": { "type": "string", "id": 1 }, @@ -902,6 +1054,18 @@ "id": 2 } } + }, + "Duration": { + "fields": { + "seconds": { + "type": "int64", + "id": 1 + }, + "nanos": { + "type": "int32", + "id": 2 + } + } } } }, @@ -910,9 +1074,9 @@ "v1": { "options": { "csharp_namespace": "Google.Cloud.Firestore.V1", - "go_package": "google.golang.org/genproto/googleapis/firestore/v1;firestore", + "go_package": "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb", "java_multiple_files": true, - "java_outer_classname": "WriteProto", + "java_outer_classname": "QueryProfileProto", "java_package": "com.google.firestore.v1", "objc_class_prefix": "GCFS", "php_namespace": "Google\\Cloud\\Firestore\\V1", @@ -928,104 +1092,6 @@ } } }, - "BitSequence": { - "fields": { - "bitmap": { - "type": "bytes", - "id": 1 - }, - "padding": { - "type": "int32", - "id": 2 - } - } - }, - "BloomFilter": { - "fields": { - "bits": { - "type": "BitSequence", - "id": 1 - }, - "hashCount": { - "type": "int32", - "id": 2 - } - } - }, - "DocumentMask": { - "fields": { - "fieldPaths": { - "rule": "repeated", - "type": "string", - "id": 1 - } - } - }, - "Precondition": { - "oneofs": { - "conditionType": { - "oneof": [ - "exists", - "updateTime" - ] - } - }, - "fields": { - "exists": { - "type": "bool", - "id": 1 - }, - "updateTime": { - "type": "google.protobuf.Timestamp", - "id": 2 - } - } - }, - "TransactionOptions": { - "oneofs": { - "mode": { - "oneof": [ - "readOnly", - "readWrite" - ] - } - }, - "fields": { - "readOnly": { - "type": "ReadOnly", - "id": 2 - }, - "readWrite": { - "type": "ReadWrite", - "id": 3 - } - }, - "nested": { - "ReadWrite": { - "fields": { - "retryTransaction": { - "type": "bytes", - "id": 1 - } - } - }, - "ReadOnly": { - "oneofs": { - "consistencySelector": { - "oneof": [ - "readTime" - ] - } - }, - "fields": { - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 2 - } - } - } - } - }, "Document": { "fields": { "name": { @@ -1061,7 +1127,10 @@ "referenceValue", "geoPointValue", "arrayValue", - "mapValue" + "mapValue", + "fieldReferenceValue", + "functionValue", + "pipelineValue" ] } }, @@ -1106,27 +1175,184 @@ "type": "ArrayValue", "id": 9 }, - "mapValue": { - "type": "MapValue", - "id": 6 + "mapValue": { + "type": "MapValue", + "id": 6 + }, + "fieldReferenceValue": { + "type": "string", + "id": 19 + }, + "functionValue": { + "type": "Function", + "id": 20 + }, + "pipelineValue": { + "type": "Pipeline", + "id": 21 + } + } + }, + "ArrayValue": { + "fields": { + "values": { + "rule": "repeated", + "type": "Value", + "id": 1 + } + } + }, + "MapValue": { + "fields": { + "fields": { + "keyType": "string", + "type": "Value", + "id": 1 + } + } + }, + "Function": { + "fields": { + "name": { + "type": "string", + "id": 1 + }, + "args": { + "rule": "repeated", + "type": "Value", + "id": 2 + }, + "options": { + "keyType": "string", + "type": "Value", + "id": 3 + } + } + }, + "Pipeline": { + "fields": { + "stages": { + "rule": "repeated", + "type": "Stage", + "id": 1 + } + }, + "nested": { + "Stage": { + "fields": { + "name": { + "type": "string", + "id": 1 + }, + "args": { + "rule": "repeated", + "type": "Value", + "id": 2 + }, + "options": { + "keyType": "string", + "type": "Value", + "id": 3 + } + } + } + } + }, + "BitSequence": { + "fields": { + "bitmap": { + "type": "bytes", + "id": 1 + }, + "padding": { + "type": "int32", + "id": 2 + } + } + }, + "BloomFilter": { + "fields": { + "bits": { + "type": "BitSequence", + "id": 1 + }, + "hashCount": { + "type": "int32", + "id": 2 } } }, - "ArrayValue": { + "DocumentMask": { "fields": { - "values": { + "fieldPaths": { "rule": "repeated", - "type": "Value", + "type": "string", "id": 1 } } }, - "MapValue": { + "Precondition": { + "oneofs": { + "conditionType": { + "oneof": [ + "exists", + "updateTime" + ] + } + }, "fields": { - "fields": { - "keyType": "string", - "type": "Value", + "exists": { + "type": "bool", "id": 1 + }, + "updateTime": { + "type": "google.protobuf.Timestamp", + "id": 2 + } + } + }, + "TransactionOptions": { + "oneofs": { + "mode": { + "oneof": [ + "readOnly", + "readWrite" + ] + } + }, + "fields": { + "readOnly": { + "type": "ReadOnly", + "id": 2 + }, + "readWrite": { + "type": "ReadWrite", + "id": 3 + } + }, + "nested": { + "ReadWrite": { + "fields": { + "retryTransaction": { + "type": "bytes", + "id": 1 + } + } + }, + "ReadOnly": { + "oneofs": { + "consistencySelector": { + "oneof": [ + "readTime" + ] + } + }, + "fields": { + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 2 + } + } } } }, @@ -1302,6 +1528,23 @@ } ] }, + "ExecutePipeline": { + "requestType": "ExecutePipelineRequest", + "responseType": "ExecutePipelineResponse", + "responseStream": true, + "options": { + "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:executePipeline", + "(google.api.http).body": "*" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{database=projects/*/databases/*}/documents:executePipeline", + "body": "*" + } + } + ] + }, "RunAggregationQuery": { "requestType": "RunAggregationQueryRequest", "responseType": "RunAggregationQueryResponse", @@ -1816,6 +2059,64 @@ } } }, + "ExecutePipelineRequest": { + "oneofs": { + "pipelineType": { + "oneof": [ + "structuredPipeline" + ] + }, + "consistencySelector": { + "oneof": [ + "transaction", + "newTransaction", + "readTime" + ] + } + }, + "fields": { + "database": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "structuredPipeline": { + "type": "StructuredPipeline", + "id": 2 + }, + "transaction": { + "type": "bytes", + "id": 5 + }, + "newTransaction": { + "type": "TransactionOptions", + "id": 6 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 7 + } + } + }, + "ExecutePipelineResponse": { + "fields": { + "transaction": { + "type": "bytes", + "id": 1 + }, + "results": { + "rule": "repeated", + "type": "Document", + "id": 2 + }, + "executionTime": { + "type": "google.protobuf.Timestamp", + "id": 3 + } + } + }, "RunAggregationQueryRequest": { "oneofs": { "queryType": { @@ -2216,6 +2517,19 @@ } } }, + "StructuredPipeline": { + "fields": { + "pipeline": { + "type": "Pipeline", + "id": 1 + }, + "options": { + "keyType": "string", + "type": "Value", + "id": 2 + } + } + }, "StructuredQuery": { "fields": { "select": { @@ -2474,7 +2788,7 @@ "Sum": { "fields": { "field": { - "type": "FieldReference", + "type": "StructuredQuery.FieldReference", "id": 1 } } @@ -2482,7 +2796,7 @@ "Avg": { "fields": { "field": { - "type": "FieldReference", + "type": "StructuredQuery.FieldReference", "id": 1 } } @@ -2694,6 +3008,82 @@ "id": 3 } } + }, + "ExplainOptions": { + "fields": { + "analyze": { + "type": "bool", + "id": 1, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + } + } + }, + "ExplainMetrics": { + "fields": { + "planSummary": { + "type": "PlanSummary", + "id": 1 + }, + "executionStats": { + "type": "ExecutionStats", + "id": 2 + } + } + }, + "PlanSummary": { + "fields": { + "indexesUsed": { + "rule": "repeated", + "type": "google.protobuf.Struct", + "id": 1 + } + } + }, + "ExecutionStats": { + "fields": { + "resultsReturned": { + "type": "int64", + "id": 1 + }, + "executionDuration": { + "type": "google.protobuf.Duration", + "id": 3 + }, + "readOperations": { + "type": "int64", + "id": 4 + }, + "debugStats": { + "type": "google.protobuf.Struct", + "id": 5 + } + } + } + } + } + } + }, + "type": { + "options": { + "cc_enable_arenas": true, + "go_package": "google.golang.org/genproto/googleapis/type/latlng;latlng", + "java_multiple_files": true, + "java_outer_classname": "LatLngProto", + "java_package": "com.google.type", + "objc_class_prefix": "GTP" + }, + "nested": { + "LatLng": { + "fields": { + "latitude": { + "type": "double", + "id": 1 + }, + "longitude": { + "type": "double", + "id": 2 } } } @@ -2701,9 +3091,9 @@ }, "api": { "options": { - "go_package": "google.golang.org/genproto/googleapis/api/annotations;annotations", + "go_package": "google.golang.org/genproto/googleapis/api;api", "java_multiple_files": true, - "java_outer_classname": "HttpProto", + "java_outer_classname": "LaunchStageProto", "java_package": "com.google.api", "objc_class_prefix": "GAPI", "cc_enable_arenas": true @@ -2720,6 +3110,10 @@ "rule": "repeated", "type": "HttpRule", "id": 1 + }, + "fullyDecodeReservedExpansion": { + "type": "bool", + "id": 2 } } }, @@ -2737,6 +3131,10 @@ } }, "fields": { + "selector": { + "type": "string", + "id": 1 + }, "get": { "type": "string", "id": 2 @@ -2761,14 +3159,14 @@ "type": "CustomHttpPattern", "id": 8 }, - "selector": { - "type": "string", - "id": 1 - }, "body": { "type": "string", "id": 7 }, + "responseBody": { + "type": "string", + "id": 12 + }, "additionalBindings": { "rule": "repeated", "type": "HttpRule", @@ -2821,29 +3219,17 @@ "UNORDERED_LIST": 6, "NON_EMPTY_DEFAULT": 7 } - } - } - }, - "type": { - "options": { - "cc_enable_arenas": true, - "go_package": "google.golang.org/genproto/googleapis/type/latlng;latlng", - "java_multiple_files": true, - "java_outer_classname": "LatLngProto", - "java_package": "com.google.type", - "objc_class_prefix": "GTP" - }, - "nested": { - "LatLng": { - "fields": { - "latitude": { - "type": "double", - "id": 1 - }, - "longitude": { - "type": "double", - "id": 2 - } + }, + "LaunchStage": { + "values": { + "LAUNCH_STAGE_UNSPECIFIED": 0, + "UNIMPLEMENTED": 6, + "PRELAUNCH": 7, + "EARLY_ACCESS": 1, + "ALPHA": 2, + "BETA": 3, + "GA": 4, + "DEPRECATED": 5 } } } @@ -2880,4 +3266,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/firestore/src/remote/datastore.ts b/packages/firestore/src/remote/datastore.ts index f790ede0d5..4c84fca96e 100644 --- a/packages/firestore/src/remote/datastore.ts +++ b/packages/firestore/src/remote/datastore.ts @@ -20,10 +20,12 @@ import { User } from '../auth/user'; import { Aggregate } from '../core/aggregate'; import { DatabaseId } from '../core/database_info'; import { queryToAggregateTarget, Query, queryToTarget } from '../core/query'; +import { StructuredPipeline } from '../core/structured_pipeline'; import { Document } from '../model/document'; import { DocumentKey } from '../model/document_key'; import { Mutation } from '../model/mutation'; import { ResourcePath } from '../model/path'; +import { PipelineStreamElement } from '../model/pipeline_stream_element'; import { ApiClientObjectMap, BatchGetDocumentsRequest as ProtoBatchGetDocumentsRequest, @@ -32,6 +34,8 @@ import { RunAggregationQueryResponse as ProtoRunAggregationQueryResponse, RunQueryRequest as ProtoRunQueryRequest, RunQueryResponse as ProtoRunQueryResponse, + ExecutePipelineRequest as ProtoExecutePipelineRequest, + ExecutePipelineResponse as ProtoExecutePipelineResponse, Value } from '../protos/firestore_proto_api'; import { debugAssert, debugCast, hardAssert } from '../util/assert'; @@ -54,7 +58,9 @@ import { toName, toQueryTarget, toResourcePath, - toRunAggregationQueryRequest + toRunAggregationQueryRequest, + fromPipelineResponse, + getEncodedDatabaseId } from './serializer'; /** @@ -236,6 +242,42 @@ export async function invokeBatchGetDocumentsRpc( return result; } +export async function invokeExecutePipeline( + datastore: Datastore, + structuredPipeline: StructuredPipeline +): Promise { + const datastoreImpl = debugCast(datastore, DatastoreImpl); + const executePipelineRequest: ProtoExecutePipelineRequest = { + database: getEncodedDatabaseId(datastoreImpl.serializer), + structuredPipeline: structuredPipeline._toProto(datastoreImpl.serializer) + }; + + const response = await datastoreImpl.invokeStreamingRPC< + ProtoExecutePipelineRequest, + ProtoExecutePipelineResponse + >( + 'ExecutePipeline', + datastoreImpl.serializer.databaseId, + ResourcePath.emptyPath(), + executePipelineRequest + ); + + const result: PipelineStreamElement[] = []; + response.forEach(proto => { + if (!proto.results || proto.results!.length === 0) { + result.push(fromPipelineResponse(datastoreImpl.serializer, proto)); + } else { + return proto.results!.forEach(document => + result.push( + fromPipelineResponse(datastoreImpl.serializer, proto, document) + ) + ); + } + }); + + return result; +} + export async function invokeRunQueryRpc( datastore: Datastore, query: Query diff --git a/packages/firestore/src/remote/internal_serializer.ts b/packages/firestore/src/remote/internal_serializer.ts index 8f27824758..1e759dab81 100644 --- a/packages/firestore/src/remote/internal_serializer.ts +++ b/packages/firestore/src/remote/internal_serializer.ts @@ -18,12 +18,23 @@ import { ensureFirestoreConfigured, Firestore } from '../api/database'; import { AggregateImpl } from '../core/aggregate'; import { queryToAggregateTarget, queryToTarget } from '../core/query'; +import { + StructuredPipeline, + StructuredPipelineOptions +} from '../core/structured_pipeline'; import { AggregateSpec } from '../lite-api/aggregate_types'; +import { getDatastore } from '../lite-api/components'; +import { Pipeline } from '../lite-api/pipeline'; import { Query } from '../lite-api/reference'; +import { ExecutePipelineRequest as ProtoExecutePipelineRequest } from '../protos/firestore_proto_api'; import { cast } from '../util/input_validation'; import { mapToArray } from '../util/obj'; -import { toQueryTarget, toRunAggregationQueryRequest } from './serializer'; +import { + getEncodedDatabaseId, + toQueryTarget, + toRunAggregationQueryRequest +} from './serializer'; /** * @internal @@ -87,3 +98,38 @@ export function _internalAggregationQueryToProtoRunAggregationQueryRequest< /* skipAliasing= */ true ).request; } + +/** + * @internal + * @private + * + * This function is for internal use only. + * + * Returns the `ExecutePipelineRequest` representation of the given query. + * Returns `null` if the Firestore client associated with the given query has + * not been initialized or has been terminated. + * + * @param pipeline - The Pipeline to convert to proto representation. + */ +export function _internalPipelineToExecutePipelineRequestProto( + pipeline: Pipeline + // eslint-disable-next-line @typescript-eslint/no-explicit-any +): any { + const firestore = cast(pipeline._db, Firestore); + const datastore = getDatastore(firestore); + const serializer = datastore.serializer; + if (serializer === undefined) { + return null; + } + + const structuredPipeline = new StructuredPipeline( + pipeline, + new StructuredPipelineOptions() + ); + const executePipelineRequest: ProtoExecutePipelineRequest = { + database: getEncodedDatabaseId(serializer), + structuredPipeline: structuredPipeline._toProto(serializer) + }; + + return executePipelineRequest; +} diff --git a/packages/firestore/src/remote/rest_connection.ts b/packages/firestore/src/remote/rest_connection.ts index 2d6889dac3..83b0c572f9 100644 --- a/packages/firestore/src/remote/rest_connection.ts +++ b/packages/firestore/src/remote/rest_connection.ts @@ -46,6 +46,7 @@ RPC_NAME_URL_MAPPING['BatchGetDocuments'] = 'batchGet'; RPC_NAME_URL_MAPPING['Commit'] = 'commit'; RPC_NAME_URL_MAPPING['RunQuery'] = 'runQuery'; RPC_NAME_URL_MAPPING['RunAggregationQuery'] = 'runAggregationQuery'; +RPC_NAME_URL_MAPPING['ExecutePipeline'] = 'executePipeline'; const RPC_URL_VERSION = 'v1'; @@ -70,7 +71,7 @@ export abstract class RestConnection implements Connection { return false; } - constructor(private readonly databaseInfo: DatabaseInfo) { + constructor(protected readonly databaseInfo: DatabaseInfo) { this.databaseId = databaseInfo.databaseId; const proto = databaseInfo.ssl ? 'https' : 'http'; const projectId = encodeURIComponent(this.databaseId.projectId); @@ -193,13 +194,17 @@ export abstract class RestConnection implements Connection { _forwardCredentials: boolean ): Promise; - private makeUrl(rpcName: string, path: string): string { + protected makeUrl(rpcName: string, path: string): string { const urlRpcName = RPC_NAME_URL_MAPPING[rpcName]; debugAssert( urlRpcName !== undefined, 'Unknown REST mapping for: ' + rpcName ); - return `${this.baseUrl}/${RPC_URL_VERSION}/${path}:${urlRpcName}`; + let url = `${this.baseUrl}/${RPC_URL_VERSION}/${path}:${urlRpcName}`; + if (this.databaseInfo.apiKey) { + url = `${url}?key=${encodeURIComponent(this.databaseInfo.apiKey)}`; + } + return url; } /** diff --git a/packages/firestore/src/remote/serializer.ts b/packages/firestore/src/remote/serializer.ts index 830875f5e1..f11781ac33 100644 --- a/packages/firestore/src/remote/serializer.ts +++ b/packages/firestore/src/remote/serializer.ts @@ -37,6 +37,8 @@ import { import { SnapshotVersion } from '../core/snapshot_version'; import { targetIsDocumentTarget, Target } from '../core/target'; import { TargetId } from '../core/types'; +import { Bytes } from '../lite-api/bytes'; +import { GeoPoint } from '../lite-api/geo_point'; import { Timestamp } from '../lite-api/timestamp'; import { TargetData, TargetPurpose } from '../local/target_data'; import { MutableDocument } from '../model/document'; @@ -55,6 +57,7 @@ import { import { normalizeTimestamp } from '../model/normalize'; import { ObjectValue } from '../model/object_value'; import { FieldPath, ResourcePath } from '../model/path'; +import { PipelineStreamElement } from '../model/pipeline_stream_element'; import { ArrayRemoveTransformOperation, ArrayUnionTransformOperation, @@ -87,7 +90,11 @@ import { TargetChangeTargetChangeType as ProtoTargetChangeTargetChangeType, Timestamp as ProtoTimestamp, Write as ProtoWrite, - WriteResult as ProtoWriteResult + WriteResult as ProtoWriteResult, + Value as ProtoValue, + MapValue as ProtoMapValue, + ExecutePipelineResponse as ProtoExecutePipelineResponse, + Pipeline } from '../protos/firestore_proto_api'; import { debugAssert, fail, hardAssert } from '../util/assert'; import { ByteString } from '../util/byte_string'; @@ -173,7 +180,7 @@ function fromRpcStatus(status: ProtoStatus): FirestoreError { * our generated proto interfaces say Int32Value must be. But GRPC actually * expects a { value: } struct. */ -function toInt32Proto( +export function toInt32Proto( serializer: JsonProtoSerializer, val: number | null ): number | { value: number } | null { @@ -431,6 +438,37 @@ export function toDocument( }; } +export function fromPipelineResponse( + serializer: JsonProtoSerializer, + proto: ProtoExecutePipelineResponse, + document?: ProtoDocument +): PipelineStreamElement { + const output: PipelineStreamElement = {}; + if (proto.transaction?.length) { + output.transaction = proto.transaction; + } + const executionTime = proto.executionTime + ? fromVersion(proto.executionTime) + : undefined; + output.executionTime = executionTime; + + if (!!document) { + output.key = document.name + ? fromName(serializer, document.name) + : undefined; + + output.fields = new ObjectValue({ mapValue: { fields: document.fields } }); + + output.createTime = document.createTime + ? fromVersion(document.createTime!) + : undefined; + output.updateTime = document.updateTime + ? fromVersion(document.updateTime!) + : undefined; + } + return output; +} + export function fromDocument( serializer: JsonProtoSerializer, document: ProtoDocument, @@ -1414,3 +1452,98 @@ export function isValidResourceName(path: ResourcePath): boolean { path.get(2) === 'databases' ); } + +export interface ProtoSerializable { + _toProto(serializer: JsonProtoSerializer): ProtoType; +} + +export interface ProtoValueSerializable extends ProtoSerializable { + // Supports runtime identification of the ProtoSerializable type. + _protoValueType: 'ProtoValue'; +} + +export function isProtoValueSerializable( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + value: any +): value is ProtoValueSerializable { + return ( + !!value && + typeof value._toProto === 'function' && + value._protoValueType === 'ProtoValue' + ); +} + +export function toMapValue( + serializer: JsonProtoSerializer, + input: Map> +): ProtoValue { + const map: ProtoMapValue = { fields: {} }; + input.forEach((exp: ProtoSerializable, key: string) => { + if (typeof key !== 'string') { + throw new Error(`Cannot encode map with non-string key: ${key}`); + } + + map.fields![key] = exp._toProto(serializer)!; + }); + return { + mapValue: map + }; +} + +export function toNullValue(value: null): ProtoValue { + return { nullValue: 'NULL_VALUE' }; +} + +export function toBooleanValue(value: boolean): ProtoValue { + return { booleanValue: value }; +} + +export function toStringValue(value: string): ProtoValue { + return { stringValue: value }; +} + +export function toPipelineValue(value: Pipeline): ProtoValue { + return { pipelineValue: value }; +} + +export function dateToTimestampValue( + serializer: JsonProtoSerializer, + value: Date +): ProtoValue { + const timestamp = Timestamp.fromDate(value); + return { + timestampValue: toTimestamp(serializer, timestamp) + }; +} + +export function timestampToTimestampValue( + serializer: JsonProtoSerializer, + value: Timestamp +): ProtoValue { + // Firestore backend truncates precision down to microseconds. To ensure + // offline mode works the same in regards to truncation, perform the + // truncation immediately without waiting for the backend to do that. + const timestamp = new Timestamp( + value.seconds, + Math.floor(value.nanoseconds / 1000) * 1000 + ); + return { + timestampValue: toTimestamp(serializer, timestamp) + }; +} + +export function toGeoPointValue(value: GeoPoint): ProtoValue { + return { + geoPointValue: { + latitude: value.latitude, + longitude: value.longitude + } + }; +} + +export function toBytesValue( + serializer: JsonProtoSerializer, + value: Bytes +): ProtoValue { + return { bytesValue: toBytes(serializer, value._byteString) }; +} diff --git a/packages/firestore/src/util/input_validation.ts b/packages/firestore/src/util/input_validation.ts index 7fd9967b5a..f3b5dda698 100644 --- a/packages/firestore/src/util/input_validation.ts +++ b/packages/firestore/src/util/input_validation.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { DocumentData } from '../lite-api/reference'; import { DocumentKey } from '../model/document_key'; import { ResourcePath } from '../model/path'; @@ -92,7 +93,7 @@ export function validateCollectionPath(path: ResourcePath): void { * Returns true if it's a non-null object without a custom prototype * (i.e. excludes Array, Date, etc.). */ -export function isPlainObject(input: unknown): boolean { +export function isPlainObject(input: unknown): input is DocumentData { return ( typeof input === 'object' && input !== null && diff --git a/packages/firestore/src/util/misc.ts b/packages/firestore/src/util/misc.ts index f2fa04d1b4..e2dc643783 100644 --- a/packages/firestore/src/util/misc.ts +++ b/packages/firestore/src/util/misc.ts @@ -153,6 +153,26 @@ export function arrayEquals( } return left.every((value, index) => comparator(value, right[index])); } + +/** + * Verifies equality for an optional value. + */ +export function isOptionalEqual( + left: T | undefined, + right: T | undefined, + equalityTest: (left: T, right: T) => boolean +): boolean { + if (left === undefined && right === undefined) { + return true; + } + + if (left === undefined || right === undefined) { + return false; + } + + return equalityTest(left, right); +} + /** * Returns the immediate lexicographically-following string. This is useful to * construct an inclusive range for indexeddb iterators. diff --git a/packages/firestore/src/util/obj.ts b/packages/firestore/src/util/obj.ts index c40bc86bc5..2b61da9447 100644 --- a/packages/firestore/src/util/obj.ts +++ b/packages/firestore/src/util/obj.ts @@ -32,7 +32,7 @@ export function objectSize(obj: object): number { } export function forEach( - obj: Dict | undefined, + obj: Record | undefined, fn: (key: string, val: V) => void ): void { for (const key in obj) { diff --git a/packages/firestore/src/util/pipeline_util.ts b/packages/firestore/src/util/pipeline_util.ts new file mode 100644 index 0000000000..a7400828fd --- /dev/null +++ b/packages/firestore/src/util/pipeline_util.ts @@ -0,0 +1,156 @@ +/** + * @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. + */ + +import { FirestoreError, vector } from '../api'; +import { + _constant, + AggregateFunction, + AliasedAggregate, + array, + constant, + Expression, + AliasedExpression, + field, + Field, + map, + Selectable +} from '../lite-api/expressions'; +import { VectorValue } from '../lite-api/vector_value'; + +import { fail } from './assert'; +import { isPlainObject } from './input_validation'; +import { isFirestoreValue } from './proto'; +import { isString } from './types'; + +export function selectablesToMap( + selectables: Array +): Map { + const result = new Map(); + for (const selectable of selectables) { + let alias: string; + let expression: Expression; + if (typeof selectable === 'string') { + alias = selectable as string; + expression = field(selectable); + } else if (selectable instanceof Field) { + alias = selectable.alias; + expression = selectable.expr; + } else if (selectable instanceof AliasedExpression) { + alias = selectable.alias; + expression = selectable.expr; + } else { + fail(0x5319, '`selectable` has an unsupported type', { selectable }); + } + + if (result.get(alias) !== undefined) { + throw new FirestoreError( + 'invalid-argument', + `Duplicate alias or field '${alias}'` + ); + } + + result.set(alias, expression); + } + return result; +} + +export function aliasedAggregateToMap( + aliasedAggregatees: AliasedAggregate[] +): Map { + return aliasedAggregatees.reduce( + (map: Map, selectable: AliasedAggregate) => { + if (map.get(selectable.alias) !== undefined) { + throw new FirestoreError( + 'invalid-argument', + `Duplicate alias or field '${selectable.alias}'` + ); + } + + map.set(selectable.alias, selectable.aggregate as AggregateFunction); + return map; + }, + new Map() as Map + ); +} + +/** + * Converts a value to an Expr, Returning either a Constant, MapFunction, + * ArrayFunction, or the input itself (if it's already an expression). + * + * @private + * @internal + * @param value + */ +export function vectorToExpr( + value: VectorValue | number[] | Expression +): Expression { + if (value instanceof Expression) { + return value; + } else if (value instanceof VectorValue) { + const result = constant(value); + return result; + } else if (Array.isArray(value)) { + const result = constant(vector(value)); + return result; + } else { + throw new Error('Unsupported value: ' + typeof value); + } +} + +/** + * Converts a value to an Expr, 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 + */ +export function fieldOrExpression(value: unknown): Expression { + if (isString(value)) { + const result = field(value); + return result; + } else { + return valueToDefaultExpr(value); + } +} +/** + * Converts a value to an Expr, Returning either a Constant, MapFunction, + * ArrayFunction, or the input itself (if it's already an expression). + * + * @private + * @internal + * @param value + */ +export function valueToDefaultExpr(value: unknown): Expression { + let result: Expression | undefined; + if (isFirestoreValue(value)) { + return constant(value); + } + if (value instanceof Expression) { + return value; + } else if (isPlainObject(value)) { + result = map(value as Record); + } else if (value instanceof Array) { + result = array(value); + } else { + result = _constant(value, undefined); + } + + return result; +} diff --git a/packages/firestore/src/util/proto.ts b/packages/firestore/src/util/proto.ts new file mode 100644 index 0000000000..a99f73cfa9 --- /dev/null +++ b/packages/firestore/src/util/proto.ts @@ -0,0 +1,155 @@ +/** + * @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. + */ + +import { + ArrayValue as ProtoArrayValue, + Function as ProtoFunction, + LatLng as ProtoLatLng, + MapValue as ProtoMapValue, + Pipeline as ProtoPipeline, + Timestamp as ProtoTimestamp, + Value as ProtoValue +} from '../protos/firestore_proto_api'; + +import { isPlainObject } from './input_validation'; + +/* eslint @typescript-eslint/no-explicit-any: 0 */ + +function isITimestamp(obj: any): obj is ProtoTimestamp { + 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: any): obj is ProtoLatLng { + 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: any): obj is ProtoArrayValue { + 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: any): obj is ProtoMapValue { + if (typeof obj !== 'object' || obj === null) { + return false; // Must be a non-null object + } + if ('fields' in obj && (obj.fields === null || isPlainObject(obj.fields))) { + return true; + } + + return false; +} +function isIFunction(obj: any): obj is ProtoFunction { + 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: any): obj is ProtoPipeline { + 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; +} + +export function isFirestoreValue(obj: any): obj is ProtoValue { + 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; +} diff --git a/packages/firestore/src/util/types.ts b/packages/firestore/src/util/types.ts index c298bfe213..ad272991ff 100644 --- a/packages/firestore/src/util/types.ts +++ b/packages/firestore/src/util/types.ts @@ -37,6 +37,10 @@ export function isNegativeZero(value: number): boolean { return value === 0 && 1 / value === 1 / -0; } +export function isNumber(value: unknown): value is number { + return typeof value === 'number'; +} + /** * Returns whether a value is an integer and in the safe integer range * @param value - The value to test for being an integer and in the safe range @@ -51,6 +55,10 @@ export function isSafeInteger(value: unknown): boolean { ); } +export function isString(value: unknown): value is string { + return typeof value === 'string'; +} + /** The subset of the browser's Window interface used by the SDK. */ export interface WindowLike { readonly localStorage: Storage; @@ -65,3 +73,19 @@ export interface DocumentLike { addEventListener(type: string, listener: EventListener): void; removeEventListener(type: string, listener: EventListener): void; } + +/** + * @beta + * Utility type to create an type that only allows one + * property of the Type param T to be set. + * + * type XorY = OneOf<{ x: unknown, y: unknown}> + * let a = { x: "foo" } // OK + * let b = { y: "foo" } // OK + * let c = { a: "foo", y: "foo" } // Not OK + */ +export type OneOf = { + [K in keyof T]: Pick & { + [P in Exclude]?: undefined; + }; +}[keyof T]; diff --git a/packages/firestore/test/integration/api/aggregation.test.ts b/packages/firestore/test/integration/api/aggregation.test.ts index ba44dddf51..c6a3489040 100644 --- a/packages/firestore/test/integration/api/aggregation.test.ts +++ b/packages/firestore/test/integration/api/aggregation.test.ts @@ -17,6 +17,7 @@ import { expect } from 'chai'; +import { it } from '../../util/mocha_extensions'; import { collection, collectionGroup, @@ -42,7 +43,6 @@ import { withTestCollection, withTestDb } from '../util/helpers'; -import { USE_EMULATOR } from '../util/settings'; apiDescribe('Count queries', persistence => { it('can run count query getCountFromServer', () => { @@ -150,7 +150,7 @@ apiDescribe('Count queries', persistence => { // production, since the Firestore Emulator does not require index creation // and will, therefore, never fail in this situation. // eslint-disable-next-line no-restricted-properties - (USE_EMULATOR ? it.skip : it)( + it.skipEnterprise.skipEmulator( 'getCountFromServer error message contains console link if missing index', () => { return withEmptyTestCollection(persistence, async coll => { @@ -161,6 +161,7 @@ apiDescribe('Count queries', persistence => { ); // TODO(b/316359394) Remove the special logic for non-default databases // once cl/582465034 is rolled out to production. + // @ts-ignore internal API usage if (coll.firestore._databaseId.isDefaultDatabase) { await expect( getCountFromServer(query_) @@ -362,7 +363,7 @@ apiDescribe('Aggregation queries', persistence => { // production, since the Firestore Emulator does not require index creation // and will, therefore, never fail in this situation. // eslint-disable-next-line no-restricted-properties - (USE_EMULATOR ? it.skip : it)( + it.skipEmulator.skipEnterprise( 'getAggregateFromServer error message contains console link good if missing index', () => { return withEmptyTestCollection(persistence, async coll => { @@ -373,6 +374,7 @@ apiDescribe('Aggregation queries', persistence => { ); // TODO(b/316359394) Remove the special logic for non-default databases // once cl/582465034 is rolled out to production. + // @ts-ignore internal API usage if (coll.firestore._databaseId.isDefaultDatabase) { await expect( getAggregateFromServer(query_, { @@ -480,26 +482,29 @@ apiDescribe('Aggregation queries - sum / average', persistence => { }); }); - it('fails when exceeding the max (5) aggregations using getAggregationFromServer', () => { - const testDocs = { - a: { author: 'authorA', title: 'titleA', pages: 100 }, - b: { author: 'authorB', title: 'titleB', pages: 50 } - }; - return withTestCollection(persistence, testDocs, async coll => { - const promise = getAggregateFromServer(coll, { - totalPages: sum('pages'), - averagePages: average('pages'), - count: count(), - totalPagesX: sum('pages'), - averagePagesY: average('pages'), - countZ: count() + it.skipEnterprise( + 'fails when exceeding the max (5) aggregations using getAggregationFromServer', + () => { + const testDocs = { + a: { author: 'authorA', title: 'titleA', pages: 100 }, + b: { author: 'authorB', title: 'titleB', pages: 50 } + }; + return withTestCollection(persistence, testDocs, async coll => { + const promise = getAggregateFromServer(coll, { + totalPages: sum('pages'), + averagePages: average('pages'), + count: count(), + totalPagesX: sum('pages'), + averagePagesY: average('pages'), + countZ: count() + }); + + await expect(promise).to.eventually.be.rejectedWith( + /maximum number of aggregations/ + ); }); - - await expect(promise).to.eventually.be.rejectedWith( - /maximum number of aggregations/ - ); - }); - }); + } + ); it('returns undefined when getting the result of an unrequested aggregation', () => { const testDocs = { @@ -940,47 +945,50 @@ apiDescribe('Aggregation queries - sum / average', persistence => { }); }); - it('performs sum over a result set of zero documents using getAggregationFromServer', () => { - const testDocs = { - a: { - author: 'authorA', - title: 'titleA', - pages: 100, - year: 1980, - rating: 5 - }, - b: { - author: 'authorB', - title: 'titleB', - pages: 50, - year: 2020, - rating: 4 - }, - c: { - author: 'authorC', - title: 'titleC', - pages: 100, - year: 1980, - rating: 3 - }, - d: { - author: 'authorD', - title: 'titleD', - pages: 50, - year: 2020, - rating: 0 - } - }; - return withTestCollection(persistence, testDocs, async coll => { - const snapshot = await getAggregateFromServer( - query(coll, where('pages', '>', 200)), - { - totalPages: sum('pages') + it.skipEnterprise( + 'performs sum over a result set of zero documents using getAggregationFromServer', + () => { + const testDocs = { + a: { + author: 'authorA', + title: 'titleA', + pages: 100, + year: 1980, + rating: 5 + }, + b: { + author: 'authorB', + title: 'titleB', + pages: 50, + year: 2020, + rating: 4 + }, + c: { + author: 'authorC', + title: 'titleC', + pages: 100, + year: 1980, + rating: 3 + }, + d: { + author: 'authorD', + title: 'titleD', + pages: 50, + year: 2020, + rating: 0 } - ); - expect(snapshot.data().totalPages).to.equal(0); - }); - }); + }; + return withTestCollection(persistence, testDocs, async coll => { + const snapshot = await getAggregateFromServer( + query(coll, where('pages', '>', 200)), + { + totalPages: sum('pages') + } + ); + expect(snapshot.data().totalPages).to.equal(0); + }); + } + ); it('performs sum only on numeric fields using getAggregationFromServer', () => { const testDocs = { diff --git a/packages/firestore/test/integration/api/array_transforms.test.ts b/packages/firestore/test/integration/api/array_transforms.test.ts index e1a628435e..19c9417fec 100644 --- a/packages/firestore/test/integration/api/array_transforms.test.ts +++ b/packages/firestore/test/integration/api/array_transforms.test.ts @@ -34,8 +34,6 @@ import { } from '../util/firebase_export'; import { apiDescribe, withTestDb, withTestDoc } from '../util/helpers'; -addEqualityMatcher(); - /** * Note: Transforms are tested pretty thoroughly in server_timestamp.test.ts * (via set, update, transactions, nested in documents, multiple transforms @@ -43,6 +41,8 @@ addEqualityMatcher(); * semantics. */ apiDescribe('Array Transforms:', persistence => { + addEqualityMatcher(); + // A document reference to read and write to. let docRef: DocumentReference; diff --git a/packages/firestore/test/integration/api/bundle.test.ts b/packages/firestore/test/integration/api/bundle.test.ts index 467026d375..3bca3c5496 100644 --- a/packages/firestore/test/integration/api/bundle.test.ts +++ b/packages/firestore/test/integration/api/bundle.test.ts @@ -86,6 +86,7 @@ apiDescribe('Bundles', persistence => { // Extract elements from BUNDLE_TEMPLATE and replace the project ID. const elements = BUNDLE_TEMPLATE.map(e => + // @ts-ignore internal API usage e.replace('{0}', projectId).replace('(default)', db._databaseId.database) ); diff --git a/packages/firestore/test/integration/api/composite_index_query.test.ts b/packages/firestore/test/integration/api/composite_index_query.test.ts index d08cc77bde..0dbc765788 100644 --- a/packages/firestore/test/integration/api/composite_index_query.test.ts +++ b/packages/firestore/test/integration/api/composite_index_query.test.ts @@ -17,6 +17,7 @@ import { expect } from 'chai'; +import { it } from '../../util/mocha_extensions'; import { CompositeIndexTestHelper } from '../util/composite_index_test_helper'; import { where, @@ -196,27 +197,33 @@ apiDescribe('Composite Index Queries', persistence => { }); }); - it('performs aggregations on documents with all aggregated fields using getAggregationFromServer', () => { - const testDocs = { - a: { author: 'authorA', title: 'titleA', pages: 100, year: 1980 }, - b: { author: 'authorB', title: 'titleB', pages: 50, year: 2020 }, - c: { author: 'authorC', title: 'titleC', pages: 150, year: 2021 }, - d: { author: 'authorD', title: 'titleD', pages: 50 } - }; - const testHelper = new CompositeIndexTestHelper(); - return testHelper.withTestDocs(persistence, testDocs, async coll => { - const snapshot = await getAggregateFromServer(testHelper.query(coll), { - totalPages: sum('pages'), - averagePages: average('pages'), - averageYear: average('year'), - count: count() + it.skipEmulator.skipEnterprise( + 'performs aggregations on documents with all aggregated fields using getAggregationFromServer', + () => { + const testDocs = { + a: { author: 'authorA', title: 'titleA', pages: 100, year: 1980 }, + b: { author: 'authorB', title: 'titleB', pages: 50, year: 2020 }, + c: { author: 'authorC', title: 'titleC', pages: 150, year: 2021 }, + d: { author: 'authorD', title: 'titleD', pages: 50 } + }; + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs(persistence, testDocs, async coll => { + const snapshot = await getAggregateFromServer( + testHelper.query(coll), + { + totalPages: sum('pages'), + averagePages: average('pages'), + averageYear: average('year'), + count: count() + } + ); + expect(snapshot.data().totalPages).to.equal(300); + expect(snapshot.data().averagePages).to.equal(100); + expect(snapshot.data().averageYear).to.equal(2007); + expect(snapshot.data().count).to.equal(3); }); - expect(snapshot.data().totalPages).to.equal(300); - expect(snapshot.data().averagePages).to.equal(100); - expect(snapshot.data().averageYear).to.equal(2007); - expect(snapshot.data().count).to.equal(3); - }); - }); + } + ); it('performs aggregates on multiple fields where one aggregate could cause short-circuit due to NaN using getAggregationFromServer', () => { const testDocs = { @@ -262,56 +269,62 @@ apiDescribe('Composite Index Queries', persistence => { }); }); - it('performs aggregates when using `array-contains-any` operator getAggregationFromServer', () => { - const testDocs = { - a: { - author: 'authorA', - title: 'titleA', - pages: 100, - year: 1980, - rating: [5, 1000] - }, - b: { - author: 'authorB', - title: 'titleB', - pages: 50, - year: 2020, - rating: [4] - }, - c: { - author: 'authorC', - title: 'titleC', - pages: 100, - year: 1980, - rating: [2222, 3] - }, - d: { - author: 'authorD', - title: 'titleD', - pages: 50, - year: 2020, - rating: [0] - } - }; - const testHelper = new CompositeIndexTestHelper(); - return testHelper.withTestDocs(persistence, testDocs, async coll => { - const snapshot = await getAggregateFromServer( - testHelper.query(coll, where('rating', 'array-contains-any', [5, 3])), - { - totalRating: sum('rating'), - averageRating: average('rating'), - totalPages: sum('pages'), - averagePages: average('pages'), - countOfDocs: count() + it.skipEnterprise( + 'performs aggregates when using `array-contains-any` operator getAggregationFromServer', + () => { + const testDocs = { + a: { + author: 'authorA', + title: 'titleA', + pages: 100, + year: 1980, + rating: [5, 1000] + }, + b: { + author: 'authorB', + title: 'titleB', + pages: 50, + year: 2020, + rating: [4] + }, + c: { + author: 'authorC', + title: 'titleC', + pages: 100, + year: 1980, + rating: [2222, 3] + }, + d: { + author: 'authorD', + title: 'titleD', + pages: 50, + year: 2020, + rating: [0] } - ); - expect(snapshot.data().totalRating).to.equal(0); - expect(snapshot.data().averageRating).to.be.null; - expect(snapshot.data().totalPages).to.equal(200); - expect(snapshot.data().averagePages).to.equal(100); - expect(snapshot.data().countOfDocs).to.equal(2); - }); - }); + }; + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs(persistence, testDocs, async coll => { + const snapshot = await getAggregateFromServer( + testHelper.query( + coll, + where('rating', 'array-contains-any', [5, 3]) + ), + { + totalRating: sum('rating'), + averageRating: average('rating'), + totalPages: sum('pages'), + averagePages: average('pages'), + countOfDocs: count() + } + ); + expect(snapshot.data().totalRating).to.equal(0); + expect(snapshot.data().averageRating).to.be.null; + expect(snapshot.data().totalPages).to.equal(200); + expect(snapshot.data().averagePages).to.equal(100); + expect(snapshot.data().countOfDocs).to.equal(2); + }); + } + ); }); describe('Multiple Inequality', () => { @@ -950,18 +963,24 @@ apiDescribe('Composite Index Queries', persistence => { }); }); - it('inequality query will reject if document key appears only in equality filter', () => { - const testHelper = new CompositeIndexTestHelper(); - return testHelper.withTestCollection(persistence, async coll => { - const query_ = testHelper.query( - coll, - where('key', '!=', 42), - where(documentId(), '==', 'doc1') - ); - await expect(testHelper.getDocs(query_)).to.be.eventually.rejectedWith( - 'Equality on key is not allowed if there are other inequality fields and key does not appear in inequalities.' - ); - }); - }); + // + it.skipEnterprise( + 'inequality query will reject if document key appears only in equality filter', + () => { + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestCollection(persistence, async coll => { + const query_ = testHelper.query( + coll, + where('key', '!=', 42), + where(documentId(), '==', 'doc1') + ); + await expect( + testHelper.getDocs(query_) + ).to.be.eventually.rejectedWith( + 'Equality on key is not allowed if there are other inequality fields and key does not appear in inequalities.' + ); + }); + } + ); }); }); diff --git a/packages/firestore/test/integration/api/database.test.ts b/packages/firestore/test/integration/api/database.test.ts index b63c03a4f6..f38a590e04 100644 --- a/packages/firestore/test/integration/api/database.test.ts +++ b/packages/firestore/test/integration/api/database.test.ts @@ -20,6 +20,7 @@ import { Deferred, isNode } from '@firebase/util'; import { expect, use } from 'chai'; import chaiAsPromised from 'chai-as-promised'; +import { it } from '../../util/mocha_extensions'; import { EventsAccumulator } from '../util/events_accumulator'; import { addDoc, @@ -1900,6 +1901,7 @@ apiDescribe('Database', persistence => { const firestore2 = newTestFirestore( newTestApp(options.projectId!, name), DEFAULT_SETTINGS, + // @ts-ignore internal API usage firestore._databaseId.database ); await enableIndexedDbPersistence(firestore2); @@ -1945,6 +1947,7 @@ apiDescribe('Database', persistence => { const firestore2 = newTestFirestore( newTestApp(options.projectId!, name), undefined, + // @ts-ignore internal API usage docRef.firestore._databaseId.database ); await enableIndexedDbPersistence(firestore2); @@ -2109,6 +2112,7 @@ apiDescribe('Database', persistence => { const deferred: Deferred = new Deferred(); const unsubscribe = onSnapshot(docRef, snapshot => {}, deferred.resolve); + // @ts-ignore internal API usage await firestore._restart(); await expect(deferred.promise) @@ -2733,58 +2737,10 @@ apiDescribe('Database', persistence => { }); }); - it('snapshot listener sorts filtered query by DocumentId same way as get query', async () => { - const testDocs = { - 'A': { a: 1 }, - 'a': { a: 1 }, - 'Aa': { a: 1 }, - '7': { a: 1 }, - '12': { a: 1 }, - '__id7__': { a: 1 }, - '__id12__': { a: 1 }, - '__id-2__': { a: 1 }, - '_id1__': { a: 1 }, - '__id1_': { a: 1 }, - '__id': { a: 1 }, - // largest long numbers - '__id9223372036854775807__': { a: 1 }, - '__id9223372036854775806__': { a: 1 }, - // smallest long numbers - '__id-9223372036854775808__': { a: 1 }, - '__id-9223372036854775807__': { a: 1 } - }; - - return withTestCollection(persistence, testDocs, async collectionRef => { - const filteredQuery = query( - collectionRef, - orderBy(documentId()), - where(documentId(), '>', '__id7__'), - where(documentId(), '<=', 'Aa') - ); - const expectedDocs = [ - '__id12__', - '__id9223372036854775806__', - '__id9223372036854775807__', - '12', - '7', - 'A', - 'Aa' - ]; - - const getSnapshot = await getDocsFromServer(filteredQuery); - expect(toIds(getSnapshot)).to.deep.equal(expectedDocs); - - const storeEvent = new EventsAccumulator(); - const unsubscribe = onSnapshot(filteredQuery, storeEvent.storeEvent); - const watchSnapshot = await storeEvent.awaitEvent(); - expect(toIds(watchSnapshot)).to.deep.equal(expectedDocs); - unsubscribe(); - }); - }); - - // eslint-disable-next-line no-restricted-properties - (persistence.gc === 'lru' ? describe : describe.skip)('offline', () => { - it('SDK orders query the same way online and offline', async () => { + // Enterprise does not sort numeric IDs before string + it.skipEnterprise( + 'snapshot listener sorts filtered query by DocumentId same way as get query', + async () => { const testDocs = { 'A': { a: 1 }, 'a': { a: 1 }, @@ -2809,37 +2765,13 @@ apiDescribe('Database', persistence => { persistence, testDocs, async collectionRef => { - const orderedQuery = query(collectionRef, orderBy(documentId())); - let expectedDocs = [ - '__id-9223372036854775808__', - '__id-9223372036854775807__', - '__id-2__', - '__id7__', - '__id12__', - '__id9223372036854775806__', - '__id9223372036854775807__', - '12', - '7', - 'A', - 'Aa', - '__id', - '__id1_', - '_id1__', - 'a' - ]; - await checkOnlineAndOfflineResultsMatch( - collectionRef, - orderedQuery, - ...expectedDocs - ); - const filteredQuery = query( collectionRef, orderBy(documentId()), where(documentId(), '>', '__id7__'), where(documentId(), '<=', 'Aa') ); - expectedDocs = [ + const expectedDocs = [ '__id12__', '__id9223372036854775806__', '__id9223372036854775807__', @@ -2848,14 +2780,100 @@ apiDescribe('Database', persistence => { 'A', 'Aa' ]; - await checkOnlineAndOfflineResultsMatch( - collectionRef, + + const getSnapshot = await getDocsFromServer(filteredQuery); + expect(toIds(getSnapshot)).to.deep.equal(expectedDocs); + + const storeEvent = new EventsAccumulator(); + const unsubscribe = onSnapshot( filteredQuery, - ...expectedDocs + storeEvent.storeEvent ); + const watchSnapshot = await storeEvent.awaitEvent(); + expect(toIds(watchSnapshot)).to.deep.equal(expectedDocs); + unsubscribe(); } ); - }); + } + ); + + // eslint-disable-next-line no-restricted-properties + (persistence.gc === 'lru' ? describe : describe.skip)('offline', () => { + it.skipEnterprise( + 'SDK orders query the same way online and offline', + async () => { + const testDocs = { + 'A': { a: 1 }, + 'a': { a: 1 }, + 'Aa': { a: 1 }, + '7': { a: 1 }, + '12': { a: 1 }, + '__id7__': { a: 1 }, + '__id12__': { a: 1 }, + '__id-2__': { a: 1 }, + '_id1__': { a: 1 }, + '__id1_': { a: 1 }, + '__id': { a: 1 }, + // largest long numbers + '__id9223372036854775807__': { a: 1 }, + '__id9223372036854775806__': { a: 1 }, + // smallest long numbers + '__id-9223372036854775808__': { a: 1 }, + '__id-9223372036854775807__': { a: 1 } + }; + + return withTestCollection( + persistence, + testDocs, + async collectionRef => { + const orderedQuery = query(collectionRef, orderBy(documentId())); + let expectedDocs = [ + '__id-9223372036854775808__', + '__id-9223372036854775807__', + '__id-2__', + '__id7__', + '__id12__', + '__id9223372036854775806__', + '__id9223372036854775807__', + '12', + '7', + 'A', + 'Aa', + '__id', + '__id1_', + '_id1__', + 'a' + ]; + await checkOnlineAndOfflineResultsMatch( + collectionRef, + orderedQuery, + ...expectedDocs + ); + + const filteredQuery = query( + collectionRef, + orderBy(documentId()), + where(documentId(), '>', '__id7__'), + where(documentId(), '<=', 'Aa') + ); + expectedDocs = [ + '__id12__', + '__id9223372036854775806__', + '__id9223372036854775807__', + '12', + '7', + 'A', + 'Aa' + ]; + await checkOnlineAndOfflineResultsMatch( + collectionRef, + filteredQuery, + ...expectedDocs + ); + } + ); + } + ); }); }); diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts new file mode 100644 index 0000000000..22bc3656ba --- /dev/null +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -0,0 +1,4346 @@ +/** + * @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. + */ + +import { FirebaseError } from '@firebase/util'; +import { expect, use } from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +import { addEqualityMatcher } from '../../util/equality_matcher'; +import { Deferred } from '../../util/promise'; +import { + GeoPoint, + Timestamp, + Bytes, + getFirestore, + terminate, + vector, + CollectionReference, + doc, + DocumentData, + Firestore, + setDoc, + collection, + documentId as documentIdFieldPath, + writeBatch, + addDoc, + DocumentReference, + deleteDoc +} from '../util/firebase_export'; +import { apiDescribe, withTestCollection } from '../util/helpers'; +import { + array, + mod, + pipelineResultEqual, + sum, + descending, + map, + execute, + add, + arrayContainsAll, + unixSecondsToTimestamp, + and, + arrayContains, + arrayContainsAny, + count, + average, + cosineDistance, + not, + countAll, + dotProduct, + endsWith, + equal, + reverse, + toUpper, + euclideanDistance, + greaterThan, + like, + lessThan, + stringContains, + divide, + lessThanOrEqual, + arrayLength, + mapGet, + notEqual, + or, + regexContains, + regexMatch, + startsWith, + stringConcat, + subtract, + conditional, + equalAny, + logicalMaximum, + notEqualAny, + multiply, + countIf, + exists, + charLength, + minimum, + maximum, + isError, + ifError, + trim, + isAbsent, + timestampSubtract, + mapRemove, + mapMerge, + documentId, + substring, + logicalMinimum, + xor, + field, + constant, + FindNearestStageOptions, + AggregateFunction, + arrayGet, + ascending, + byteLength, + FunctionExpression, + timestampAdd, + timestampToUnixMicros, + timestampToUnixMillis, + timestampToUnixSeconds, + toLower, + unixMicrosToTimestamp, + unixMillisToTimestamp, + vectorLength, + countDistinct, + ceil, + floor, + exp, + pow, + round, + collectionId, + ln, + log, + sqrt, + stringReverse, + length, + abs, + concat, + currentTimestamp, + ifAbsent, + join, + log10, + arraySum, + PipelineSnapshot, + timestampTruncate, + split, + type +} from '../util/pipeline_export'; + +use(chaiAsPromised); + +const timestampDeltaMS = 1000; + +apiDescribe.skipClassic('Pipelines', persistence => { + addEqualityMatcher(); + + let firestore: Firestore; + let randomCol: CollectionReference; + let beginDocCreation: number = 0; + let endDocCreation: number = 0; + + async function testCollectionWithDocs(docs: { + [id: string]: DocumentData; + }): Promise> { + beginDocCreation = new Date().valueOf(); + for (const id in docs) { + if (docs.hasOwnProperty(id)) { + const ref = doc(randomCol, id); + await setDoc(ref, docs[id]); + } + } + endDocCreation = new Date().valueOf(); + return randomCol; + } + + function expectResults(snapshot: PipelineSnapshot, ...docs: string[]): void; + function expectResults( + snapshot: PipelineSnapshot, + ...data: DocumentData[] + ): void; + + function expectResults( + snapshot: PipelineSnapshot, + ...data: DocumentData[] | string[] + ): void { + const docs = snapshot.results; + + expect(docs.length).to.equal(data.length); + + if (data.length > 0) { + if (typeof data[0] === 'string') { + const actualIds = docs.map(doc => doc.id); + expect(actualIds).to.deep.equal(data); + } else { + docs.forEach(r => { + expect(r.data()).to.deep.equal(data.shift()); + }); + } + } + } + + async function setupBookDocs(): Promise> { + const bookDocs: { [id: string]: DocumentData } = { + book1: { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + embedding: vector([10, 1, 1, 1, 1, 1, 1, 1, 1, 1]) + }, + book2: { + title: 'Pride and Prejudice', + author: 'Jane Austen', + genre: 'Romance', + published: 1813, + rating: 4.5, + tags: ['classic', 'social commentary', 'love'], + awards: { none: true }, + embedding: vector([1, 10, 1, 1, 1, 1, 1, 1, 1, 1]) + }, + book3: { + title: 'One Hundred Years of Solitude', + author: 'Gabriel García Márquez', + genre: 'Magical Realism', + published: 1967, + rating: 4.3, + tags: ['family', 'history', 'fantasy'], + awards: { nobel: true, nebula: false }, + embedding: vector([1, 1, 10, 1, 1, 1, 1, 1, 1, 1]) + }, + book4: { + title: 'The Lord of the Rings', + author: 'J.R.R. Tolkien', + genre: 'Fantasy', + published: 1954, + rating: 4.7, + tags: ['adventure', 'magic', 'epic'], + awards: { hugo: false, nebula: false }, + remarks: null, + cost: NaN, + embedding: vector([1, 1, 1, 10, 1, 1, 1, 1, 1, 1]) + }, + book5: { + title: "The Handmaid's Tale", + author: 'Margaret Atwood', + genre: 'Dystopian', + published: 1985, + rating: 4.1, + tags: ['feminism', 'totalitarianism', 'resistance'], + awards: { 'arthur c. clarke': true, 'booker prize': false }, + embedding: vector([1, 1, 1, 1, 10, 1, 1, 1, 1, 1]) + }, + book6: { + title: 'Crime and Punishment', + author: 'Fyodor Dostoevsky', + genre: 'Psychological Thriller', + published: 1866, + rating: 4.3, + tags: ['philosophy', 'crime', 'redemption'], + awards: { none: true }, + embedding: vector([1, 1, 1, 1, 1, 10, 1, 1, 1, 1]) + }, + book7: { + title: 'To Kill a Mockingbird', + author: 'Harper Lee', + genre: 'Southern Gothic', + published: 1960, + rating: 4.2, + tags: ['racism', 'injustice', 'coming-of-age'], + awards: { pulitzer: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 10, 1, 1, 1]) + }, + book8: { + title: '1984', + author: 'George Orwell', + genre: 'Dystopian', + published: 1949, + rating: 4.2, + tags: ['surveillance', 'totalitarianism', 'propaganda'], + awards: { prometheus: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 1, 10, 1, 1]) + }, + book9: { + title: 'The Great Gatsby', + author: 'F. Scott Fitzgerald', + genre: 'Modernist', + published: 1925, + rating: 4.0, + tags: ['wealth', 'american dream', 'love'], + awards: { none: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 1, 1, 10, 1]) + }, + book10: { + title: 'Dune', + author: 'Frank Herbert', + genre: 'Science Fiction', + published: 1965, + rating: 4.6, + tags: ['politics', 'desert', 'ecology'], + awards: { hugo: true, nebula: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 1, 1, 1, 10]) + } + }; + return testCollectionWithDocs(bookDocs); + } + + let testDeferred: Deferred | undefined; + let withTestCollectionPromise: Promise | undefined; + + beforeEach(async () => { + const setupDeferred = new Deferred(); + testDeferred = new Deferred(); + withTestCollectionPromise = withTestCollection( + persistence, + {}, + async (collectionRef, firestoreInstance) => { + randomCol = collectionRef; + firestore = firestoreInstance; + await setupBookDocs(); + setupDeferred.resolve(); + + return testDeferred?.promise; + } + ); + + await setupDeferred.promise; + }); + + afterEach(async () => { + testDeferred?.resolve(); + await withTestCollectionPromise; + }); + + describe('pipeline results', () => { + it('empty snapshot as expected', async () => { + const snapshot = await execute( + firestore.pipeline().collection(randomCol.path).limit(0) + ); + expect(snapshot.results.length).to.equal(0); + }); + + it('full snapshot as expected', async () => { + const ppl = firestore + .pipeline() + .collection(randomCol.path) + .sort(ascending('__name__')); + const snapshot = await execute(ppl); + expect(snapshot.results.length).to.equal(10); + expectResults( + snapshot, + 'book1', + 'book10', + 'book2', + 'book3', + 'book4', + 'book5', + 'book6', + 'book7', + 'book8', + 'book9' + ); + }); + + it('result equals works', async () => { + const ppl = firestore + .pipeline() + .collection(randomCol.path) + .sort(ascending('title')) + .limit(1); + const snapshot1 = await execute(ppl); + const snapshot2 = await execute(ppl); + expect(snapshot1.results.length).to.equal(1); + expect(snapshot2.results.length).to.equal(1); + expect(pipelineResultEqual(snapshot1.results[0], snapshot2.results[0])).to + .be.true; + }); + + it('returns execution time', async () => { + const start = new Date().valueOf(); + const pipeline = firestore.pipeline().collection(randomCol.path); + + const snapshot = await execute(pipeline); + const end = new Date().valueOf(); + + expect(snapshot.executionTime.toDate().valueOf()).to.approximately( + (start + end) / 2, + timestampDeltaMS + ); + }); + + it('returns execution time for an empty query', async () => { + const start = new Date().valueOf(); + const pipeline = firestore.pipeline().collection(randomCol.path).limit(0); + + const snapshot = await execute(pipeline); + const end = new Date().valueOf(); + + expect(snapshot.results.length).to.equal(0); + + expect(snapshot.executionTime.toDate().valueOf()).to.approximately( + (start + end) / 2, + timestampDeltaMS + ); + }); + + it('returns create and update time for each document', async () => { + const pipeline = firestore.pipeline().collection(randomCol.path); + + let snapshot = await execute(pipeline); + expect(snapshot.results.length).to.equal(10); + snapshot.results.forEach(doc => { + expect(doc.createTime).to.not.be.null; + expect(doc.updateTime).to.not.be.null; + + expect(doc.createTime!.toDate().valueOf()).to.approximately( + (beginDocCreation + endDocCreation) / 2, + timestampDeltaMS + ); + expect(doc.updateTime!.toDate().valueOf()).to.approximately( + (beginDocCreation + endDocCreation) / 2, + timestampDeltaMS + ); + expect(doc.createTime?.valueOf()).to.equal(doc.updateTime?.valueOf()); + }); + + const wb = writeBatch(firestore); + snapshot.results.forEach(doc => { + wb.update(doc.ref!, { newField: 'value' }); + }); + await wb.commit(); + + snapshot = await execute(pipeline); + expect(snapshot.results.length).to.equal(10); + snapshot.results.forEach(doc => { + expect(doc.createTime).to.not.be.null; + expect(doc.updateTime).to.not.be.null; + expect(doc.createTime!.toDate().valueOf()).to.be.lessThan( + doc.updateTime!.toDate().valueOf() + ); + }); + }); + + it('returns execution time for an aggregate query', async () => { + const start = new Date().valueOf(); + const pipeline = firestore + .pipeline() + .collection(randomCol.path) + .aggregate(average('rating').as('avgRating')); + + const snapshot = await execute(pipeline); + const end = new Date().valueOf(); + + expect(snapshot.results.length).to.equal(1); + + expect(snapshot.executionTime.toDate().valueOf()).to.approximately( + (start + end) / 2, + timestampDeltaMS + ); + }); + + it('returns undefined create and update time for each result in an aggregate query', async () => { + const pipeline = firestore + .pipeline() + .collection(randomCol.path) + .aggregate({ + accumulators: [average('rating').as('avgRating')], + groups: ['genre'] + }); + + const snapshot = await execute(pipeline); + + expect(snapshot.results.length).to.equal(8); + + snapshot.results.forEach(doc => { + expect(doc.updateTime).to.be.undefined; + expect(doc.createTime).to.be.undefined; + }); + }); + }); + + describe('pipeline sources', () => { + it('supports CollectionReference as source', async () => { + const snapshot = await execute( + firestore.pipeline().collection(randomCol) + ); + expect(snapshot.results.length).to.equal(10); + }); + + it('supports list of documents as source', async () => { + const collName = randomCol.id; + + const snapshot = await execute( + firestore + .pipeline() + .documents([ + `${collName}/book1`, + doc(randomCol, 'book2'), + doc(randomCol, 'book3').path + ]) + ); + expect(snapshot.results.length).to.equal(3); + }); + + it('reject CollectionReference for another DB', async () => { + const db2 = getFirestore(firestore.app, 'notDefault'); + + expect(() => { + firestore.pipeline().collection(collection(db2, 'foo')); + }).to.throw(/Invalid CollectionReference/); + + await terminate(db2); + }); + + it('reject DocumentReference for another DB', async () => { + const db2 = getFirestore(firestore.app, 'notDefault'); + + expect(() => { + firestore.pipeline().documents([doc(db2, 'foo/bar')]); + }).to.throw(/Invalid DocumentReference/); + + await terminate(db2); + }); + + it('supports collection group as source', async () => { + const randomSubCollectionId = Math.random().toString(16).slice(2); + const doc1 = await addDoc( + collection(randomCol, 'book1', randomSubCollectionId), + { order: 1 } + ); + const doc2 = await addDoc( + collection(randomCol, 'book2', randomSubCollectionId), + { order: 2 } + ); + const snapshot = await execute( + firestore + .pipeline() + .collectionGroup(randomSubCollectionId) + .sort(ascending('order')) + ); + expectResults(snapshot, doc1.id, doc2.id); + }); + + it('supports database as source', async () => { + const randomId = Math.random().toString(16).slice(2); + const doc1 = await addDoc(collection(randomCol, 'book1', 'sub'), { + order: 1, + randomId + }); + const doc2 = await addDoc(collection(randomCol, 'book2', 'sub'), { + order: 2, + randomId + }); + const snapshot = await execute( + firestore + .pipeline() + .database() + .where(equal('randomId', randomId)) + .sort(ascending('order')) + ); + expectResults(snapshot, doc1.id, doc2.id); + }); + }); + + describe('supported data types', () => { + it('accepts and returns all data types', async () => { + const refDate = new Date(); + const refTimestamp = Timestamp.now(); + const constants = [ + constant(1).as('number'), + constant('a string').as('string'), + constant(true).as('boolean'), + constant(null).as('null'), + constant(new GeoPoint(0.1, 0.2)).as('geoPoint'), + constant(refTimestamp).as('timestamp'), + constant(refDate).as('date'), + constant( + Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0])) + ).as('bytes'), + constant(doc(firestore, 'foo', 'bar')).as('documentReference'), + constant(vector([1, 2, 3])).as('vectorValue'), + map({ + 'number': 1, + 'string': 'a string', + 'boolean': true, + 'null': null, + 'geoPoint': new GeoPoint(0.1, 0.2), + 'timestamp': refTimestamp, + 'date': refDate, + 'uint8Array': Bytes.fromUint8Array( + new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0]) + ), + 'documentReference': doc(firestore, 'foo', 'bar'), + 'vectorValue': vector([1, 2, 3]), + 'map': { + 'number': 2, + 'string': 'b string' + }, + 'array': [1, 'c string'] + }).as('map'), + array([ + 1, + 'a string', + true, + null, + new GeoPoint(0.1, 0.2), + refTimestamp, + refDate, + Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0])), + doc(firestore, 'foo', 'bar'), + vector([1, 2, 3]), + { + 'number': 2, + 'string': 'b string' + } + ]).as('array') + ]; + + const snapshots = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(constants[0], ...constants.slice(1)) + ); + + expectResults(snapshots, { + 'number': 1, + 'string': 'a string', + 'boolean': true, + 'null': null, + 'geoPoint': new GeoPoint(0.1, 0.2), + 'timestamp': refTimestamp, + 'date': Timestamp.fromDate(refDate), + 'bytes': Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0])), + 'documentReference': doc(firestore, 'foo', 'bar'), + 'vectorValue': vector([1, 2, 3]), + 'map': { + 'number': 1, + 'string': 'a string', + 'boolean': true, + 'null': null, + 'geoPoint': new GeoPoint(0.1, 0.2), + 'timestamp': refTimestamp, + 'date': Timestamp.fromDate(refDate), + 'uint8Array': Bytes.fromUint8Array( + new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0]) + ), + 'documentReference': doc(firestore, 'foo', 'bar'), + 'vectorValue': vector([1, 2, 3]), + 'map': { + 'number': 2, + 'string': 'b string' + }, + 'array': [1, 'c string'] + }, + 'array': [ + 1, + 'a string', + true, + null, + new GeoPoint(0.1, 0.2), + refTimestamp, + Timestamp.fromDate(refDate), + Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0])), + doc(firestore, 'foo', 'bar'), + vector([1, 2, 3]), + { + 'number': 2, + 'string': 'b string' + } + ] + }); + }); + + it('throws on undefined in a map', async () => { + expect(() => { + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select( + map({ + 'number': 1, + undefined + }).as('foo') + ); + }).to.throw( + 'Function map() called with invalid data. Unsupported field value: undefined' + ); + }); + + it('throws on undefined in an array', async () => { + expect(() => { + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(array([1, undefined]).as('foo')); + }).to.throw( + 'Function array() called with invalid data. Unsupported field value: undefined' + ); + }); + + it('converts arrays and plain objects to functionValues if the customer intent is unspecified', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + 'title', + 'author', + 'genre', + 'rating', + 'published', + 'tags', + 'awards' + ) + .addFields( + array([ + 1, + 2, + field('genre'), + multiply('rating', 10), + [field('title')], + { + published: field('published') + } + ]).as('metadataArray'), + map({ + genre: field('genre'), + rating: multiply('rating', 10), + nestedArray: [field('title')], + nestedMap: { + published: field('published') + } + }).as('metadata') + ) + .where( + and( + equal('metadataArray', [ + 1, + 2, + field('genre'), + multiply('rating', 10), + [field('title')], + { + published: field('published') + } + ]), + equal('metadata', { + genre: field('genre'), + rating: multiply('rating', 10), + nestedArray: [field('title')], + nestedMap: { + published: field('published') + } + }) + ) + ) + ); + + expect(snapshot.results.length).to.equal(1); + + expectResults(snapshot, { + title: 'The Lord of the Rings', + author: 'J.R.R. Tolkien', + genre: 'Fantasy', + published: 1954, + rating: 4.7, + tags: ['adventure', 'magic', 'epic'], + awards: { hugo: false, nebula: false }, + metadataArray: [ + 1, + 2, + 'Fantasy', + 47, + ['The Lord of the Rings'], + { + published: 1954 + } + ], + metadata: { + genre: 'Fantasy', + rating: 47, + nestedArray: ['The Lord of the Rings'], + nestedMap: { + published: 1954 + } + } + }); + }); + + it('supports boolean value constants as a BooleanExpression', async () => { + const snapshots = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select( + conditional(constant(true), constant('TRUE'), constant('FALSE')).as( + 'true' + ), + conditional( + constant(false), + constant('TRUE'), + constant('FALSE') + ).as('false') + ) + ); + + expectResults(snapshots, { + 'true': 'TRUE', + 'false': 'FALSE' + }); + }); + }); + + describe('stages', () => { + describe('aggregate stage', () => { + it('supports aggregate', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate(countAll().as('count')) + ); + expectResults(snapshot, { count: 10 }); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('genre', 'Science Fiction')) + .aggregate( + countAll().as('count'), + average('rating').as('avgRating'), + maximum('rating').as('maxRating'), + sum('rating').as('sumRating') + ) + ); + expectResults(snapshot, { + count: 2, + avgRating: 4.4, + maxRating: 4.6, + sumRating: 8.8 + }); + }); + + it('throws on Duplicate aliases', async () => { + expect(() => + firestore + .pipeline() + .collection(randomCol.path) + .aggregate(countAll().as('count'), count('foo').as('count')) + ).to.throw("Duplicate alias or field 'count'"); + }); + + it('throws on duplicate group aliases', async () => { + expect(() => + firestore + .pipeline() + .collection(randomCol.path) + .aggregate({ + accumulators: [countAll().as('count')], + groups: ['bax', field('bar').as('bax')] + }) + ).to.throw("Duplicate alias or field 'bax'"); + }); + + it('supports aggregate options', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate({ + accumulators: [countAll().as('count')] + }) + ); + expectResults(snapshot, { count: 10 }); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('genre', 'Science Fiction')) + .aggregate( + countAll().as('count'), + average('rating').as('avgRating'), + maximum('rating').as('maxRating'), + sum('rating').as('sumRating') + ) + ); + expectResults(snapshot, { + count: 2, + avgRating: 4.4, + maxRating: 4.6, + sumRating: 8.8 + }); + }); + + it('rejects groups without accumulators', async () => { + await expect( + execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(lessThan('published', 1900)) + .aggregate({ + accumulators: [], + groups: ['genre'] + }) + ) + ).to.be.rejected; + }); + + it('returns group and accumulate results', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(lessThan(field('published'), 1984)) + .aggregate({ + accumulators: [average('rating').as('avgRating')], + groups: ['genre'] + }) + .where(greaterThan('avgRating', 4.3)) + .sort(field('avgRating').descending()) + ); + expectResults( + snapshot, + { avgRating: 4.7, genre: 'Fantasy' }, + { avgRating: 4.5, genre: 'Romance' }, + { avgRating: 4.4, genre: 'Science Fiction' } + ); + }); + + it('returns min, max, count, and countAll accumulations', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate( + count('cost').as('booksWithCost'), + countAll().as('count'), + maximum('rating').as('maxRating'), + minimum('published').as('minPublished') + ) + ); + expectResults(snapshot, { + booksWithCost: 1, + count: 10, + maxRating: 4.7, + minPublished: 1813 + }); + }); + + it('returns countif accumulation', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate(countIf(field('rating').greaterThan(4.3)).as('count')) + ); + const expectedResults = { + count: 3 + }; + expectResults(snapshot, expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate(field('rating').greaterThan(4.3).countIf().as('count')) + ); + expectResults(snapshot, expectedResults); + }); + + it('returns countDistinct accumulation', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate(countDistinct('genre').as('distinctGenres')) + ); + expectResults(snapshot, { distinctGenres: 8 }); + }); + }); + + describe('distinct stage', () => { + it('returns distinct values as expected', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .distinct('genre', 'author') + .sort(field('genre').ascending(), field('author').ascending()) + ); + expectResults( + snapshot, + { genre: 'Dystopian', author: 'George Orwell' }, + { genre: 'Dystopian', author: 'Margaret Atwood' }, + { genre: 'Fantasy', author: 'J.R.R. Tolkien' }, + { genre: 'Magical Realism', author: 'Gabriel García Márquez' }, + { genre: 'Modernist', author: 'F. Scott Fitzgerald' }, + { genre: 'Psychological Thriller', author: 'Fyodor Dostoevsky' }, + { genre: 'Romance', author: 'Jane Austen' }, + { genre: 'Science Fiction', author: 'Douglas Adams' }, + { genre: 'Science Fiction', author: 'Frank Herbert' }, + { genre: 'Southern Gothic', author: 'Harper Lee' } + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .distinct('genre', 'author') + .sort({ + orderings: [ + field('genre').ascending(), + field('author').ascending() + ] + }) + ); + expectResults( + snapshot, + { genre: 'Dystopian', author: 'George Orwell' }, + { genre: 'Dystopian', author: 'Margaret Atwood' }, + { genre: 'Fantasy', author: 'J.R.R. Tolkien' }, + { genre: 'Magical Realism', author: 'Gabriel García Márquez' }, + { genre: 'Modernist', author: 'F. Scott Fitzgerald' }, + { genre: 'Psychological Thriller', author: 'Fyodor Dostoevsky' }, + { genre: 'Romance', author: 'Jane Austen' }, + { genre: 'Science Fiction', author: 'Douglas Adams' }, + { genre: 'Science Fiction', author: 'Frank Herbert' }, + { genre: 'Southern Gothic', author: 'Harper Lee' } + ); + }); + }); + + describe('select stage', () => { + it('can select fields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .sort(field('author').ascending()) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams' + }, + { title: 'The Great Gatsby', author: 'F. Scott Fitzgerald' }, + { title: 'Dune', author: 'Frank Herbert' }, + { title: 'Crime and Punishment', author: 'Fyodor Dostoevsky' }, + { + title: 'One Hundred Years of Solitude', + author: 'Gabriel García Márquez' + }, + { title: '1984', author: 'George Orwell' }, + { title: 'To Kill a Mockingbird', author: 'Harper Lee' }, + { title: 'The Lord of the Rings', author: 'J.R.R. Tolkien' }, + { title: 'Pride and Prejudice', author: 'Jane Austen' }, + { title: "The Handmaid's Tale", author: 'Margaret Atwood' } + ); + }); + + it('throws on Duplicate aliases', async () => { + expect(() => { + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(constant(1).as('foo'), constant(2).as('foo')); + }).to.throw("Duplicate alias or field 'foo'"); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select({ selections: ['title', field('author').as('auth0r')] }) + .sort(field('auth0r').ascending()) + .limit(2) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + auth0r: 'Douglas Adams' + }, + { title: 'The Great Gatsby', auth0r: 'F. Scott Fitzgerald' } + ); + }); + }); + + describe('addField stage', () => { + it('can add fields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .addFields(constant('bar').as('foo')) + .sort(field('author').ascending()) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + foo: 'bar' + }, + { + title: 'The Great Gatsby', + author: 'F. Scott Fitzgerald', + foo: 'bar' + }, + { title: 'Dune', author: 'Frank Herbert', foo: 'bar' }, + { + title: 'Crime and Punishment', + author: 'Fyodor Dostoevsky', + foo: 'bar' + }, + { + title: 'One Hundred Years of Solitude', + author: 'Gabriel García Márquez', + foo: 'bar' + }, + { title: '1984', author: 'George Orwell', foo: 'bar' }, + { + title: 'To Kill a Mockingbird', + author: 'Harper Lee', + foo: 'bar' + }, + { + title: 'The Lord of the Rings', + author: 'J.R.R. Tolkien', + foo: 'bar' + }, + { title: 'Pride and Prejudice', author: 'Jane Austen', foo: 'bar' }, + { + title: "The Handmaid's Tale", + author: 'Margaret Atwood', + foo: 'bar' + } + ); + }); + + it('throws on Duplicate aliases', async () => { + expect(() => + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .addFields(constant('bar').as('foo'), constant('baz').as('foo')) + .sort(field('author').ascending()) + ).to.throw("Duplicate alias or field 'foo'"); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .addFields({ + fields: [constant('bar').as('foo')] + }) + .sort(field('author').ascending()) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + foo: 'bar' + }, + { + title: 'The Great Gatsby', + author: 'F. Scott Fitzgerald', + foo: 'bar' + }, + { title: 'Dune', author: 'Frank Herbert', foo: 'bar' }, + { + title: 'Crime and Punishment', + author: 'Fyodor Dostoevsky', + foo: 'bar' + }, + { + title: 'One Hundred Years of Solitude', + author: 'Gabriel García Márquez', + foo: 'bar' + }, + { title: '1984', author: 'George Orwell', foo: 'bar' }, + { + title: 'To Kill a Mockingbird', + author: 'Harper Lee', + foo: 'bar' + }, + { + title: 'The Lord of the Rings', + author: 'J.R.R. Tolkien', + foo: 'bar' + }, + { title: 'Pride and Prejudice', author: 'Jane Austen', foo: 'bar' }, + { + title: "The Handmaid's Tale", + author: 'Margaret Atwood', + foo: 'bar' + } + ); + }); + }); + + describe('removeFields stage', () => { + it('can remove fields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .sort(field('author').ascending()) + .removeFields(field('author')) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy" + }, + { + title: 'The Great Gatsby' + }, + { title: 'Dune' }, + { + title: 'Crime and Punishment' + }, + { + title: 'One Hundred Years of Solitude' + }, + { title: '1984' }, + { + title: 'To Kill a Mockingbird' + }, + { + title: 'The Lord of the Rings' + }, + { title: 'Pride and Prejudice' }, + { + title: "The Handmaid's Tale" + } + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author', 'genre') + .sort(field('author').ascending()) + .removeFields({ + fields: [field('author'), 'genre'] + }) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy" + }, + { + title: 'The Great Gatsby' + }, + { title: 'Dune' }, + { + title: 'Crime and Punishment' + }, + { + title: 'One Hundred Years of Solitude' + }, + { title: '1984' }, + { + title: 'To Kill a Mockingbird' + }, + { + title: 'The Lord of the Rings' + }, + { title: 'Pride and Prejudice' }, + { + title: "The Handmaid's Tale" + } + ); + }); + }); + + describe('findNearest stage', () => { + it('can find nearest', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .sort(field('author').ascending()) + .removeFields(field('author')) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy" + }, + { + title: 'The Great Gatsby' + }, + { title: 'Dune' }, + { + title: 'Crime and Punishment' + }, + { + title: 'One Hundred Years of Solitude' + }, + { title: '1984' }, + { + title: 'To Kill a Mockingbird' + }, + { + title: 'The Lord of the Rings' + }, + { title: 'Pride and Prejudice' }, + { + title: "The Handmaid's Tale" + } + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author', 'genre') + .sort(field('author').ascending()) + .removeFields({ + fields: [field('author'), 'genre'] + }) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy" + }, + { + title: 'The Great Gatsby' + }, + { title: 'Dune' }, + { + title: 'Crime and Punishment' + }, + { + title: 'One Hundred Years of Solitude' + }, + { title: '1984' }, + { + title: 'To Kill a Mockingbird' + }, + { + title: 'The Lord of the Rings' + }, + { title: 'Pride and Prejudice' }, + { + title: "The Handmaid's Tale" + } + ); + }); + }); + + describe('where stage', () => { + it('where with and (2 conditions)', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + and( + greaterThan('rating', 4.5), + equalAny('genre', ['Science Fiction', 'Romance', 'Fantasy']) + ) + ) + ); + expectResults(snapshot, 'book10', 'book4'); + }); + + it('where with and (3 conditions)', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + and( + greaterThan('rating', 4.5), + equalAny('genre', ['Science Fiction', 'Romance', 'Fantasy']), + lessThan('published', 1965) + ) + ) + ); + expectResults(snapshot, 'book4'); + }); + + it('where with or', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + or( + equal('genre', 'Romance'), + equal('genre', 'Dystopian'), + equal('genre', 'Fantasy') + ) + ) + .sort(ascending('title')) + .select('title') + ); + expectResults( + snapshot, + { title: '1984' }, + { title: 'Pride and Prejudice' }, + { title: "The Handmaid's Tale" }, + { title: 'The Lord of the Rings' } + ); + }); + + it('where with xor', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + xor( + equal('genre', 'Romance'), + equal('genre', 'Dystopian'), + equal('genre', 'Fantasy'), + equal('published', 1949) + ) + ) + .select('title') + ); + expectResults( + snapshot, + { title: 'Pride and Prejudice' }, + { title: 'The Lord of the Rings' }, + { title: "The Handmaid's Tale" } + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where({ + condition: and( + greaterThan('rating', 4.5), + equalAny('genre', ['Science Fiction', 'Romance', 'Fantasy']) + ) + }) + ); + expectResults(snapshot, 'book10', 'book4'); + }); + }); + + describe('sort, offset, and limit stages', () => { + it('supports sort, offset, and limits', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('author').ascending()) + .offset(5) + .limit(3) + .select('title', 'author') + ); + expectResults( + snapshot, + { title: '1984', author: 'George Orwell' }, + { title: 'To Kill a Mockingbird', author: 'Harper Lee' }, + { title: 'The Lord of the Rings', author: 'J.R.R. Tolkien' } + ); + }); + + it('sort, offset, and limit stages support options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort({ + orderings: [field('author').ascending()] + }) + .offset({ offset: 5 }) + .limit({ limit: 3 }) + .select('title', 'author') + ); + expectResults( + snapshot, + { title: '1984', author: 'George Orwell' }, + { title: 'To Kill a Mockingbird', author: 'Harper Lee' }, + { title: 'The Lord of the Rings', author: 'J.R.R. Tolkien' } + ); + }); + }); + + describe('raw stage', () => { + it('can select fields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .rawStage('select', [ + { + title: field('title'), + metadata: { + author: field('author') + } + } + ]) + .sort(field('author').ascending()) + .limit(1) + ); + expectResults(snapshot, { + metadata: { + author: 'Frank Herbert' + }, + title: 'Dune' + }); + }); + + it('can add fields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('author').ascending()) + .limit(1) + .select('title', 'author') + .rawStage('add_fields', [ + { + display: stringConcat('title', ' - ', field('author')) + } + ]) + ); + expectResults(snapshot, { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + display: "The Hitchhiker's Guide to the Galaxy - Douglas Adams" + }); + }); + + it('can filter with where', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .rawStage('where', [field('author').equal('Douglas Adams')]) + ); + expectResults(snapshot, { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams' + }); + }); + + it('can limit, offset, and sort', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .rawStage('sort', [ + { + direction: 'ascending', + expression: field('author') + } + ]) + .rawStage('offset', [3]) + .rawStage('limit', [1]) + ); + expectResults(snapshot, { + author: 'Fyodor Dostoevsky', + title: 'Crime and Punishment' + }); + }); + + it('can perform aggregate query', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author', 'rating') + .rawStage('aggregate', [ + { averageRating: field('rating').average() }, + {} + ]) + ); + expectResults(snapshot, { + averageRating: 4.3100000000000005 + }); + }); + + it('can perform distinct query', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author', 'rating') + .rawStage('distinct', [{ rating: field('rating') }]) + .sort(field('rating').descending()) + ); + expectResults( + snapshot, + { + rating: 4.7 + }, + { + rating: 4.6 + }, + { + rating: 4.5 + }, + { + rating: 4.3 + }, + { + rating: 4.2 + }, + { + rating: 4.1 + }, + { + rating: 4.0 + } + ); + }); + + it('can perform FindNearest query', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .rawStage( + 'find_nearest', + [ + field('embedding'), + vector([10, 1, 2, 1, 1, 1, 1, 1, 1, 1]), + 'euclidean' + ], + { + 'distance_field': field('computedDistance'), + limit: 2 + } + ) + .select('title', 'computedDistance') + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + computedDistance: 1 + }, + { + title: 'One Hundred Years of Solitude', + computedDistance: 12.041594578792296 + } + ); + }); + }); + + describe('replaceWith stage', () => { + it('run pipeline with replaceWith field name', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .replaceWith('awards') + ); + expectResults(snapshot, { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }); + }); + + it('run pipeline with replaceWith Expr result', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .replaceWith( + map({ + foo: 'bar', + baz: { + title: field('title') + } + }) + ) + ); + expectResults(snapshot, { + foo: 'bar', + baz: { title: "The Hitchhiker's Guide to the Galaxy" } + }); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .replaceWith({ map: 'awards' }) + ); + expectResults(snapshot, { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }); + }); + }); + + describe('sample stage', () => { + it('run pipeline with sample limit of 3', async () => { + const snapshot = await execute( + firestore.pipeline().collection(randomCol.path).sample(3) + ); + expect(snapshot.results.length).to.equal(3); + }); + + it('run pipeline with sample limit of {documents: 3}', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sample({ documents: 3 }) + ); + expect(snapshot.results.length).to.equal(3); + }); + + it('run pipeline with sample limit of {percentage: 0.6}', async () => { + let avgSize = 0; + const numIterations = 30; + for (let i = 0; i < numIterations; i++) { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sample({ percentage: 0.6 }) + ); + + avgSize += snapshot.results.length; + } + avgSize /= numIterations; + expect(avgSize).to.be.closeTo(6, 1); + }); + }); + + describe('union stage', () => { + it('run pipeline with union', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .union(firestore.pipeline().collection(randomCol.path)) + .sort(field(documentIdFieldPath()).ascending()) + ); + expectResults( + snapshot, + 'book1', + 'book1', + 'book10', + 'book10', + 'book2', + 'book2', + 'book3', + 'book3', + 'book4', + 'book4', + 'book5', + 'book5', + 'book6', + 'book6', + 'book7', + 'book7', + 'book8', + 'book8', + 'book9', + 'book9' + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .union({ other: firestore.pipeline().collection(randomCol.path) }) + .sort(field(documentIdFieldPath()).ascending()) + ); + expectResults( + snapshot, + 'book1', + 'book1', + 'book10', + 'book10', + 'book2', + 'book2', + 'book3', + 'book3', + 'book4', + 'book4', + 'book5', + 'book5', + 'book6', + 'book6', + 'book7', + 'book7', + 'book8', + 'book8', + 'book9', + 'book9' + ); + }); + }); + + describe('unnest stage', () => { + it('run pipeline with unnest', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .unnest(field('tags').as('tag')) + .select( + 'title', + 'author', + 'genre', + 'published', + 'rating', + 'tags', + 'tag', + 'awards', + 'nestedField' + ) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'comedy', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } } + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'space', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } } + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'adventure', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } } + } + ); + }); + + it('unnest with index field', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .unnest(field('tags').as('tag'), 'tagsIndex') + .select( + 'title', + 'author', + 'genre', + 'published', + 'rating', + 'tags', + 'tag', + 'awards', + 'nestedField', + 'tagsIndex' + ) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'comedy', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + tagsIndex: 0 + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'space', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + tagsIndex: 1 + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'adventure', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + tagsIndex: 2 + } + ); + }); + + it('unnest an expr', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .unnest(array([1, 2, 3]).as('copy')) + .select( + 'title', + 'author', + 'genre', + 'published', + 'rating', + 'tags', + 'copy', + 'awards', + 'nestedField' + ) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + copy: 1, + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } } + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + copy: 2, + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } } + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + copy: 3, + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } } + } + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .unnest({ + selectable: field('tags').as('tag'), + indexField: 'tagsIndex' + }) + .select( + 'title', + 'author', + 'genre', + 'published', + 'rating', + 'tags', + 'tag', + 'awards', + 'nestedField', + 'tagsIndex' + ) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'comedy', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + tagsIndex: 0 + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'space', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + tagsIndex: 1 + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'adventure', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + tagsIndex: 2 + } + ); + }); + }); + + describe('findNearest stage', () => { + it('run pipeline with findNearest', async () => { + const measures: Array = [ + 'euclidean', + 'dot_product', + 'cosine' + ]; + for (const measure of measures) { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .findNearest({ + field: 'embedding', + vectorValue: vector([10, 1, 3, 1, 2, 1, 1, 1, 1, 1]), + limit: 3, + distanceMeasure: measure + }) + .select('title') + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy" + }, + { + title: 'One Hundred Years of Solitude' + }, + { + title: "The Handmaid's Tale" + } + ); + } + }); + + it('optionally returns the computed distance', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .findNearest({ + field: 'embedding', + vectorValue: vector([10, 1, 2, 1, 1, 1, 1, 1, 1, 1]), + limit: 2, + distanceMeasure: 'euclidean', + distanceField: 'computedDistance' + }) + .select('title', 'computedDistance') + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + computedDistance: 1 + }, + { + title: 'One Hundred Years of Solitude', + computedDistance: 12.041594578792296 + } + ); + }); + }); + }); + + describe('error handling', () => { + it('error properties are propagated from the firestore backend', async () => { + try { + const myPipeline = firestore + .pipeline() + .collection(randomCol.path) + .rawStage('select', [ + // incorrect parameter type + field('title') + ]); + + await execute(myPipeline); + + expect.fail('expected pipeline.execute() to throw'); + } catch (e: unknown) { + expect(e instanceof FirebaseError).to.be.true; + const err = e as FirebaseError; + expect(err['code']).to.equal('invalid-argument'); + expect(typeof err['message']).to.equal('string'); + + expect(err['message']).to.match(/^3 INVALID_ARGUMENT: .*$/); + } + }); + }); + + describe('function expressions', () => { + it('logical max works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select( + 'title', + logicalMaximum(constant(1960), field('published'), 1961).as( + 'published-safe' + ) + ) + .sort(field('title').ascending()) + .limit(3) + ); + expectResults( + snapshot, + { title: '1984', 'published-safe': 1961 }, + { title: 'Crime and Punishment', 'published-safe': 1961 }, + { title: 'Dune', 'published-safe': 1965 } + ); + }); + + it('logical min works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select( + 'title', + logicalMinimum(constant(1960), field('published'), 1961).as( + 'published-safe' + ) + ) + .sort(field('title').ascending()) + .limit(3) + ); + expectResults( + snapshot, + { title: '1984', 'published-safe': 1949 }, + { title: 'Crime and Punishment', 'published-safe': 1866 }, + { title: 'Dune', 'published-safe': 1960 } + ); + }); + + it('conditional works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select( + 'title', + conditional( + lessThan(field('published'), 1960), + constant(1960), + field('published') + ).as('published-safe'), + field('rating') + .greaterThanOrEqual(4.5) + .conditional(constant('great'), constant('good')) + .as('rating') + ) + .sort(field('title').ascending()) + .limit(3) + ); + expectResults( + snapshot, + { title: '1984', 'published-safe': 1960, rating: 'good' }, + { + title: 'Crime and Punishment', + 'published-safe': 1960, + rating: 'good' + }, + { title: 'Dune', 'published-safe': 1965, rating: 'great' } + ); + }); + + it('equalAny works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equalAny('published', [1979, 1999, 1967])) + .sort(descending('title')) + .select('title') + ); + expectResults( + snapshot, + { title: "The Hitchhiker's Guide to the Galaxy" }, + { title: 'One Hundred Years of Solitude' } + ); + }); + + it('notEqualAny works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + notEqualAny( + 'published', + [1965, 1925, 1949, 1960, 1866, 1985, 1954, 1967, 1979] + ) + ) + .select('title') + ); + expectResults(snapshot, { title: 'Pride and Prejudice' }); + }); + + it('arrayContains works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(arrayContains('tags', 'comedy')) + .select('title') + ); + expectResults(snapshot, { + title: "The Hitchhiker's Guide to the Galaxy" + }); + }); + + it('arrayContainsAny works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(arrayContainsAny('tags', ['comedy', 'classic'])) + .sort(descending('title')) + .select('title') + ); + expectResults( + snapshot, + { title: "The Hitchhiker's Guide to the Galaxy" }, + { title: 'Pride and Prejudice' } + ); + }); + + it('arrayContainsAll works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(arrayContainsAll('tags', ['adventure', 'magic'])) + .select('title') + ); + expectResults(snapshot, { title: 'The Lord of the Rings' }); + }); + + it('arrayLength works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(arrayLength('tags').as('tagsCount')) + .where(equal('tagsCount', 3)) + ); + expect(snapshot.results.length).to.equal(10); + }); + + it('testStrConcat', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(ascending('author')) + .select( + field('author').stringConcat(' - ', field('title')).as('bookInfo') + ) + .limit(1) + ); + expectResults(snapshot, { + bookInfo: "Douglas Adams - The Hitchhiker's Guide to the Galaxy" + }); + }); + + it('testStartsWith', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(startsWith('title', 'The')) + .select('title') + .sort(field('title').ascending()) + ); + expectResults( + snapshot, + { title: 'The Great Gatsby' }, + { title: "The Handmaid's Tale" }, + { title: "The Hitchhiker's Guide to the Galaxy" }, + { title: 'The Lord of the Rings' } + ); + }); + + it('testEndsWith', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(endsWith('title', 'y')) + .select('title') + .sort(field('title').descending()) + ); + expectResults( + snapshot, + { title: "The Hitchhiker's Guide to the Galaxy" }, + { title: 'The Great Gatsby' } + ); + }); + + it('testStrContains', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(stringContains('title', "'s")) + .select('title') + .sort(field('title').ascending()) + ); + expectResults( + snapshot, + { title: "The Handmaid's Tale" }, + { title: "The Hitchhiker's Guide to the Galaxy" } + ); + }); + + it('testLength', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(charLength('title').as('titleLength'), field('title')) + .where(greaterThan('titleLength', 20)) + .sort(field('title').ascending()) + ); + + expectResults( + snapshot, + + { + titleLength: 29, + title: 'One Hundred Years of Solitude' + }, + { + titleLength: 36, + title: "The Hitchhiker's Guide to the Galaxy" + }, + { + titleLength: 21, + title: 'The Lord of the Rings' + }, + { + titleLength: 21, + title: 'To Kill a Mockingbird' + } + ); + }); + + it('testLike', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(like('title', '%Guide%')) + .select('title') + ); + expectResults(snapshot, { + title: "The Hitchhiker's Guide to the Galaxy" + }); + }); + + it('testRegexContains', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(regexContains('title', '(?i)(the|of)')) + ); + expect(snapshot.results.length).to.equal(5); + }); + + it('testRegexMatches', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(regexMatch('title', '.*(?i)(the|of).*')) + ); + expect(snapshot.results.length).to.equal(5); + }); + + it('testArithmeticOperations', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', 'To Kill a Mockingbird')) + .select( + add(field('rating'), 1).as('ratingPlusOne'), + subtract(field('published'), 1900).as('yearsSince1900'), + field('rating').multiply(10).as('ratingTimesTen'), + divide('rating', 2).as('ratingDividedByTwo'), + multiply('rating', 20).as('ratingTimes20'), + add('rating', 3).as('ratingPlus3'), + mod('rating', 2).as('ratingMod2') + ) + .limit(1) + ); + expectResults(snapshot, { + ratingPlusOne: 5.2, + yearsSince1900: 60, + ratingTimesTen: 42, + ratingDividedByTwo: 2.1, + ratingTimes20: 84, + ratingPlus3: 7.2, + ratingMod2: 0.20000000000000018 + }); + }); + + it('testComparisonOperators', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + and( + greaterThan('rating', 4.2), + lessThanOrEqual(field('rating'), 4.5), + notEqual('genre', 'Science Fiction') + ) + ) + .select('rating', 'title') + .sort(field('title').ascending()) + ); + expectResults( + snapshot, + { rating: 4.3, title: 'Crime and Punishment' }, + { + rating: 4.3, + title: 'One Hundred Years of Solitude' + }, + { rating: 4.5, title: 'Pride and Prejudice' } + ); + }); + + it('testLogicalOperators', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + or( + and( + greaterThan('rating', 4.5), + equal('genre', 'Science Fiction') + ), + lessThan('published', 1900) + ) + ) + .select('title') + .sort(field('title').ascending()) + ); + expectResults( + snapshot, + { title: 'Crime and Punishment' }, + { title: 'Dune' }, + { title: 'Pride and Prejudice' } + ); + }); + + it('testChecks', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + equal('rating', null).as('ratingIsNull'), + equal('rating', NaN).as('ratingIsNaN'), + isError(divide(constant(1), constant(0))).as('isError'), + ifError(divide(constant(1), constant(0)), constant('was error')).as( + 'ifError' + ), + ifError( + divide(constant(1), constant(0)).greaterThan(1), + constant(true) + ) + .not() + .as('ifErrorBooleanExpression'), + isAbsent('foo').as('isAbsent'), + notEqual('title', null).as('titleIsNotNull'), + notEqual('cost', NaN).as('costIsNotNan'), + exists('fooBarBaz').as('fooBarBazExists'), + field('title').exists().as('titleExists') + ) + ); + expectResults(snapshot, { + ratingIsNull: false, + ratingIsNaN: false, + isError: true, + ifError: 'was error', + ifErrorBooleanExpression: false, + isAbsent: true, + titleIsNotNull: true, + costIsNotNan: false, + fooBarBazExists: false, + titleExists: true + }); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + field('rating').equal(null).as('ratingIsNull'), + field('rating').equal(NaN).as('ratingIsNaN'), + divide(constant(1), constant(0)).isError().as('isError'), + divide(constant(1), constant(0)) + .ifError(constant('was error')) + .as('ifError'), + divide(constant(1), constant(0)) + .greaterThan(1) + .ifError(constant(true)) + .not() + .as('ifErrorBooleanExpression'), + field('foo').isAbsent().as('isAbsent'), + field('title').notEqual(null).as('titleIsNotNull'), + field('cost').notEqual(NaN).as('costIsNotNan') + ) + ); + expectResults(snapshot, { + ratingIsNull: false, + ratingIsNaN: false, + isError: true, + ifError: 'was error', + ifErrorBooleanExpression: false, + isAbsent: true, + titleIsNotNull: true, + costIsNotNan: false + }); + }); + + it('testMapGet', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('published').descending()) + .select( + field('awards').mapGet('hugo').as('hugoAward'), + field('awards').mapGet('others').as('others'), + field('title') + ) + .where(equal('hugoAward', true)) + ); + expectResults( + snapshot, + { + hugoAward: true, + title: "The Hitchhiker's Guide to the Galaxy", + others: { unknown: { year: 1980 } } + }, + { hugoAward: true, title: 'Dune' } + ); + }); + + it('testDistanceFunctions', async () => { + const sourceVector = vector([0.1, 0.1]); + const targetVector = vector([0.5, 0.8]); + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select( + cosineDistance(constant(sourceVector), targetVector).as( + 'cosineDistance' + ), + dotProduct(constant(sourceVector), targetVector).as( + 'dotProductDistance' + ), + euclideanDistance(constant(sourceVector), targetVector).as( + 'euclideanDistance' + ) + ) + .limit(1) + ); + + expectResults(snapshot, { + cosineDistance: 0.02560880430538015, + dotProductDistance: 0.13, + euclideanDistance: 0.806225774829855 + }); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select( + constant(sourceVector) + .cosineDistance(targetVector) + .as('cosineDistance'), + constant(sourceVector) + .dotProduct(targetVector) + .as('dotProductDistance'), + constant(sourceVector) + .euclideanDistance(targetVector) + .as('euclideanDistance') + ) + .limit(1) + ); + + expectResults(snapshot, { + cosineDistance: 0.02560880430538015, + dotProductDistance: 0.13, + euclideanDistance: 0.806225774829855 + }); + }); + + it('testVectorLength', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(vectorLength(constant(vector([1, 2, 3]))).as('vectorLength')) + ); + expectResults(snapshot, { + vectorLength: 3 + }); + }); + + it('testNestedFields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('awards.hugo', true)) + .sort(descending('title')) + .select('title', 'awards.hugo') + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + 'awards.hugo': true + }, + { title: 'Dune', 'awards.hugo': true } + ); + }); + + it('test mapGet with field name including . notation', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + title: 'foo', + nested: { + level: { + '1': 'bar' + }, + 'level.1': { + 'level.2': 'baz' + } + } + }) + ) + .select( + 'title', + field('nested.level.1'), + mapGet('nested', 'level.1').mapGet('level.2').as('nested') + ) + ); + expectResults(snapshot, { + title: 'foo', + 'nested.level.`1`': 'bar', + nested: 'baz' + }); + }); + + describe('rawFunction', () => { + it('add selectable', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(descending('rating')) + .limit(1) + .select( + new FunctionExpression('add', [field('rating'), constant(1)]).as( + 'rating' + ) + ) + ); + expectResults(snapshot, { + rating: 5.7 + }); + }); + + it('and (variadic) selectable', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + new FunctionExpression('and', [ + field('rating').greaterThan(0), + field('title').charLength().lessThan(5), + field('tags').arrayContains('propaganda') + ]).asBoolean() + ) + .select('title') + ); + expectResults(snapshot, { + title: '1984' + }); + }); + + it('array contains any', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + new FunctionExpression('array_contains_any', [ + field('tags'), + array(['politics']) + ]).asBoolean() + ) + .select('title') + ); + expectResults(snapshot, { + title: 'Dune' + }); + }); + + it('countif aggregate', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate( + new AggregateFunction('count_if', [ + field('rating').greaterThanOrEqual(4.5) + ]).as('countOfBest') + ) + ); + expectResults(snapshot, { + countOfBest: 3 + }); + }); + + it('sort by char_len', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort( + new FunctionExpression('char_length', [ + field('title') + ]).ascending(), + descending('__name__') + ) + .limit(3) + .select('title') + ); + expectResults( + snapshot, + { + title: '1984' + }, + { + title: 'Dune' + }, + { + title: 'The Great Gatsby' + } + ); + }); + }); + + it('supports array', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(array([1, 2, 3, 4]).as('metadata')) + ); + expect(snapshot.results.length).to.equal(1); + expectResults(snapshot, { + metadata: [1, 2, 3, 4] + }); + }); + + it('evaluates expression in array', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + array([1, 2, field('genre'), multiply('rating', 10)]).as('metadata') + ) + ); + expect(snapshot.results.length).to.equal(1); + expectResults(snapshot, { + metadata: [1, 2, 'Fantasy', 47] + }); + }); + + it('supports arrayGet', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayGet('tags', 0).as('firstTag')) + ); + const expectedResults = [ + { + firstTag: 'adventure' + }, + { + firstTag: 'politics' + }, + { + firstTag: 'classic' + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayGet(0).as('firstTag')) + ); + expectResults(snapshot, ...expectedResults); + }); + + it('supports map', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + map({ + foo: 'bar' + }).as('metadata') + ) + ); + + expect(snapshot.results.length).to.equal(1); + expectResults(snapshot, { + metadata: { + foo: 'bar' + } + }); + }); + + it('evaluates expression in map', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + map({ + genre: field('genre'), + rating: field('rating').multiply(10) + }).as('metadata') + ) + ); + + expect(snapshot.results.length).to.equal(1); + expectResults(snapshot, { + metadata: { + genre: 'Fantasy', + rating: 47 + } + }); + }); + + it('supports mapRemove', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(mapRemove('awards', 'hugo').as('awards')) + ); + expectResults(snapshot, { + awards: { nebula: false } + }); + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('awards').mapRemove('hugo').as('awards')) + ); + expectResults(snapshot, { + awards: { nebula: false } + }); + }); + + it('supports mapMerge', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(mapMerge('awards', { fakeAward: true }).as('awards')) + ); + expectResults(snapshot, { + awards: { nebula: false, hugo: false, fakeAward: true } + }); + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('awards').mapMerge({ fakeAward: true }).as('awards')) + ); + expectResults(snapshot, { + awards: { nebula: false, hugo: false, fakeAward: true } + }); + }); + + it('supports timestamp conversions', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select( + unixSecondsToTimestamp(constant(1741380235)).as( + 'unixSecondsToTimestamp' + ), + unixMillisToTimestamp(constant(1741380235123)).as( + 'unixMillisToTimestamp' + ), + unixMicrosToTimestamp(constant(1741380235123456)).as( + 'unixMicrosToTimestamp' + ), + timestampToUnixSeconds( + constant(new Timestamp(1741380235, 123456789)) + ).as('timestampToUnixSeconds'), + timestampToUnixMicros( + constant(new Timestamp(1741380235, 123456789)) + ).as('timestampToUnixMicros'), + timestampToUnixMillis( + constant(new Timestamp(1741380235, 123456789)) + ).as('timestampToUnixMillis') + ) + ); + expectResults(snapshot, { + unixMicrosToTimestamp: new Timestamp(1741380235, 123456000), + unixMillisToTimestamp: new Timestamp(1741380235, 123000000), + unixSecondsToTimestamp: new Timestamp(1741380235, 0), + timestampToUnixSeconds: 1741380235, + timestampToUnixMicros: 1741380235123456, + timestampToUnixMillis: 1741380235123 + }); + }); + + it('supports timestamp math', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(constant(new Timestamp(1741380235, 0)).as('timestamp')) + .select( + timestampAdd('timestamp', 'day', 10).as('plus10days'), + timestampAdd('timestamp', 'hour', 10).as('plus10hours'), + timestampAdd('timestamp', 'minute', 10).as('plus10minutes'), + timestampAdd('timestamp', 'second', 10).as('plus10seconds'), + timestampAdd('timestamp', 'microsecond', 10).as('plus10micros'), + timestampAdd('timestamp', 'millisecond', 10).as('plus10millis'), + timestampSubtract('timestamp', 'day', 10).as('minus10days'), + timestampSubtract('timestamp', 'hour', 10).as('minus10hours'), + timestampSubtract('timestamp', 'minute', 10).as('minus10minutes'), + timestampSubtract('timestamp', 'second', 10).as('minus10seconds'), + timestampSubtract('timestamp', 'microsecond', 10).as( + 'minus10micros' + ), + timestampSubtract('timestamp', 'millisecond', 10).as( + 'minus10millis' + ) + ) + ); + expectResults(snapshot, { + plus10days: new Timestamp(1742244235, 0), + plus10hours: new Timestamp(1741416235, 0), + plus10minutes: new Timestamp(1741380835, 0), + plus10seconds: new Timestamp(1741380245, 0), + plus10micros: new Timestamp(1741380235, 10000), + plus10millis: new Timestamp(1741380235, 10000000), + minus10days: new Timestamp(1740516235, 0), + minus10hours: new Timestamp(1741344235, 0), + minus10minutes: new Timestamp(1741379635, 0), + minus10seconds: new Timestamp(1741380225, 0), + minus10micros: new Timestamp(1741380234, 999990000), + minus10millis: new Timestamp(1741380234, 990000000) + }); + }).timeout(10000); + + it('supports byteLength', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .select( + constant( + Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0])) + ).as('bytes') + ) + .select(byteLength('bytes').as('byteLength')) + ); + + expectResults(snapshot, { + byteLength: 8 + }); + }); + + it('supports not', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .select(constant(true).as('trueField')) + .select('trueField', not(equal('trueField', true)).as('falseField')) + ); + + expectResults(snapshot, { + trueField: true, + falseField: false + }); + }); + + it('can reverse an array', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('tags').arrayReverse().as('reversedTags')) + ); + expectResults(snapshot, { + reversedTags: ['adventure', 'space', 'comedy'] + }); + }); + + it('can reverse an array with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(reverse('tags').as('reversedTags')) + ); + expectResults(snapshot, { + reversedTags: ['adventure', 'space', 'comedy'] + }); + }); + + it('can compute the ceiling of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').ceil().as('ceilingRating')) + ); + expectResults(snapshot, { + ceilingRating: 5 + }); + }); + + it('can compute the ceiling of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(ceil('rating').as('ceilingRating')) + ); + expectResults(snapshot, { + ceilingRating: 5 + }); + }); + + it('can compute the floor of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').floor().as('floorRating')) + ); + expectResults(snapshot, { + floorRating: 4 + }); + }); + + it('can compute the floor of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(floor('rating').as('floorRating')) + ); + expectResults(snapshot, { + floorRating: 4 + }); + }); + + it('can compute e to the power of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('The Lord of the Rings')) + .limit(1) + .select(field('rating').exp().as('expRating')) + ); + expectResults(snapshot, { + expRating: 109.94717245212352 + }); + }); + + it('can compute e to the power of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('The Lord of the Rings')) + .limit(1) + .select(exp('rating').as('expRating')) + ); + expect(snapshot.results[0].get('expRating')).to.be.approximately( + 109.94717245212351, + 0.000001 + ); + }); + + it('can compute the power of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').pow(2).as('powerRating')) + ); + expect(snapshot.results[0].get('powerRating')).to.be.approximately( + 17.64, + 0.0001 + ); + }); + + it('can compute the power of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(pow('rating', 2).as('powerRating')) + ); + expect(snapshot.results[0].get('powerRating')).to.be.approximately( + 17.64, + 0.0001 + ); + }); + + it('can round a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').round().as('roundedRating')) + ); + expectResults(snapshot, { + roundedRating: 4 + }); + }); + + it('can round a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(round('rating').as('roundedRating')) + ); + expectResults(snapshot, { + roundedRating: 4 + }); + }); + + it('can round a numeric value away from zero for positive half-way values', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .addFields(constant(1.5).as('positiveHalf')) + .select(field('positiveHalf').round().as('roundedRating')) + ); + expectResults(snapshot, { + roundedRating: 2 + }); + }); + + it('can round a numeric value away from zero for negative half-way values', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .addFields(constant(-1.5).as('negativeHalf')) + .select(field('negativeHalf').round().as('roundedRating')) + ); + expectResults(snapshot, { + roundedRating: -2 + }); + }); + + it('can round a numeric value to specified precision', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + foo: 4.123456 + }) + ) + .select( + field('foo').round(0).as('0'), + round('foo', 1).as('1'), + round('foo', constant(2)).as('2'), + round(field('foo'), 4).as('4') + ) + ); + expectResults(snapshot, { + '0': 4, + '1': 4.1, + '2': 4.12, + '4': 4.1235 + }); + }); + + it('can get the collectionId from a path', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(field('__name__').collectionId().as('collectionId')) + ); + expectResults(snapshot, { + collectionId: randomCol.id + }); + }); + + it('can get the collectionId from a path with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(collectionId('__name__').as('collectionId')) + ); + expectResults(snapshot, { + collectionId: randomCol.id + }); + }); + + it('can compute the length of a string value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('title').length().as('titleLength')) + ); + expectResults(snapshot, { + titleLength: 36 + }); + }); + + it('can compute the length of a string value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(length('title').as('titleLength')) + ); + expectResults(snapshot, { + titleLength: 36 + }); + }); + + it('can compute the length of an array value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('tags').length().as('tagsLength')) + ); + expectResults(snapshot, { + tagsLength: 3 + }); + }); + + it('can compute the length of an array value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(length('tags').as('tagsLength')) + ); + expectResults(snapshot, { + tagsLength: 3 + }); + }); + + it('can compute the length of a map value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('awards').length().as('awardsLength')) + ); + expectResults(snapshot, { + awardsLength: 3 + }); + }); + + it('can compute the length of a vector value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('embedding').length().as('embeddingLength')) + ); + expectResults(snapshot, { + embeddingLength: 10 + }); + }); + + it('can compute the length of a bytes value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(constant('12é').as('value')) + .limit(1) + .select(field('value').byteLength().as('valueLength')) + ); + expectResults(snapshot, { + valueLength: 4 + }); + }); + + it('can compute the natural logarithm of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').ln().as('lnRating')) + ); + expect(snapshot.results[0]!.data().lnRating).to.be.closeTo(1.435, 0.001); + }); + + it('can compute the natural logarithm of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(ln('rating').as('lnRating')) + ); + expect(snapshot.results[0]!.data().lnRating).to.be.closeTo(1.435, 0.001); + }); + + it('can compute the natural logarithm of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(ln('rating').as('lnRating')) + ); + expectResults(snapshot, { + lnRating: 1.4350845252893227 + }); + }); + + it('can compute the logarithm of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(log(field('rating'), 10).as('logRating')) + ); + expectResults(snapshot, { + logRating: 0.6232492903979004 + }); + }); + + it('can compute the logarithm of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(log('rating', 10).as('logRating')) + ); + expectResults(snapshot, { + logRating: 0.6232492903979004 + }); + }); + + it('can round a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').round().as('roundedRating')) + ); + expectResults(snapshot, { + roundedRating: 4 + }); + }); + + it('can round a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(round('rating').as('roundedRating')) + ); + expectResults(snapshot, { + roundedRating: 4 + }); + }); + + it('can compute the square root of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').sqrt().as('sqrtRating')) + ); + expectResults(snapshot, { + sqrtRating: 2.04939015319192 + }); + }); + + it('can compute the square root of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(sqrt('rating').as('sqrtRating')) + ); + expectResults(snapshot, { + sqrtRating: 2.04939015319192 + }); + }); + + it('can reverse a string', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('title').reverse().as('reversedTitle')) + ); + expectResults(snapshot, { + reversedTitle: "yxalaG eht ot ediuG s'rekihhctiH ehT" + }); + }); + + it('can reverse a string with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(stringReverse('title').as('reversedTitle')) + ); + expectResults(snapshot, { + reversedTitle: "yxalaG eht ot ediuG s'rekihhctiH ehT" + }); + }); + + it('supports Document_id', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + documentId(field('__name__')).as('docId'), + documentId(field('__path__')).as('noDocId') + ) + ); + expectResults(snapshot, { + docId: 'book4', + noDocId: null + }); + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('__name__').documentId().as('docId')) + ); + expectResults(snapshot, { + docId: 'book4' + }); + }); + + it('supports substring', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(substring('title', 9, 2).as('of')) + ); + expectResults(snapshot, { + of: 'of' + }); + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('title').substring(9, 2).as('of')) + ); + expectResults(snapshot, { + of: 'of' + }); + }); + + it('supports substring without length', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(substring('title', 9).as('of')) + ); + expectResults(snapshot, { + of: 'of the Rings' + }); + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('title').substring(9).as('of')) + ); + expectResults(snapshot, { + of: 'of the Rings' + }); + }); + + it('test toLower', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(ascending('title')) + .select(toLower('author').as('lowercaseAuthor')) + .limit(1) + ); + expectResults(snapshot, { + lowercaseAuthor: 'george orwell' + }); + }); + + it('test toUpper', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(ascending('title')) + .select(toUpper('author').as('uppercaseAuthor')) + .limit(1) + ); + expectResults(snapshot, { uppercaseAuthor: 'GEORGE ORWELL' }); + }); + + it('testTrim', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + spacedTitle: " The Hitchhiker's Guide to the Galaxy ", + userNameWithQuotes: '"alice"', + bytes: Bytes.fromUint8Array( + Uint8Array.from([0x00, 0x01, 0x02, 0x00, 0x00]) + ) + }) + ) + .select( + trim('spacedTitle').as('trimmedTitle'), + field('spacedTitle'), + field('userNameWithQuotes').trim('"').as('userName'), + field('bytes') + .trim(Bytes.fromUint8Array(Uint8Array.from([0x00]))) + .as('bytes') + ) + .limit(1) + ); + expectResults(snapshot, { + spacedTitle: " The Hitchhiker's Guide to the Galaxy ", + trimmedTitle: "The Hitchhiker's Guide to the Galaxy", + userName: 'alice', + bytes: Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02])) + }); + }); + + it('test reverse', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .limit(1) + .select(reverse('title').as('reverseTitle')) + ); + expectResults(snapshot, { reverseTitle: '4891' }); + }); + + it('testAbs', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select( + constant(-10).as('neg10'), + constant(-22.22).as('neg22'), + constant(1).as('pos1') + ) + .select( + abs('neg10').as('10'), + abs(field('neg22')).as('22'), + field('pos1').as('1') + ) + ); + expectResults(snapshot, { + '10': 10, + '22': 22.22, + '1': 1 + }); + }); + + it('can compute the base-10 logarithm of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('The Lord of the Rings')) + .limit(1) + .select(field('rating').log10().as('log10Rating')) + ); + expect(snapshot.results[0]!.data().log10Rating).to.be.closeTo( + 0.672, + 0.001 + ); + }); + + it('can compute the base-10 logarithm of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('The Lord of the Rings')) + .limit(1) + .select(log10('rating').as('log10Rating')) + ); + expect(snapshot.results[0]!.data().log10Rating).to.be.closeTo( + 0.672, + 0.001 + ); + }); + + it('can concat fields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .addFields( + concat('author', ' ', field('title')).as('display'), + field('author').concat(': ', field('title')).as('display2') + ) + .where(equal('author', 'Douglas Adams')) + .select('display', 'display2') + ); + expectResults(snapshot, { + display: "Douglas Adams The Hitchhiker's Guide to the Galaxy", + display2: "Douglas Adams: The Hitchhiker's Guide to the Galaxy" + }); + }); + + it('supports currentTimestamp', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .addFields(currentTimestamp().as('now')) + .select('now') + ); + const now = snapshot.results[0].get('now') as Timestamp; + expect(now).instanceof(Timestamp); + expect( + now.toDate().getUTCSeconds() - new Date().getUTCSeconds() + ).lessThan(5000); + }); + + it('supports ifAbsent', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + title: 'foo' + }) + ) + .select( + ifAbsent('title', 'default title').as('title'), + field('name').ifAbsent('default name').as('name'), + field('name').ifAbsent(field('title')).as('nameOrTitle') + ) + ); + + expectResults(snapshot, { + title: 'foo', + name: 'default name', + nameOrTitle: 'foo' + }); + }); + + it('supports join', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + tags: ['foo', 'bar', 'baz'], + delimeter: '|' + }) + ) + .select(join('tags', ',').as('csv'), field('tags').join('|').as('or')) + ); + + expectResults(snapshot, { + csv: 'foo,bar,baz', + or: 'foo|bar|baz' + }); + }); + + it('can compute the sum of the elements in an array', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('The Lord of the Rings')) + .limit(1) + .addFields(array([150, 200]).as('sales')) + .select(field('sales').arraySum().as('totalSales')) + ); + expectResults(snapshot, { + totalSales: 350 + }); + }); + + it('can compute the sum of the elements in an array with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('The Lord of the Rings')) + .limit(1) + .addFields(array([150, 200]).as('sales')) + .select(arraySum('sales').as('totalSales')) + ); + expectResults(snapshot, { + totalSales: 350 + }); + }); + + it('truncate timestamp', async () => { + const results = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .replaceWith( + map({ + timestamp: new Timestamp( + Date.UTC(2025, 10, 30, 1, 2, 3) / 1000, + 456789 + ) + }) + ) + .select( + timestampTruncate('timestamp', 'year').as('trunc_year'), + timestampTruncate(field('timestamp'), 'month').as('trunc_month'), + timestampTruncate(field('timestamp'), constant('day')).as( + 'trunc_day' + ), + field('timestamp') + .timestampTruncate(constant('day'), 'MST') + .as('trunc_day_mst'), + field('timestamp').timestampTruncate('hour').as('trunc_hour'), + field('timestamp') + .timestampTruncate(constant('minute')) + .as('trunc_minute'), + field('timestamp').timestampTruncate('second').as('trunc_second') + ) + ); + + expectResults(results, { + 'trunc_year': new Timestamp(Date.UTC(2025, 0) / 1000, 0), + 'trunc_month': new Timestamp(Date.UTC(2025, 10) / 1000, 0), + 'trunc_day': new Timestamp(Date.UTC(2025, 10, 30) / 1000, 0), + 'trunc_day_mst': new Timestamp( + Date.UTC(2025, 10, 29) / 1000 + 7 * 3600, + 0 + ), + 'trunc_hour': new Timestamp(Date.UTC(2025, 10, 30, 1) / 1000, 0), + 'trunc_minute': new Timestamp(Date.UTC(2025, 10, 30, 1, 2) / 1000, 0), + 'trunc_second': new Timestamp(Date.UTC(2025, 10, 30, 1, 2, 3) / 1000, 0) + }); + }); + + it('supports split', async () => { + const results = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .replaceWith( + map({ + csv: 'foo,bar,baz', + data: 'baz:bar:foo', + csvDelimeter: ',', + bytes: Bytes.fromUint8Array( + Uint8Array.from([0x01, 0x00, 0x02, 0x00, 0x03]) + ) + }) + ) + .select( + split('csv', field('csvDelimeter')).as('csv'), + split(field('data'), ':').as('data'), + field('bytes') + .split(constant(Bytes.fromUint8Array(Uint8Array.from([0x00])))) + .as('bytes') + ) + ); + + expectResults(results, { + csv: ['foo', 'bar', 'baz'], + data: ['baz', 'bar', 'foo'], + bytes: [ + Bytes.fromUint8Array(Uint8Array.from([0x01])), + Bytes.fromUint8Array(Uint8Array.from([0x02])), + Bytes.fromUint8Array(Uint8Array.from([0x03])) + ] + }); + + void expect( + execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .replaceWith( + map({ + csv: 'foo,bar,baz' + }) + ) + .select( + field('csv') + .split(constant(Bytes.fromUint8Array(Uint8Array.from([0x00])))) + .as('dontSplitStringAndBytes') + ) + ) + ).to.be.rejected; + }); + + it('supports type', async () => { + const result = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .replaceWith( + map({ + int: constant(1), + float: constant(1.1), + str: constant('a string'), + bool: constant(true), + null: constant(null), + geoPoint: constant(new GeoPoint(0.1, 0.2)), + timestamp: constant(new Timestamp(123456, 0)), + date: constant(new Date()), + bytes: constant( + Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0])) + ), + docRef: constant(doc(firestore, 'foo', 'bar')), + vector: constant(vector([1, 2, 3])), + map: map({ + 'number': 1, + 'string': 'a string' + }), + array: array([1, 'a string']) + }) + ) + .select( + type('int').as('int'), + field('float').type().as('float'), + field('str').type().as('str'), + type('bool').as('bool'), + type('null').as('null'), + type('geoPoint').as('geoPoint'), + type('timestamp').as('timestamp'), + type('date').as('date'), + type('bytes').as('bytes'), + type('docRef').as('docRef'), + type('vector').as('vector'), + type('map').as('map'), + type('array').as('array') + ) + ); + + expectResults(result, { + int: 'int64', + float: 'float64', + str: 'string', + bool: 'boolean', + null: 'null', + geoPoint: 'geo_point', + timestamp: 'timestamp', + date: 'timestamp', + bytes: 'bytes', + docRef: 'reference', + vector: 'vector', + map: 'map', + array: 'array' + }); + }); + + // TODO(new-expression): Add new expression tests above this line + }); + + describe('pagination', () => { + let addedDocs: DocumentReference[] = []; + + /** + * Adds several books to the test collection. These + * additional books support pagination test scenarios + * that would otherwise not be possible with the original + * set of books. + * @param collectionReference + */ + async function addBooks( + collectionReference: CollectionReference + ): Promise { + let docRef = doc(collectionReference, 'book11'); + addedDocs.push(docRef); + await setDoc(docRef, { + title: 'Jonathan Strange & Mr Norrell', + author: 'Susanna Clarke', + genre: 'Fantasy', + published: 2004, + rating: 4.6, + tags: ['historical fantasy', 'magic', 'alternate history', 'england'], + awards: { hugo: false, nebula: false } + }); + docRef = doc(collectionReference, 'book12'); + addedDocs.push(docRef); + await setDoc(docRef, { + title: 'The Master and Margarita', + author: 'Mikhail Bulgakov', + genre: 'Satire', + published: 1967, // Though written much earlier + rating: 4.6, + tags: [ + 'russian literature', + 'supernatural', + 'philosophy', + 'dark comedy' + ], + awards: {} + }); + docRef = doc(collectionReference, 'book13'); + addedDocs.push(docRef); + await setDoc(docRef, { + title: 'A Long Way to a Small, Angry Planet', + author: 'Becky Chambers', + genre: 'Science Fiction', + published: 2014, + rating: 4.6, + tags: ['space opera', 'found family', 'character-driven', 'optimistic'], + awards: { hugo: false, nebula: false, kitschies: true } + }); + } + + afterEach(async () => { + for (let i = 0; i < addedDocs.length; i++) { + await deleteDoc(addedDocs[i]); + } + addedDocs = []; + }); + + it('supports pagination with filters', async () => { + await addBooks(randomCol); + const pageSize = 2; + const pipeline = firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'rating', '__name__') + .sort(field('rating').descending(), field('__name__').ascending()); + + let snapshot = await execute(pipeline.limit(pageSize)); + expectResults( + snapshot, + { title: 'The Lord of the Rings', rating: 4.7 }, + { title: 'Dune', rating: 4.6 } + ); + + const lastDoc = snapshot.results[snapshot.results.length - 1]; + + snapshot = await execute( + pipeline + .where( + or( + and( + field('rating').equal(lastDoc.get('rating')), + field('__name__').greaterThan(lastDoc.ref) + ), + field('rating').lessThan(lastDoc.get('rating')) + ) + ) + .limit(pageSize) + ); + expectResults( + snapshot, + { title: 'Jonathan Strange & Mr Norrell', rating: 4.6 }, + { title: 'The Master and Margarita', rating: 4.6 } + ); + }); + + it('supports pagination with offsets', async () => { + await addBooks(randomCol); + + const secondFilterField = '__name__'; + + const pipeline = firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'rating', secondFilterField) + .sort( + field('rating').descending(), + field(secondFilterField).ascending() + ); + + const pageSize = 2; + let currPage = 0; + + let snapshot = await execute( + pipeline.offset(currPage++ * pageSize).limit(pageSize) + ); + + expectResults( + snapshot, + { + title: 'The Lord of the Rings', + rating: 4.7 + }, + { title: 'Dune', rating: 4.6 } + ); + + snapshot = await execute( + pipeline.offset(currPage++ * pageSize).limit(pageSize) + ); + expectResults( + snapshot, + { + title: 'Jonathan Strange & Mr Norrell', + rating: 4.6 + }, + { title: 'The Master and Margarita', rating: 4.6 } + ); + + snapshot = await execute( + pipeline.offset(currPage++ * pageSize).limit(pageSize) + ); + expectResults( + snapshot, + { + title: 'A Long Way to a Small, Angry Planet', + rating: 4.6 + }, + { + title: 'Pride and Prejudice', + rating: 4.5 + } + ); + }); + }); + + describe('stage options', () => { + describe('forceIndex', () => { + // SKIP: requires pre-existing index + // eslint-disable-next-line no-restricted-properties + it.skip('Collection Stage', async () => { + const snapshot = await execute( + firestore.pipeline().collection({ + collection: randomCol, + forceIndex: 'unknown' + }) + ); + expect(snapshot.results.length).to.equal(10); + }); + + // SKIP: requires pre-existing index + // eslint-disable-next-line no-restricted-properties + it.skip('CollectionGroup Stage', async () => { + const snapshot = await execute( + firestore.pipeline().collectionGroup({ + collectionId: randomCol.id, + forceIndex: 'unknown' + }) + ); + expect(snapshot.results.length).to.equal(10); + }); + }); + }); +}); diff --git a/packages/firestore/test/integration/api/provider.test.ts b/packages/firestore/test/integration/api/provider.test.ts index cc7888a538..b89056395e 100644 --- a/packages/firestore/test/integration/api/provider.test.ts +++ b/packages/firestore/test/integration/api/provider.test.ts @@ -29,7 +29,9 @@ import { enableIndexedDbPersistence, setDoc, memoryLocalCache, - getDocFromCache + getDocFromCache, + // @ts-ignore internal API usage + ensureFirestoreConfigured } from '../util/firebase_export'; import { DEFAULT_SETTINGS } from '../util/settings'; @@ -67,10 +69,15 @@ describe('Firestore Provider', () => { const fs4 = getFirestore(app, 'name1'); const fs5 = getFirestore(app, 'name2'); + // @ts-ignore internal API usage expect(fs1._databaseId.database).to.be.equal('init1'); + // @ts-ignore internal API usage expect(fs2._databaseId.database).to.be.equal('init2'); + // @ts-ignore internal API usage expect(fs3._databaseId.database).to.be.equal('(default)'); + // @ts-ignore internal API usage expect(fs4._databaseId.database).to.be.equal('name1'); + // @ts-ignore internal API usage expect(fs5._databaseId.database).to.be.equal('name2'); expect(fs1).to.not.be.equal(fs2); @@ -200,4 +207,18 @@ describe('Firestore Provider', () => { return terminate(firestore).then(() => terminate(firestore)); }); + + it('passes API key to database info', () => { + const app = initializeApp( + { apiKey: 'fake-api-key-x', projectId: 'test-project' }, + 'test-app-getFirestore-x' + ); + const fs = getFirestore(app); + ensureFirestoreConfigured(fs); + + // @ts-ignore internal API usage + expect(fs._firestoreClient?._databaseInfo.apiKey).to.equal( + 'fake-api-key-x' + ); + }); }); diff --git a/packages/firestore/test/integration/api/query.test.ts b/packages/firestore/test/integration/api/query.test.ts index a12c843bf2..0ebf1011bc 100644 --- a/packages/firestore/test/integration/api/query.test.ts +++ b/packages/firestore/test/integration/api/query.test.ts @@ -19,6 +19,7 @@ import { isNode } from '@firebase/util'; import { expect } from 'chai'; import { addEqualityMatcher } from '../../util/equality_matcher'; +import { it } from '../../util/mocha_extensions'; import { Deferred } from '../../util/promise'; import { EventsAccumulator } from '../util/events_accumulator'; import { @@ -32,7 +33,6 @@ import { doc, DocumentChange, DocumentChangeType, - DocumentData, documentId, enableNetwork, endAt, @@ -61,18 +61,13 @@ import { } from '../util/firebase_export'; import { apiDescribe, - RetryError, toChangesArray, toDataArray, - PERSISTENCE_MODE_UNSPECIFIED, withEmptyTestCollection, - withRetry, withTestCollection, withTestDb, checkOnlineAndOfflineResultsMatch } from '../util/helpers'; -import { USE_EMULATOR } from '../util/settings'; -import { captureExistenceFilterMismatches } from '../util/testing_hooks_util'; apiDescribe('Queries', persistence => { addEqualityMatcher(); @@ -711,7 +706,7 @@ apiDescribe('Queries', persistence => { }); // eslint-disable-next-line no-restricted-properties - (USE_EMULATOR ? it.skip : it)( + it.skipEmulator.skipEnterprise( 'can catch error message for missing index with error handler', () => { return withEmptyTestCollection(persistence, async coll => { @@ -730,6 +725,7 @@ apiDescribe('Queries', persistence => { err => { expect(err.code).to.equal('failed-precondition'); expect(err.message).to.exist; + // @ts-ignore internal API usage if (coll.firestore._databaseId.isDefaultDatabase) { expect(err.message).to.match( /index.*https:\/\/console\.firebase\.google\.com/ @@ -986,7 +982,7 @@ apiDescribe('Queries', persistence => { }); }); - it('can use IN filters', async () => { + it.skipEnterprise('can use IN filters', async () => { const testDocs = { a: { zip: 98101 }, b: { zip: 91102 }, @@ -1145,7 +1141,7 @@ apiDescribe('Queries', persistence => { }); }); - it('can use array-contains-any filters', async () => { + it.skipEnterprise('can use array-contains-any filters', async () => { const testDocs = { a: { array: [42] }, b: { array: ['a', 42, 'c'] }, @@ -1969,429 +1965,6 @@ apiDescribe('Queries', persistence => { }); }); - // TODO(b/291365820): Stop skipping this test when running against the - // Firestore emulator once the emulator is improved to include a bloom filter - // in the existence filter messages that it sends. - // eslint-disable-next-line no-restricted-properties - (USE_EMULATOR ? it.skip : it)( - 'resuming a query should use bloom filter to avoid full requery', - async () => { - // Prepare the names and contents of the 100 documents to create. - const testDocs: { [key: string]: object } = {}; - for (let i = 0; i < 100; i++) { - testDocs['doc' + (1000 + i)] = { key: 42 }; - } - - // Ensure that the local cache is configured to use LRU garbage - // collection (rather than eager garbage collection) so that the resume - // token and document data does not get prematurely evicted. - const lruPersistence = persistence.toLruGc(); - - return withRetry(async attemptNumber => { - return withTestCollection( - lruPersistence, - testDocs, - async (coll, db) => { - // Run a query to populate the local cache with the 100 documents - // and a resume token. - const snapshot1 = await getDocs(coll); - expect(snapshot1.size, 'snapshot1.size').to.equal(100); - const createdDocuments = snapshot1.docs.map( - snapshot => snapshot.ref - ); - - // Delete 50 of the 100 documents. Use a different Firestore - // instance to avoid affecting the local cache. - const deletedDocumentIds = new Set(); - await withTestDb(PERSISTENCE_MODE_UNSPECIFIED, async db2 => { - const batch = writeBatch(db2); - for (let i = 0; i < createdDocuments.length; i += 2) { - const documentToDelete = doc(db2, createdDocuments[i].path); - batch.delete(documentToDelete); - deletedDocumentIds.add(documentToDelete.id); - } - await batch.commit(); - }); - - // Wait for 10 seconds, during which Watch will stop tracking the - // query and will send an existence filter rather than "delete" - // events when the query is resumed. - await new Promise(resolve => setTimeout(resolve, 10000)); - - // Resume the query and save the resulting snapshot for - // verification. Use some internal testing hooks to "capture" the - // existence filter mismatches to verify that Watch sent a bloom - // filter, and it was used to avert a full requery. - const [existenceFilterMismatches, snapshot2] = - await captureExistenceFilterMismatches(() => getDocs(coll)); - - // Verify that the snapshot from the resumed query contains the - // expected documents; that is, that it contains the 50 documents - // that were _not_ deleted. - const actualDocumentIds = snapshot2.docs - .map(documentSnapshot => documentSnapshot.ref.id) - .sort(); - const expectedDocumentIds = createdDocuments - .filter(documentRef => !deletedDocumentIds.has(documentRef.id)) - .map(documentRef => documentRef.id) - .sort(); - expect(actualDocumentIds, 'snapshot2.docs').to.deep.equal( - expectedDocumentIds - ); - - // Verify that Watch sent an existence filter with the correct - // counts when the query was resumed. - expect( - existenceFilterMismatches, - 'existenceFilterMismatches' - ).to.have.length(1); - const { localCacheCount, existenceFilterCount, bloomFilter } = - existenceFilterMismatches[0]; - expect(localCacheCount, 'localCacheCount').to.equal(100); - expect(existenceFilterCount, 'existenceFilterCount').to.equal(50); - - // Verify that Watch sent a valid bloom filter. - if (!bloomFilter) { - expect.fail( - 'The existence filter should have specified a bloom filter ' + - 'in its `unchanged_names` field.' - ); - throw new Error('should never get here'); - } - - expect(bloomFilter.hashCount, 'bloomFilter.hashCount').to.be.above( - 0 - ); - expect( - bloomFilter.bitmapLength, - 'bloomFilter.bitmapLength' - ).to.be.above(0); - expect(bloomFilter.padding, 'bloomFilterPadding').to.be.above(0); - expect(bloomFilter.padding, 'bloomFilterPadding').to.be.below(8); - - // Verify that the bloom filter was successfully used to avert a - // full requery. If a false positive occurred then retry the entire - // test. Although statistically rare, false positives are expected - // to happen occasionally. When a false positive _does_ happen, just - // retry the test with a different set of documents. If that retry - // also_ experiences a false positive, then fail the test because - // that is so improbable that something must have gone wrong. - if (attemptNumber === 1 && !bloomFilter.applied) { - throw new RetryError(); - } - - expect( - bloomFilter.applied, - `bloomFilter.applied with attemptNumber=${attemptNumber}` - ).to.be.true; - } - ); - }); - } - ).timeout('90s'); - - // TODO(b/291365820): Stop skipping this test when running against the - // Firestore emulator once the emulator is improved to include a bloom filter - // in the existence filter messages that it sends. - // eslint-disable-next-line no-restricted-properties - (USE_EMULATOR ? it.skip : it)( - 'bloom filter should avert a full re-query when documents were added, ' + - 'deleted, removed, updated, and unchanged since the resume token', - async () => { - // Prepare the names and contents of the 20 documents to create. - const testDocs: { [key: string]: object } = {}; - for (let i = 0; i < 20; i++) { - testDocs['doc' + (1000 + i)] = { - key: 42, - removed: false - }; - } - - // Ensure that the local cache is configured to use LRU garbage - // collection (rather than eager garbage collection) so that the resume - // token and document data does not get prematurely evicted. - const lruPersistence = persistence.toLruGc(); - - return withRetry(async attemptNumber => { - return withTestCollection(lruPersistence, testDocs, async coll => { - // Run a query to populate the local cache with the 20 documents - // and a resume token. - const snapshot1 = await getDocs( - query(coll, where('removed', '==', false)) - ); - expect(snapshot1.size, 'snapshot1.size').to.equal(20); - const createdDocuments = snapshot1.docs.map(snapshot => snapshot.ref); - - // Out of the 20 existing documents, leave 5 docs untouched, delete 5 docs, - // remove 5 docs, update 5 docs, and add 15 new docs. - const deletedDocumentIds = new Set(); - const removedDocumentIds = new Set(); - const updatedDocumentIds = new Set(); - const addedDocumentIds: string[] = []; - - // Use a different Firestore instance to avoid affecting the local cache. - await withTestDb(PERSISTENCE_MODE_UNSPECIFIED, async db2 => { - const batch = writeBatch(db2); - - for (let i = 0; i < createdDocuments.length; i += 4) { - const documentToDelete = doc(db2, createdDocuments[i].path); - batch.delete(documentToDelete); - deletedDocumentIds.add(documentToDelete.id); - } - expect(deletedDocumentIds.size).to.equal(5); - - // Update 5 documents to no longer match the query. - for (let i = 1; i < createdDocuments.length; i += 4) { - const documentToModify = doc(db2, createdDocuments[i].path); - batch.update(documentToModify, { - removed: true - }); - removedDocumentIds.add(documentToModify.id); - } - expect(removedDocumentIds.size).to.equal(5); - - // Update 5 documents, but ensure they still match the query. - for (let i = 2; i < createdDocuments.length; i += 4) { - const documentToModify = doc(db2, createdDocuments[i].path); - batch.update(documentToModify, { - key: 43 - }); - updatedDocumentIds.add(documentToModify.id); - } - expect(updatedDocumentIds.size).to.equal(5); - - for (let i = 0; i < 15; i += 1) { - const documentToAdd = doc( - db2, - coll.path + '/newDoc' + (1000 + i) - ); - batch.set(documentToAdd, { - key: 42, - removed: false - }); - addedDocumentIds.push(documentToAdd.id); - } - - // Ensure the sets above are disjoint. - const mergedSet = new Set(); - [ - deletedDocumentIds, - removedDocumentIds, - updatedDocumentIds, - addedDocumentIds - ].forEach(set => { - set.forEach(documentId => mergedSet.add(documentId)); - }); - expect(mergedSet.size).to.equal(30); - - await batch.commit(); - }); - - // Wait for 10 seconds, during which Watch will stop tracking the - // query and will send an existence filter rather than "delete" - // events when the query is resumed. - await new Promise(resolve => setTimeout(resolve, 10000)); - - // Resume the query and save the resulting snapshot for - // verification. Use some internal testing hooks to "capture" the - // existence filter mismatches to verify that Watch sent a bloom - // filter, and it was used to avert a full requery. - const [existenceFilterMismatches, snapshot2] = - await captureExistenceFilterMismatches(() => - getDocs(query(coll, where('removed', '==', false))) - ); - - // Verify that the snapshot from the resumed query contains the - // expected documents; that is, 10 existing documents that still - // match the query, and 15 documents that are newly added. - const actualDocumentIds = snapshot2.docs - .map(documentSnapshot => documentSnapshot.ref.id) - .sort(); - const expectedDocumentIds = createdDocuments - .map(documentRef => documentRef.id) - .filter(documentId => !deletedDocumentIds.has(documentId)) - .filter(documentId => !removedDocumentIds.has(documentId)) - .concat(addedDocumentIds) - .sort(); - - expect(actualDocumentIds, 'snapshot2.docs').to.deep.equal( - expectedDocumentIds - ); - expect(actualDocumentIds.length).to.equal(25); - - // Verify that Watch sent an existence filter with the correct - // counts when the query was resumed. - expect( - existenceFilterMismatches, - 'existenceFilterMismatches' - ).to.have.length(1); - const { localCacheCount, existenceFilterCount, bloomFilter } = - existenceFilterMismatches[0]; - expect(localCacheCount, 'localCacheCount').to.equal(35); - expect(existenceFilterCount, 'existenceFilterCount').to.equal(25); - - // Verify that Watch sent a valid bloom filter. - if (!bloomFilter) { - expect.fail( - 'The existence filter should have specified a bloom filter ' + - 'in its `unchanged_names` field.' - ); - throw new Error('should never get here'); - } - - // Verify that the bloom filter was successfully used to avert a - // full requery. If a false positive occurred then retry the entire - // test. Although statistically rare, false positives are expected - // to happen occasionally. When a false positive _does_ happen, just - // retry the test with a different set of documents. If that retry - // also_ experiences a false positive, then fail the test because - // that is so improbable that something must have gone wrong. - if (attemptNumber === 1 && !bloomFilter.applied) { - throw new RetryError(); - } - - expect( - bloomFilter.applied, - `bloomFilter.applied with attemptNumber=${attemptNumber}` - ).to.be.true; - }); - }); - } - ).timeout('90s'); - - // TODO(b/291365820): Stop skipping this test when running against the - // Firestore emulator once the emulator is improved to include a bloom filter - // in the existence filter messages that it sends. - // eslint-disable-next-line no-restricted-properties - (USE_EMULATOR ? it.skip : it)( - 'bloom filter should correctly encode complex Unicode characters', - async () => { - // Firestore does not do any Unicode normalization on the document IDs. - // Therefore, two document IDs that are canonically-equivalent (i.e. they - // visually appear identical) but are represented by a different sequence - // of Unicode code points are treated as distinct document IDs. - const testDocIds = [ - 'DocumentToDelete', - // The next two strings both end with "e" with an accent: the first uses - // the dedicated Unicode code point for this character, while the second - // uses the standard lowercase "e" followed by the accent combining - // character. - 'LowercaseEWithAcuteAccent_\u00E9', - 'LowercaseEWithAcuteAccent_\u0065\u0301', - // The next two strings both end with an "e" with two different accents - // applied via the following two combining characters. The combining - // characters are specified in a different order and Firestore treats - // these document IDs as unique, despite the order of the combining - // characters being irrelevant. - 'LowercaseEWithMultipleAccents_\u0065\u0301\u0327', - 'LowercaseEWithMultipleAccents_\u0065\u0327\u0301', - // The next string contains a character outside the BMP (the "basic - // multilingual plane"); that is, its code point is greater than 0xFFFF. - // In UTF-16 (which JavaScript uses to store Unicode strings) this - // requires a surrogate pair, two 16-bit code units, to represent this - // character. Make sure that its presence is correctly tested in the - // bloom filter, which uses UTF-8 encoding. - 'Smiley_\u{1F600}' - ]; - - // Verify assumptions about the equivalence of strings in `testDocIds`. - expect(testDocIds[1].normalize()).equals(testDocIds[2].normalize()); - expect(testDocIds[3].normalize()).equals(testDocIds[4].normalize()); - expect(testDocIds[5]).equals('Smiley_\uD83D\uDE00'); - - // Create the mapping from document ID to document data for the document - // IDs specified in `testDocIds`. - const testDocs = testDocIds.reduce((map, docId) => { - map[docId] = { foo: 42 }; - return map; - }, {} as { [key: string]: DocumentData }); - - // Ensure that the local cache is configured to use LRU garbage collection - // (rather than eager garbage collection) so that the resume token and - // document data does not get prematurely evicted. - const lruPersistence = persistence.toLruGc(); - - return withTestCollection(lruPersistence, testDocs, async (coll, db) => { - // Run a query to populate the local cache with documents that have - // names with complex Unicode characters. - const snapshot1 = await getDocs(coll); - const snapshot1DocumentIds = snapshot1.docs.map( - documentSnapshot => documentSnapshot.id - ); - expect(snapshot1DocumentIds, 'snapshot1DocumentIds').to.have.members( - testDocIds - ); - - // Delete one of the documents so that the next call to getDocs() will - // experience an existence filter mismatch. Use a different Firestore - // instance to avoid affecting the local cache. - const documentToDelete = doc(coll, 'DocumentToDelete'); - await withTestDb(PERSISTENCE_MODE_UNSPECIFIED, async db2 => { - await deleteDoc(doc(db2, documentToDelete.path)); - }); - - // Wait for 10 seconds, during which Watch will stop tracking the query - // and will send an existence filter rather than "delete" events when - // the query is resumed. - await new Promise(resolve => setTimeout(resolve, 10000)); - - // Resume the query and save the resulting snapshot for verification. - // Use some internal testing hooks to "capture" the existence filter - // mismatches. - const [existenceFilterMismatches, snapshot2] = - await captureExistenceFilterMismatches(() => getDocs(coll)); - const snapshot2DocumentIds = snapshot2.docs.map( - documentSnapshot => documentSnapshot.id - ); - const testDocIdsMinusDeletedDocId = testDocIds.filter( - documentId => documentId !== documentToDelete.id - ); - expect(snapshot2DocumentIds, 'snapshot2DocumentIds').to.have.members( - testDocIdsMinusDeletedDocId - ); - - // Verify that Watch sent an existence filter with the correct counts. - expect( - existenceFilterMismatches, - 'existenceFilterMismatches' - ).to.have.length(1); - const existenceFilterMismatch = existenceFilterMismatches[0]; - expect( - existenceFilterMismatch.localCacheCount, - 'localCacheCount' - ).to.equal(testDocIds.length); - expect( - existenceFilterMismatch.existenceFilterCount, - 'existenceFilterCount' - ).to.equal(testDocIds.length - 1); - - // Verify that we got a bloom filter from Watch. - const bloomFilter = existenceFilterMismatch.bloomFilter!; - expect(bloomFilter?.mightContain, 'bloomFilter.mightContain').to.not.be - .undefined; - - // The bloom filter application should statistically be successful - // almost every time; the _only_ time when it would _not_ be successful - // is if there is a false positive when testing for 'DocumentToDelete' - // in the bloom filter. So verify that the bloom filter application is - // successful, unless there was a false positive. - const isFalsePositive = bloomFilter.mightContain(documentToDelete); - expect(bloomFilter.applied, 'bloomFilter.applied').to.equal( - !isFalsePositive - ); - - // Verify that the bloom filter contains the document paths with complex - // Unicode characters. - for (const testDoc of snapshot2.docs.map(snapshot => snapshot.ref)) { - expect( - bloomFilter.mightContain(testDoc), - `bloomFilter.mightContain('${testDoc.path}')` - ).to.be.true; - } - }); - } - ).timeout('90s'); - it('can query large documents with multi-byte character strings', () => { function randomMultiByteCharString(length: number): string { const charCodes: number[] = []; diff --git a/packages/firestore/test/integration/api/query_to_pipeline.test.ts b/packages/firestore/test/integration/api/query_to_pipeline.test.ts new file mode 100644 index 0000000000..34afdc6ab0 --- /dev/null +++ b/packages/firestore/test/integration/api/query_to_pipeline.test.ts @@ -0,0 +1,817 @@ +/** + * @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. + */ + +import { expect, use } from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +import { addEqualityMatcher } from '../../util/equality_matcher'; +import { + doc, + DocumentData, + setDoc, + query, + where, + FieldPath, + orderBy, + limit, + limitToLast, + startAt, + startAfter, + endAt, + endBefore, + collectionGroup, + collection, + and, + documentId, + addDoc, + getDoc, + or, + getDocs +} from '../util/firebase_export'; +import { + apiDescribe, + PERSISTENCE_MODE_UNSPECIFIED, + withTestCollection +} from '../util/helpers'; +import { execute, PipelineSnapshot } from '../util/pipeline_export'; + +use(chaiAsPromised); + +// This is the Query integration tests from the lite API (no cache support) +// with some additional test cases added for more complete coverage. +apiDescribe.skipClassic('Query to Pipeline', persistence => { + addEqualityMatcher(); + + function verifyResults( + actual: PipelineSnapshot, + ...expected: DocumentData[] + ): void { + const results = actual.results; + expect(results.length).to.equal(expected.length); + + for (let i = 0; i < expected.length; ++i) { + expect(results[i].data()).to.deep.equal(expected[i]); + } + } + + it('supports default query', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { 1: { foo: 1 } }, + async (collRef, db) => { + const snapshot = await execute(db.pipeline().createFrom(collRef)); + verifyResults(snapshot, { foo: 1 }); + } + ); + }); + + it('supports filtered query', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 } + }, + async (collRef, db) => { + const query1 = query(collRef, where('foo', '==', 1)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 1 }); + } + ); + }); + + it('supports filtered query (with FieldPath)', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 } + }, + async (collRef, db) => { + const query1 = query(collRef, where(new FieldPath('foo'), '==', 1)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 1 }); + } + ); + }); + + it('supports ordered query (with default order)', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 } + }, + async (collRef, db) => { + const query1 = query(collRef, orderBy('foo')); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 1 }, { foo: 2 }); + } + ); + }); + + it('supports ordered query (with asc)', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 } + }, + async (collRef, db) => { + const query1 = query(collRef, orderBy('foo', 'asc')); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 1 }, { foo: 2 }); + } + ); + }); + + it('supports ordered query (with desc)', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 } + }, + async (collRef, db) => { + const query1 = query(collRef, orderBy('foo', 'desc')); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 2 }, { foo: 1 }); + } + ); + }); + + it('supports limit query', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 } + }, + async (collRef, db) => { + const query1 = query(collRef, orderBy('foo'), limit(1)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 1 }); + } + ); + }); + + it('supports limitToLast query', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 }, + 3: { foo: 3 } + }, + async (collRef, db) => { + const query1 = query(collRef, orderBy('foo'), limitToLast(2)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 2 }, { foo: 3 }); + } + ); + }); + + it('supports startAt', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 } + }, + async (collRef, db) => { + const query1 = query(collRef, orderBy('foo'), startAt(2)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 2 }); + } + ); + }); + + it('supports startAt with limitToLast', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 }, + 3: { foo: 3 }, + 4: { foo: 4 }, + 5: { foo: 5 } + }, + async (collRef, db) => { + const query1 = query( + collRef, + orderBy('foo'), + startAt(3), + limitToLast(4) + ); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 3 }, { foo: 4 }, { foo: 5 }); + } + ); + }); + + it('supports endAt with limitToLast', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 }, + 3: { foo: 3 }, + 4: { foo: 4 }, + 5: { foo: 5 } + }, + async (collRef, db) => { + const query1 = query(collRef, orderBy('foo'), endAt(3), limitToLast(2)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 2 }, { foo: 3 }); + } + ); + }); + + it('supports startAfter (with DocumentSnapshot)', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { id: 1, foo: 1, bar: 1, baz: 1 }, + 2: { id: 2, foo: 1, bar: 1, baz: 2 }, + 3: { id: 3, foo: 1, bar: 1, baz: 2 }, + 4: { id: 4, foo: 1, bar: 2, baz: 1 }, + 5: { id: 5, foo: 1, bar: 2, baz: 2 }, + 6: { id: 6, foo: 1, bar: 2, baz: 2 }, + 7: { id: 7, foo: 2, bar: 1, baz: 1 }, + 8: { id: 8, foo: 2, bar: 1, baz: 2 }, + 9: { id: 9, foo: 2, bar: 1, baz: 2 }, + 10: { id: 10, foo: 2, bar: 2, baz: 1 }, + 11: { id: 11, foo: 2, bar: 2, baz: 2 }, + 12: { id: 12, foo: 2, bar: 2, baz: 2 } + }, + async (collRef, db) => { + let docRef = await getDoc(doc(collRef, '2')); + let query1 = query( + collRef, + orderBy('foo'), + orderBy('bar'), + orderBy('baz'), + startAfter(docRef) + ); + let snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults( + snapshot, + { id: 3, foo: 1, bar: 1, baz: 2 }, + { id: 4, foo: 1, bar: 2, baz: 1 }, + { id: 5, foo: 1, bar: 2, baz: 2 }, + { id: 6, foo: 1, bar: 2, baz: 2 }, + { id: 7, foo: 2, bar: 1, baz: 1 }, + { id: 8, foo: 2, bar: 1, baz: 2 }, + { id: 9, foo: 2, bar: 1, baz: 2 }, + { id: 10, foo: 2, bar: 2, baz: 1 }, + { id: 11, foo: 2, bar: 2, baz: 2 }, + { id: 12, foo: 2, bar: 2, baz: 2 } + ); + + docRef = await getDoc(doc(collRef, '3')); + query1 = query( + collRef, + orderBy('foo'), + orderBy('bar'), + orderBy('baz'), + startAfter(docRef) + ); + snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults( + snapshot, + { id: 4, foo: 1, bar: 2, baz: 1 }, + { id: 5, foo: 1, bar: 2, baz: 2 }, + { id: 6, foo: 1, bar: 2, baz: 2 }, + { id: 7, foo: 2, bar: 1, baz: 1 }, + { id: 8, foo: 2, bar: 1, baz: 2 }, + { id: 9, foo: 2, bar: 1, baz: 2 }, + { id: 10, foo: 2, bar: 2, baz: 1 }, + { id: 11, foo: 2, bar: 2, baz: 2 }, + { id: 12, foo: 2, bar: 2, baz: 2 } + ); + } + ); + }); + + it('supports startAt (with DocumentSnapshot)', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { id: 1, foo: 1, bar: 1, baz: 1 }, + 2: { id: 2, foo: 1, bar: 1, baz: 2 }, + 3: { id: 3, foo: 1, bar: 1, baz: 2 }, + 4: { id: 4, foo: 1, bar: 2, baz: 1 }, + 5: { id: 5, foo: 1, bar: 2, baz: 2 }, + 6: { id: 6, foo: 1, bar: 2, baz: 2 }, + 7: { id: 7, foo: 2, bar: 1, baz: 1 }, + 8: { id: 8, foo: 2, bar: 1, baz: 2 }, + 9: { id: 9, foo: 2, bar: 1, baz: 2 }, + 10: { id: 10, foo: 2, bar: 2, baz: 1 }, + 11: { id: 11, foo: 2, bar: 2, baz: 2 }, + 12: { id: 12, foo: 2, bar: 2, baz: 2 } + }, + async (collRef, db) => { + let docRef = await getDoc(doc(collRef, '2')); + let query1 = query( + collRef, + orderBy('foo'), + orderBy('bar'), + orderBy('baz'), + startAt(docRef) + ); + let snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults( + snapshot, + { id: 2, foo: 1, bar: 1, baz: 2 }, + { id: 3, foo: 1, bar: 1, baz: 2 }, + { id: 4, foo: 1, bar: 2, baz: 1 }, + { id: 5, foo: 1, bar: 2, baz: 2 }, + { id: 6, foo: 1, bar: 2, baz: 2 }, + { id: 7, foo: 2, bar: 1, baz: 1 }, + { id: 8, foo: 2, bar: 1, baz: 2 }, + { id: 9, foo: 2, bar: 1, baz: 2 }, + { id: 10, foo: 2, bar: 2, baz: 1 }, + { id: 11, foo: 2, bar: 2, baz: 2 }, + { id: 12, foo: 2, bar: 2, baz: 2 } + ); + + docRef = await getDoc(doc(collRef, '3')); + query1 = query( + collRef, + orderBy('foo'), + orderBy('bar'), + orderBy('baz'), + startAt(docRef) + ); + snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults( + snapshot, + { id: 3, foo: 1, bar: 1, baz: 2 }, + { id: 4, foo: 1, bar: 2, baz: 1 }, + { id: 5, foo: 1, bar: 2, baz: 2 }, + { id: 6, foo: 1, bar: 2, baz: 2 }, + { id: 7, foo: 2, bar: 1, baz: 1 }, + { id: 8, foo: 2, bar: 1, baz: 2 }, + { id: 9, foo: 2, bar: 1, baz: 2 }, + { id: 10, foo: 2, bar: 2, baz: 1 }, + { id: 11, foo: 2, bar: 2, baz: 2 }, + { id: 12, foo: 2, bar: 2, baz: 2 } + ); + } + ); + }); + + it('supports startAfter', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 } + }, + async (collRef, db) => { + const query1 = query(collRef, orderBy('foo'), startAfter(1)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 2 }); + } + ); + }); + + it('supports endAt', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 } + }, + async (collRef, db) => { + const query1 = query(collRef, orderBy('foo'), endAt(1)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 1 }); + } + ); + }); + + it('supports endBefore', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 } + }, + async (collRef, db) => { + const query1 = query(collRef, orderBy('foo'), endBefore(2)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 1 }); + } + ); + }); + + it('supports pagination', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 } + }, + async (collRef, db) => { + let query1 = query(collRef, orderBy('foo'), limit(1)); + const pipeline1 = db.pipeline().createFrom(query1); + let snapshot = await execute(pipeline1); + verifyResults(snapshot, { foo: 1 }); + + // Pass the document snapshot from the previous snapshot + query1 = query(query1, startAfter(snapshot.results[0].get('foo'))); + snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 2 }); + } + ); + }); + + it('supports pagination on DocumentIds', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1 }, + 2: { foo: 2 } + }, + async (collRef, db) => { + let query1 = query( + collRef, + orderBy('foo'), + orderBy(documentId(), 'asc'), + limit(1) + ); + const pipeline1 = db.pipeline().createFrom(query1); + let snapshot = await execute(pipeline1); + verifyResults(snapshot, { foo: 1 }); + + // Pass the document snapshot from the previous snapshot + query1 = query( + query1, + startAfter( + snapshot.results[0].get('foo'), + snapshot.results[0].ref?.id + ) + ); + snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 2 }); + } + ); + }); + + it('supports collection groups', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + {}, + async (collRef, db) => { + const collectionGroupId = `${collRef.id}group`; + + const fooDoc = doc( + collRef.firestore, + `${collRef.id}/foo/${collectionGroupId}/doc1` + ); + const barDoc = doc( + collRef.firestore, + `${collRef.id}/bar/baz/boo/${collectionGroupId}/doc2` + ); + await setDoc(fooDoc, { foo: 1 }); + await setDoc(barDoc, { bar: 1 }); + + const query1 = collectionGroup(collRef.firestore, collectionGroupId); + const snapshot = await execute(db.pipeline().createFrom(query1)); + + verifyResults(snapshot, { bar: 1 }, { foo: 1 }); + } + ); + }); + + it('supports query over collection path with special characters', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + {}, + async (collRef, db) => { + const docWithSpecials = doc(collRef, 'so!@#$%^&*()_+special'); + + const collectionWithSpecials = collection( + docWithSpecials, + 'so!@#$%^&*()_+special' + ); + await addDoc(collectionWithSpecials, { foo: 1 }); + await addDoc(collectionWithSpecials, { foo: 2 }); + + const snapshot = await execute( + db + .pipeline() + .createFrom(query(collectionWithSpecials, orderBy('foo', 'asc'))) + ); + + verifyResults(snapshot, { foo: 1 }, { foo: 2 }); + } + ); + }); + + it('supports multiple inequality on same field', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + '01': { id: 1, foo: 1, bar: 1, baz: 1 }, + '02': { id: 2, foo: 1, bar: 1, baz: 2 }, + '03': { id: 3, foo: 1, bar: 1, baz: 2 }, + '04': { id: 4, foo: 1, bar: 2, baz: 1 }, + '05': { id: 5, foo: 1, bar: 2, baz: 2 }, + '06': { id: 6, foo: 1, bar: 2, baz: 2 }, + '07': { id: 7, foo: 2, bar: 1, baz: 1 }, + '08': { id: 8, foo: 2, bar: 1, baz: 2 }, + '09': { id: 9, foo: 2, bar: 1, baz: 2 }, + '10': { id: 10, foo: 2, bar: 2, baz: 1 }, + '11': { id: 11, foo: 2, bar: 2, baz: 2 }, + '12': { id: 12, foo: 2, bar: 2, baz: 2 } + }, + async (collRef, db) => { + const query1 = query( + collRef, + and(where('id', '>', 2), where('id', '<=', 10)) + ); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults( + snapshot, + { id: 3, foo: 1, bar: 1, baz: 2 }, + { id: 4, foo: 1, bar: 2, baz: 1 }, + { id: 5, foo: 1, bar: 2, baz: 2 }, + { id: 6, foo: 1, bar: 2, baz: 2 }, + { id: 7, foo: 2, bar: 1, baz: 1 }, + { id: 8, foo: 2, bar: 1, baz: 2 }, + { id: 9, foo: 2, bar: 1, baz: 2 }, + { id: 10, foo: 2, bar: 2, baz: 1 } + ); + } + ); + }); + + it('supports multiple inequality on different fields', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + '01': { id: 1, foo: 1, bar: 1, baz: 1 }, + '02': { id: 2, foo: 1, bar: 1, baz: 2 }, + '03': { id: 3, foo: 1, bar: 1, baz: 2 }, + '04': { id: 4, foo: 1, bar: 2, baz: 1 }, + '05': { id: 5, foo: 1, bar: 2, baz: 2 }, + '06': { id: 6, foo: 1, bar: 2, baz: 2 }, + '07': { id: 7, foo: 2, bar: 1, baz: 1 }, + '08': { id: 8, foo: 2, bar: 1, baz: 2 }, + '09': { id: 9, foo: 2, bar: 1, baz: 2 }, + '10': { id: 10, foo: 2, bar: 2, baz: 1 }, + '11': { id: 11, foo: 2, bar: 2, baz: 2 }, + '12': { id: 12, foo: 2, bar: 2, baz: 2 } + }, + async (collRef, db) => { + const query1 = query( + collRef, + and(where('id', '>=', 2), where('baz', '<', 2)) + ); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults( + snapshot, + { id: 4, foo: 1, bar: 2, baz: 1 }, + { id: 7, foo: 2, bar: 1, baz: 1 }, + { id: 10, foo: 2, bar: 2, baz: 1 } + ); + } + ); + }); + + it('supports collectionGroup query', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { 1: { foo: 1 } }, + async (collRef, db) => { + const snapshot = await execute( + db.pipeline().createFrom(collectionGroup(db, collRef.id)) + ); + verifyResults(snapshot, { foo: 1 }); + } + ); + }); + + it('supports eq nan', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1, bar: NaN }, + 2: { foo: 2, bar: 1 }, + 3: { foo: 3, bar: 'bar' } + }, + async (collRef, db) => { + const query1 = query(collRef, where('bar', '==', NaN)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 1, bar: NaN }); + } + ); + }); + + it('supports neq nan', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1, bar: NaN }, + 2: { foo: 2, bar: 1 }, + 3: { foo: 3, bar: 'bar' } + }, + async (collRef, db) => { + const query1 = query(collRef, where('bar', '!=', NaN)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 2, bar: 1 }, { foo: 3, bar: 'bar' }); + } + ); + }); + + it('supports eq null', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1, bar: null }, + 2: { foo: 2, bar: 1 } + }, + async (collRef, db) => { + const query1 = query(collRef, where('bar', '==', null)); + const classicSnapshot = await getDocs(query1); + const classicData = classicSnapshot.docs.map(d => d.data()); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, ...classicData); + } + ); + }); + + it('supports neq null', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1, bar: null }, + 2: { foo: 2, bar: 1 } + }, + async (collRef, db) => { + const query1 = query(collRef, where('bar', '!=', null)); + const classicSnapshot = await getDocs(query1); + const classicData = classicSnapshot.docs.map(d => d.data()); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, ...classicData); + } + ); + }); + + it('supports neq', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1, bar: 0 }, + 2: { foo: 2, bar: 1 } + }, + async (collRef, db) => { + const query1 = query(collRef, where('bar', '!=', 0)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 2, bar: 1 }); + } + ); + }); + + it('supports array contains', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1, bar: [0, 2, 4, 6] }, + 2: { foo: 2, bar: [1, 3, 5, 7] } + }, + async (collRef, db) => { + const query1 = query(collRef, where('bar', 'array-contains', 4)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 1, bar: [0, 2, 4, 6] }); + } + ); + }); + + it('supports array contains any', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1, bar: [0, 2, 4, 6] }, + 2: { foo: 2, bar: [1, 3, 5, 7] }, + 3: { foo: 3, bar: [10, 20, 30, 40] } + }, + async (collRef, db) => { + const query1 = query( + collRef, + where('bar', 'array-contains-any', [4, 5]) + ); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults( + snapshot, + { foo: 1, bar: [0, 2, 4, 6] }, + { foo: 2, bar: [1, 3, 5, 7] } + ); + } + ); + }); + + it('supports in', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1, bar: 2 }, + 2: { foo: 2 }, + 3: { foo: 3, bar: 10 } + }, + async (collRef, db) => { + const query1 = query(collRef, where('bar', 'in', [0, 10, 20])); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 3, bar: 10 }); + } + ); + }); + + it('supports in with 1', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1, bar: 2 }, + 2: { foo: 2 }, + 3: { foo: 3, bar: 10 } + }, + async (collRef, db) => { + const query1 = query(collRef, where('bar', 'in', [2])); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 1, bar: 2 }); + } + ); + }); + + it('supports not in', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1, bar: 2 }, + 2: { foo: 2, bar: 1 }, + 3: { foo: 3, bar: 10 } + }, + async (collRef, db) => { + const query1 = query( + collRef, + where('bar', 'not-in', [0, 10, 20]), + orderBy('foo') + ); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 1, bar: 2 }, { foo: 2, bar: 1 }); + } + ); + }); + + it('supports not in with 1', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1, bar: 2 }, + 2: { foo: 2 }, + 3: { foo: 3, bar: 10 } + }, + async (collRef, db) => { + const query1 = query(collRef, where('bar', 'not-in', [2])); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 3, bar: 10 }); + } + ); + }); + + it('supports or operator', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + 1: { foo: 1, bar: 2 }, + 2: { foo: 2, bar: 0 }, + 3: { foo: 3, bar: 10 } + }, + async (collRef, db) => { + const query1 = query( + collRef, + or(where('bar', '==', 2), where('foo', '==', 3)), + orderBy('foo') + ); + const snapshot = await execute(db.pipeline().createFrom(query1)); + verifyResults(snapshot, { foo: 1, bar: 2 }, { foo: 3, bar: 10 }); + } + ); + }); +}); diff --git a/packages/firestore/test/integration/api_internal/console.test.ts b/packages/firestore/test/integration/api_internal/console.test.ts new file mode 100644 index 0000000000..88474adad4 --- /dev/null +++ b/packages/firestore/test/integration/api_internal/console.test.ts @@ -0,0 +1,69 @@ +/** + * @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. + */ + +import { expect } from 'chai'; + +import { + count, + setDoc, + getAggregateFromServer, + getDoc, + average +} from '../util/firebase_export'; +import { apiDescribe, withTestCollection, withTestDoc } from '../util/helpers'; + +apiDescribe('console support', persistence => { + it('supports DocumentSnapshot serialization to proto', async () => { + await withTestDoc(persistence, async (docRef, firestore) => { + await setDoc(docRef, { foo: 3, bar: 3.5 }); + const doc = await getDoc(docRef); + expect(doc._fieldsProto()).to.deep.equal({ + 'foo': { + 'integerValue': '3' + }, + 'bar': { + 'doubleValue': 3.5 + } + }); + }); + }); + + it('supports AggregateSnapshot serialization to proto', async () => { + await withTestCollection( + persistence, + { + 1: { foo: 1 }, + 2: { foo: 1 } + }, + async collRef => { + const doc = await getAggregateFromServer(collRef, { + count: count(), + avg: average('foo') + }); + // @ts-ignore internal API usage + expect(doc._fieldsProto()).to.deep.equal({ + 'count': { + 'integerValue': '2' + }, + 'avg': { + 'doubleValue': 1.0 + } + }); + } + ); + }); +}); diff --git a/packages/firestore/test/integration/api_internal/pipeline.test.ts b/packages/firestore/test/integration/api_internal/pipeline.test.ts new file mode 100644 index 0000000000..4011aa7fb1 --- /dev/null +++ b/packages/firestore/test/integration/api_internal/pipeline.test.ts @@ -0,0 +1,200 @@ +/** + * @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. + */ + +import { expect } from 'chai'; + +import { Deferred } from '../../util/promise'; +import { + addDoc, + CollectionReference, + Firestore, + vector +} from '../util/firebase_export'; +import { apiDescribe, withTestCollection } from '../util/helpers'; +import { + field, + _internalPipelineToExecutePipelineRequestProto, + execute +} from '../util/pipeline_export'; + +apiDescribe.skipClassic('Pipelines', persistence => { + let firestore: Firestore; + let randomCol: CollectionReference; + let testDeferred: Deferred | undefined; + let withTestCollectionPromise: Promise | undefined; + + beforeEach(async () => { + const setupDeferred = new Deferred(); + testDeferred = new Deferred(); + withTestCollectionPromise = withTestCollection( + persistence, + {}, + async (collectionRef, firestoreInstance) => { + randomCol = collectionRef; + firestore = firestoreInstance; + setupDeferred.resolve(); + + return testDeferred?.promise; + } + ); + + await setupDeferred.promise; + }); + + afterEach(async () => { + testDeferred?.resolve(); + await withTestCollectionPromise; + }); + + describe('console support', () => { + it('supports pipeline query serialization to proto', async () => { + // Perform the same test as the console + const pipeline = firestore + .pipeline() + .collection('customers') + .where(field('country').equal('United Kingdom')); + + const proto = _internalPipelineToExecutePipelineRequestProto(pipeline); + + const expectedStructuredPipelineProto = + '{"pipeline":{"stages":[{"name":"collection","options":{},"args":[{"referenceValue":"/customers"}]},{"name":"where","options":{},"args":[{"functionValue":{"name":"equal","args":[{"fieldReferenceValue":"country"},{"stringValue":"United Kingdom"}]}}]}]}}'; + expect(JSON.stringify(proto.structuredPipeline)).to.equal( + expectedStructuredPipelineProto + ); + }); + + it('supports PipelineSnapshot serialization to proto', async () => { + await addDoc(randomCol, { + title: '1984', + author: 'George Orwell', + genre: 'Dystopian', + published: 1949, + rating: 4.2, + tags: ['surveillance', 'totalitarianism', 'propaganda'], + awards: { prometheus: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 1, 10, 1, 1]) + }); + + // Perform the same test as the console + const pipeline = firestore + .pipeline() + .collection(randomCol) + .sort(field('title').ascending()) + .limit(1); + + const result = await execute(pipeline); + + expect(result.results[0]._fieldsProto()).to.deep.equal({ + 'author': { + 'stringValue': 'George Orwell' + }, + 'awards': { + 'mapValue': { + 'fields': { + 'prometheus': { + 'booleanValue': true + } + } + } + }, + 'embedding': { + 'mapValue': { + 'fields': { + '__type__': { + 'stringValue': '__vector__' + }, + 'value': { + 'arrayValue': { + 'values': [ + { + 'doubleValue': 1 + }, + { + 'doubleValue': 1 + }, + { + 'doubleValue': 1 + }, + { + 'doubleValue': 1 + }, + { + 'doubleValue': 1 + }, + { + 'doubleValue': 1 + }, + { + 'doubleValue': 1 + }, + { + 'doubleValue': 10 + }, + { + 'doubleValue': 1 + }, + { + 'doubleValue': 1 + } + ] + } + } + } + } + }, + 'genre': { + 'stringValue': 'Dystopian' + }, + 'published': { + 'integerValue': '1949' + }, + 'rating': { + 'doubleValue': 4.2 + }, + 'tags': { + 'arrayValue': { + 'values': [ + { + 'stringValue': 'surveillance' + }, + { + 'stringValue': 'totalitarianism' + }, + { + 'stringValue': 'propaganda' + } + ] + } + }, + 'title': { + 'stringValue': '1984' + } + }); + }); + + it('performs validation', async () => { + expect(() => { + const pipeline = firestore + .pipeline() + .collection('customers') + .where(field('country').equal(new Map([]))); + + _internalPipelineToExecutePipelineRequestProto(pipeline); + }).to.throw(); + }); + }); +}); diff --git a/packages/firestore/test/integration/api_internal/query.test.ts b/packages/firestore/test/integration/api_internal/query.test.ts new file mode 100644 index 0000000000..9d2fb5a38a --- /dev/null +++ b/packages/firestore/test/integration/api_internal/query.test.ts @@ -0,0 +1,467 @@ +/** + * @license + * Copyright 2017 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai'; + +import { addEqualityMatcher } from '../../util/equality_matcher'; +import { it } from '../../util/mocha_extensions'; +import { + deleteDoc, + doc, + DocumentData, + getDocs, + query, + where, + writeBatch +} from '../util/firebase_export'; +import { + apiDescribe, + RetryError, + PERSISTENCE_MODE_UNSPECIFIED, + withRetry, + withTestCollection, + withTestDb +} from '../util/helpers'; +import { USE_EMULATOR } from '../util/settings'; +import { captureExistenceFilterMismatches } from '../util/testing_hooks_util'; + +addEqualityMatcher(); + +apiDescribe('Queries', persistence => { + // TODO(b/291365820): Stop skipping this test when running against the + // Firestore emulator once the emulator is improved to include a bloom filter + // in the existence filter messages that it sends. + // eslint-disable-next-line no-restricted-properties + (USE_EMULATOR ? it.skip : it)( + 'resuming a query should use bloom filter to avoid full requery', + async () => { + // Prepare the names and contents of the 100 documents to create. + const testDocs: { [key: string]: object } = {}; + for (let i = 0; i < 100; i++) { + testDocs['doc' + (1000 + i)] = { key: 42 }; + } + + // Ensure that the local cache is configured to use LRU garbage + // collection (rather than eager garbage collection) so that the resume + // token and document data does not get prematurely evicted. + const lruPersistence = persistence.toLruGc(); + + return withRetry(async attemptNumber => { + return withTestCollection( + lruPersistence, + testDocs, + async (coll, db) => { + // Run a query to populate the local cache with the 100 documents + // and a resume token. + const snapshot1 = await getDocs(coll); + expect(snapshot1.size, 'snapshot1.size').to.equal(100); + const createdDocuments = snapshot1.docs.map( + snapshot => snapshot.ref + ); + + // Delete 50 of the 100 documents. Use a different Firestore + // instance to avoid affecting the local cache. + const deletedDocumentIds = new Set(); + await withTestDb(PERSISTENCE_MODE_UNSPECIFIED, async db2 => { + const batch = writeBatch(db2); + for (let i = 0; i < createdDocuments.length; i += 2) { + const documentToDelete = doc(db2, createdDocuments[i].path); + batch.delete(documentToDelete); + deletedDocumentIds.add(documentToDelete.id); + } + await batch.commit(); + }); + + // Wait for 10 seconds, during which Watch will stop tracking the + // query and will send an existence filter rather than "delete" + // events when the query is resumed. + await new Promise(resolve => setTimeout(resolve, 10000)); + + // Resume the query and save the resulting snapshot for + // verification. Use some internal testing hooks to "capture" the + // existence filter mismatches to verify that Watch sent a bloom + // filter, and it was used to avert a full requery. + const [existenceFilterMismatches, snapshot2] = + await captureExistenceFilterMismatches(() => getDocs(coll)); + + // Verify that the snapshot from the resumed query contains the + // expected documents; that is, that it contains the 50 documents + // that were _not_ deleted. + const actualDocumentIds = snapshot2.docs + .map(documentSnapshot => documentSnapshot.ref.id) + .sort(); + const expectedDocumentIds = createdDocuments + .filter(documentRef => !deletedDocumentIds.has(documentRef.id)) + .map(documentRef => documentRef.id) + .sort(); + expect(actualDocumentIds, 'snapshot2.docs').to.deep.equal( + expectedDocumentIds + ); + + // Verify that Watch sent an existence filter with the correct + // counts when the query was resumed. + expect( + existenceFilterMismatches, + 'existenceFilterMismatches' + ).to.have.length(1); + const { localCacheCount, existenceFilterCount, bloomFilter } = + existenceFilterMismatches[0]; + expect(localCacheCount, 'localCacheCount').to.equal(100); + expect(existenceFilterCount, 'existenceFilterCount').to.equal(50); + + // Verify that Watch sent a valid bloom filter. + if (!bloomFilter) { + expect.fail( + 'The existence filter should have specified a bloom filter ' + + 'in its `unchanged_names` field.' + ); + throw new Error('should never get here'); + } + + expect(bloomFilter.hashCount, 'bloomFilter.hashCount').to.be.above( + 0 + ); + expect( + bloomFilter.bitmapLength, + 'bloomFilter.bitmapLength' + ).to.be.above(0); + expect(bloomFilter.padding, 'bloomFilterPadding').to.be.above(0); + expect(bloomFilter.padding, 'bloomFilterPadding').to.be.below(8); + + // Verify that the bloom filter was successfully used to avert a + // full requery. If a false positive occurred then retry the entire + // test. Although statistically rare, false positives are expected + // to happen occasionally. When a false positive _does_ happen, just + // retry the test with a different set of documents. If that retry + // also_ experiences a false positive, then fail the test because + // that is so improbable that something must have gone wrong. + if (attemptNumber === 1 && !bloomFilter.applied) { + throw new RetryError(); + } + + expect( + bloomFilter.applied, + `bloomFilter.applied with attemptNumber=${attemptNumber}` + ).to.be.true; + } + ); + }); + } + ).timeout('90s'); + + // TODO(b/291365820): Stop skipping this test when running against the + // Firestore emulator once the emulator is improved to include a bloom filter + // in the existence filter messages that it sends. + // eslint-disable-next-line no-restricted-properties + (USE_EMULATOR ? it.skip : it)( + 'bloom filter should avert a full re-query when documents were added, ' + + 'deleted, removed, updated, and unchanged since the resume token', + async () => { + // Prepare the names and contents of the 20 documents to create. + const testDocs: { [key: string]: object } = {}; + for (let i = 0; i < 20; i++) { + testDocs['doc' + (1000 + i)] = { + key: 42, + removed: false + }; + } + + // Ensure that the local cache is configured to use LRU garbage + // collection (rather than eager garbage collection) so that the resume + // token and document data does not get prematurely evicted. + const lruPersistence = persistence.toLruGc(); + + return withRetry(async attemptNumber => { + return withTestCollection(lruPersistence, testDocs, async coll => { + // Run a query to populate the local cache with the 20 documents + // and a resume token. + const snapshot1 = await getDocs( + query(coll, where('removed', '==', false)) + ); + expect(snapshot1.size, 'snapshot1.size').to.equal(20); + const createdDocuments = snapshot1.docs.map(snapshot => snapshot.ref); + + // Out of the 20 existing documents, leave 5 docs untouched, delete 5 docs, + // remove 5 docs, update 5 docs, and add 15 new docs. + const deletedDocumentIds = new Set(); + const removedDocumentIds = new Set(); + const updatedDocumentIds = new Set(); + const addedDocumentIds: string[] = []; + + // Use a different Firestore instance to avoid affecting the local cache. + await withTestDb(PERSISTENCE_MODE_UNSPECIFIED, async db2 => { + const batch = writeBatch(db2); + + for (let i = 0; i < createdDocuments.length; i += 4) { + const documentToDelete = doc(db2, createdDocuments[i].path); + batch.delete(documentToDelete); + deletedDocumentIds.add(documentToDelete.id); + } + expect(deletedDocumentIds.size).to.equal(5); + + // Update 5 documents to no longer match the query. + for (let i = 1; i < createdDocuments.length; i += 4) { + const documentToModify = doc(db2, createdDocuments[i].path); + batch.update(documentToModify, { + removed: true + }); + removedDocumentIds.add(documentToModify.id); + } + expect(removedDocumentIds.size).to.equal(5); + + // Update 5 documents, but ensure they still match the query. + for (let i = 2; i < createdDocuments.length; i += 4) { + const documentToModify = doc(db2, createdDocuments[i].path); + batch.update(documentToModify, { + key: 43 + }); + updatedDocumentIds.add(documentToModify.id); + } + expect(updatedDocumentIds.size).to.equal(5); + + for (let i = 0; i < 15; i += 1) { + const documentToAdd = doc( + db2, + coll.path + '/newDoc' + (1000 + i) + ); + batch.set(documentToAdd, { + key: 42, + removed: false + }); + addedDocumentIds.push(documentToAdd.id); + } + + // Ensure the sets above are disjoint. + const mergedSet = new Set(); + [ + deletedDocumentIds, + removedDocumentIds, + updatedDocumentIds, + addedDocumentIds + ].forEach(set => { + set.forEach(documentId => mergedSet.add(documentId)); + }); + expect(mergedSet.size).to.equal(30); + + await batch.commit(); + }); + + // Wait for 10 seconds, during which Watch will stop tracking the + // query and will send an existence filter rather than "delete" + // events when the query is resumed. + await new Promise(resolve => setTimeout(resolve, 10000)); + + // Resume the query and save the resulting snapshot for + // verification. Use some internal testing hooks to "capture" the + // existence filter mismatches to verify that Watch sent a bloom + // filter, and it was used to avert a full requery. + const [existenceFilterMismatches, snapshot2] = + await captureExistenceFilterMismatches(() => + getDocs(query(coll, where('removed', '==', false))) + ); + + // Verify that the snapshot from the resumed query contains the + // expected documents; that is, 10 existing documents that still + // match the query, and 15 documents that are newly added. + const actualDocumentIds = snapshot2.docs + .map(documentSnapshot => documentSnapshot.ref.id) + .sort(); + const expectedDocumentIds = createdDocuments + .map(documentRef => documentRef.id) + .filter(documentId => !deletedDocumentIds.has(documentId)) + .filter(documentId => !removedDocumentIds.has(documentId)) + .concat(addedDocumentIds) + .sort(); + + expect(actualDocumentIds, 'snapshot2.docs').to.deep.equal( + expectedDocumentIds + ); + expect(actualDocumentIds.length).to.equal(25); + + // Verify that Watch sent an existence filter with the correct + // counts when the query was resumed. + expect( + existenceFilterMismatches, + 'existenceFilterMismatches' + ).to.have.length(1); + const { localCacheCount, existenceFilterCount, bloomFilter } = + existenceFilterMismatches[0]; + expect(localCacheCount, 'localCacheCount').to.equal(35); + expect(existenceFilterCount, 'existenceFilterCount').to.equal(25); + + // Verify that Watch sent a valid bloom filter. + if (!bloomFilter) { + expect.fail( + 'The existence filter should have specified a bloom filter ' + + 'in its `unchanged_names` field.' + ); + throw new Error('should never get here'); + } + + // Verify that the bloom filter was successfully used to avert a + // full requery. If a false positive occurred then retry the entire + // test. Although statistically rare, false positives are expected + // to happen occasionally. When a false positive _does_ happen, just + // retry the test with a different set of documents. If that retry + // also_ experiences a false positive, then fail the test because + // that is so improbable that something must have gone wrong. + if (attemptNumber === 1 && !bloomFilter.applied) { + throw new RetryError(); + } + + expect( + bloomFilter.applied, + `bloomFilter.applied with attemptNumber=${attemptNumber}` + ).to.be.true; + }); + }); + } + ).timeout('90s'); + + // TODO(b/291365820): Stop skipping this test when running against the + // Firestore emulator once the emulator is improved to include a bloom filter + // in the existence filter messages that it sends. + // eslint-disable-next-line no-restricted-properties + (USE_EMULATOR ? it.skip : it)( + 'bloom filter should correctly encode complex Unicode characters', + async () => { + // Firestore does not do any Unicode normalization on the document IDs. + // Therefore, two document IDs that are canonically-equivalent (i.e. they + // visually appear identical) but are represented by a different sequence + // of Unicode code points are treated as distinct document IDs. + const testDocIds = [ + 'DocumentToDelete', + // The next two strings both end with "e" with an accent: the first uses + // the dedicated Unicode code point for this character, while the second + // uses the standard lowercase "e" followed by the accent combining + // character. + 'LowercaseEWithAcuteAccent_\u00E9', + 'LowercaseEWithAcuteAccent_\u0065\u0301', + // The next two strings both end with an "e" with two different accents + // applied via the following two combining characters. The combining + // characters are specified in a different order and Firestore treats + // these document IDs as unique, despite the order of the combining + // characters being irrelevant. + 'LowercaseEWithMultipleAccents_\u0065\u0301\u0327', + 'LowercaseEWithMultipleAccents_\u0065\u0327\u0301', + // The next string contains a character outside the BMP (the "basic + // multilingual plane"); that is, its code point is greater than 0xFFFF. + // In UTF-16 (which JavaScript uses to store Unicode strings) this + // requires a surrogate pair, two 16-bit code units, to represent this + // character. Make sure that its presence is correctly tested in the + // bloom filter, which uses UTF-8 encoding. + 'Smiley_\u{1F600}' + ]; + + // Verify assumptions about the equivalence of strings in `testDocIds`. + expect(testDocIds[1].normalize()).equals(testDocIds[2].normalize()); + expect(testDocIds[3].normalize()).equals(testDocIds[4].normalize()); + expect(testDocIds[5]).equals('Smiley_\uD83D\uDE00'); + + // Create the mapping from document ID to document data for the document + // IDs specified in `testDocIds`. + const testDocs = testDocIds.reduce((map, docId) => { + map[docId] = { foo: 42 }; + return map; + }, {} as { [key: string]: DocumentData }); + + // Ensure that the local cache is configured to use LRU garbage collection + // (rather than eager garbage collection) so that the resume token and + // document data does not get prematurely evicted. + const lruPersistence = persistence.toLruGc(); + + return withTestCollection(lruPersistence, testDocs, async (coll, db) => { + // Run a query to populate the local cache with documents that have + // names with complex Unicode characters. + const snapshot1 = await getDocs(coll); + const snapshot1DocumentIds = snapshot1.docs.map( + documentSnapshot => documentSnapshot.id + ); + expect(snapshot1DocumentIds, 'snapshot1DocumentIds').to.have.members( + testDocIds + ); + + // Delete one of the documents so that the next call to getDocs() will + // experience an existence filter mismatch. Use a different Firestore + // instance to avoid affecting the local cache. + const documentToDelete = doc(coll, 'DocumentToDelete'); + await withTestDb(PERSISTENCE_MODE_UNSPECIFIED, async db2 => { + await deleteDoc(doc(db2, documentToDelete.path)); + }); + + // Wait for 10 seconds, during which Watch will stop tracking the query + // and will send an existence filter rather than "delete" events when + // the query is resumed. + await new Promise(resolve => setTimeout(resolve, 10000)); + + // Resume the query and save the resulting snapshot for verification. + // Use some internal testing hooks to "capture" the existence filter + // mismatches. + const [existenceFilterMismatches, snapshot2] = + await captureExistenceFilterMismatches(() => getDocs(coll)); + const snapshot2DocumentIds = snapshot2.docs.map( + documentSnapshot => documentSnapshot.id + ); + const testDocIdsMinusDeletedDocId = testDocIds.filter( + documentId => documentId !== documentToDelete.id + ); + expect(snapshot2DocumentIds, 'snapshot2DocumentIds').to.have.members( + testDocIdsMinusDeletedDocId + ); + + // Verify that Watch sent an existence filter with the correct counts. + expect( + existenceFilterMismatches, + 'existenceFilterMismatches' + ).to.have.length(1); + const existenceFilterMismatch = existenceFilterMismatches[0]; + expect( + existenceFilterMismatch.localCacheCount, + 'localCacheCount' + ).to.equal(testDocIds.length); + expect( + existenceFilterMismatch.existenceFilterCount, + 'existenceFilterCount' + ).to.equal(testDocIds.length - 1); + + // Verify that we got a bloom filter from Watch. + const bloomFilter = existenceFilterMismatch.bloomFilter!; + expect(bloomFilter?.mightContain, 'bloomFilter.mightContain').to.not.be + .undefined; + + // The bloom filter application should statistically be successful + // almost every time; the _only_ time when it would _not_ be successful + // is if there is a false positive when testing for 'DocumentToDelete' + // in the bloom filter. So verify that the bloom filter application is + // successful, unless there was a false positive. + const isFalsePositive = bloomFilter.mightContain(documentToDelete); + expect(bloomFilter.applied, 'bloomFilter.applied').to.equal( + !isFalsePositive + ); + + // Verify that the bloom filter contains the document paths with complex + // Unicode characters. + for (const testDoc of snapshot2.docs.map(snapshot => snapshot.ref)) { + expect( + bloomFilter.mightContain(testDoc), + `bloomFilter.mightContain('${testDoc.path}')` + ).to.be.true; + } + }); + } + ).timeout('90s'); +}); diff --git a/packages/firestore/test/integration/util/composite_index_test_helper.ts b/packages/firestore/test/integration/util/composite_index_test_helper.ts index a908ed1345..fbabe977dc 100644 --- a/packages/firestore/test/integration/util/composite_index_test_helper.ts +++ b/packages/firestore/test/integration/util/composite_index_test_helper.ts @@ -40,7 +40,9 @@ import { deleteDoc as deleteDocument, doc, and, + // @ts-ignore internal API usage _AutoId, + // @ts-ignore internal API usage _FieldPath, newTestFirestore, newTestApp, diff --git a/packages/firestore/test/integration/util/helpers.ts b/packages/firestore/test/integration/util/helpers.ts index b36ed98029..04546ce35b 100644 --- a/packages/firestore/test/integration/util/helpers.ts +++ b/packages/firestore/test/integration/util/helpers.ts @@ -18,6 +18,8 @@ import { isIndexedDBAvailable } from '@firebase/util'; import { expect } from 'chai'; +import { describe } from '../../util/mocha_extensions'; + import { clearIndexedDbPersistence, collection, @@ -44,6 +46,7 @@ import { Query, getDocsFromServer, getDocsFromCache, + // @ts-ignore internal API usage _AutoId } from './firebase_export'; import { @@ -177,7 +180,10 @@ export function isPersistenceAvailable(): boolean { * persistence both disabled and enabled (if the browser is supported). */ function apiDescribeInternal( - describeFn: Mocha.PendingSuiteFunction, + describeFn: + | Mocha.PendingSuiteFunction + | Mocha.SuiteFunction + | Mocha.ExclusiveSuiteFunction, message: string, testSuite: (persistence: PersistenceMode) => void ): void { @@ -204,6 +210,9 @@ interface ApiDescribe { (message: string, testSuite: (persistence: PersistenceMode) => void): void; skip: ApiSuiteFunction; only: ApiSuiteFunction; + skipEnterprise: ApiSuiteFunction; + skipEmulator: ApiSuiteFunction; + skipClassic: ApiSuiteFunction; } export const apiDescribe = apiDescribeInternal.bind( @@ -214,6 +223,15 @@ export const apiDescribe = apiDescribeInternal.bind( apiDescribe.skip = apiDescribeInternal.bind(null, describe.skip); // eslint-disable-next-line no-restricted-properties apiDescribe.only = apiDescribeInternal.bind(null, describe.only); +apiDescribe.skipEnterprise = apiDescribeInternal.bind( + null, + describe.skipEnterprise +); +apiDescribe.skipClassic = apiDescribeInternal.bind(null, describe.skipClassic); +apiDescribe.skipEmulator = apiDescribeInternal.bind( + null, + describe.skipEmulator +); /** Converts the documents in a QuerySnapshot to an array with the data of each document. */ export function toDataArray(docSet: QuerySnapshot): DocumentData[] { diff --git a/packages/firestore/test/integration/util/internal_helpers.ts b/packages/firestore/test/integration/util/internal_helpers.ts index e5e64b5fbf..b196599f40 100644 --- a/packages/firestore/test/integration/util/internal_helpers.ts +++ b/packages/firestore/test/integration/util/internal_helpers.ts @@ -62,7 +62,8 @@ export function getDefaultDatabaseInfo(): DatabaseInfo { DEFAULT_SETTINGS.experimentalLongPollingOptions ?? {} ), /*use FetchStreams= */ false, - /*isUsingEmulator=*/ false + /*isUsingEmulator=*/ false, + undefined ); } diff --git a/packages/firestore/test/integration/util/pipeline_export.ts b/packages/firestore/test/integration/util/pipeline_export.ts new file mode 100644 index 0000000000..d2495d772a --- /dev/null +++ b/packages/firestore/test/integration/util/pipeline_export.ts @@ -0,0 +1,23 @@ +/** + * @license + * Copyright 2017 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Imports firebase via the raw sources and re-exports it. The +// "/integration/firestore" test suite replaces this file with a +// reference to the minified sources. If you change any exports in this file, +// you need to also adjust "integration/firestore/pipeline_export.ts". + +export * from '../../../pipelines/pipelines'; diff --git a/packages/firestore/test/integration/util/testing_hooks_util.ts b/packages/firestore/test/integration/util/testing_hooks_util.ts index 72604f91a8..7b99cf4040 100644 --- a/packages/firestore/test/integration/util/testing_hooks_util.ts +++ b/packages/firestore/test/integration/util/testing_hooks_util.ts @@ -17,7 +17,9 @@ import { DocumentReference, + // @ts-ignore internal API usage _TestingHooks as TestingHooks, + // @ts-ignore internal API usage _TestingHooksExistenceFilterMismatchInfo as ExistenceFilterMismatchInfoInternal } from './firebase_export'; diff --git a/packages/firestore/test/lite/integration.test.ts b/packages/firestore/test/lite/integration.test.ts index 54595ade4d..63f55b1aa6 100644 --- a/packages/firestore/test/lite/integration.test.ts +++ b/packages/firestore/test/lite/integration.test.ts @@ -93,6 +93,7 @@ import { DEFAULT_SETTINGS, USE_EMULATOR } from '../integration/util/settings'; +import { it, describe } from '../util/mocha_extensions'; import { Post, @@ -2463,27 +2464,24 @@ describe('Count queries', () => { // production, since the Firestore Emulator does not require index creation // and will, therefore, never fail in this situation. // eslint-disable-next-line no-restricted-properties - (USE_EMULATOR ? it.skip : it)( - 'getCount error message contains console link if missing index', - () => { - return withTestCollection(async coll => { - const query_ = query( - coll, - where('key1', '==', 42), - where('key2', '<', 42) + it.skip('getCount error message contains console link if missing index', () => { + return withTestCollection(async coll => { + const query_ = query( + coll, + where('key1', '==', 42), + where('key2', '<', 42) + ); + // TODO(b/316359394) Remove the special logic for non-default databases + // once cl/582465034 is rolled out to production. + if (coll.firestore._databaseId.isDefaultDatabase) { + await expect(getCount(query_)).to.be.eventually.rejectedWith( + /index.*https:\/\/console\.firebase\.google\.com/ ); - // TODO(b/316359394) Remove the special logic for non-default databases - // once cl/582465034 is rolled out to production. - if (coll.firestore._databaseId.isDefaultDatabase) { - await expect(getCount(query_)).to.be.eventually.rejectedWith( - /index.*https:\/\/console\.firebase\.google\.com/ - ); - } else { - await expect(getCount(query_)).to.be.eventually.rejected; - } - }); - } - ); + } else { + await expect(getCount(query_)).to.be.eventually.rejected; + } + }); + }); }); describe('Aggregate queries', () => { @@ -2772,7 +2770,7 @@ describe('Aggregate queries', () => { // production, since the Firestore Emulator does not require index creation // and will, therefore, never fail in this situation. // eslint-disable-next-line no-restricted-properties - (USE_EMULATOR ? it.skip : it)( + it.skipEmulator.skipEnterprise( 'getAggregate error message contains console link if missing index', () => { return withTestCollection(async coll => { @@ -2906,26 +2904,29 @@ describe('Aggregate queries - sum / average', () => { }); }); - it('fails when exceeding the max (5) aggregations using getAggregationFromServer', () => { - const testDocs = [ - { author: 'authorA', title: 'titleA', pages: 100 }, - { author: 'authorB', title: 'titleB', pages: 50 } - ]; - return withTestCollectionAndInitialData(testDocs, async coll => { - const promise = getAggregate(coll, { - totalPages: sum('pages'), - averagePages: average('pages'), - count: count(), - totalPagesX: sum('pages'), - averagePagesY: average('pages'), - countZ: count() - }); + it.skipEmulator.skipEnterprise( + 'fails when exceeding the max (5) aggregations using getAggregationFromServer', + () => { + const testDocs = [ + { author: 'authorA', title: 'titleA', pages: 100 }, + { author: 'authorB', title: 'titleB', pages: 50 } + ]; + return withTestCollectionAndInitialData(testDocs, async coll => { + const promise = getAggregate(coll, { + totalPages: sum('pages'), + averagePages: average('pages'), + count: count(), + totalPagesX: sum('pages'), + averagePagesY: average('pages'), + countZ: count() + }); - await expect(promise).to.eventually.be.rejectedWith( - /maximum number of aggregations/ - ); - }); - }); + await expect(promise).to.eventually.be.rejectedWith( + /maximum number of aggregations/ + ); + }); + } + ); // Only run tests that require indexes against the emulator, because we don't // have a way to dynamically create the indexes when running the tests. diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts new file mode 100644 index 0000000000..477d976eb4 --- /dev/null +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -0,0 +1,4140 @@ +/** + * @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-disable-next-line import/no-extraneous-dependencies +import { FirebaseError } from '@firebase/util'; +import { expect, use } from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +import { Bytes } from '../../src/lite-api/bytes'; +import { + Firestore, + getFirestore, + terminate +} from '../../src/lite-api/database'; +import { documentId as documentIdFieldPath } from '../../src/lite-api/field_path'; +import { vector } from '../../src/lite-api/field_value_impl'; +import { GeoPoint } from '../../src/lite-api/geo_point'; +import { + pipelineResultEqual, + PipelineSnapshot +} from '../../src/lite-api/pipeline-result'; +import { execute } from '../../src/lite-api/pipeline_impl'; +import { + DocumentData, + CollectionReference, + collection, + doc, + DocumentReference +} from '../../src/lite-api/reference'; +import { addDoc, setDoc, deleteDoc } from '../../src/lite-api/reference_impl'; +import { FindNearestStageOptions } from '../../src/lite-api/stage_options'; +import { Timestamp } from '../../src/lite-api/timestamp'; +import { writeBatch } from '../../src/lite-api/write_batch'; +import { addEqualityMatcher } from '../util/equality_matcher'; +import { describe } from '../util/mocha_extensions'; +import { Deferred } from '../util/promise'; + +import { withTestCollection } from './helpers'; +import { + field, + and, + array, + constant, + add, + subtract, + multiply, + average, + substring, + count, + mapMerge, + mapRemove, + ifError, + isAbsent, + isError, + or, + map, + length, + mod, + documentId, + equal, + notEqual, + lessThan, + countIf, + lessThanOrEqual, + greaterThan, + arrayContains, + arrayContainsAny, + equalAny, + notEqualAny, + xor, + conditional, + logicalMaximum, + logicalMinimum, + exists, + reverse, + like, + regexContains, + regexMatch, + stringContains, + startsWith, + endsWith, + mapGet, + countAll, + minimum, + maximum, + cosineDistance, + dotProduct, + euclideanDistance, + vectorLength, + unixMicrosToTimestamp, + timestampToUnixMicros, + unixMillisToTimestamp, + timestampToUnixMillis, + unixSecondsToTimestamp, + timestampToUnixSeconds, + timestampAdd, + timestampSubtract, + ascending, + descending, + FunctionExpression, + AggregateFunction, + stringConcat, + arrayContainsAll, + arrayLength, + charLength, + divide, + not, + toLower, + toUpper, + trim, + byteLength, + arrayGet, + abs, + sum, + countDistinct, + ceil, + floor, + exp, + pow, + round, + collectionId, + ln, + log, + sqrt, + stringReverse, + log10, + concat, + currentTimestamp, + ifAbsent, + join, + arraySum +} from './pipeline_export'; + +use(chaiAsPromised); + +const timestampDeltaMS = 1000; + +describe.skipClassic('Firestore Pipelines', () => { + addEqualityMatcher(); + + let firestore: Firestore; + let randomCol: CollectionReference; + let beginDocCreation: number = 0; + let endDocCreation: number = 0; + + async function testCollectionWithDocs(docs: { + [id: string]: DocumentData; + }): Promise> { + beginDocCreation = new Date().valueOf(); + for (const id in docs) { + if (docs.hasOwnProperty(id)) { + const ref = doc(randomCol, id); + await setDoc(ref, docs[id]); + } + } + endDocCreation = new Date().valueOf(); + return randomCol; + } + + function expectResults(snapshot: PipelineSnapshot, ...docs: string[]): void; + function expectResults( + snapshot: PipelineSnapshot, + ...data: DocumentData[] + ): void; + + function expectResults( + snapshot: PipelineSnapshot, + ...data: DocumentData[] | string[] + ): void { + const docs = snapshot.results; + + expect(docs.length).to.equal(data.length); + + if (data.length > 0) { + if (typeof data[0] === 'string') { + const actualIds = docs.map(doc => doc.id); + expect(actualIds).to.deep.equal(data); + } else { + docs.forEach(r => { + expect(r.data()).to.deep.equal(data.shift()); + }); + } + } + } + + async function setupBookDocs(): Promise> { + const bookDocs: { [id: string]: DocumentData } = { + book1: { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + embedding: vector([10, 1, 1, 1, 1, 1, 1, 1, 1, 1]) + }, + book2: { + title: 'Pride and Prejudice', + author: 'Jane Austen', + genre: 'Romance', + published: 1813, + rating: 4.5, + tags: ['classic', 'social commentary', 'love'], + awards: { none: true }, + embedding: vector([1, 10, 1, 1, 1, 1, 1, 1, 1, 1]) + }, + book3: { + title: 'One Hundred Years of Solitude', + author: 'Gabriel García Márquez', + genre: 'Magical Realism', + published: 1967, + rating: 4.3, + tags: ['family', 'history', 'fantasy'], + awards: { nobel: true, nebula: false }, + embedding: vector([1, 1, 10, 1, 1, 1, 1, 1, 1, 1]) + }, + book4: { + title: 'The Lord of the Rings', + author: 'J.R.R. Tolkien', + genre: 'Fantasy', + published: 1954, + rating: 4.7, + tags: ['adventure', 'magic', 'epic'], + awards: { hugo: false, nebula: false }, + remarks: null, + cost: NaN, + embedding: vector([1, 1, 1, 10, 1, 1, 1, 1, 1, 1]) + }, + book5: { + title: "The Handmaid's Tale", + author: 'Margaret Atwood', + genre: 'Dystopian', + published: 1985, + rating: 4.1, + tags: ['feminism', 'totalitarianism', 'resistance'], + awards: { 'arthur c. clarke': true, 'booker prize': false }, + embedding: vector([1, 1, 1, 1, 10, 1, 1, 1, 1, 1]) + }, + book6: { + title: 'Crime and Punishment', + author: 'Fyodor Dostoevsky', + genre: 'Psychological Thriller', + published: 1866, + rating: 4.3, + tags: ['philosophy', 'crime', 'redemption'], + awards: { none: true }, + embedding: vector([1, 1, 1, 1, 1, 10, 1, 1, 1, 1]) + }, + book7: { + title: 'To Kill a Mockingbird', + author: 'Harper Lee', + genre: 'Southern Gothic', + published: 1960, + rating: 4.2, + tags: ['racism', 'injustice', 'coming-of-age'], + awards: { pulitzer: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 10, 1, 1, 1]) + }, + book8: { + title: '1984', + author: 'George Orwell', + genre: 'Dystopian', + published: 1949, + rating: 4.2, + tags: ['surveillance', 'totalitarianism', 'propaganda'], + awards: { prometheus: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 1, 10, 1, 1]) + }, + book9: { + title: 'The Great Gatsby', + author: 'F. Scott Fitzgerald', + genre: 'Modernist', + published: 1925, + rating: 4.0, + tags: ['wealth', 'american dream', 'love'], + awards: { none: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 1, 1, 10, 1]) + }, + book10: { + title: 'Dune', + author: 'Frank Herbert', + genre: 'Science Fiction', + published: 1965, + rating: 4.6, + tags: ['politics', 'desert', 'ecology'], + awards: { hugo: true, nebula: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 1, 1, 1, 10]) + } + }; + return testCollectionWithDocs(bookDocs); + } + + let testDeferred: Deferred | undefined; + let withTestCollectionPromise: Promise | undefined; + + beforeEach(async () => { + const setupDeferred = new Deferred(); + testDeferred = new Deferred(); + withTestCollectionPromise = withTestCollection(async collectionRef => { + randomCol = collectionRef; + firestore = collectionRef.firestore; + await setupBookDocs(); + setupDeferred.resolve(); + + return testDeferred?.promise; + }); + + await setupDeferred.promise; + }); + + afterEach(async () => { + testDeferred?.resolve(); + await withTestCollectionPromise; + }); + + describe('pipeline results', () => { + it('empty snapshot as expected', async () => { + const snapshot = await execute( + firestore.pipeline().collection(randomCol.path).limit(0) + ); + expect(snapshot.results.length).to.equal(0); + }); + + it('full snapshot as expected', async () => { + const ppl = firestore + .pipeline() + .collection(randomCol.path) + .sort(ascending('__name__')); + const snapshot = await execute(ppl); + expect(snapshot.results.length).to.equal(10); + expectResults( + snapshot, + 'book1', + 'book10', + 'book2', + 'book3', + 'book4', + 'book5', + 'book6', + 'book7', + 'book8', + 'book9' + ); + }); + + it('result equals works', async () => { + const ppl = firestore + .pipeline() + .collection(randomCol.path) + .sort(ascending('title')) + .limit(1); + const snapshot1 = await execute(ppl); + const snapshot2 = await execute(ppl); + expect(snapshot1.results.length).to.equal(1); + expect(snapshot2.results.length).to.equal(1); + expect(pipelineResultEqual(snapshot1.results[0], snapshot2.results[0])).to + .be.true; + }); + + it('returns execution time', async () => { + const start = new Date().valueOf(); + const pipeline = firestore.pipeline().collection(randomCol.path); + + const snapshot = await execute(pipeline); + const end = new Date().valueOf(); + + expect(snapshot.executionTime.toDate().valueOf()).to.approximately( + (start + end) / 2, + timestampDeltaMS + ); + }); + + it('returns execution time for an empty query', async () => { + const start = new Date().valueOf(); + const pipeline = firestore.pipeline().collection(randomCol.path).limit(0); + + const snapshot = await execute(pipeline); + const end = new Date().valueOf(); + + expect(snapshot.results.length).to.equal(0); + + expect(snapshot.executionTime.toDate().valueOf()).to.approximately( + (start + end) / 2, + timestampDeltaMS + ); + }); + + it('returns create and update time for each document', async () => { + const pipeline = firestore.pipeline().collection(randomCol.path); + + let snapshot = await execute(pipeline); + expect(snapshot.results.length).to.equal(10); + snapshot.results.forEach(doc => { + expect(doc.createTime).to.not.be.null; + expect(doc.updateTime).to.not.be.null; + + expect(doc.createTime!.toDate().valueOf()).to.approximately( + (beginDocCreation + endDocCreation) / 2, + timestampDeltaMS + ); + expect(doc.updateTime!.toDate().valueOf()).to.approximately( + (beginDocCreation + endDocCreation) / 2, + timestampDeltaMS + ); + expect(doc.createTime?.valueOf()).to.equal(doc.updateTime?.valueOf()); + }); + + const wb = writeBatch(firestore); + snapshot.results.forEach(doc => { + wb.update(doc.ref!, { newField: 'value' }); + }); + await wb.commit(); + + snapshot = await execute(pipeline); + expect(snapshot.results.length).to.equal(10); + snapshot.results.forEach(doc => { + expect(doc.createTime).to.not.be.null; + expect(doc.updateTime).to.not.be.null; + expect(doc.createTime!.toDate().valueOf()).to.be.lessThan( + doc.updateTime!.toDate().valueOf() + ); + }); + }); + + it('returns execution time for an aggregate query', async () => { + const start = new Date().valueOf(); + const pipeline = firestore + .pipeline() + .collection(randomCol.path) + .aggregate(average('rating').as('avgRating')); + + const snapshot = await execute(pipeline); + const end = new Date().valueOf(); + + expect(snapshot.results.length).to.equal(1); + + expect(snapshot.executionTime.toDate().valueOf()).to.approximately( + (start + end) / 2, + timestampDeltaMS + ); + }); + + it('returns undefined create and update time for each result in an aggregate query', async () => { + const pipeline = firestore + .pipeline() + .collection(randomCol.path) + .aggregate({ + accumulators: [average('rating').as('avgRating')], + groups: ['genre'] + }); + + const snapshot = await execute(pipeline); + + expect(snapshot.results.length).to.equal(8); + + snapshot.results.forEach(doc => { + expect(doc.updateTime).to.be.undefined; + expect(doc.createTime).to.be.undefined; + }); + }); + }); + + describe('pipeline sources', () => { + it('supports CollectionReference as source', async () => { + const snapshot = await execute( + firestore.pipeline().collection(randomCol) + ); + expect(snapshot.results.length).to.equal(10); + }); + + it('supports list of documents as source', async () => { + const collName = randomCol.id; + + const snapshot = await execute( + firestore + .pipeline() + .documents([ + `${collName}/book1`, + doc(randomCol, 'book2'), + doc(randomCol, 'book3').path + ]) + ); + expect(snapshot.results.length).to.equal(3); + }); + + it('reject CollectionReference for another DB', async () => { + const db2 = getFirestore(firestore.app, 'notDefault'); + + expect(() => { + firestore.pipeline().collection(collection(db2, 'foo')); + }).to.throw(/Invalid CollectionReference/); + + await terminate(db2); + }); + + it('reject DocumentReference for another DB', async () => { + const db2 = getFirestore(firestore.app, 'notDefault'); + + expect(() => { + firestore.pipeline().documents([doc(db2, 'foo/bar')]); + }).to.throw(/Invalid DocumentReference/); + + await terminate(db2); + }); + + it('supports collection group as source', async () => { + const randomSubCollectionId = Math.random().toString(16).slice(2); + const doc1 = await addDoc( + collection(randomCol, 'book1', randomSubCollectionId), + { order: 1 } + ); + const doc2 = await addDoc( + collection(randomCol, 'book2', randomSubCollectionId), + { order: 2 } + ); + const snapshot = await execute( + firestore + .pipeline() + .collectionGroup(randomSubCollectionId) + .sort(ascending('order')) + ); + expectResults(snapshot, doc1.id, doc2.id); + }); + + it('supports database as source', async () => { + const randomId = Math.random().toString(16).slice(2); + const doc1 = await addDoc(collection(randomCol, 'book1', 'sub'), { + order: 1, + randomId + }); + const doc2 = await addDoc(collection(randomCol, 'book2', 'sub'), { + order: 2, + randomId + }); + const snapshot = await execute( + firestore + .pipeline() + .database() + .where(equal('randomId', randomId)) + .sort(ascending('order')) + ); + expectResults(snapshot, doc1.id, doc2.id); + }); + + it('can create pipeline from a query', async () => { + const snapshot = await execute( + firestore + .pipeline() + .createFrom(randomCol) + .sort(field('__name__').ascending()) + .limit(1) + ); + expectResults(snapshot, 'book1'); + }); + }); + + describe('supported data types', () => { + it('accepts and returns all data types', async () => { + const refDate = new Date(); + const refTimestamp = Timestamp.now(); + const constants = [ + constant(1).as('number'), + constant('a string').as('string'), + constant(true).as('boolean'), + constant(null).as('null'), + constant(new GeoPoint(0.1, 0.2)).as('geoPoint'), + constant(refTimestamp).as('timestamp'), + constant(refDate).as('date'), + constant( + Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0])) + ).as('bytes'), + constant(doc(firestore, 'foo', 'bar')).as('documentReference'), + constant(vector([1, 2, 3])).as('vectorValue'), + map({ + 'number': 1, + 'string': 'a string', + 'boolean': true, + 'null': null, + 'geoPoint': new GeoPoint(0.1, 0.2), + 'timestamp': refTimestamp, + 'date': refDate, + 'uint8Array': Bytes.fromUint8Array( + new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0]) + ), + 'documentReference': doc(firestore, 'foo', 'bar'), + 'vectorValue': vector([1, 2, 3]), + 'map': { + 'number': 2, + 'string': 'b string' + }, + 'array': [1, 'c string'] + }).as('map'), + array([ + 1, + 'a string', + true, + null, + new GeoPoint(0.1, 0.2), + refTimestamp, + refDate, + Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0])), + doc(firestore, 'foo', 'bar'), + vector([1, 2, 3]), + { + 'number': 2, + 'string': 'b string' + } + ]).as('array') + ]; + + const snapshots = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(constants[0], ...constants.slice(1)) + ); + + expectResults(snapshots, { + 'number': 1, + 'string': 'a string', + 'boolean': true, + 'null': null, + 'geoPoint': new GeoPoint(0.1, 0.2), + 'timestamp': refTimestamp, + 'date': Timestamp.fromDate(refDate), + 'bytes': Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0])), + 'documentReference': doc(firestore, 'foo', 'bar'), + 'vectorValue': vector([1, 2, 3]), + 'map': { + 'number': 1, + 'string': 'a string', + 'boolean': true, + 'null': null, + 'geoPoint': new GeoPoint(0.1, 0.2), + 'timestamp': refTimestamp, + 'date': Timestamp.fromDate(refDate), + 'uint8Array': Bytes.fromUint8Array( + new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0]) + ), + 'documentReference': doc(firestore, 'foo', 'bar'), + 'vectorValue': vector([1, 2, 3]), + 'map': { + 'number': 2, + 'string': 'b string' + }, + 'array': [1, 'c string'] + }, + 'array': [ + 1, + 'a string', + true, + null, + new GeoPoint(0.1, 0.2), + refTimestamp, + Timestamp.fromDate(refDate), + Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0])), + doc(firestore, 'foo', 'bar'), + vector([1, 2, 3]), + { + 'number': 2, + 'string': 'b string' + } + ] + }); + }); + + it('throws on undefined in a map', async () => { + expect(() => { + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select( + map({ + 'number': 1, + undefined + }).as('foo') + ); + }).to.throw( + 'Function map() called with invalid data. Unsupported field value: undefined' + ); + }); + + it('throws on undefined in an array', async () => { + expect(() => { + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(array([1, undefined]).as('foo')); + }).to.throw( + 'Function array() called with invalid data. Unsupported field value: undefined' + ); + }); + + it('converts arrays and plain objects to functionValues if the customer intent is unspecified', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + 'title', + 'author', + 'genre', + 'rating', + 'published', + 'tags', + 'awards' + ) + .addFields( + array([ + 1, + 2, + field('genre'), + multiply('rating', 10), + [field('title')], + { + published: field('published') + } + ]).as('metadataArray'), + map({ + genre: field('genre'), + rating: multiply('rating', 10), + nestedArray: [field('title')], + nestedMap: { + published: field('published') + } + }).as('metadata') + ) + .where( + and( + equal('metadataArray', [ + 1, + 2, + field('genre'), + multiply('rating', 10), + [field('title')], + { + published: field('published') + } + ]), + equal('metadata', { + genre: field('genre'), + rating: multiply('rating', 10), + nestedArray: [field('title')], + nestedMap: { + published: field('published') + } + }) + ) + ) + ); + + expect(snapshot.results.length).to.equal(1); + + expectResults(snapshot, { + title: 'The Lord of the Rings', + author: 'J.R.R. Tolkien', + genre: 'Fantasy', + published: 1954, + rating: 4.7, + tags: ['adventure', 'magic', 'epic'], + awards: { hugo: false, nebula: false }, + metadataArray: [ + 1, + 2, + 'Fantasy', + 47, + ['The Lord of the Rings'], + { + published: 1954 + } + ], + metadata: { + genre: 'Fantasy', + rating: 47, + nestedArray: ['The Lord of the Rings'], + nestedMap: { + published: 1954 + } + } + }); + }); + + it('supports boolean value constants as a BooleanExpression', async () => { + const snapshots = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select( + conditional(constant(true), constant('TRUE'), constant('FALSE')).as( + 'true' + ), + conditional( + constant(false), + constant('TRUE'), + constant('FALSE') + ).as('false') + ) + ); + + expectResults(snapshots, { + 'true': 'TRUE', + 'false': 'FALSE' + }); + }); + }); + + describe('stages', () => { + describe('aggregate stage', () => { + it('supports aggregate', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate(countAll().as('count')) + ); + expectResults(snapshot, { count: 10 }); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('genre', 'Science Fiction')) + .aggregate( + countAll().as('count'), + average('rating').as('avgRating'), + maximum('rating').as('maxRating'), + sum('rating').as('sumRating') + ) + ); + expectResults(snapshot, { + count: 2, + avgRating: 4.4, + maxRating: 4.6, + sumRating: 8.8 + }); + }); + + it('supports aggregate options', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate({ + accumulators: [countAll().as('count')] + }) + ); + expectResults(snapshot, { count: 10 }); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('genre', 'Science Fiction')) + .aggregate( + countAll().as('count'), + average('rating').as('avgRating'), + maximum('rating').as('maxRating'), + sum('rating').as('sumRating') + ) + ); + expectResults(snapshot, { + count: 2, + avgRating: 4.4, + maxRating: 4.6, + sumRating: 8.8 + }); + }); + + it('rejects groups without accumulators', async () => { + await expect( + execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(lessThan('published', 1900)) + .aggregate({ + accumulators: [], + groups: ['genre'] + }) + ) + ).to.be.rejected; + }); + + it('returns group and accumulate results', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(lessThan(field('published'), 1984)) + .aggregate({ + accumulators: [average('rating').as('avgRating')], + groups: ['genre'] + }) + .where(greaterThan('avgRating', 4.3)) + .sort(field('avgRating').descending()) + ); + expectResults( + snapshot, + { avgRating: 4.7, genre: 'Fantasy' }, + { avgRating: 4.5, genre: 'Romance' }, + { avgRating: 4.4, genre: 'Science Fiction' } + ); + }); + + it('returns minimum, maximum, count, and countAll accumulations', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate( + count('cost').as('booksWithCost'), + countAll().as('count'), + maximum('rating').as('maxRating'), + minimum('published').as('minPublished') + ) + ); + expectResults(snapshot, { + booksWithCost: 1, + count: 10, + maxRating: 4.7, + minPublished: 1813 + }); + }); + + it('returns countif accumulation', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate(countIf(field('rating').greaterThan(4.3)).as('count')) + ); + const expectedResults = { + count: 3 + }; + expectResults(snapshot, expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate(field('rating').greaterThan(4.3).countIf().as('count')) + ); + expectResults(snapshot, expectedResults); + }); + + it('returns countDistinct accumulation', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate(countDistinct('genre').as('distinctGenres')) + ); + expectResults(snapshot, { distinctGenres: 8 }); + }); + }); + + describe('distinct stage', () => { + it('returns distinct values as expected', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .distinct('genre', 'author') + .sort(field('genre').ascending(), field('author').ascending()) + ); + expectResults( + snapshot, + { genre: 'Dystopian', author: 'George Orwell' }, + { genre: 'Dystopian', author: 'Margaret Atwood' }, + { genre: 'Fantasy', author: 'J.R.R. Tolkien' }, + { genre: 'Magical Realism', author: 'Gabriel García Márquez' }, + { genre: 'Modernist', author: 'F. Scott Fitzgerald' }, + { genre: 'Psychological Thriller', author: 'Fyodor Dostoevsky' }, + { genre: 'Romance', author: 'Jane Austen' }, + { genre: 'Science Fiction', author: 'Douglas Adams' }, + { genre: 'Science Fiction', author: 'Frank Herbert' }, + { genre: 'Southern Gothic', author: 'Harper Lee' } + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .distinct('genre', 'author') + .sort({ + orderings: [ + field('genre').ascending(), + field('author').ascending() + ] + }) + ); + expectResults( + snapshot, + { genre: 'Dystopian', author: 'George Orwell' }, + { genre: 'Dystopian', author: 'Margaret Atwood' }, + { genre: 'Fantasy', author: 'J.R.R. Tolkien' }, + { genre: 'Magical Realism', author: 'Gabriel García Márquez' }, + { genre: 'Modernist', author: 'F. Scott Fitzgerald' }, + { genre: 'Psychological Thriller', author: 'Fyodor Dostoevsky' }, + { genre: 'Romance', author: 'Jane Austen' }, + { genre: 'Science Fiction', author: 'Douglas Adams' }, + { genre: 'Science Fiction', author: 'Frank Herbert' }, + { genre: 'Southern Gothic', author: 'Harper Lee' } + ); + }); + }); + + describe('select stage', () => { + it('can select fields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .sort(field('author').ascending()) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams' + }, + { title: 'The Great Gatsby', author: 'F. Scott Fitzgerald' }, + { title: 'Dune', author: 'Frank Herbert' }, + { title: 'Crime and Punishment', author: 'Fyodor Dostoevsky' }, + { + title: 'One Hundred Years of Solitude', + author: 'Gabriel García Márquez' + }, + { title: '1984', author: 'George Orwell' }, + { title: 'To Kill a Mockingbird', author: 'Harper Lee' }, + { title: 'The Lord of the Rings', author: 'J.R.R. Tolkien' }, + { title: 'Pride and Prejudice', author: 'Jane Austen' }, + { title: "The Handmaid's Tale", author: 'Margaret Atwood' } + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select({ selections: ['title', field('author').as('auth0r')] }) + .sort(field('auth0r').ascending()) + .limit(2) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + auth0r: 'Douglas Adams' + }, + { title: 'The Great Gatsby', auth0r: 'F. Scott Fitzgerald' } + ); + }); + }); + + describe('addField stage', () => { + it('can add fields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .addFields(constant('bar').as('foo')) + .sort(field('author').ascending()) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + foo: 'bar' + }, + { + title: 'The Great Gatsby', + author: 'F. Scott Fitzgerald', + foo: 'bar' + }, + { title: 'Dune', author: 'Frank Herbert', foo: 'bar' }, + { + title: 'Crime and Punishment', + author: 'Fyodor Dostoevsky', + foo: 'bar' + }, + { + title: 'One Hundred Years of Solitude', + author: 'Gabriel García Márquez', + foo: 'bar' + }, + { title: '1984', author: 'George Orwell', foo: 'bar' }, + { + title: 'To Kill a Mockingbird', + author: 'Harper Lee', + foo: 'bar' + }, + { + title: 'The Lord of the Rings', + author: 'J.R.R. Tolkien', + foo: 'bar' + }, + { title: 'Pride and Prejudice', author: 'Jane Austen', foo: 'bar' }, + { + title: "The Handmaid's Tale", + author: 'Margaret Atwood', + foo: 'bar' + } + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .addFields({ + fields: [constant('bar').as('foo')] + }) + .sort(field('author').ascending()) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + foo: 'bar' + }, + { + title: 'The Great Gatsby', + author: 'F. Scott Fitzgerald', + foo: 'bar' + }, + { title: 'Dune', author: 'Frank Herbert', foo: 'bar' }, + { + title: 'Crime and Punishment', + author: 'Fyodor Dostoevsky', + foo: 'bar' + }, + { + title: 'One Hundred Years of Solitude', + author: 'Gabriel García Márquez', + foo: 'bar' + }, + { title: '1984', author: 'George Orwell', foo: 'bar' }, + { + title: 'To Kill a Mockingbird', + author: 'Harper Lee', + foo: 'bar' + }, + { + title: 'The Lord of the Rings', + author: 'J.R.R. Tolkien', + foo: 'bar' + }, + { title: 'Pride and Prejudice', author: 'Jane Austen', foo: 'bar' }, + { + title: "The Handmaid's Tale", + author: 'Margaret Atwood', + foo: 'bar' + } + ); + }); + }); + + describe('removeFields stage', () => { + it('can remove fields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .sort(field('author').ascending()) + .removeFields(field('author')) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy" + }, + { + title: 'The Great Gatsby' + }, + { title: 'Dune' }, + { + title: 'Crime and Punishment' + }, + { + title: 'One Hundred Years of Solitude' + }, + { title: '1984' }, + { + title: 'To Kill a Mockingbird' + }, + { + title: 'The Lord of the Rings' + }, + { title: 'Pride and Prejudice' }, + { + title: "The Handmaid's Tale" + } + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author', 'genre') + .sort(field('author').ascending()) + .removeFields({ + fields: [field('author'), 'genre'] + }) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy" + }, + { + title: 'The Great Gatsby' + }, + { title: 'Dune' }, + { + title: 'Crime and Punishment' + }, + { + title: 'One Hundred Years of Solitude' + }, + { title: '1984' }, + { + title: 'To Kill a Mockingbird' + }, + { + title: 'The Lord of the Rings' + }, + { title: 'Pride and Prejudice' }, + { + title: "The Handmaid's Tale" + } + ); + }); + }); + + describe('findNearest stage', () => { + it('can find nearest', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .sort(field('author').ascending()) + .removeFields(field('author')) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy" + }, + { + title: 'The Great Gatsby' + }, + { title: 'Dune' }, + { + title: 'Crime and Punishment' + }, + { + title: 'One Hundred Years of Solitude' + }, + { title: '1984' }, + { + title: 'To Kill a Mockingbird' + }, + { + title: 'The Lord of the Rings' + }, + { title: 'Pride and Prejudice' }, + { + title: "The Handmaid's Tale" + } + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author', 'genre') + .sort(field('author').ascending()) + .removeFields({ + fields: [field('author'), 'genre'] + }) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy" + }, + { + title: 'The Great Gatsby' + }, + { title: 'Dune' }, + { + title: 'Crime and Punishment' + }, + { + title: 'One Hundred Years of Solitude' + }, + { title: '1984' }, + { + title: 'To Kill a Mockingbird' + }, + { + title: 'The Lord of the Rings' + }, + { title: 'Pride and Prejudice' }, + { + title: "The Handmaid's Tale" + } + ); + }); + }); + + describe('where stage', () => { + it('where with and (2 conditions)', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + and( + greaterThan('rating', 4.5), + equalAny('genre', ['Science Fiction', 'Romance', 'Fantasy']) + ) + ) + ); + expectResults(snapshot, 'book10', 'book4'); + }); + + it('where with and (3 conditions)', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + and( + greaterThan('rating', 4.5), + equalAny('genre', ['Science Fiction', 'Romance', 'Fantasy']), + lessThan('published', 1965) + ) + ) + ); + expectResults(snapshot, 'book4'); + }); + + it('where with or', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + or( + equal('genre', 'Romance'), + equal('genre', 'Dystopian'), + equal('genre', 'Fantasy') + ) + ) + .sort(ascending('title')) + .select('title') + ); + expectResults( + snapshot, + { title: '1984' }, + { title: 'Pride and Prejudice' }, + { title: "The Handmaid's Tale" }, + { title: 'The Lord of the Rings' } + ); + }); + + it('where with xor', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + xor( + equal('genre', 'Romance'), + equal('genre', 'Dystopian'), + equal('genre', 'Fantasy'), + equal('published', 1949) + ) + ) + .select('title') + ); + expectResults( + snapshot, + { title: 'Pride and Prejudice' }, + { title: 'The Lord of the Rings' }, + { title: "The Handmaid's Tale" } + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where({ + condition: and( + greaterThan('rating', 4.5), + equalAny('genre', ['Science Fiction', 'Romance', 'Fantasy']) + ) + }) + ); + expectResults(snapshot, 'book10', 'book4'); + }); + }); + + describe('sort, offset, and limit stages', () => { + it('supports sort, offset, and limits', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('author').ascending()) + .offset(5) + .limit(3) + .select('title', 'author') + ); + expectResults( + snapshot, + { title: '1984', author: 'George Orwell' }, + { title: 'To Kill a Mockingbird', author: 'Harper Lee' }, + { title: 'The Lord of the Rings', author: 'J.R.R. Tolkien' } + ); + }); + + it('sort, offset, and limit stages support options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort({ + orderings: [field('author').ascending()] + }) + .offset({ offset: 5 }) + .limit({ limit: 3 }) + .select('title', 'author') + ); + expectResults( + snapshot, + { title: '1984', author: 'George Orwell' }, + { title: 'To Kill a Mockingbird', author: 'Harper Lee' }, + { title: 'The Lord of the Rings', author: 'J.R.R. Tolkien' } + ); + }); + }); + + describe('raw stage', () => { + it('can select fields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .rawStage('select', [ + { + title: field('title'), + metadata: { + author: field('author') + } + } + ]) + .sort(field('author').ascending()) + .limit(1) + ); + expectResults(snapshot, { + metadata: { + author: 'Frank Herbert' + }, + title: 'Dune' + }); + }); + + it('can add fields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('author').ascending()) + .limit(1) + .select('title', 'author') + .rawStage('add_fields', [ + { + display: stringConcat('title', ' - ', field('author')) + } + ]) + ); + expectResults(snapshot, { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + display: "The Hitchhiker's Guide to the Galaxy - Douglas Adams" + }); + }); + + it('can filter with where', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .rawStage('where', [field('author').equal('Douglas Adams')]) + ); + expectResults(snapshot, { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams' + }); + }); + + it('can limit, offset, and sort', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author') + .rawStage('sort', [ + { + direction: 'ascending', + expression: field('author') + } + ]) + .rawStage('offset', [3]) + .rawStage('limit', [1]) + ); + expectResults(snapshot, { + author: 'Fyodor Dostoevsky', + title: 'Crime and Punishment' + }); + }); + + it('can perform aggregate query', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author', 'rating') + .rawStage('aggregate', [ + { averageRating: field('rating').average() }, + {} + ]) + ); + expectResults(snapshot, { + averageRating: 4.3100000000000005 + }); + }); + + it('can perform distinct query', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'author', 'rating') + .rawStage('distinct', [{ rating: field('rating') }]) + .sort(field('rating').descending()) + ); + expectResults( + snapshot, + { + rating: 4.7 + }, + { + rating: 4.6 + }, + { + rating: 4.5 + }, + { + rating: 4.3 + }, + { + rating: 4.2 + }, + { + rating: 4.1 + }, + { + rating: 4.0 + } + ); + }); + + it('can perform FindNearest query', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .rawStage( + 'find_nearest', + [ + field('embedding'), + vector([10, 1, 2, 1, 1, 1, 1, 1, 1, 1]), + 'euclidean' + ], + { + 'distance_field': field('computedDistance'), + limit: 2 + } + ) + .select('title', 'computedDistance') + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + computedDistance: 1 + }, + { + title: 'One Hundred Years of Solitude', + computedDistance: 12.041594578792296 + } + ); + }); + }); + + describe('replaceWith stage', () => { + it('run pipeline with replaceWith field name', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .replaceWith('awards') + ); + expectResults(snapshot, { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }); + }); + + it('run pipeline with replaceWith Expr result', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .replaceWith( + map({ + foo: 'bar', + baz: { + title: field('title') + } + }) + ) + ); + expectResults(snapshot, { + foo: 'bar', + baz: { title: "The Hitchhiker's Guide to the Galaxy" } + }); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .replaceWith({ map: 'awards' }) + ); + expectResults(snapshot, { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }); + }); + }); + + describe('sample stage', () => { + it('run pipeline with sample limit of 3', async () => { + const snapshot = await execute( + firestore.pipeline().collection(randomCol.path).sample(3) + ); + expect(snapshot.results.length).to.equal(3); + }); + + it('run pipeline with sample limit of {documents: 3}', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sample({ documents: 3 }) + ); + expect(snapshot.results.length).to.equal(3); + }); + + it('run pipeline with sample limit of {percentage: 0.6}', async () => { + let avgSize = 0; + const numIterations = 30; + for (let i = 0; i < numIterations; i++) { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sample({ percentage: 0.6 }) + ); + + avgSize += snapshot.results.length; + } + avgSize /= numIterations; + expect(avgSize).to.be.closeTo(6, 1); + }); + }); + + describe('union stage', () => { + it('run pipeline with union', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .union(firestore.pipeline().collection(randomCol.path)) + .sort(field(documentIdFieldPath()).ascending()) + ); + expectResults( + snapshot, + 'book1', + 'book1', + 'book10', + 'book10', + 'book2', + 'book2', + 'book3', + 'book3', + 'book4', + 'book4', + 'book5', + 'book5', + 'book6', + 'book6', + 'book7', + 'book7', + 'book8', + 'book8', + 'book9', + 'book9' + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .union({ other: firestore.pipeline().collection(randomCol.path) }) + .sort(field(documentIdFieldPath()).ascending()) + ); + expectResults( + snapshot, + 'book1', + 'book1', + 'book10', + 'book10', + 'book2', + 'book2', + 'book3', + 'book3', + 'book4', + 'book4', + 'book5', + 'book5', + 'book6', + 'book6', + 'book7', + 'book7', + 'book8', + 'book8', + 'book9', + 'book9' + ); + }); + }); + + describe('unnest stage', () => { + it('run pipeline with unnest', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .unnest(field('tags').as('tag')) + .select( + 'title', + 'author', + 'genre', + 'published', + 'rating', + 'tags', + 'tag', + 'awards', + 'nestedField' + ) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'comedy', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } } + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'space', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } } + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'adventure', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } } + } + ); + }); + + it('unnest with index field', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .unnest(field('tags').as('tag'), 'tagsIndex') + .select( + 'title', + 'author', + 'genre', + 'published', + 'rating', + 'tags', + 'tag', + 'awards', + 'nestedField', + 'tagsIndex' + ) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'comedy', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + tagsIndex: 0 + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'space', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + tagsIndex: 1 + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'adventure', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + tagsIndex: 2 + } + ); + }); + + it('unnest an expr', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .unnest(array([1, 2, 3]).as('copy')) + .select( + 'title', + 'author', + 'genre', + 'published', + 'rating', + 'tags', + 'copy', + 'awards', + 'nestedField' + ) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + copy: 1, + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } } + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + copy: 2, + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } } + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + copy: 3, + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } } + } + ); + }); + + it('supports options', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + .unnest({ + selectable: field('tags').as('tag'), + indexField: 'tagsIndex' + }) + .select( + 'title', + 'author', + 'genre', + 'published', + 'rating', + 'tags', + 'tag', + 'awards', + 'nestedField', + 'tagsIndex' + ) + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'comedy', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + tagsIndex: 0 + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'space', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + tagsIndex: 1 + }, + { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + tag: 'adventure', + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + tagsIndex: 2 + } + ); + }); + }); + + describe('findNearest stage', () => { + it('run pipeline with findNearest', async () => { + const measures: Array = [ + 'euclidean', + 'dot_product', + 'cosine' + ]; + for (const measure of measures) { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .findNearest({ + field: 'embedding', + vectorValue: vector([10, 1, 3, 1, 2, 1, 1, 1, 1, 1]), + limit: 3, + distanceMeasure: measure + }) + .select('title') + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy" + }, + { + title: 'One Hundred Years of Solitude' + }, + { + title: "The Handmaid's Tale" + } + ); + } + }); + + it('optionally returns the computed distance', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .findNearest({ + field: 'embedding', + vectorValue: vector([10, 1, 2, 1, 1, 1, 1, 1, 1, 1]), + limit: 2, + distanceMeasure: 'euclidean', + distanceField: 'computedDistance' + }) + .select('title', 'computedDistance') + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + computedDistance: 1 + }, + { + title: 'One Hundred Years of Solitude', + computedDistance: 12.041594578792296 + } + ); + }); + }); + }); + + describe('error handling', () => { + it('error properties are propagated from the firestore backend', async () => { + try { + const myPipeline = firestore + .pipeline() + .collection(randomCol.path) + .rawStage('select', [ + // incorrect parameter type + field('title') + ]); + + await execute(myPipeline); + + expect.fail('expected pipeline.execute() to throw'); + } catch (e: unknown) { + expect(e instanceof FirebaseError).to.be.true; + const err = e as FirebaseError; + // Backend returns the code as `failed-precondition` when using the REST transport + expect(err['code']).to.equal('failed-precondition'); + expect(typeof err['message']).to.equal('string'); + + expect(err['message']).to.match( + /Request failed with error: Expected value type of MAP_VALUE when parsing 'fields' but received FIELD_REFERENCE_VALUE instead/ + ); + } + }); + }); + + describe('function expressions', () => { + it('logical max works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select( + 'title', + logicalMaximum(constant(1960), field('published'), 1961).as( + 'published-safe' + ) + ) + .sort(field('title').ascending()) + .limit(3) + ); + expectResults( + snapshot, + { title: '1984', 'published-safe': 1961 }, + { title: 'Crime and Punishment', 'published-safe': 1961 }, + { title: 'Dune', 'published-safe': 1965 } + ); + }); + + it('logical min works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select( + 'title', + logicalMinimum(constant(1960), field('published'), 1961).as( + 'published-safe' + ) + ) + .sort(field('title').ascending()) + .limit(3) + ); + expectResults( + snapshot, + { title: '1984', 'published-safe': 1949 }, + { title: 'Crime and Punishment', 'published-safe': 1866 }, + { title: 'Dune', 'published-safe': 1960 } + ); + }); + + it('conditional works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select( + 'title', + conditional( + lessThan(field('published'), 1960), + constant(1960), + field('published') + ).as('published-safe'), + field('rating') + .greaterThanOrEqual(4.5) + .conditional(constant('great'), constant('good')) + .as('rating') + ) + .sort(field('title').ascending()) + .limit(3) + ); + expectResults( + snapshot, + { title: '1984', 'published-safe': 1960, rating: 'good' }, + { + title: 'Crime and Punishment', + 'published-safe': 1960, + rating: 'good' + }, + { title: 'Dune', 'published-safe': 1965, rating: 'great' } + ); + }); + + it('equalAny works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equalAny('published', [1979, 1999, 1967])) + .sort(descending('title')) + .select('title') + ); + expectResults( + snapshot, + { title: "The Hitchhiker's Guide to the Galaxy" }, + { title: 'One Hundred Years of Solitude' } + ); + }); + + it('notEqualAny works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + notEqualAny( + 'published', + [1965, 1925, 1949, 1960, 1866, 1985, 1954, 1967, 1979] + ) + ) + .select('title') + ); + expectResults(snapshot, { title: 'Pride and Prejudice' }); + }); + + it('arrayContains works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(arrayContains('tags', 'comedy')) + .select('title') + ); + expectResults(snapshot, { + title: "The Hitchhiker's Guide to the Galaxy" + }); + }); + + it('arrayContainsAny works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(arrayContainsAny('tags', ['comedy', 'classic'])) + .sort(descending('title')) + .select('title') + ); + expectResults( + snapshot, + { title: "The Hitchhiker's Guide to the Galaxy" }, + { title: 'Pride and Prejudice' } + ); + }); + + it('arrayContainsAll works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(arrayContainsAll('tags', ['adventure', 'magic'])) + .select('title') + ); + expectResults(snapshot, { title: 'The Lord of the Rings' }); + }); + + it('arrayLength works', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(arrayLength('tags').as('tagsCount')) + .where(equal('tagsCount', 3)) + ); + expect(snapshot.results.length).to.equal(10); + }); + + it('testStrConcat', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(ascending('author')) + .select( + field('author').stringConcat(' - ', field('title')).as('bookInfo') + ) + .limit(1) + ); + expectResults(snapshot, { + bookInfo: "Douglas Adams - The Hitchhiker's Guide to the Galaxy" + }); + }); + + it('testStartsWith', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(startsWith('title', 'The')) + .select('title') + .sort(field('title').ascending()) + ); + expectResults( + snapshot, + { title: 'The Great Gatsby' }, + { title: "The Handmaid's Tale" }, + { title: "The Hitchhiker's Guide to the Galaxy" }, + { title: 'The Lord of the Rings' } + ); + }); + + it('testEndsWith', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(endsWith('title', 'y')) + .select('title') + .sort(field('title').descending()) + ); + expectResults( + snapshot, + { title: "The Hitchhiker's Guide to the Galaxy" }, + { title: 'The Great Gatsby' } + ); + }); + + it('testStrContains', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(stringContains('title', "'s")) + .select('title') + .sort(field('title').ascending()) + ); + expectResults( + snapshot, + { title: "The Handmaid's Tale" }, + { title: "The Hitchhiker's Guide to the Galaxy" } + ); + }); + + it('testLength', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(charLength('title').as('titleLength'), field('title')) + .where(greaterThan('titleLength', 20)) + .sort(field('title').ascending()) + ); + + expectResults( + snapshot, + + { + titleLength: 29, + title: 'One Hundred Years of Solitude' + }, + { + titleLength: 36, + title: "The Hitchhiker's Guide to the Galaxy" + }, + { + titleLength: 21, + title: 'The Lord of the Rings' + }, + { + titleLength: 21, + title: 'To Kill a Mockingbird' + } + ); + }); + + it('testLike', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(like('title', '%Guide%')) + .select('title') + ); + expectResults(snapshot, { + title: "The Hitchhiker's Guide to the Galaxy" + }); + }); + + it('testRegexContains', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(regexContains('title', '(?i)(the|of)')) + ); + expect(snapshot.results.length).to.equal(5); + }); + + it('testRegexMatches', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(regexMatch('title', '.*(?i)(the|of).*')) + ); + expect(snapshot.results.length).to.equal(5); + }); + + it('testArithmeticOperations', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', 'To Kill a Mockingbird')) + .select( + add(field('rating'), 1).as('ratingPlusOne'), + subtract(field('published'), 1900).as('yearsSince1900'), + field('rating').multiply(10).as('ratingTimesTen'), + divide('rating', 2).as('ratingDividedByTwo'), + multiply('rating', 20).as('ratingTimes20'), + add('rating', 3).as('ratingPlus3'), + mod('rating', 2).as('ratingMod2') + ) + .limit(1) + ); + expectResults(snapshot, { + ratingPlusOne: 5.2, + yearsSince1900: 60, + ratingTimesTen: 42, + ratingDividedByTwo: 2.1, + ratingTimes20: 84, + ratingPlus3: 7.2, + ratingMod2: 0.20000000000000018 + }); + }); + + it('testComparisonOperators', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + and( + greaterThan('rating', 4.2), + lessThanOrEqual(field('rating'), 4.5), + notEqual('genre', 'Science Fiction') + ) + ) + .select('rating', 'title') + .sort(field('title').ascending()) + ); + expectResults( + snapshot, + { rating: 4.3, title: 'Crime and Punishment' }, + { + rating: 4.3, + title: 'One Hundred Years of Solitude' + }, + { rating: 4.5, title: 'Pride and Prejudice' } + ); + }); + + it('testLogicalOperators', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + or( + and( + greaterThan('rating', 4.5), + equal('genre', 'Science Fiction') + ), + lessThan('published', 1900) + ) + ) + .select('title') + .sort(field('title').ascending()) + ); + expectResults( + snapshot, + { title: 'Crime and Punishment' }, + { title: 'Dune' }, + { title: 'Pride and Prejudice' } + ); + }); + + it('testChecks', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + equal('rating', null).as('ratingIsNull'), + equal('rating', NaN).as('ratingIsNaN'), + isError(divide(constant(1), constant(0))).as('isError'), + ifError(divide(constant(1), constant(0)), constant('was error')).as( + 'ifError' + ), + ifError( + divide(constant(1), constant(0)).greaterThan(1), + constant(true) + ) + .not() + .as('ifErrorBooleanExpression'), + isAbsent('foo').as('isAbsent'), + notEqual('title', null).as('titleIsNotNull'), + notEqual('cost', NaN).as('costIsNotNan'), + exists('fooBarBaz').as('fooBarBazExists'), + field('title').exists().as('titleExists') + ) + ); + expectResults(snapshot, { + ratingIsNull: false, + ratingIsNaN: false, + isError: true, + ifError: 'was error', + ifErrorBooleanExpression: false, + isAbsent: true, + titleIsNotNull: true, + costIsNotNan: false, + fooBarBazExists: false, + titleExists: true + }); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + field('rating').equal(null).as('ratingIsNull'), + field('rating').equal(NaN).as('ratingIsNaN'), + divide(constant(1), constant(0)).isError().as('isError'), + divide(constant(1), constant(0)) + .ifError(constant('was error')) + .as('ifError'), + divide(constant(1), constant(0)) + .greaterThan(1) + .ifError(constant(true)) + .not() + .as('ifErrorBooleanExpression'), + field('foo').isAbsent().as('isAbsent'), + field('title').notEqual(null).as('titleIsNotNull'), + field('cost').notEqual(NaN).as('costIsNotNan') + ) + ); + expectResults(snapshot, { + ratingIsNull: false, + ratingIsNaN: false, + isError: true, + ifError: 'was error', + ifErrorBooleanExpression: false, + isAbsent: true, + titleIsNotNull: true, + costIsNotNan: false + }); + }); + + it('testMapGet', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('published').descending()) + .select( + field('awards').mapGet('hugo').as('hugoAward'), + field('awards').mapGet('others').as('others'), + field('title') + ) + .where(equal('hugoAward', true)) + ); + expectResults( + snapshot, + { + hugoAward: true, + title: "The Hitchhiker's Guide to the Galaxy", + others: { unknown: { year: 1980 } } + }, + { hugoAward: true, title: 'Dune' } + ); + }); + + it('testDistanceFunctions', async () => { + const sourceVector = vector([0.1, 0.1]); + const targetVector = vector([0.5, 0.8]); + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select( + cosineDistance(constant(sourceVector), targetVector).as( + 'cosineDistance' + ), + dotProduct(constant(sourceVector), targetVector).as( + 'dotProductDistance' + ), + euclideanDistance(constant(sourceVector), targetVector).as( + 'euclideanDistance' + ) + ) + .limit(1) + ); + + expectResults(snapshot, { + cosineDistance: 0.02560880430538015, + dotProductDistance: 0.13, + euclideanDistance: 0.806225774829855 + }); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select( + constant(sourceVector) + .cosineDistance(targetVector) + .as('cosineDistance'), + constant(sourceVector) + .dotProduct(targetVector) + .as('dotProductDistance'), + constant(sourceVector) + .euclideanDistance(targetVector) + .as('euclideanDistance') + ) + .limit(1) + ); + + expectResults(snapshot, { + cosineDistance: 0.02560880430538015, + dotProductDistance: 0.13, + euclideanDistance: 0.806225774829855 + }); + }); + + it('testVectorLength', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(vectorLength(constant(vector([1, 2, 3]))).as('vectorLength')) + ); + expectResults(snapshot, { + vectorLength: 3 + }); + }); + + it('testNestedFields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('awards.hugo', true)) + .sort(descending('title')) + .select('title', 'awards.hugo') + ); + expectResults( + snapshot, + { + title: "The Hitchhiker's Guide to the Galaxy", + 'awards.hugo': true + }, + { title: 'Dune', 'awards.hugo': true } + ); + }); + + it('test mapGet with field name including . notation', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + title: 'foo', + nested: { + level: { + '1': 'bar' + }, + 'level.1': { + 'level.2': 'baz' + } + } + }) + ) + .select( + 'title', + field('nested.level.1'), + mapGet('nested', 'level.1').mapGet('level.2').as('nested') + ) + ); + expectResults(snapshot, { + title: 'foo', + 'nested.level.`1`': 'bar', + nested: 'baz' + }); + }); + + describe('rawFunction', () => { + it('add selectable', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(descending('rating')) + .limit(1) + .select( + new FunctionExpression('add', [field('rating'), constant(1)]).as( + 'rating' + ) + ) + ); + expectResults(snapshot, { + rating: 5.7 + }); + }); + + it('and (variadic) selectable', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + new FunctionExpression('and', [ + field('rating').greaterThan(0), + field('title').charLength().lessThan(5), + field('tags').arrayContains('propaganda') + ]).asBoolean() + ) + .select('title') + ); + expectResults(snapshot, { + title: '1984' + }); + }); + + it('array contains any', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + new FunctionExpression('array_contains_any', [ + field('tags'), + array(['politics']) + ]).asBoolean() + ) + .select('title') + ); + expectResults(snapshot, { + title: 'Dune' + }); + }); + + it('countif aggregate', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate( + new AggregateFunction('count_if', [ + field('rating').greaterThanOrEqual(4.5) + ]).as('countOfBest') + ) + ); + expectResults(snapshot, { + countOfBest: 3 + }); + }); + + it('sort by char_len', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort( + new FunctionExpression('char_length', [ + field('title') + ]).ascending(), + descending('__name__') + ) + .limit(3) + .select('title') + ); + expectResults( + snapshot, + { + title: '1984' + }, + { + title: 'Dune' + }, + { + title: 'The Great Gatsby' + } + ); + }); + }); + + it('supports array', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(array([1, 2, 3, 4]).as('metadata')) + ); + expect(snapshot.results.length).to.equal(1); + expectResults(snapshot, { + metadata: [1, 2, 3, 4] + }); + }); + + it('evaluates expression in array', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + array([1, 2, field('genre'), multiply('rating', 10)]).as('metadata') + ) + ); + expect(snapshot.results.length).to.equal(1); + expectResults(snapshot, { + metadata: [1, 2, 'Fantasy', 47] + }); + }); + + it('supports arrayGet', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayGet('tags', 0).as('firstTag')) + ); + const expectedResults = [ + { + firstTag: 'adventure' + }, + { + firstTag: 'politics' + }, + { + firstTag: 'classic' + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayGet(0).as('firstTag')) + ); + expectResults(snapshot, ...expectedResults); + }); + + it('supports map', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + map({ + foo: 'bar' + }).as('metadata') + ) + ); + + expect(snapshot.results.length).to.equal(1); + expectResults(snapshot, { + metadata: { + foo: 'bar' + } + }); + }); + + it('evaluates expression in map', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + map({ + genre: field('genre'), + rating: field('rating').multiply(10) + }).as('metadata') + ) + ); + + expect(snapshot.results.length).to.equal(1); + expectResults(snapshot, { + metadata: { + genre: 'Fantasy', + rating: 47 + } + }); + }); + + it('supports mapRemove', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(mapRemove('awards', 'hugo').as('awards')) + ); + expectResults(snapshot, { + awards: { nebula: false } + }); + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('awards').mapRemove('hugo').as('awards')) + ); + expectResults(snapshot, { + awards: { nebula: false } + }); + }); + + it('supports mapMerge', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(mapMerge('awards', { fakeAward: true }).as('awards')) + ); + expectResults(snapshot, { + awards: { nebula: false, hugo: false, fakeAward: true } + }); + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('awards').mapMerge({ fakeAward: true }).as('awards')) + ); + expectResults(snapshot, { + awards: { nebula: false, hugo: false, fakeAward: true } + }); + }); + + it('supports timestamp conversions', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select( + unixSecondsToTimestamp(constant(1741380235)).as( + 'unixSecondsToTimestamp' + ), + unixMillisToTimestamp(constant(1741380235123)).as( + 'unixMillisToTimestamp' + ), + unixMicrosToTimestamp(constant(1741380235123456)).as( + 'unixMicrosToTimestamp' + ), + timestampToUnixSeconds( + constant(new Timestamp(1741380235, 123456789)) + ).as('timestampToUnixSeconds'), + timestampToUnixMicros( + constant(new Timestamp(1741380235, 123456789)) + ).as('timestampToUnixMicros'), + timestampToUnixMillis( + constant(new Timestamp(1741380235, 123456789)) + ).as('timestampToUnixMillis') + ) + ); + expectResults(snapshot, { + unixMicrosToTimestamp: new Timestamp(1741380235, 123456000), + unixMillisToTimestamp: new Timestamp(1741380235, 123000000), + unixSecondsToTimestamp: new Timestamp(1741380235, 0), + timestampToUnixSeconds: 1741380235, + timestampToUnixMicros: 1741380235123456, + timestampToUnixMillis: 1741380235123 + }); + }); + + it('supports timestamp math', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(constant(new Timestamp(1741380235, 0)).as('timestamp')) + .select( + timestampAdd('timestamp', 'day', 10).as('plus10days'), + timestampAdd('timestamp', 'hour', 10).as('plus10hours'), + timestampAdd('timestamp', 'minute', 10).as('plus10minutes'), + timestampAdd('timestamp', 'second', 10).as('plus10seconds'), + timestampAdd('timestamp', 'microsecond', 10).as('plus10micros'), + timestampAdd('timestamp', 'millisecond', 10).as('plus10millis'), + timestampSubtract('timestamp', 'day', 10).as('minus10days'), + timestampSubtract('timestamp', 'hour', 10).as('minus10hours'), + timestampSubtract('timestamp', 'minute', 10).as('minus10minutes'), + timestampSubtract('timestamp', 'second', 10).as('minus10seconds'), + timestampSubtract('timestamp', 'microsecond', 10).as( + 'minus10micros' + ), + timestampSubtract('timestamp', 'millisecond', 10).as( + 'minus10millis' + ) + ) + ); + expectResults(snapshot, { + plus10days: new Timestamp(1742244235, 0), + plus10hours: new Timestamp(1741416235, 0), + plus10minutes: new Timestamp(1741380835, 0), + plus10seconds: new Timestamp(1741380245, 0), + plus10micros: new Timestamp(1741380235, 10000), + plus10millis: new Timestamp(1741380235, 10000000), + minus10days: new Timestamp(1740516235, 0), + minus10hours: new Timestamp(1741344235, 0), + minus10minutes: new Timestamp(1741379635, 0), + minus10seconds: new Timestamp(1741380225, 0), + minus10micros: new Timestamp(1741380234, 999990000), + minus10millis: new Timestamp(1741380234, 990000000) + }); + }).timeout(10000); + + it('supports byteLength', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .select( + constant( + Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0])) + ).as('bytes') + ) + .select(byteLength('bytes').as('byteLength')) + ); + + expectResults(snapshot, { + byteLength: 8 + }); + }); + + it('supports not', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .select(constant(true).as('trueField')) + .select('trueField', not(equal('trueField', true)).as('falseField')) + ); + + expectResults(snapshot, { + trueField: true, + falseField: false + }); + }); + + it('can reverse an array', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('tags').arrayReverse().as('reversedTags')) + ); + expectResults(snapshot, { + reversedTags: ['adventure', 'space', 'comedy'] + }); + }); + + it('can reverse an array with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(reverse('tags').as('reversedTags')) + ); + expectResults(snapshot, { + reversedTags: ['adventure', 'space', 'comedy'] + }); + }); + + it('can compute the ceiling of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').ceil().as('ceilingRating')) + ); + expectResults(snapshot, { + ceilingRating: 5 + }); + }); + + it('can compute the ceiling of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(ceil('rating').as('ceilingRating')) + ); + expectResults(snapshot, { + ceilingRating: 5 + }); + }); + + it('can compute the floor of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').floor().as('floorRating')) + ); + expectResults(snapshot, { + floorRating: 4 + }); + }); + + it('can compute the floor of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(floor('rating').as('floorRating')) + ); + expectResults(snapshot, { + floorRating: 4 + }); + }); + + it('can compute e to the power of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('The Lord of the Rings')) + .limit(1) + .select(field('rating').exp().as('expRating')) + ); + expect(snapshot.results[0].get('expRating')).to.be.approximately( + 109.94717245212352, + 0.00001 + ); + }); + + it('can compute e to the power of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('The Lord of the Rings')) + .limit(1) + .select(exp('rating').as('expRating')) + ); + expect(snapshot.results[0].get('expRating')).to.be.approximately( + 109.94717245212351, + 0.000001 + ); + }); + + it('can compute the power of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').pow(2).as('powerRating')) + ); + expect(snapshot.results[0].get('powerRating')).to.be.approximately( + 17.64, + 0.0001 + ); + }); + + it('can compute the power of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(pow('rating', 2).as('powerRating')) + ); + expect(snapshot.results[0].get('powerRating')).to.be.approximately( + 17.64, + 0.0001 + ); + }); + + it('can round a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').round().as('roundedRating')) + ); + expectResults(snapshot, { + roundedRating: 4 + }); + }); + + it('can round a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(round('rating').as('roundedRating')) + ); + expectResults(snapshot, { + roundedRating: 4 + }); + }); + + it('can round a numeric value away from zero for positive half-way values', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .addFields(constant(1.5).as('positiveHalf')) + .select(field('positiveHalf').round().as('roundedRating')) + ); + expectResults(snapshot, { + roundedRating: 2 + }); + }); + + it('can round a numeric value away from zero for negative half-way values', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .addFields(constant(-1.5).as('negativeHalf')) + .select(field('negativeHalf').round().as('roundedRating')) + ); + expectResults(snapshot, { + roundedRating: -2 + }); + }); + + it('can round a numeric value to specified precision', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + foo: 4.123456 + }) + ) + .select( + field('foo').round(0).as('0'), + round('foo', 1).as('1'), + round('foo', constant(2)).as('2'), + round(field('foo'), 4).as('4') + ) + ); + expectResults(snapshot, { + '0': 4, + '1': 4.1, + '2': 4.12, + '4': 4.1235 + }); + }); + + it('can get the collectionId from a path', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(field('__name__').collectionId().as('collectionId')) + ); + expectResults(snapshot, { + collectionId: randomCol.id + }); + }); + + it('can get the collectionId from a path with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(collectionId('__name__').as('collectionId')) + ); + expectResults(snapshot, { + collectionId: randomCol.id + }); + }); + + it('can compute the length of a string value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('title').length().as('titleLength')) + ); + expectResults(snapshot, { + titleLength: 36 + }); + }); + + it('can compute the length of a string value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(length('title').as('titleLength')) + ); + expectResults(snapshot, { + titleLength: 36 + }); + }); + + it('can compute the length of an array value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('tags').length().as('tagsLength')) + ); + expectResults(snapshot, { + tagsLength: 3 + }); + }); + + it('can compute the length of an array value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(length('tags').as('tagsLength')) + ); + expectResults(snapshot, { + tagsLength: 3 + }); + }); + + it('can compute the length of a map value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('awards').length().as('awardsLength')) + ); + expectResults(snapshot, { + awardsLength: 3 + }); + }); + + it('can compute the length of a vector value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('embedding').length().as('embeddingLength')) + ); + expectResults(snapshot, { + embeddingLength: 10 + }); + }); + + it('can compute the length of a bytes value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(constant('12é').as('value')) + .limit(1) + .select(field('value').byteLength().as('valueLength')) + ); + expectResults(snapshot, { + valueLength: 4 + }); + }); + + it('can compute the natural logarithm of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').ln().as('lnRating')) + ); + expect(snapshot.results[0]!.data().lnRating).to.be.closeTo(1.435, 0.001); + }); + + it('can compute the natural logarithm of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(ln('rating').as('lnRating')) + ); + expect(snapshot.results[0]!.data().lnRating).to.be.closeTo(1.435, 0.001); + }); + + it('can compute the natural logarithm of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(ln('rating').as('lnRating')) + ); + expectResults(snapshot, { + lnRating: 1.4350845252893227 + }); + }); + + it('can compute the logarithm of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(log(field('rating'), 10).as('logRating')) + ); + expectResults(snapshot, { + logRating: 0.6232492903979004 + }); + }); + + it('can compute the logarithm of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(log('rating', 10).as('logRating')) + ); + expectResults(snapshot, { + logRating: 0.6232492903979004 + }); + }); + + it('can round a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').round().as('roundedRating')) + ); + expectResults(snapshot, { + roundedRating: 4 + }); + }); + + it('can round a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(round('rating').as('roundedRating')) + ); + expectResults(snapshot, { + roundedRating: 4 + }); + }); + + it('can compute the square root of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('rating').sqrt().as('sqrtRating')) + ); + expectResults(snapshot, { + sqrtRating: 2.04939015319192 + }); + }); + + it('can compute the square root of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(sqrt('rating').as('sqrtRating')) + ); + expectResults(snapshot, { + sqrtRating: 2.04939015319192 + }); + }); + + it('can reverse a string', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(field('title').reverse().as('reversedTitle')) + ); + expectResults(snapshot, { + reversedTitle: "yxalaG eht ot ediuG s'rekihhctiH ehT" + }); + }); + + it('can reverse a string with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal("The Hitchhiker's Guide to the Galaxy")) + .limit(1) + .select(stringReverse('title').as('reversedTitle')) + ); + expectResults(snapshot, { + reversedTitle: "yxalaG eht ot ediuG s'rekihhctiH ehT" + }); + }); + + it('supports Document_id', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + documentId(field('__name__')).as('docId'), + documentId(field('__path__')).as('noDocId') + ) + ); + expectResults(snapshot, { + docId: 'book4', + noDocId: null + }); + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('__name__').documentId().as('docId')) + ); + expectResults(snapshot, { + docId: 'book4' + }); + }); + + it('supports substring', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(substring('title', 9, 2).as('of')) + ); + expectResults(snapshot, { + of: 'of' + }); + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('title').substring(9, 2).as('of')) + ); + expectResults(snapshot, { + of: 'of' + }); + }); + + it('supports substring without length', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(substring('title', 9).as('of')) + ); + expectResults(snapshot, { + of: 'of the Rings' + }); + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('title').substring(9).as('of')) + ); + expectResults(snapshot, { + of: 'of the Rings' + }); + }); + + it('test toLower', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(ascending('title')) + .select(toLower('author').as('lowercaseAuthor')) + .limit(1) + ); + expectResults(snapshot, { + lowercaseAuthor: 'george orwell' + }); + }); + + it('test toUpper', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(ascending('title')) + .select(toUpper('author').as('uppercaseAuthor')) + .limit(1) + ); + expectResults(snapshot, { uppercaseAuthor: 'GEORGE ORWELL' }); + }); + + it('testTrim', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .addFields( + constant(" The Hitchhiker's Guide to the Galaxy ").as('spacedTitle') + ) + .select(trim('spacedTitle').as('trimmedTitle'), field('spacedTitle')) + .limit(1) + ); + expectResults(snapshot, { + spacedTitle: " The Hitchhiker's Guide to the Galaxy ", + trimmedTitle: "The Hitchhiker's Guide to the Galaxy" + }); + }); + + it('test reverse', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .limit(1) + .select(reverse('title').as('reverseTitle')) + ); + expectResults(snapshot, { reverseTitle: '4891' }); + }); + + it('testAbs', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select( + constant(-10).as('neg10'), + constant(-22.22).as('neg22'), + constant(1).as('pos1') + ) + .select( + abs('neg10').as('10'), + abs(field('neg22')).as('22'), + field('pos1').as('1') + ) + ); + expectResults(snapshot, { + '10': 10, + '22': 22.22, + '1': 1 + }); + }); + + it('can compute the base-10 logarithm of a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('The Lord of the Rings')) + .limit(1) + .select(field('rating').log10().as('log10Rating')) + ); + expect(snapshot.results[0]!.data().log10Rating).to.be.closeTo( + 0.672, + 0.001 + ); + }); + + it('can compute the base-10 logarithm of a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('The Lord of the Rings')) + .limit(1) + .select(log10('rating').as('log10Rating')) + ); + expect(snapshot.results[0]!.data().log10Rating).to.be.closeTo( + 0.672, + 0.001 + ); + }); + + it('can concat fields', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .addFields( + concat('author', ' ', field('title')).as('display'), + field('author').concat(': ', field('title')).as('display2') + ) + .where(equal('author', 'Douglas Adams')) + .select('display', 'display2') + ); + expectResults(snapshot, { + display: "Douglas Adams The Hitchhiker's Guide to the Galaxy", + display2: "Douglas Adams: The Hitchhiker's Guide to the Galaxy" + }); + }); + + it('supports currentTimestamp', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .addFields(currentTimestamp().as('now')) + .select('now') + ); + const now = snapshot.results[0].get('now') as Timestamp; + expect(now).instanceof(Timestamp); + expect( + now.toDate().getUTCSeconds() - new Date().getUTCSeconds() + ).lessThan(5000); + }); + + it('supports ifAbsent', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + title: 'foo' + }) + ) + .select( + ifAbsent('title', 'default title').as('title'), + field('name').ifAbsent('default name').as('name'), + field('name').ifAbsent(field('title')).as('nameOrTitle') + ) + ); + + expectResults(snapshot, { + title: 'foo', + name: 'default name', + nameOrTitle: 'foo' + }); + }); + + it('supports join', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + tags: ['foo', 'bar', 'baz'], + delimeter: '|' + }) + ) + .select(join('tags', ',').as('csv'), field('tags').join('|').as('or')) + ); + + expectResults(snapshot, { + csv: 'foo,bar,baz', + or: 'foo|bar|baz' + }); + }); + + it('can compute the sum of the elements in an array', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('The Lord of the Rings')) + .limit(1) + .addFields(array([150, 200]).as('sales')) + .select(field('sales').arraySum().as('totalSales')) + ); + expectResults(snapshot, { + totalSales: 350 + }); + }); + + it('can compute the sum of the elements in an array with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('The Lord of the Rings')) + .limit(1) + .addFields(array([150, 200]).as('sales')) + .select(arraySum('sales').as('totalSales')) + ); + expectResults(snapshot, { + totalSales: 350 + }); + }); + + // TODO(new-expression): Add new expression tests above this line + }); + + describe('pagination', () => { + let addedDocs: DocumentReference[] = []; + + /** + * Adds several books to the test collection. These + * additional books support pagination test scenarios + * that would otherwise not be possible with the original + * set of books. + * @param collectionReference + */ + async function addBooks( + collectionReference: CollectionReference + ): Promise { + let docRef = doc(collectionReference, 'book11'); + addedDocs.push(docRef); + await setDoc(docRef, { + title: 'Jonathan Strange & Mr Norrell', + author: 'Susanna Clarke', + genre: 'Fantasy', + published: 2004, + rating: 4.6, + tags: ['historical fantasy', 'magic', 'alternate history', 'england'], + awards: { hugo: false, nebula: false } + }); + docRef = doc(collectionReference, 'book12'); + addedDocs.push(docRef); + await setDoc(docRef, { + title: 'The Master and Margarita', + author: 'Mikhail Bulgakov', + genre: 'Satire', + published: 1967, // Though written much earlier + rating: 4.6, + tags: [ + 'russian literature', + 'supernatural', + 'philosophy', + 'dark comedy' + ], + awards: {} + }); + docRef = doc(collectionReference, 'book13'); + addedDocs.push(docRef); + await setDoc(docRef, { + title: 'A Long Way to a Small, Angry Planet', + author: 'Becky Chambers', + genre: 'Science Fiction', + published: 2014, + rating: 4.6, + tags: ['space opera', 'found family', 'character-driven', 'optimistic'], + awards: { hugo: false, nebula: false, kitschies: true } + }); + } + + afterEach(async () => { + for (let i = 0; i < addedDocs.length; i++) { + await deleteDoc(addedDocs[i]); + } + addedDocs = []; + }); + + it('supports pagination with filters', async () => { + await addBooks(randomCol); + const pageSize = 2; + const pipeline = firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'rating', '__name__') + .sort(field('rating').descending(), field('__name__').ascending()); + + let snapshot = await execute(pipeline.limit(pageSize)); + expectResults( + snapshot, + { title: 'The Lord of the Rings', rating: 4.7 }, + { title: 'Dune', rating: 4.6 } + ); + + const lastDoc = snapshot.results[snapshot.results.length - 1]; + + snapshot = await execute( + pipeline + .where( + or( + and( + field('rating').equal(lastDoc.get('rating')), + field('__name__').greaterThan(lastDoc.ref) + ), + field('rating').lessThan(lastDoc.get('rating')) + ) + ) + .limit(pageSize) + ); + expectResults( + snapshot, + { title: 'Jonathan Strange & Mr Norrell', rating: 4.6 }, + { title: 'The Master and Margarita', rating: 4.6 } + ); + }); + + it('supports pagination with offsets', async () => { + await addBooks(randomCol); + + const secondFilterField = '__name__'; + + const pipeline = firestore + .pipeline() + .collection(randomCol.path) + .select('title', 'rating', secondFilterField) + .sort( + field('rating').descending(), + field(secondFilterField).ascending() + ); + + const pageSize = 2; + let currPage = 0; + + let snapshot = await execute( + pipeline.offset(currPage++ * pageSize).limit(pageSize) + ); + + expectResults( + snapshot, + { + title: 'The Lord of the Rings', + rating: 4.7 + }, + { title: 'Dune', rating: 4.6 } + ); + + snapshot = await execute( + pipeline.offset(currPage++ * pageSize).limit(pageSize) + ); + expectResults( + snapshot, + { + title: 'Jonathan Strange & Mr Norrell', + rating: 4.6 + }, + { title: 'The Master and Margarita', rating: 4.6 } + ); + + snapshot = await execute( + pipeline.offset(currPage++ * pageSize).limit(pageSize) + ); + expectResults( + snapshot, + { + title: 'A Long Way to a Small, Angry Planet', + rating: 4.6 + }, + { + title: 'Pride and Prejudice', + rating: 4.5 + } + ); + }); + }); + + describe('stage options', () => { + describe('forceIndex', () => { + // SKIP: requires pre-existing index + // eslint-disable-next-line no-restricted-properties + it.skip('Collection Stage', async () => { + const snapshot = await execute( + firestore.pipeline().collection({ + collection: randomCol, + forceIndex: 'unknown' + }) + ); + expect(snapshot.results.length).to.equal(10); + }); + + // SKIP: requires pre-existing index + // eslint-disable-next-line no-restricted-properties + it.skip('CollectionGroup Stage', async () => { + const snapshot = await execute( + firestore.pipeline().collectionGroup({ + collectionId: randomCol.id, + forceIndex: 'unknown' + }) + ); + expect(snapshot.results.length).to.equal(10); + }); + }); + }); +}); diff --git a/packages/firestore/test/lite/pipeline_export.ts b/packages/firestore/test/lite/pipeline_export.ts new file mode 100644 index 0000000000..d5f60db9d3 --- /dev/null +++ b/packages/firestore/test/lite/pipeline_export.ts @@ -0,0 +1,24 @@ +/** + * @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. + */ + +// Imports firebase via the raw sources and re-exports it. The +// "/integration/firestore" test suite replaces this file with a +// reference to the minified sources. If you change any exports in this file, +// you need to also adjust "integration/firestore/pipeline_export.ts". + +// @ts-ignore +export * from '../../lite/pipelines/pipelines.ts'; diff --git a/packages/firestore/test/unit/api/document_change.test.ts b/packages/firestore/test/unit/api/document_change.test.ts index faae8b4d4c..8ce40f599b 100644 --- a/packages/firestore/test/unit/api/document_change.test.ts +++ b/packages/firestore/test/unit/api/document_change.test.ts @@ -18,8 +18,8 @@ import { expect } from 'chai'; import { Query } from '../../../src/api/reference'; -import { ExpUserDataWriter } from '../../../src/api/reference_impl'; import { QuerySnapshot } from '../../../src/api/snapshot'; +import { ExpUserDataWriter } from '../../../src/api/user_data_writer'; import { Query as InternalQuery } from '../../../src/core/query'; import { View } from '../../../src/core/view'; import { documentKeySet } from '../../../src/model/collections'; diff --git a/packages/firestore/test/unit/api/pipeline_impl.test.ts b/packages/firestore/test/unit/api/pipeline_impl.test.ts new file mode 100644 index 0000000000..f11db5a427 --- /dev/null +++ b/packages/firestore/test/unit/api/pipeline_impl.test.ts @@ -0,0 +1,202 @@ +/** + * @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. + */ + +import { expect } from 'chai'; +import * as sinon from 'sinon'; + +import { Timestamp } from '../../../src'; +import { Firestore } from '../../../src/api/database'; +import { execute } from '../../../src/api/pipeline_impl'; +import { + MemoryOfflineComponentProvider, + OnlineComponentProvider +} from '../../../src/core/component_provider'; +import { + ExecutePipelineRequest as ProtoExecutePipelineRequest, + ExecutePipelineResponse as ProtoExecutePipelineResponse +} from '../../../src/protos/firestore_proto_api'; +import { newTestFirestore } from '../../util/api_helpers'; + +const FIRST_CALL = 0; +const EXECUTE_PIPELINE_REQUEST = 3; + +function fakePipelineResponse( + firestore: Firestore, + response?: ProtoExecutePipelineResponse[] +): sinon.SinonSpy { + response = response ?? [ + { + executionTime: Timestamp.now().toDate().toISOString(), + results: [] + } + ]; + const fake = sinon.fake.resolves(response); + + firestore._componentsProvider = { + _offline: { + build: () => new MemoryOfflineComponentProvider() + }, + _online: { + build: () => { + const provider = new OnlineComponentProvider(); + const ogCreateDatastore = provider.createDatastore.bind(provider); + provider.createDatastore = config => { + const datastore = ogCreateDatastore(config); + // @ts-ignore + datastore.invokeStreamingRPC = fake; + return datastore; + }; + return provider; + } + } + }; + + return fake; +} + +describe('execute(Pipeline|PipelineOptions)', () => { + it('returns execution time with empty results', async () => { + const firestore = newTestFirestore(); + + const executeTime = Timestamp.now(); + const spy = fakePipelineResponse(firestore, [ + { + executionTime: executeTime.toDate().toISOString(), + results: [] + } + ]); + + const pipelineSnapshot = await execute( + firestore.pipeline().collection('foo') + ); + + expect(pipelineSnapshot.results.length).to.equal(0); + expect(spy.calledOnce); + + expect(pipelineSnapshot.executionTime.toJSON()).to.deep.equal( + executeTime.toJSON() + ); + }); + + it('serializes the pipeline', async () => { + const firestore = newTestFirestore(); + const spy = fakePipelineResponse(firestore); + + await execute({ + pipeline: firestore.pipeline().collection('foo') + }); + + const executePipelineRequest: ProtoExecutePipelineRequest = { + database: 'projects/new-project/databases/(default)', + structuredPipeline: { + 'options': {}, + 'pipeline': { + 'stages': [ + { + 'args': [ + { + 'referenceValue': '/foo' + } + ], + 'name': 'collection', + 'options': {} + } + ] + } + } + }; + expect(spy.args[FIRST_CALL][EXECUTE_PIPELINE_REQUEST]).to.deep.equal( + executePipelineRequest + ); + }); + + it('serializes the pipeline options', async () => { + const firestore = newTestFirestore(); + const spy = fakePipelineResponse(firestore); + + await execute({ + pipeline: firestore.pipeline().collection('foo'), + indexMode: 'recommended' + }); + + const executePipelineRequest: ProtoExecutePipelineRequest = { + database: 'projects/new-project/databases/(default)', + structuredPipeline: { + 'options': { + 'index_mode': { + 'stringValue': 'recommended' + } + }, + 'pipeline': { + 'stages': [ + { + 'args': [ + { + 'referenceValue': '/foo' + } + ], + 'name': 'collection', + 'options': {} + } + ] + } + } + }; + expect(spy.args[FIRST_CALL][EXECUTE_PIPELINE_REQUEST]).to.deep.equal( + executePipelineRequest + ); + }); + + it('serializes the pipeline raw options', async () => { + const firestore = newTestFirestore(); + const spy = fakePipelineResponse(firestore); + + await execute({ + pipeline: firestore.pipeline().collection('foo'), + rawOptions: { + 'foo': 'bar' + } + }); + + const executePipelineRequest: ProtoExecutePipelineRequest = { + database: 'projects/new-project/databases/(default)', + structuredPipeline: { + 'options': { + 'foo': { + 'stringValue': 'bar' + } + }, + 'pipeline': { + 'stages': [ + { + 'args': [ + { + 'referenceValue': '/foo' + } + ], + 'name': 'collection', + 'options': {} + } + ] + } + } + }; + expect(spy.args[FIRST_CALL][EXECUTE_PIPELINE_REQUEST]).to.deep.equal( + executePipelineRequest + ); + }); +}); diff --git a/packages/firestore/test/unit/core/options_util.test.ts b/packages/firestore/test/unit/core/options_util.test.ts new file mode 100644 index 0000000000..0549c2c8a9 --- /dev/null +++ b/packages/firestore/test/unit/core/options_util.test.ts @@ -0,0 +1,224 @@ +/** + * @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. + */ + +import { expect } from 'chai'; + +import { ParseContext } from '../../../src/api/parse_context'; +import { OptionsUtil } from '../../../src/core/options_util'; +import { UserDataSource } from '../../../src/lite-api/user_data_reader'; +import { testUserDataReader } from '../../util/helpers'; + +describe('OptionsUtil', () => { + let context: ParseContext | undefined; + beforeEach(async () => { + context = testUserDataReader(false).createContext( + UserDataSource.Argument, + 'beforeEach' + ); + }); + + afterEach(async () => { + context = undefined; + }); + + it('should support known options', () => { + const optionsUtil = new OptionsUtil({ + fooBar: { + serverName: 'foo_bar' + } + }); + const proto = optionsUtil.getOptionsProto(context!, { + fooBar: 'recommended' + }); + + expect(proto).deep.equal({ + 'foo_bar': { + stringValue: 'recommended' + } + }); + }); + + it('should support unknown options', () => { + const optionsUtil = new OptionsUtil({}); + const proto = optionsUtil.getOptionsProto(context!, {}, { baz: 'foo' }); + + expect(proto).to.deep.equal({ + baz: { + stringValue: 'foo' + } + }); + }); + + it('should support unknown nested options', () => { + const optionsUtil = new OptionsUtil({}); + const proto = optionsUtil.getOptionsProto( + context!, + {}, + { 'foo.bar': 'baz' } + ); + + expect(proto).to.deep.equal({ + foo: { + mapValue: { + fields: { + bar: { stringValue: 'baz' } + } + } + } + }); + }); + + it('should support options override', () => { + const optionsUtil = new OptionsUtil({ + indexMode: { + serverName: 'index_mode' + } + }); + const proto = optionsUtil.getOptionsProto( + context!, + { + indexMode: 'recommended' + }, + { + 'index_mode': 'baz' + } + ); + + expect(proto).to.deep.equal({ + 'index_mode': { + stringValue: 'baz' + } + }); + }); + + it('should support options override of nested field', () => { + const optionsUtil = new OptionsUtil({ + foo: { + serverName: 'foo', + nestedOptions: { + bar: { + serverName: 'bar' + }, + waldo: { + serverName: 'waldo' + } + } + } + }); + const proto = optionsUtil.getOptionsProto( + context!, + { + foo: { bar: 'yep', waldo: 'found' } + }, + { + 'foo.bar': 123, + 'foo.baz': true + } + ); + + expect(proto).to.deep.equal({ + foo: { + mapValue: { + fields: { + bar: { + integerValue: '123' + }, + waldo: { + stringValue: 'found' + }, + baz: { + booleanValue: true + } + } + } + } + }); + }); + + it('will replace a nested object if given a new object', () => { + const optionsUtil = new OptionsUtil({ + foo: { + serverName: 'foo', + nestedOptions: { + bar: { + serverName: 'bar' + }, + waldo: { + serverName: 'waldo' + } + } + } + }); + const proto = optionsUtil.getOptionsProto( + context!, + { + foo: { bar: 'yep', waldo: 'found' } + }, + { + foo: { + bar: 123 + } + } + ); + + expect(proto).to.deep.equal({ + foo: { + mapValue: { + fields: { + bar: { + integerValue: '123' + } + } + } + } + }); + }); + + it('will replace a top level property that is not an object if given a nested field with dot notation', () => { + const optionsUtil = new OptionsUtil({ + foo: { + serverName: 'foo' + } + }); + + const proto = optionsUtil.getOptionsProto( + context!, + { + foo: 'bar' + }, + { + 'foo.bar': '123', + 'foo.waldo': true + } + ); + + expect(proto).to.deep.equal({ + foo: { + mapValue: { + fields: { + bar: { + stringValue: '123' + }, + waldo: { + booleanValue: true + } + } + } + } + }); + }); +}); diff --git a/packages/firestore/test/unit/core/structured_pipeline.test.ts b/packages/firestore/test/unit/core/structured_pipeline.test.ts new file mode 100644 index 0000000000..759dfecea4 --- /dev/null +++ b/packages/firestore/test/unit/core/structured_pipeline.test.ts @@ -0,0 +1,187 @@ +/** + * @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. + */ + +import { expect } from 'chai'; +import * as sinon from 'sinon'; + +import { DatabaseId } from '../../../src/core/database_info'; +import { + StructuredPipeline, + StructuredPipelineOptions +} from '../../../src/core/structured_pipeline'; +import { UserDataSource } from '../../../src/lite-api/user_data_reader'; +import { Pipeline as PipelineProto } from '../../../src/protos/firestore_proto_api'; +import { + JsonProtoSerializer, + ProtoSerializable +} from '../../../src/remote/serializer'; +import { testUserDataReader } from '../../util/helpers'; + +describe('StructuredPipeline', () => { + it('should serialize the pipeline argument', () => { + const pipeline: ProtoSerializable = { + _toProto: sinon.fake.returns({} as PipelineProto) + }; + const structuredPipelineOptions = new StructuredPipelineOptions(); + structuredPipelineOptions._readUserData( + testUserDataReader(false).createContext(UserDataSource.Argument, 'test') + ); + const structuredPipeline = new StructuredPipeline( + pipeline, + structuredPipelineOptions + ); + + const proto = structuredPipeline._toProto( + new JsonProtoSerializer(DatabaseId.empty(), false) + ); + + expect(proto).to.deep.equal({ + pipeline: {}, + options: {} + }); + + expect((pipeline._toProto as sinon.SinonSpy).calledOnce).to.be.true; + }); + + it('should support known options', () => { + const pipeline: ProtoSerializable = { + _toProto: sinon.fake.returns({} as PipelineProto) + }; + + const options = new StructuredPipelineOptions({ + indexMode: 'recommended' + }); + options._readUserData( + testUserDataReader(false).createContext(UserDataSource.Argument, 'test') + ); + const structuredPipeline = new StructuredPipeline(pipeline, options); + + const proto = structuredPipeline._toProto( + new JsonProtoSerializer(DatabaseId.empty(), false) + ); + + expect(proto).to.deep.equal({ + pipeline: {}, + options: { + 'index_mode': { + stringValue: 'recommended' + } + } + }); + + expect((pipeline._toProto as sinon.SinonSpy).calledOnce).to.be.true; + }); + + it('should support unknown options', () => { + const pipeline: ProtoSerializable = { + _toProto: sinon.fake.returns({} as PipelineProto) + }; + const options = new StructuredPipelineOptions( + {}, + { + 'foo_bar': 'baz' + } + ); + options._readUserData( + testUserDataReader(false).createContext(UserDataSource.Argument, 'test') + ); + const structuredPipeline = new StructuredPipeline(pipeline, options); + + const proto = structuredPipeline._toProto( + new JsonProtoSerializer(DatabaseId.empty(), false) + ); + + expect(proto).to.deep.equal({ + pipeline: {}, + options: { + 'foo_bar': { + stringValue: 'baz' + } + } + }); + + expect((pipeline._toProto as sinon.SinonSpy).calledOnce).to.be.true; + }); + + it('should support unknown nested options', () => { + const pipeline: ProtoSerializable = { + _toProto: sinon.fake.returns({} as PipelineProto) + }; + const options = new StructuredPipelineOptions( + {}, + { + 'foo.bar': 'baz' + } + ); + options._readUserData( + testUserDataReader(false).createContext(UserDataSource.Argument, 'test') + ); + const structuredPipeline = new StructuredPipeline(pipeline, options); + + const proto = structuredPipeline._toProto( + new JsonProtoSerializer(DatabaseId.empty(), false) + ); + + expect(proto).to.deep.equal({ + pipeline: {}, + options: { + 'foo': { + mapValue: { + fields: { + 'bar': { stringValue: 'baz' } + } + } + } + } + }); + + expect((pipeline._toProto as sinon.SinonSpy).calledOnce).to.be.true; + }); + + it('should support options override', () => { + const pipeline: ProtoSerializable = { + _toProto: sinon.fake.returns({} as PipelineProto) + }; + const options = new StructuredPipelineOptions( + { + indexMode: 'recommended' + }, + { + 'index_mode': 'baz' + } + ); + options._readUserData( + testUserDataReader(false).createContext(UserDataSource.Argument, 'test') + ); + const structuredPipeline = new StructuredPipeline(pipeline, options); + + const proto = structuredPipeline._toProto( + new JsonProtoSerializer(DatabaseId.empty(), false) + ); + + expect(proto).to.deep.equal({ + pipeline: {}, + options: { + 'index_mode': { + stringValue: 'baz' + } + } + }); + + expect((pipeline._toProto as sinon.SinonSpy).calledOnce).to.be.true; + }); +}); diff --git a/packages/firestore/test/unit/remote/fetch_connection.test.ts b/packages/firestore/test/unit/remote/fetch_connection.test.ts index 5a9aa67436..4de0ba5a72 100644 --- a/packages/firestore/test/unit/remote/fetch_connection.test.ts +++ b/packages/firestore/test/unit/remote/fetch_connection.test.ts @@ -43,6 +43,7 @@ describe('Fetch Connection', () => { DatabaseId.empty(), '', '', + '', new FirestoreSettingsImpl({ host: 'abc.cloudworkstations.dev' }) diff --git a/packages/firestore/test/unit/remote/grpc_connection.node.test.ts b/packages/firestore/test/unit/remote/grpc_connection.node.test.ts new file mode 100644 index 0000000000..8364cbbd5e --- /dev/null +++ b/packages/firestore/test/unit/remote/grpc_connection.node.test.ts @@ -0,0 +1,81 @@ +/** + * @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. + */ + +import { Metadata } from '@grpc/grpc-js'; +import { expect } from 'chai'; + +import { DatabaseId, DatabaseInfo } from '../../../src/core/database_info'; +import { ResourcePath } from '../../../src/model/path'; +import { GrpcConnection } from '../../../src/platform/node/grpc_connection'; + +export class TestGrpcConnection extends GrpcConnection { + mockStub = { + lastMetadata: null, + mockRpc( + req: unknown, + metadata: Metadata, + callback: (err: unknown, resp: unknown) => void + ) { + this.lastMetadata = metadata; + callback(null, null); + } + } as { + lastMetadata: null | Metadata; + [index: string]: unknown; + }; + + protected ensureActiveStub(): unknown { + return this.mockStub; + } +} + +describe('GrpcConnection', () => { + const testDatabaseInfo = new DatabaseInfo( + new DatabaseId('testproject'), + 'test-app-id', + 'persistenceKey', + 'example.com', + /*ssl=*/ false, + /*forceLongPolling=*/ false, + /*autoDetectLongPolling=*/ false, + /*longPollingOptions=*/ {}, + /*useFetchStreams=*/ false, + /*isUsingEmulator=*/ false, + 'grpc-connection-test-api-key' + ); + const connection = new TestGrpcConnection( + { google: { firestore: { v1: {} } } }, + testDatabaseInfo + ); + + it('Passes the API Key from DatabaseInfo to the grpc stub', async () => { + const request = { + database: 'projects/testproject/databases/(default)', + writes: [] + }; + await connection.invokeRPC( + 'mockRpc', + ResourcePath.emptyPath(), + request, + null, + null + ); + expect( + connection.mockStub.lastMetadata?.get('x-goog-api-key') + ).to.deep.equal(['grpc-connection-test-api-key']); + }); +}); diff --git a/packages/firestore/test/unit/remote/rest_connection.test.ts b/packages/firestore/test/unit/remote/rest_connection.test.ts index 100b8b8368..3501a910f6 100644 --- a/packages/firestore/test/unit/remote/rest_connection.test.ts +++ b/packages/firestore/test/unit/remote/rest_connection.test.ts @@ -68,7 +68,8 @@ describe('RestConnection', () => { /*autoDetectLongPolling=*/ false, /*longPollingOptions=*/ {}, /*useFetchStreams=*/ false, - /*isUsingEmulator=*/ false + /*isUsingEmulator=*/ false, + 'rest-connection-test-api-key' ); const connection = new TestRestConnection(testDatabaseInfo); @@ -83,7 +84,7 @@ describe('RestConnection', () => { null ); expect(connection.lastUrl).to.equal( - 'http://example.com/v1/projects/testproject/databases/(default)/documents:commit' + 'http://example.com/v1/projects/testproject/databases/(default)/documents:commit?key=rest-connection-test-api-key' ); }); diff --git a/packages/firestore/test/unit/remote/serializer.helper.ts b/packages/firestore/test/unit/remote/serializer.helper.ts index d523c8fab8..451f7ddf7a 100644 --- a/packages/firestore/test/unit/remote/serializer.helper.ts +++ b/packages/firestore/test/unit/remote/serializer.helper.ts @@ -28,7 +28,7 @@ import { serverTimestamp, Timestamp } from '../../../src'; -import { ExpUserDataWriter } from '../../../src/api/reference_impl'; +import { ExpUserDataWriter } from '../../../src/api/user_data_writer'; import { DatabaseId } from '../../../src/core/database_info'; import { ArrayContainsAnyFilter, diff --git a/packages/firestore/test/unit/remote/web_channel_connection.browser.test.ts b/packages/firestore/test/unit/remote/web_channel_connection.browser.test.ts new file mode 100644 index 0000000000..6558fb84de --- /dev/null +++ b/packages/firestore/test/unit/remote/web_channel_connection.browser.test.ts @@ -0,0 +1,70 @@ +/** + * @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. + */ + +import { + WebChannelOptions, + WebChannelTransport +} from '@firebase/webchannel-wrapper'; +import { expect } from 'chai'; + +import { DatabaseId, DatabaseInfo } from '../../../src/core/database_info'; +import { WebChannelConnection } from '../../../src/platform/browser/webchannel_connection'; + +export class TestWebChannelConnection extends WebChannelConnection { + transport: { lastOptions?: WebChannelOptions } & WebChannelTransport = { + lastOptions: undefined, + createWebChannel(url: string, options: WebChannelOptions): never { + this.lastOptions = options; + + // Throw here so we don't have to mock out any more of Web Channel + throw new Error('Not implemented for test'); + } + }; + protected createWebChannelTransport(): WebChannelTransport { + return this.transport; + } +} + +describe('WebChannelConnection', () => { + const testDatabaseInfo = new DatabaseInfo( + new DatabaseId('testproject'), + 'test-app-id', + 'persistenceKey', + 'example.com', + /*ssl=*/ false, + /*forceLongPolling=*/ false, + /*autoDetectLongPolling=*/ false, + /*longPollingOptions=*/ {}, + /*useFetchStreams=*/ false, + /*isUsingEmulator=*/ false, + 'wc-connection-test-api-key' + ); + + it('Passes the API Key from DatabaseInfo to makeHeaders for openStream', async () => { + const connection = new TestWebChannelConnection(testDatabaseInfo); + + expect(() => connection.openStream('mockRpc', null, null)).to.throw( + 'Not implemented for test' + ); + + const headers = connection.transport.lastOptions + ?.initMessageHeaders as unknown as { [key: string]: string }; + expect(headers['x-goog-api-key']).to.deep.equal( + 'wc-connection-test-api-key' + ); + }); +}); diff --git a/packages/firestore/test/unit/specs/spec_builder.ts b/packages/firestore/test/unit/specs/spec_builder.ts index 3e52c5873b..afc6791dbd 100644 --- a/packages/firestore/test/unit/specs/spec_builder.ts +++ b/packages/firestore/test/unit/specs/spec_builder.ts @@ -16,7 +16,7 @@ */ import { IndexConfiguration } from '../../../src/api/index_configuration'; -import { ExpUserDataWriter } from '../../../src/api/reference_impl'; +import { ExpUserDataWriter } from '../../../src/api/user_data_writer'; import { ListenOptions, ListenerDataSource as Source diff --git a/packages/firestore/test/unit/specs/spec_test_runner.ts b/packages/firestore/test/unit/specs/spec_test_runner.ts index 51d2229b8a..50806cb2a4 100644 --- a/packages/firestore/test/unit/specs/spec_test_runner.ts +++ b/packages/firestore/test/unit/specs/spec_test_runner.ts @@ -283,7 +283,8 @@ abstract class TestRunner { /*autoDetectLongPolling=*/ false, /*longPollingOptions=*/ {}, /*useFetchStreams=*/ false, - /*isUsingEmulator=*/ false + /*isUsingEmulator=*/ false, + 'test-api-key' ); // TODO(mrschmidt): During client startup in `firestore_client`, we block diff --git a/packages/firestore/test/util/api_helpers.ts b/packages/firestore/test/util/api_helpers.ts index d248c9213b..dc66a70a85 100644 --- a/packages/firestore/test/util/api_helpers.ts +++ b/packages/firestore/test/util/api_helpers.ts @@ -32,7 +32,7 @@ import { EmptyAppCheckTokenProvider, EmptyAuthCredentialsProvider } from '../../src/api/credentials'; -import { ExpUserDataWriter } from '../../src/api/reference_impl'; +import { ExpUserDataWriter } from '../../src/api/user_data_writer'; import { DatabaseId } from '../../src/core/database_info'; import { newQueryForPath, Query as InternalQuery } from '../../src/core/query'; import { diff --git a/packages/firestore/test/util/mocha_extensions.ts b/packages/firestore/test/util/mocha_extensions.ts new file mode 100644 index 0000000000..df8598e5fe --- /dev/null +++ b/packages/firestore/test/util/mocha_extensions.ts @@ -0,0 +1,98 @@ +/** + * @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. + */ + +/* eslint-disable no-restricted-properties */ + +import { USE_EMULATOR } from '../integration/util/settings'; + +// Helper to make a type itselt (T) and optionally union that with (T['skip']) +type tOrSkipT = T | (T extends { skip: unknown } ? T['skip'] : T); + +interface ExtendMochaTypeWithHelpers { + // Declare helpers + skipEmulator: tOrSkipT; + skipEnterprise: tOrSkipT; + skipClassic: tOrSkipT; +} + +declare module 'mocha' { + // TODO add mocha types that must be extended + interface TestFunction extends ExtendMochaTypeWithHelpers {} + interface PendingTestFunction + extends ExtendMochaTypeWithHelpers {} + interface SuiteFunction extends ExtendMochaTypeWithHelpers {} + interface PendingSuiteFunction + extends ExtendMochaTypeWithHelpers {} +} + +// Define helpers +export function mixinSkipImplementations(obj: unknown): void { + Object.defineProperty(obj, 'skipEmulator', { + get(): unknown { + if (this === it.skip) { + return this; + } + if (this === describe.skip) { + return this; + } + if (USE_EMULATOR) { + return this.skip; + } + return this; + } + }); + + Object.defineProperty(obj, 'skipEnterprise', { + get(): unknown { + if (this === it.skip) { + return this; + } + if (this === describe.skip) { + return this; + } + if (process.env.RUN_ENTERPRISE_TESTS) { + return this.skip; + } + return this; + } + }); + + Object.defineProperty(obj, 'skipClassic', { + get(): unknown { + if (this === it.skip) { + return this; + } + if (this === describe.skip) { + return this; + } + if (!process.env.RUN_ENTERPRISE_TESTS) { + return this.skip; + } + return this; + } + }); +} + +// TODO add mocha functions that must be extended +[global.it, global.it.skip, global.describe, global.describe.skip].forEach( + mixinSkipImplementations +); + +// Export modified it and describe. +const it = global.it; +const describe = global.describe; +export { it, describe }; diff --git a/repo-scripts/prune-dts/extract-public-api.ts b/repo-scripts/prune-dts/extract-public-api.ts index c751739956..4e3c0c3c1f 100644 --- a/repo-scripts/prune-dts/extract-public-api.ts +++ b/repo-scripts/prune-dts/extract-public-api.ts @@ -141,7 +141,8 @@ export async function generateApi( typescriptDtsPath: string, rollupDtsPath: string, untrimmedRollupDtsPath: string, - publicDtsPath: string + publicDtsPath: string, + otherExportDtsPaths: string[] ): Promise { console.log(`Configuring API Extractor for ${packageName}`); writeTypeScriptConfig(packageRoot); @@ -160,7 +161,7 @@ export async function generateApi( }); console.log('Generated rollup DTS'); - pruneDts(rollupDtsPath, publicDtsPath); + pruneDts(rollupDtsPath, publicDtsPath, otherExportDtsPaths); console.log('Pruned DTS file'); await addBlankLines(publicDtsPath); console.log('Added blank lines after imports'); @@ -221,6 +222,13 @@ const argv = yargs 'The output file for the customer-facing .d.ts file that only ' + 'includes the public APIs', require: true + }, + otherExportsPublicDtsFiles: { + type: 'string', + desc: + 'Optional. A comma-separated list of customer-facing of .d.ts' + + 'files for other exports from this package.', + require: false } }) .parseSync(); @@ -231,5 +239,10 @@ void generateApi( path.resolve(argv.typescriptDts), path.resolve(argv.rollupDts), path.resolve(argv.untrimmedRollupDts), - path.resolve(argv.publicDts) + path.resolve(argv.publicDts), + argv.otherExportsPublicDtsFiles + ? argv.otherExportsPublicDtsFiles + .split(',') + .map(filePath => path.resolve(filePath)) + : [] ); diff --git a/repo-scripts/prune-dts/prune-dts.ts b/repo-scripts/prune-dts/prune-dts.ts index 70cfc2933b..bbfad0a3f3 100644 --- a/repo-scripts/prune-dts/prune-dts.ts +++ b/repo-scripts/prune-dts/prune-dts.ts @@ -18,6 +18,7 @@ import * as yargs from 'yargs'; import * as ts from 'typescript'; import * as fs from 'fs'; +import * as path from 'path'; import { ESLint } from 'eslint'; /** @@ -33,16 +34,32 @@ import { ESLint } from 'eslint'; * @param inputLocation The file path to the .d.ts produced by API explorer. * @param outputLocation The output location for the pruned .d.ts file. */ -export function pruneDts(inputLocation: string, outputLocation: string): void { +export function pruneDts( + inputLocation: string, + outputLocation: string, + otherExportFileLocations: string[] = [] +): void { const compilerOptions = {}; const host = ts.createCompilerHost(compilerOptions); - const program = ts.createProgram([inputLocation], compilerOptions, host); + const program = ts.createProgram( + [inputLocation, ...otherExportFileLocations], + compilerOptions, + host + ); const printer: ts.Printer = ts.createPrinter(); const sourceFile = program.getSourceFile(inputLocation)!; + const otherExportSourceFiles = otherExportFileLocations + .map(otherFileLocation => program.getSourceFile(otherFileLocation)) + .filter(value => value !== undefined) as ts.SourceFile[]; const result: ts.TransformationResult = ts.transform(sourceFile, [ - dropPrivateApiTransformer.bind(null, program, host) + dropPrivateApiTransformer.bind( + null, + program, + host, + otherExportSourceFiles + ) ]); const transformedSourceFile: ts.SourceFile = result.transformed[0]; let content = printer.printFile(transformedSourceFile); @@ -503,14 +520,74 @@ function extractExportedSymbol( return undefined; } +function findExternalExport( + typeChecker: ts.TypeChecker, + sourceFile: ts.SourceFile, + node: + | ts.InterfaceDeclaration + | ts.ClassDeclaration + | ts.TypeAliasDeclaration + | ts.EnumDeclaration, + otherExportSourceFiles: ts.SourceFile[] +): ts.SourceFile | undefined { + if (!node.name) return undefined; + + const localSymbolName = node.name.text; + + for (const otherExportSourceFile of otherExportSourceFiles) { + const otherExportedSymbols = typeChecker.getExportsOfModule( + typeChecker.getSymbolAtLocation(otherExportSourceFile)! + ); + + for (const symbol of otherExportedSymbols) { + // TODO: ideally this would compare definitions to handle the case + // of name collisions with different definitions. However, this + // implementation currently does not handle function exports, + // which is the only place we expect name collisions. + if (symbol.name === localSymbolName) { + return otherExportSourceFile; + } + } + } + + return undefined; +} + function dropPrivateApiTransformer( program: ts.Program, host: ts.CompilerHost, + otherExportSourceFiles: ts.SourceFile[], context: ts.TransformationContext ): ts.Transformer { const typeChecker = program.getTypeChecker(); return (sourceFile: ts.SourceFile) => { + const imports: Record> = {}; + + // Get exported symbols + const directExportedSymbols = typeChecker.getExportsOfModule( + typeChecker.getSymbolAtLocation(sourceFile)! + ); + // Map exported symbols to aliases. + // For the statement `export { X as Y };`, this list would contain a symbol + // for `X`. + const aliasedExportedSymbols = directExportedSymbols + .map(symbol => + symbol.flags & ts.SymbolFlags.Alias + ? typeChecker.getAliasedSymbol(symbol) + : undefined + ) + .filter(symbol => symbol !== undefined); + + function ensureImportsForFile(filename: string): Array { + let importsForFile = imports[filename]; + if (!importsForFile) { + importsForFile = []; + imports[filename] = importsForFile; + } + return importsForFile; + } + function visit(node: ts.Node): ts.Node { if ( ts.isInterfaceDeclaration(node) || @@ -522,11 +599,50 @@ function dropPrivateApiTransformer( ts.isEnumDeclaration(node) ) { // Remove any types that are not exported. + // First we check the modifiers for the symbol `export function X`. If + // the export keyword is found, the symbol is modified. + // Second we check if the symbol has an alias that is exported elsewhere, + // for example: `function X; export { X as Y }`. If the alias is + // exported elsewhere, then we also have to keep the symbol. if ( !ts .getModifiers(node) ?.find(m => m.kind === ts.SyntaxKind.ExportKeyword) ) { + // Try to get a symbol for this node. + const symbol = + 'name' in node && node.name + ? typeChecker.getSymbolAtLocation(node.name) + : undefined; + // Check if that symbol is in the list of aliased exported symbols. + // If it is, we keep the symbol. Otherwise, we remove the symbol. + if (!symbol || !aliasedExportedSymbols.includes(symbol)) { + // NO-OP block to keep the condition readable + return ts.factory.createNotEmittedStatement(node); + } + } + } + + if ( + ts.isInterfaceDeclaration(node) || + ts.isClassDeclaration(node) || + ts.isTypeAliasDeclaration(node) || + ts.isEnumDeclaration(node) + ) { + // Remove any types that are exported externally + const externalExportFile = findExternalExport( + typeChecker, + sourceFile, + node, + otherExportSourceFiles + ); + if (externalExportFile && node.name) { + ensureImportsForFile( + path.relative( + path.dirname(sourceFile.fileName), + externalExportFile.fileName + ) + ).push(node.name.text); return ts.factory.createNotEmittedStatement(node); } } @@ -580,7 +696,40 @@ function dropPrivateApiTransformer( context ) as T; } - return visitNodeAndChildren(sourceFile); + const result = visitNodeAndChildren(sourceFile); + + const moreImports: ts.ImportDeclaration[] = []; + for (let filename in imports) { + const importSpecifiers: ts.ImportSpecifier[] = []; + for (let identifier of imports[filename]) { + importSpecifiers.push( + ts.factory.createImportSpecifier( + false, + undefined, + ts.factory.createIdentifier(identifier) + ) + ); + } + let outFileName = filename.startsWith('.') ? filename : `./${filename}`; + outFileName = outFileName.replace('.d.ts', ''); + const importDeclaration = ts.factory.createImportDeclaration( + [], + ts.factory.createImportClause( + true, + undefined, + ts.factory.createNamedImports(importSpecifiers) + ), + ts.factory.createStringLiteral(outFileName, true) + ); + + moreImports.push(importDeclaration); + } + + return ts.factory.updateSourceFile( + result, + [...moreImports, ...result.statements], + true + ); }; } diff --git a/repo-scripts/size-analysis/bundle-definitions/firestore.json b/repo-scripts/size-analysis/bundle-definitions/firestore.json index f5ddafd167..4f53991cec 100644 --- a/repo-scripts/size-analysis/bundle-definitions/firestore.json +++ b/repo-scripts/size-analysis/bundle-definitions/firestore.json @@ -128,6 +128,134 @@ } ] }, + { + "name": "Pipeline Query with lt filter (execute)", + "dependencies": [ + { + "packageName": "firebase", + "versionOrTag": "latest", + "imports": [ + { + "path": "app", + "imports": [ + "initializeApp" + ] + } + ] + }, + { + "packageName": "firebase", + "versionOrTag": "latest", + "imports": [ + { + "path": "firestore", + "imports": [ + "getFirestore" + ] + } + ] + }, + { + "packageName": "firebase", + "versionOrTag": "latest", + "imports": [ + { + "path": "firestore/pipelines", + "imports": [ + "lessThan", + "Field", + "execute" + ] + } + ] + } + ] + }, + { + "name": "Pipeline Query with lt filter (useFirestorePipelines)", + "dependencies": [ + { + "packageName": "firebase", + "versionOrTag": "latest", + "imports": [ + { + "path": "app", + "imports": [ + "initializeApp" + ] + } + ] + }, + { + "packageName": "firebase", + "versionOrTag": "latest", + "imports": [ + { + "path": "firestore", + "imports": [ + "getFirestore" + ] + } + ] + }, + { + "packageName": "firebase", + "versionOrTag": "latest", + "imports": [ + { + "path": "firestore/pipelines", + "imports": [ + "lessThan", + "Field" + ] + } + ] + } + ] + }, + { + "name": "Pipeline Query with lt plus and function", + "dependencies": [ + { + "packageName": "firebase", + "versionOrTag": "latest", + "imports": [ + { + "path": "app", + "imports": [ + "initializeApp" + ] + } + ] + }, + { + "packageName": "firebase", + "versionOrTag": "latest", + "imports": [ + { + "path": "firestore", + "imports": [ + "getFirestore" + ] + } + ] + }, + { + "packageName": "firebase", + "versionOrTag": "latest", + "imports": [ + { + "path": "firestore/pipelines", + "imports": [ + "lessThan", + "Field", + "and" + ] + } + ] + } + ] + }, { "name": "Query Cursors", "dependencies": [ diff --git a/scripts/build/rollup_replace_declare_module.js b/scripts/build/rollup_replace_declare_module.js new file mode 100644 index 0000000000..0fa45b8aed --- /dev/null +++ b/scripts/build/rollup_replace_declare_module.js @@ -0,0 +1,141 @@ +/** + * @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. + */ + +/** + * Returns a rollup plugin to replace any `declare module X { Y }` code blocks with `Y`. + * This was developed to support the generation of `global_index.d.ts` + * used for the Google3 import of `firebase/firestore` + * + * @param fileName perform the replace in this file + * @param moduleName search for and replace this module declaration + */ +export function replaceDeclareModule(fileName, moduleName) { + return { + name: 'replace-declare-module', + generateBundle(options, bundle) { + if (!bundle[fileName]) { + console.warn( + `[replace-declare-module] File not found in bundle: ${fileName}` + ); + return; + } + + const chunk = bundle[fileName]; + if (chunk.type === 'chunk') { + do { + const originalString = chunk.code; + const blockInfo = findDeclareModuleBlock(originalString, moduleName); + const fullBlock = blockInfo?.fullBlock; + const innerContent = blockInfo?.innerContent; + + if (!fullBlock || !innerContent) break; + + // 1. Get the segment of the string BEFORE the full block starts. + const beforeBlock = originalString.substring(0, fullBlock.start); + + // 2. Extract the inner content string based on its start and length. + // We use innerContent indices here to get the actual content inside the braces. + const innerContentString = originalString.substring( + innerContent.start, + innerContent.start + innerContent.length + ); + + // 3. Get the segment of the string AFTER the full block ends. + // The start index of the 'after' segment is the end index of the full block. + const afterBlockStart = fullBlock.start + fullBlock.length; + const afterBlock = originalString.substring(afterBlockStart); + + // 4. Concatenate the three parts: Before + Inner Content + After + chunk.code = beforeBlock + innerContentString + afterBlock; + } while (true); + } + } + }; +} + +/** + * Searches a multi-line string for a TypeScript module declaration pattern, + * finds the matching closing brace while respecting nested braces, and + * returns the start and length information for the full block and its inner content. + * + * @param inputString The multi-line string content to search within. + * @param moduleName The module name of the declare module block to search for. + * @returns An object containing the BlockInfo for the full block and inner content, or null if not found. + */ +function findDeclareModuleBlock(inputString, moduleName) { + // We escape potential regex characters in the module name to ensure it matches literally. + const escapedModuleName = moduleName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + + // Construct the RegExp object dynamically. It searches for: + // 'declare module ' + single quote + escaped module name + single quote + space + '{' + const searchRegex = new RegExp(`declare module '${escapedModuleName}' {`); + const match = inputString.match(searchRegex); + + if (!match || match.index === undefined) { + console.log('No matching module declaration found.'); + return { fullBlock: null, innerContent: null }; + } + + const fullBlockStartIndex = match.index; + + // 2. Determine the exact index of the opening brace '{' + // The match[0] gives the text that matched the regex, e.g., "declare module './my-module' {" + const matchText = match[0]; + const openBraceOffset = matchText.lastIndexOf('{'); + const openBraceIndex = fullBlockStartIndex + openBraceOffset; + + let braceCount = 1; + let closeBraceIndex = -1; + + // 3. Iterate from the character *after* the opening brace to find the matching '}' + for (let i = openBraceIndex + 1; i < inputString.length; i++) { + const char = inputString[i]; + + if (char === '{') { + braceCount++; + } else if (char === '}') { + braceCount--; + } + + // 4. Check if we found the outer closing brace + if (braceCount === 0) { + closeBraceIndex = i; + break; + } + } + + if (closeBraceIndex === -1) { + console.log('Found opening brace but no matching closing brace.'); + return null; + } + + // 5. Calculate results + + // Full Block: from 'declare module...' to matching '}' + const fullBlock = { + start: fullBlockStartIndex, + length: closeBraceIndex - fullBlockStartIndex + 1 + }; + + // Inner Content: from char after '{' to char before '}' + const innerContent = { + start: openBraceIndex + 1, + length: closeBraceIndex - (openBraceIndex + 1) + }; + + return { fullBlock, innerContent }; +} diff --git a/scripts/size_report/report_binary_size.ts b/scripts/size_report/report_binary_size.ts index da1ad16670..34dce01924 100644 --- a/scripts/size_report/report_binary_size.ts +++ b/scripts/size_report/report_binary_size.ts @@ -57,7 +57,7 @@ function generateReportForCDNScripts(): Report[] { ...special_files.map((file: string) => `${firebaseRoot}/${file}`), ...pkgJson.components.map( (component: string) => - `${firebaseRoot}/firebase-${component.replace('/', '-')}.js` + `${firebaseRoot}/firebase-${component.replaceAll('/', '-')}.js` ), ...compatPkgJson.components.map( (component: string) => `${firebaseRoot}/firebase-${component}-compat.js` diff --git a/yarn.lock b/yarn.lock index 213ecd4d2c..caa33e3d21 100644 --- a/yarn.lock +++ b/yarn.lock @@ -223,11 +223,21 @@ resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + "@babel/helper-validator-identifier@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + "@babel/helper-validator-option@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" @@ -257,6 +267,13 @@ dependencies: "@babel/types" "^7.26.7" +"@babel/parser@^7.20.15": + version "7.28.4" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz#da25d4643532890932cc03f7705fe19637e03fa8" + integrity sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg== + dependencies: + "@babel/types" "^7.28.4" + "@babel/parser@^7.26.8": version "7.26.8" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.26.8.tgz#deca2b4d99e5e1b1553843b99823f118da6107c2" @@ -1013,6 +1030,14 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" +"@babel/types@^7.28.4": + version "7.28.4" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz#0a4e618f4c60a7cd6c11cb2d48060e4dbe38ac3a" + integrity sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@bazel/runfiles@^6.3.1": version "6.3.1" resolved "https://registry.npmjs.org/@bazel/runfiles/-/runfiles-6.3.1.tgz#3f8824b2d82853377799d42354b4df78ab0ace0b" @@ -1588,6 +1613,13 @@ resolved "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== +"@jsdoc/salty@^0.2.1": + version "0.2.9" + resolved "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.9.tgz#4d8c147f7ca011532681ce86352a77a0178f1dec" + integrity sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw== + dependencies: + lodash "^4.17.21" + "@kwsites/file-exists@^1.1.1": version "1.1.1" resolved "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz#ad1efcac13e1987d8dbaf235ef3be5b0d96faa99" @@ -3094,6 +3126,11 @@ dependencies: "@types/node" "*" +"@types/linkify-it@^5": + version "5.0.0" + resolved "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz#21413001973106cda1c3a9b91eedd4ccd5469d76" + integrity sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q== + "@types/listr@0.14.9": version "0.14.9" resolved "https://registry.npmjs.org/@types/listr/-/listr-0.14.9.tgz#736581cfdfcdb821bace0a3e5b05e91182e00c85" @@ -3107,6 +3144,19 @@ resolved "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== +"@types/markdown-it@^14.1.1": + version "14.1.2" + resolved "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz#57f2532a0800067d9b934f3521429a2e8bfb4c61" + integrity sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog== + dependencies: + "@types/linkify-it" "^5" + "@types/mdurl" "^2" + +"@types/mdurl@^2": + version "2.0.0" + resolved "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz#d43878b5b20222682163ae6f897b20447233bdfd" + integrity sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg== + "@types/mime@^1": version "1.3.5" resolved "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" @@ -4617,7 +4667,7 @@ blocking-proxy@^1.0.0: dependencies: minimist "^1.2.0" -bluebird@3.7.2: +bluebird@3.7.2, bluebird@^3.7.2: version "3.7.2" resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -5030,6 +5080,13 @@ caseless@~0.12.0: resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== +catharsis@^0.9.0: + version "0.9.0" + resolved "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz#40382a168be0e6da308c277d3a2b3eb40c7d2121" + integrity sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A== + dependencies: + lodash "^4.17.15" + chai-as-promised@7.1.2: version "7.1.2" resolved "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.2.tgz#70cd73b74afd519754161386421fb71832c6d041" @@ -6146,7 +6203,7 @@ deep-freeze@0.0.1: resolved "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz#3a0b0005de18672819dfd38cd31f91179c893e84" integrity sha512-Z+z8HiAvsGwmjqlphnHW5oz6yWlOwu6EQfFTjmeTWlDeda3FS2yv3jhq35TX/ewmsnqB+RX2IdsIOyjJCQN5tg== -deep-is@^0.1.3: +deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -6613,6 +6670,11 @@ ent@~2.2.0: punycode "^1.4.1" safe-regex-test "^1.1.0" +entities@^4.4.0: + version "4.5.0" + resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + env-paths@^2.2.0: version "2.2.1" resolved "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" @@ -6841,6 +6903,18 @@ escape-string-regexp@^2.0.0: resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== +escodegen@^1.13.0: + version "1.14.3" + resolved "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" + integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== + dependencies: + esprima "^4.0.1" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + escodegen@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" @@ -6980,7 +7054,7 @@ esniff@^2.0.1: event-emitter "^0.3.5" type "^2.7.2" -espree@^9.6.0, espree@^9.6.1: +espree@^9.0.0, espree@^9.6.0, espree@^9.6.1: version "9.6.1" resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== @@ -7008,7 +7082,7 @@ esrecurse@^4.3.0: dependencies: estraverse "^5.2.0" -estraverse@^4.1.1: +estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== @@ -7336,7 +7410,7 @@ fast-levenshtein@^1.0.0: resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz#e6a754cc8f15e58987aa9cbd27af66fd6f4e5af9" integrity sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw== -fast-levenshtein@^2.0.6: +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== @@ -8253,6 +8327,17 @@ glob@^10.0.0, glob@^10.2.2, glob@^10.3.10, glob@^10.4.1: package-json-from-dist "^1.0.0" path-scurry "^1.11.1" +glob@^8.0.0: + version "8.1.0" + resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + global-dirs@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" @@ -8414,7 +8499,7 @@ graceful-fs@4.2.10: resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.5, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.5, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -10064,6 +10149,13 @@ js-yaml@~3.13.1: argparse "^1.0.7" esprima "^4.0.0" +js2xmlparser@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz#2a1fdf01e90585ef2ae872a01bc169c6a8d5e60a" + integrity sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA== + dependencies: + xmlcreate "^2.0.4" + jsbn@1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" @@ -10074,6 +10166,27 @@ jsbn@~0.1.0: resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== +jsdoc@^4.0.0: + version "4.0.4" + resolved "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz#86565a9e39cc723a3640465b3fb189a22d1206ca" + integrity sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw== + dependencies: + "@babel/parser" "^7.20.15" + "@jsdoc/salty" "^0.2.1" + "@types/markdown-it" "^14.1.1" + bluebird "^3.7.2" + catharsis "^0.9.0" + escape-string-regexp "^2.0.0" + js2xmlparser "^4.0.2" + klaw "^3.0.0" + markdown-it "^14.1.0" + markdown-it-anchor "^8.6.7" + marked "^4.0.10" + mkdirp "^1.0.4" + requizzle "^0.2.3" + strip-json-comments "^3.1.0" + underscore "~1.13.2" + jsesc@^3.0.2: version "3.1.0" resolved "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" @@ -10432,6 +10545,13 @@ klaw-sync@^6.0.0: dependencies: graceful-fs "^4.1.11" +klaw@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz#b11bec9cf2492f06756d6e809ab73a2910259146" + integrity sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g== + dependencies: + graceful-fs "^4.1.9" + kuler@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" @@ -10518,6 +10638,14 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + libnpmaccess@^4.0.1: version "4.0.3" resolved "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-4.0.3.tgz#dfb0e5b0a53c315a2610d300e46b4ddeb66e7eec" @@ -10577,6 +10705,13 @@ lines-and-columns@^1.1.6: resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +linkify-it@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421" + integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ== + dependencies: + uc.micro "^2.0.0" + listr-silent-renderer@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" @@ -11099,6 +11234,23 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +markdown-it-anchor@^8.6.7: + version "8.6.7" + resolved "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz#ee6926daf3ad1ed5e4e3968b1740eef1c6399634" + integrity sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA== + +markdown-it@^14.1.0: + version "14.1.0" + resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45" + integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg== + dependencies: + argparse "^2.0.1" + entities "^4.4.0" + linkify-it "^5.0.0" + mdurl "^2.0.0" + punycode.js "^2.3.1" + uc.micro "^2.1.0" + marked-terminal@^7.0.0: version "7.2.1" resolved "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.2.1.tgz#9c1ae073a245a03c6a13e3eeac6f586f29856068" @@ -11122,6 +11274,11 @@ marked@^13.0.2: resolved "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz#5c5b4a5d0198060c7c9bc6ef9420a7fed30f822d" integrity sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA== +marked@^4.0.10: + version "4.3.0" + resolved "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== + matchdep@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" @@ -11146,6 +11303,11 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" +mdurl@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" + integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w== + media-typer@0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -11345,7 +11507,7 @@ minimatch@^3.0.0, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.0.5, minimatc dependencies: brace-expansion "^1.1.7" -minimatch@^5.1.0: +minimatch@^5.0.1, minimatch@^5.1.0: version "5.1.6" resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== @@ -12335,6 +12497,18 @@ optimist@~0.6.0: minimist "~0.0.1" wordwrap "~0.0.2" +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + optionator@^0.9.3: version "0.9.4" resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" @@ -13126,6 +13300,11 @@ prelude-ls@^1.2.1: resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + prettier@2.8.8, prettier@^2.7.1: version "2.8.8" resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" @@ -13214,6 +13393,22 @@ proto3-json-serializer@^2.0.2: dependencies: protobufjs "^7.2.5" +protobufjs-cli@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.3.tgz#c58b8566784f0fa1aff11e8d875a31de999637fe" + integrity sha512-MqD10lqF+FMsOayFiNOdOGNlXc4iKDCf0ZQPkPR+gizYh9gqUeGTWulABUCdI+N67w5RfJ6xhgX4J8pa8qmMXQ== + dependencies: + chalk "^4.0.0" + escodegen "^1.13.0" + espree "^9.0.0" + estraverse "^5.1.0" + glob "^8.0.0" + jsdoc "^4.0.0" + minimist "^1.2.0" + semver "^7.1.2" + tmp "^0.2.1" + uglify-js "^3.7.7" + protobufjs@7.4.0, protobufjs@^7.2.5, protobufjs@^7.3.2: version "7.4.0" resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz#7efe324ce9b3b61c82aae5de810d287bc08a248a" @@ -13344,6 +13539,11 @@ pumpify@^1.3.5: inherits "^2.0.3" pump "^2.0.0" +punycode.js@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" + integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA== + punycode@^1.3.2, punycode@^1.4.1: version "1.4.1" resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" @@ -13909,6 +14109,13 @@ requires-port@^1.0.0: resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== +requizzle@^0.2.3: + version "0.2.4" + resolved "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz#319eb658b28c370f0c20f968fa8ceab98c13d27c" + integrity sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw== + dependencies: + lodash "^4.17.21" + resolve-alpn@^1.0.0: version "1.2.1" resolved "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" @@ -14374,6 +14581,11 @@ semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semve resolved "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +semver@^7.1.2: + version "7.7.2" + resolved "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== + semver@~7.3.0: version "7.3.8" resolved "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" @@ -15298,7 +15510,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@3.1.1, strip-json-comments@^3.1.1, strip-json-comments@~3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1, strip-json-comments@~3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -15935,6 +16147,13 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + type-detect@4.0.8: version "4.0.8" resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -16111,7 +16330,12 @@ ua-parser-js@^0.7.30: resolved "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.40.tgz#c87d83b7bb25822ecfa6397a0da5903934ea1562" integrity sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ== -uglify-js@^3.1.4, uglify-js@^3.4.9: +uc.micro@^2.0.0, uc.micro@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" + integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== + +uglify-js@^3.1.4, uglify-js@^3.4.9, uglify-js@^3.7.7: version "3.19.3" resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f" integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== @@ -16141,7 +16365,7 @@ unc-path-regex@^0.1.2: resolved "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" integrity sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg== -underscore@>=1.8.3, underscore@^1.9.1: +underscore@>=1.8.3, underscore@^1.9.1, underscore@~1.13.2: version "1.13.7" resolved "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz#970e33963af9a7dda228f17ebe8399e5fbe63a10" integrity sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g== @@ -16909,7 +17133,7 @@ winston@^3.0.0: triple-beam "^1.3.0" winston-transport "^4.9.0" -word-wrap@^1.2.5: +word-wrap@^1.2.5, word-wrap@~1.2.3: version "1.2.5" resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== @@ -17088,6 +17312,11 @@ xmlbuilder@~11.0.0: resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== +xmlcreate@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz#0c5ab0f99cdd02a81065fa9cd8f8ae87624889be" + integrity sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg== + xtend@^4.0.0, xtend@^4.0.2, xtend@~4.0.1: version "4.0.2" resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" From f8a2beb2500fcdc6f26415ef55caf9ae58ce1021 Mon Sep 17 00:00:00 2001 From: Mark Duckworth <1124037+MarkDuckworth@users.noreply.github.com> Date: Thu, 8 Jan 2026 21:53:53 +0000 Subject: [PATCH 033/174] TSDoc tag cleanup (#9442) --- docs-devsite/firestore_.md | 8 +- docs-devsite/firestore_.vectorvalue.md | 2 - docs-devsite/firestore_lite.md | 2 +- docs-devsite/firestore_lite.vectorvalue.md | 2 - ...estore_lite_pipelines.aggregatefunction.md | 30 +- ...estore_lite_pipelines.booleanexpression.md | 187 +- .../firestore_lite_pipelines.expression.md | 3058 ++++---- .../firestore_lite_pipelines.field.md | 24 +- ...store_lite_pipelines.functionexpression.md | 4 +- docs-devsite/firestore_lite_pipelines.md | 6488 ++++++++-------- .../firestore_lite_pipelines.pipeline.md | 1160 ++- ...firestore_lite_pipelines.pipelineresult.md | 18 +- ...restore_lite_pipelines.pipelinesnapshot.md | 6 +- ...firestore_lite_pipelines.pipelinesource.md | 10 +- .../firestore_lite_pipelines.vectorvalue.md | 2 - .../firestore_pipelines.aggregatefunction.md | 30 +- .../firestore_pipelines.booleanexpression.md | 187 +- .../firestore_pipelines.expression.md | 3058 ++++---- docs-devsite/firestore_pipelines.field.md | 24 +- .../firestore_pipelines.functionexpression.md | 4 +- docs-devsite/firestore_pipelines.md | 6501 ++++++++--------- ...estore_pipelines.pipelineexecuteoptions.md | 45 +- .../firestore_pipelines.pipelineresult.md | 18 +- .../firestore_pipelines.pipelinesnapshot.md | 6 +- .../firestore_pipelines.pipelinesource.md | 10 +- .../firestore_pipelines.vectorvalue.md | 2 - packages/firestore/src/api/aggregate.ts | 8 +- packages/firestore/src/api/cache_config.ts | 2 +- .../src/api/persistent_cache_index_manager.ts | 2 +- packages/firestore/src/api/pipeline_impl.ts | 38 +- packages/firestore/src/core/database_info.ts | 4 +- packages/firestore/src/lite-api/aggregate.ts | 14 +- .../firestore/src/lite-api/aggregate_types.ts | 4 +- packages/firestore/src/lite-api/bytes.ts | 2 +- .../firestore/src/lite-api/expressions.ts | 2237 +++--- packages/firestore/src/lite-api/geo_point.ts | 2 +- .../firestore/src/lite-api/pipeline-result.ts | 28 +- .../firestore/src/lite-api/pipeline-source.ts | 16 +- packages/firestore/src/lite-api/pipeline.ts | 259 +- .../firestore/src/lite-api/pipeline_impl.ts | 21 +- .../src/lite-api/pipeline_options.ts | 1 + packages/firestore/src/lite-api/reference.ts | 4 +- packages/firestore/src/lite-api/stage.ts | 4 +- .../firestore/src/lite-api/stage_options.ts | 56 +- .../firestore/src/lite-api/vector_value.ts | 4 +- .../src/local/document_overlay_cache.ts | 2 +- packages/firestore/src/local/index_manager.ts | 4 +- .../src/local/local_documents_view.ts | 10 +- .../src/local/shared_client_state.ts | 2 +- packages/firestore/src/util/array.ts | 12 +- packages/firestore/src/util/assert.ts | 8 +- packages/firestore/src/util/async_queue.ts | 2 +- .../firestore/src/util/bundle_builder_impl.ts | 10 +- .../src/util/bundle_reader_sync_impl.ts | 2 +- packages/firestore/src/util/debug_uid.ts | 2 +- .../firestore/src/util/json_validation.ts | 4 +- packages/firestore/src/util/logic_utils.ts | 4 +- packages/firestore/src/util/pipeline_util.ts | 6 +- packages/firestore/src/util/testing_hooks.ts | 4 +- .../firestore/src/util/testing_hooks_spi.ts | 2 +- packages/firestore/src/util/types.ts | 5 +- 61 files changed, 11500 insertions(+), 12171 deletions(-) diff --git a/docs-devsite/firestore_.md b/docs-devsite/firestore_.md index 5d237fcafe..3787d34b27 100644 --- a/docs-devsite/firestore_.md +++ b/docs-devsite/firestore_.md @@ -34,7 +34,7 @@ https://github.com/firebase/firebase-js-sdk | [enableIndexedDbPersistence(firestore, persistenceSettings)](./firestore_.md#enableindexeddbpersistence_224174f) | Attempts to enable persistent storage, if possible.On failure, enableIndexedDbPersistence() will reject the promise or throw an exception. There are several reasons why this can fail, which can be identified by the code on the error.\* failed-precondition: The app is already open in another browser tab. \* unimplemented: The browser is incompatible with the offline persistence implementation.Note that even after a failure, the [Firestore](./firestore_.firestore.md#firestore_class) instance will remain usable, however offline persistence will be disabled.Note: enableIndexedDbPersistence() must be called before any other functions (other than [initializeFirestore()](./firestore_.md#initializefirestore_fc7d200), [getFirestore()](./firestore_.md#getfirestore) or [clearIndexedDbPersistence()](./firestore_.md#clearindexeddbpersistence_231a8e0).Persistence cannot be used in a Node.js environment. | | [enableMultiTabIndexedDbPersistence(firestore)](./firestore_.md#enablemultitabindexeddbpersistence_231a8e0) | Attempts to enable multi-tab persistent storage, if possible. If enabled across all tabs, all operations share access to local persistence, including shared execution of queries and latency-compensated local document updates across all connected instances.On failure, enableMultiTabIndexedDbPersistence() will reject the promise or throw an exception. There are several reasons why this can fail, which can be identified by the code on the error.\* failed-precondition: The app is already open in another browser tab and multi-tab is not enabled. \* unimplemented: The browser is incompatible with the offline persistence implementation.Note that even after a failure, the [Firestore](./firestore_.firestore.md#firestore_class) instance will remain usable, however offline persistence will be disabled. | | [enableNetwork(firestore)](./firestore_.md#enablenetwork_231a8e0) | Re-enables use of the network for this [Firestore](./firestore_.firestore.md#firestore_class) instance after a prior call to [disableNetwork()](./firestore_.md#disablenetwork_231a8e0). | -| [getPersistentCacheIndexManager(firestore)](./firestore_.md#getpersistentcacheindexmanager_231a8e0) | Returns the PersistentCache Index Manager used by the given Firestore object. The PersistentCacheIndexManager instance, or null if local persistent storage is not in use. | +| [getPersistentCacheIndexManager(firestore)](./firestore_.md#getpersistentcacheindexmanager_231a8e0) | Returns the PersistentCache Index Manager used by the given Firestore object. | | [loadBundle(firestore, bundleData)](./firestore_.md#loadbundle_bec5b75) | Loads a Firestore bundle into the local cache. | | [namedQuery(firestore, name)](./firestore_.md#namedquery_6438876) | Reads a Firestore [Query](./firestore_.query.md#query_class) from local cache, identified by the given name.The named queries are packaged into bundles on the server side (along with resulting documents), and loaded to local cache using loadBundle. Once in local cache, use this method to extract a [Query](./firestore_.query.md#query_class) by name. | | [onSnapshotResume(firestore, snapshotJson, onNext, onError, onCompletion, converter)](./firestore_.md#onsnapshotresume_7c84f5e) | Attaches a listener for QuerySnapshot events based on data generated by invoking [QuerySnapshot.toJSON()](./firestore_.querysnapshot.md#querysnapshottojson) You may either pass individual onNext and onError callbacks or pass a single observer object with next and error callbacks. The listener can be cancelled by calling the function that is returned when onSnapshot is called.NOTE: Although an onCompletion callback can be provided, it will never be called because the snapshot stream is never-ending. | @@ -170,7 +170,7 @@ https://github.com/firebase/firebase-js-sdk | [SnapshotMetadata](./firestore_.snapshotmetadata.md#snapshotmetadata_class) | Metadata about a snapshot, describing the state of the snapshot. | | [Timestamp](./firestore_.timestamp.md#timestamp_class) | A Timestamp represents a point in time independent of any time zone or calendar, represented as seconds and fractions of seconds at nanosecond resolution in UTC Epoch time.It is encoded using the Proleptic Gregorian Calendar which extends the Gregorian calendar backwards to year one. It is encoded assuming all minutes are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.For examples and further specifications, refer to the [Timestamp definition](https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto). | | [Transaction](./firestore_.transaction.md#transaction_class) | A reference to a transaction.The Transaction object passed to a transaction's updateFunction provides the methods to read and write data within the transaction context. See [runTransaction()](./firestore_.md#runtransaction_6f03ec4). | -| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). VectorValue | +| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). | | [WriteBatch](./firestore_.writebatch.md#writebatch_class) | A write batch, used to perform multiple writes as a single atomic unit.A WriteBatch object can be acquired by calling [writeBatch()](./firestore_.md#writebatch_231a8e0). It provides methods for adding writes to the write batch. None of the writes will be committed (or visible locally) until [WriteBatch.commit()](./firestore_.writebatch.md#writebatchcommit) is called. | ## Interfaces @@ -660,8 +660,6 @@ A `Promise` that is resolved once the network has been enabled. Returns the PersistentCache Index Manager used by the given `Firestore` object. - The `PersistentCacheIndexManager` instance, or `null` if local persistent storage is not in use. - Signature: ```typescript @@ -678,6 +676,8 @@ export declare function getPersistentCacheIndexManager(firestore: Firestore): Pe [PersistentCacheIndexManager](./firestore_.persistentcacheindexmanager.md#persistentcacheindexmanager_class) \| null +The `PersistentCacheIndexManager` instance, or `null` if local persistent storage is not in use. + ### loadBundle(firestore, bundleData) {:#loadbundle_bec5b75} Loads a Firestore bundle into the local cache. diff --git a/docs-devsite/firestore_.vectorvalue.md b/docs-devsite/firestore_.vectorvalue.md index 1fc4e2b35a..fe03c3a690 100644 --- a/docs-devsite/firestore_.vectorvalue.md +++ b/docs-devsite/firestore_.vectorvalue.md @@ -12,8 +12,6 @@ https://github.com/firebase/firebase-js-sdk # VectorValue class Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). - VectorValue - Signature: ```typescript diff --git a/docs-devsite/firestore_lite.md b/docs-devsite/firestore_lite.md index 20fafd66c5..1a2ca88300 100644 --- a/docs-devsite/firestore_lite.md +++ b/docs-devsite/firestore_lite.md @@ -119,7 +119,7 @@ https://github.com/firebase/firebase-js-sdk | [QueryStartAtConstraint](./firestore_lite.querystartatconstraint.md#querystartatconstraint_class) | A QueryStartAtConstraint is used to exclude documents from the start of a result set returned by a Firestore query. QueryStartAtConstraints are created by invoking [startAt()](./firestore_.md#startat_9a4477f) or [startAfter()](./firestore_.md#startafter_9a4477f) and can then be passed to [query()](./firestore_.md#query_9f7b0f4) to create a new query instance that also contains this QueryStartAtConstraint. | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) | A Timestamp represents a point in time independent of any time zone or calendar, represented as seconds and fractions of seconds at nanosecond resolution in UTC Epoch time.It is encoded using the Proleptic Gregorian Calendar which extends the Gregorian calendar backwards to year one. It is encoded assuming all minutes are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.For examples and further specifications, refer to the [Timestamp definition](https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto). | | [Transaction](./firestore_lite.transaction.md#transaction_class) | A reference to a transaction.The Transaction object passed to a transaction's updateFunction provides the methods to read and write data within the transaction context. See [runTransaction()](./firestore_.md#runtransaction_6f03ec4). | -| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). VectorValue | +| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). | | [WriteBatch](./firestore_lite.writebatch.md#writebatch_class) | A write batch, used to perform multiple writes as a single atomic unit.A WriteBatch object can be acquired by calling [writeBatch()](./firestore_.md#writebatch_231a8e0). It provides methods for adding writes to the write batch. None of the writes will be committed (or visible locally) until [WriteBatch.commit()](./firestore_.writebatch.md#writebatchcommit) is called. | ## Interfaces diff --git a/docs-devsite/firestore_lite.vectorvalue.md b/docs-devsite/firestore_lite.vectorvalue.md index 17c18e4c4e..4b675d4c94 100644 --- a/docs-devsite/firestore_lite.vectorvalue.md +++ b/docs-devsite/firestore_lite.vectorvalue.md @@ -12,8 +12,6 @@ https://github.com/firebase/firebase-js-sdk # VectorValue class Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). - VectorValue - Signature: ```typescript diff --git a/docs-devsite/firestore_lite_pipelines.aggregatefunction.md b/docs-devsite/firestore_lite_pipelines.aggregatefunction.md index 17925a6144..fe3dfc3b93 100644 --- a/docs-devsite/firestore_lite_pipelines.aggregatefunction.md +++ b/docs-devsite/firestore_lite_pipelines.aggregatefunction.md @@ -37,14 +37,7 @@ export declare class AggregateFunction | Method | Modifiers | Description | | --- | --- | --- | -| [as(name)](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunctionas) | | (Public Preview) Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. -```typescript -// Calculate the average price of all items and assign it the alias "averagePrice". -firestore.pipeline().collection("items") - .aggregate(field("price").average().as("averagePrice")); - -``` - | +| [as(name)](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunctionas) | | (Public Preview) Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. | ## AggregateFunction.(constructor) @@ -84,13 +77,6 @@ exprType: ExpressionType; Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. -```typescript -// Calculate the average price of all items and assign it the alias "averagePrice". -firestore.pipeline().collection("items") - .aggregate(field("price").average().as("averagePrice")); - -``` - Signature: ```typescript @@ -101,9 +87,21 @@ as(name: string): AliasedAggregate; | Parameter | Type | Description | | --- | --- | --- | -| name | string | The alias to assign to this AggregateFunction. A new that wraps this AggregateFunction and associates it with the provided alias. | +| name | string | The alias to assign to this AggregateFunction. | Returns: [AliasedAggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregate_class) +A new [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) that wraps this AggregateFunction and associates it with the provided alias. + +### 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")); + +``` + diff --git a/docs-devsite/firestore_lite_pipelines.booleanexpression.md b/docs-devsite/firestore_lite_pipelines.booleanexpression.md index f77b0e503d..f970712c06 100644 --- a/docs-devsite/firestore_lite_pipelines.booleanexpression.md +++ b/docs-devsite/firestore_lite_pipelines.booleanexpression.md @@ -26,57 +26,13 @@ export declare abstract class BooleanExpression extends Expression | Method | Modifiers | Description | | --- | --- | --- | -| [conditional(thenExpr, elseExpr)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressionconditional) | | (Public Preview) Creates a conditional expression that evaluates to the 'then' expression if this expression evaluates to true, or evaluates to the 'else' expression if this expressions evaluates false. -```typescript -// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". -field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor")); - -``` - | -| [countIf()](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioncountif) | | (Public Preview) Creates an aggregation that finds the count of input documents satisfying this boolean expression. -```typescript -// Find the count of documents with a score greater than 90 -field("score").greaterThan(90).countIf().as("highestScore"); - -``` - A new AggregateFunction representing the 'countIf' aggregation. | -| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. -```typescript -// Create an expression that protects against a divide by zero error -// but always returns a boolean expression. -constant(50).divide('length').gt(1).ifError(constant(false)); - -``` - | -| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. -```typescript -// Create an expression that protects against a divide by zero error -// but always returns a boolean expression. -constant(50).divide('length').gt(1).ifError(false); - -``` - | -| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. -```typescript -// Create an expression that protects against a divide by zero error. -constant(50).divide('length').gt(1).ifError(constant(0)); - -``` - | -| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. -```typescript -// Create an expression that protects against a divide by zero error. -constant(50).divide('length').gt(1).ifError(0); - -``` - | -| [not()](./firestore_lite_pipelines.booleanexpression.md#booleanexpressionnot) | | (Public Preview) Creates an expression that negates this boolean expression. -```typescript -// Find documents where the 'tags' field does not contain 'completed' -field("tags").arrayContains("completed").not(); - -``` - A new representing the negated filter condition. | +| [conditional(thenExpr, elseExpr)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressionconditional) | | (Public Preview) Creates a conditional expression that evaluates to the 'then' expression if this expression evaluates to true, or evaluates to the 'else' expression if this expressions evaluates false. | +| [countIf()](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioncountif) | | (Public Preview) Creates an aggregation that finds the count of input documents satisfying this boolean expression. | +| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [not()](./firestore_lite_pipelines.booleanexpression.md#booleanexpressionnot) | | (Public Preview) Creates an expression that negates this boolean expression. | ## BooleanExpression.conditional() @@ -85,12 +41,6 @@ field("tags").arrayContains("completed").not(); Creates a conditional expression that evaluates to the 'then' expression if `this` expression evaluates to `true`, or evaluates to the 'else' expression if `this` expressions evaluates `false`. -```typescript -// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". -field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor")); - -``` - Signature: ```typescript @@ -102,25 +52,29 @@ conditional(thenExpr: Expression, elseExpr: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | | thenExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is true. | -| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. A new representing the conditional expression. | +| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## BooleanExpression.countIf() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the conditional expression. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that finds the count of input documents satisfying this boolean expression. ```typescript -// Find the count of documents with a score greater than 90 -field("score").greaterThan(90).countIf().as("highestScore"); +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor")); ``` - A new `AggregateFunction` representing the 'countIf' aggregation. + +## BooleanExpression.countIf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the count of input documents satisfying this boolean expression. Signature: @@ -131,20 +85,24 @@ countIf(): AggregateFunction; [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -## BooleanExpression.ifError() +A new `AggregateFunction` representing the 'countIf' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. ```typescript -// Create an expression that protects against a divide by zero error -// but always returns a boolean expression. -constant(50).divide('length').gt(1).ifError(constant(false)); +// Find the count of documents with a score greater than 90 +field("score").greaterThan(90).countIf().as("highestScore"); ``` +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + Signature: ```typescript @@ -155,26 +113,31 @@ ifError(catchValue: BooleanExpression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| catchValue | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | +| catchValue | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The value that will be returned if this expression produces an error. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## BooleanExpression.ifError() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. ```typescript // Create an expression that protects against a divide by zero error // but always returns a boolean expression. -constant(50).divide('length').gt(1).ifError(false); +constant(50).divide('length').gt(1).ifError(constant(false)); ``` +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + Signature: ```typescript @@ -185,25 +148,31 @@ ifError(catchValue: boolean): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| catchValue | boolean | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | +| catchValue | boolean | The value that will be returned if this expression produces an error. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## BooleanExpression.ifError() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. ```typescript -// Create an expression that protects against a divide by zero error. -constant(50).divide('length').gt(1).ifError(constant(0)); +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +constant(50).divide('length').gt(1).ifError(false); ``` +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + Signature: ```typescript @@ -214,25 +183,30 @@ ifError(catchValue: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| catchValue | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | +| catchValue | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The value that will be returned if this expression produces an error. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## BooleanExpression.ifError() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. ```typescript // Create an expression that protects against a divide by zero error. -constant(50).divide('length').gt(1).ifError(0); +constant(50).divide('length').gt(1).ifError(constant(0)); ``` +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + Signature: ```typescript @@ -243,25 +217,29 @@ ifError(catchValue: unknown): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| catchValue | unknown | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | +| catchValue | unknown | The value that will be returned if this expression produces an error. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## BooleanExpression.not() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that negates this boolean expression. ```typescript -// Find documents where the 'tags' field does not contain 'completed' -field("tags").arrayContains("completed").not(); +// Create an expression that protects against a divide by zero error. +constant(50).divide('length').gt(1).ifError(0); ``` - A new representing the negated filter condition. + +## BooleanExpression.not() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that negates this boolean expression. Signature: @@ -272,3 +250,14 @@ not(): BooleanExpression; [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the negated filter condition. + +### Example + + +```typescript +// Find documents where the 'tags' field does not contain 'completed' +field("tags").arrayContains("completed").not(); + +``` + diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index fbaba7d825..b8790f8879 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -13,13 +13,13 @@ https://github.com/firebase/firebase-js-sdk > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Represents an expression that can be evaluated to a value within the execution of a . +Represents an expression that can be evaluated to a value within the execution of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class). 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 `Expr` class provides a fluent API for building expressions. You can chain together method calls to create complex expressions. +The `Expression` class provides a fluent API for building expressions. You can chain together method calls to create complex expressions. Signature: @@ -37,821 +37,134 @@ export declare abstract class Expression | Method | Modifiers | Description | | --- | --- | --- | -| [abs()](./firestore_lite_pipelines.expression.md#expressionabs) | | (Public Preview) Creates an expression that computes the absolute value of a numeric value. -```typescript -// Compute the absolute value of the 'price' field. -field("price").abs(); - -``` - A new representing the absolute value of the numeric value. | -| [add(second)](./firestore_lite_pipelines.expression.md#expressionadd) | | (Public Preview) Creates an expression that adds this expression to another expression. -```typescript -// Add the value of the 'quantity' field and the 'reserve' field. -field("quantity").add(field("reserve")); - -``` - | -| [arrayConcat(secondArray, otherArrays)](./firestore_lite_pipelines.expression.md#expressionarrayconcat) | | (Public Preview) Creates an expression that concatenates an array expression with one or more other arrays. -```typescript -// Combine the 'items' array with another array field. -field("items").arrayConcat(field("otherItems")); - -``` - | -| [arrayContains(expression)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific element. -```typescript -// Check if the 'sizes' array contains the value from the 'selectedSize' field -field("sizes").arrayContains(field("selectedSize")); - -``` - | -| [arrayContains(value)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific value. -```typescript -// Check if the 'colors' array contains "red" -field("colors").arrayContains("red"); - -``` - | -| [arrayContainsAll(values)](./firestore_lite_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. -```typescript -// Check if the 'tags' array contains both the value in field "tag1" and the literal value "tag2" -field("tags").arrayContainsAll([field("tag1"), "tag2"]); - -``` - | -| [arrayContainsAll(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. -```typescript -// Check if the 'tags' array contains both of the values from field "tag1" and the literal value "tag2" -field("tags").arrayContainsAll(array([field("tag1"), "tag2"])); - -``` - | -| [arrayContainsAny(values)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. -```typescript -// Check if the 'categories' array contains either values from field "cate1" or "cate2" -field("categories").arrayContainsAny([field("cate1"), field("cate2")]); - -``` - | -| [arrayContainsAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. -```typescript -// Check if the 'groups' array contains either the value from the 'userGroup' field -// or the value "guest" -field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); - -``` - | -| [arrayGet(offset)](./firestore_lite_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the 'tags' field array at index `1`. -field('tags').arrayGet(1); - -``` - | -| [arrayGet(offsetExpr)](./firestore_lite_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -field('tags').arrayGet(field('favoriteTag')); - -``` - | -| [arrayLength()](./firestore_lite_pipelines.expression.md#expressionarraylength) | | (Public Preview) Creates an expression that calculates the length of an array. -```typescript -// Get the number of items in the 'cart' array -field("cart").arrayLength(); - -``` - A new Expr representing the length of the array. | -| [arrayReverse()](./firestore_lite_pipelines.expression.md#expressionarrayreverse) | | (Public Preview) Creates an expression that reverses an array. -```typescript -// Reverse the value of the 'myArray' field. -field("myArray").arrayReverse(); - -``` - A new representing the reversed array. | -| [arraySum()](./firestore_lite_pipelines.expression.md#expressionarraysum) | | (Public Preview) Creates an expression that computes the sum of the elements in an array. -```typescript -// Compute the sum of the elements in the 'scores' field. -field("scores").arraySum(); - -``` - A new representing the sum of the elements in the array. | -| [as(name)](./firestore_lite_pipelines.expression.md#expressionas) | | (Public Preview) 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. -```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")); - -``` - | -| [asBoolean()](./firestore_lite_pipelines.expression.md#expressionasboolean) | | (Public Preview) Wraps the expression in a \[BooleanExpression\]. A \[BooleanExpression\] representing the same expression. | -| [ascending()](./firestore_lite_pipelines.expression.md#expressionascending) | | (Public Preview) Creates an that sorts documents in ascending order based on this expression. -```typescript -// Sort documents by the 'name' field in ascending order -pipeline().collection("users") - .sort(field("name").ascending()); - -``` - A new Ordering for ascending sorting. | -| [average()](./firestore_lite_pipelines.expression.md#expressionaverage) | | (Public Preview) Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. -```typescript -// Calculate the average age of users -field("age").average().as("averageAge"); - -``` - A new AggregateFunction representing the 'average' aggregation. | -| [byteLength()](./firestore_lite_pipelines.expression.md#expressionbytelength) | | (Public Preview) Creates an expression that calculates the length of this string expression in bytes. -```typescript -// Calculate the length of the 'myString' field in bytes. -field("myString").byteLength(); - -``` - A new representing the length of the string in bytes. | -| [ceil()](./firestore_lite_pipelines.expression.md#expressionceil) | | (Public Preview) Creates an expression that computes the ceiling of a numeric value. -```typescript -// Compute the ceiling of the 'price' field. -field("price").ceil(); - -``` - A new representing the ceiling of the numeric value. | -| [charLength()](./firestore_lite_pipelines.expression.md#expressioncharlength) | | (Public Preview) Creates an expression that calculates the character length of a string in UTF-8. -```typescript -// Get the character length of the 'name' field in its UTF-8 form. -field("name").charLength(); - -``` - A new Expr representing the length of the string. | -| [collectionId()](./firestore_lite_pipelines.expression.md#expressioncollectionid) | | (Public Preview) Creates an expression that returns the collection ID from a path. -```typescript -// Get the collection ID from a path. -field("__path__").collectionId(); - -``` - A new representing the collectionId operation. | -| [concat(second, others)](./firestore_lite_pipelines.expression.md#expressionconcat) | | (Public Preview) Creates an expression that concatenates expression results together. -```typescript -// Combine the 'firstName', ' ', and 'lastName' fields into a single value. -field("firstName").concat(constant(" "), field("lastName")); - -``` - | -| [cosineDistance(vectorExpression)](./firestore_lite_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the cosine distance between two vectors. -```typescript -// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field -field("userVector").cosineDistance(field("itemVector")); - -``` - | -| [cosineDistance(vector)](./firestore_lite_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the Cosine distance between two vectors. -```typescript -// Calculate the Cosine distance between the 'location' field and a target location -field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); - -``` - | -| [count()](./firestore_lite_pipelines.expression.md#expressioncount) | | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. -```typescript -// Count the total number of products -field("productId").count().as("totalProducts"); - -``` - A new AggregateFunction representing the 'count' aggregation. | -| [countDistinct()](./firestore_lite_pipelines.expression.md#expressioncountdistinct) | | (Public Preview) Creates an aggregation that counts the number of distinct values of the expression or field. -```typescript -// Count the distinct number of products -field("productId").countDistinct().as("distinctProducts"); - -``` - A new AggregateFunction representing the 'count\_distinct' aggregation. | -| [descending()](./firestore_lite_pipelines.expression.md#expressiondescending) | | (Public Preview) Creates an that sorts documents in descending order based on this expression. -```typescript -// Sort documents by the 'createdAt' field in descending order -firestore.pipeline().collection("users") - .sort(field("createdAt").descending()); - -``` - A new Ordering for descending sorting. | -| [divide(divisor)](./firestore_lite_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by another expression. -```typescript -// Divide the 'total' field by the 'count' field -field("total").divide(field("count")); - -``` - | -| [divide(divisor)](./firestore_lite_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by a constant value. -```typescript -// Divide the 'value' field by 10 -field("value").divide(10); - -``` - | -| [documentId()](./firestore_lite_pipelines.expression.md#expressiondocumentid) | | (Public Preview) Creates an expression that returns the document ID from a path. -```typescript -// Get the document ID from a path. -field("__path__").documentId(); - -``` - A new representing the documentId operation. | -| [dotProduct(vectorExpression)](./firestore_lite_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. -```typescript -// Calculate the dot product between a feature vector and a target vector -field("features").dotProduct([0.5, 0.8, 0.2]); - -``` - | -| [dotProduct(vector)](./firestore_lite_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. -```typescript -// Calculate the dot product between a feature vector and a target vector -field("features").dotProduct(new VectorValue([0.5, 0.8, 0.2])); - -``` - | -| [endsWith(suffix)](./firestore_lite_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix. -```typescript -// Check if the 'filename' field ends with ".txt" -field("filename").endsWith(".txt"); - -``` - | -| [endsWith(suffix)](./firestore_lite_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix (represented as an expression). -```typescript -// Check if the 'url' field ends with the value of the 'extension' field -field("url").endsWith(field("extension")); - -``` - | -| [equal(expression)](./firestore_lite_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to another expression. -```typescript -// Check if the 'age' field is equal to 21 -field("age").equal(21); - -``` - | -| [equal(value)](./firestore_lite_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to a constant value. -```typescript -// Check if the 'city' field is equal to "London" -field("city").equal("London"); - -``` - | -| [equalAny(values)](./firestore_lite_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. -```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -field("category").equalAny("Electronics", field("primaryType")); - -``` - | -| [equalAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. -```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -field("category").equalAny(array(["Electronics", field("primaryType")])); - -``` - | -| [euclideanDistance(vectorExpression)](./firestore_lite_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. -```typescript -// Calculate the Euclidean distance between the 'location' field and a target location -field("location").euclideanDistance([37.7749, -122.4194]); - -``` - | -| [euclideanDistance(vector)](./firestore_lite_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. -```typescript -// Calculate the Euclidean distance between the 'location' field and a target location -field("location").euclideanDistance(new VectorValue([37.7749, -122.4194])); - -``` - | -| [exists()](./firestore_lite_pipelines.expression.md#expressionexists) | | (Public Preview) Creates an expression that checks if a field exists in the document. -```typescript -// Check if the document has a field named "phoneNumber" -field("phoneNumber").exists(); - -``` - A new Expr representing the 'exists' check. | -| [exp()](./firestore_lite_pipelines.expression.md#expressionexp) | | (Public Preview) Creates an expression that computes e to the power of this expression. -```typescript -// Compute e to the power of the 'value' field. -field("value").exp(); - -``` - A new representing the exp of the numeric value. | -| [floor()](./firestore_lite_pipelines.expression.md#expressionfloor) | | (Public Preview) Creates an expression that computes the floor of a numeric value. -```typescript -// Compute the floor of the 'price' field. -field("price").floor(); - -``` - A new representing the floor of the numeric value. | -| [greaterThan(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than another expression. -```typescript -// Check if the 'age' field is greater than the 'limit' field -field("age").greaterThan(field("limit")); - -``` - | -| [greaterThan(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than a constant value. -```typescript -// Check if the 'price' field is greater than 100 -field("price").greaterThan(100); - -``` - | -| [greaterThanOrEqual(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to another expression. -```typescript -// Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1 -field("quantity").greaterThanOrEqual(field('requirement').add(1)); - -``` - | -| [greaterThanOrEqual(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to a constant value. -```typescript -// Check if the 'score' field is greater than or equal to 80 -field("score").greaterThanOrEqual(80); - -``` - | -| [ifAbsent(elseValue)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of the this expression evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -field("optional_field").ifAbsent("default_value") - -``` - | -| [ifAbsent(elseExpression)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or if that is -// absent, then returns the value of the field ` -field("optional_field").ifAbsent(field('default_field')) - -``` - | -| [ifError(catchExpr)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. -```typescript -// Returns the first item in the title field arrays, or returns -// the entire title field if the array is empty or the field is another type. -field("title").arrayGet(0).ifError(field("title")); - -``` - | -| [ifError(catchValue)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. -```typescript -// Returns the first item in the title field arrays, or returns -// "Default Title" -field("title").arrayGet(0).ifError("Default Title"); - -``` - | -| [isAbsent()](./firestore_lite_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. -```typescript -// Check if the field `value` is absent. -field("value").isAbsent(); - -``` - A new representing the 'isAbsent' check. | -| [isError()](./firestore_lite_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. -```typescript -// Check if the result of a calculation is an error -field("title").arrayContains(1).isError(); - -``` - A new representing the 'isError' check. | -| [join(delimiterExpression)](./firestore_lite_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array into a string. -```typescript -// Join the elements of the 'tags' field with the delimiter from the 'separator' field. -field("tags").join(field("separator")) - -``` - | -| [join(delimiter)](./firestore_lite_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array field into a string. -```typescript -// Join the elements of the 'tags' field with a comma and space. -field("tags").join(", ") - -``` - | -| [length()](./firestore_lite_pipelines.expression.md#expressionlength) | | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. -```typescript -// Get the length of the 'name' field. -field("name").length(); - -// Get the number of items in the 'cart' array. -field("cart").length(); - -``` - A new Expr representing the length of the string, array, map, vector, or bytes. | -| [lessThan(experession)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than another expression. -```typescript -// Check if the 'age' field is less than 'limit' -field("age").lessThan(field('limit')); - -``` - | -| [lessThan(value)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than a constant value. -```typescript -// Check if the 'price' field is less than 50 -field("price").lessThan(50); - -``` - | -| [lessThanOrEqual(expression)](./firestore_lite_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to another expression. -```typescript -// Check if the 'quantity' field is less than or equal to 20 -field("quantity").lessThan(constant(20)); - -``` - | -| [lessThanOrEqual(value)](./firestore_lite_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to a constant value. -```typescript -// Check if the 'score' field is less than or equal to 70 -field("score").lessThan(70); - -``` - | -| [like(pattern)](./firestore_lite_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. -```typescript -// Check if the 'title' field contains the word "guide" (case-sensitive) -field("title").like("%guide%"); - -``` - | -| [like(pattern)](./firestore_lite_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. -```typescript -// Check if the 'title' field contains the word "guide" (case-sensitive) -field("title").like("%guide%"); - -``` - | -| [ln()](./firestore_lite_pipelines.expression.md#expressionln) | | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. -```typescript -// Compute the natural logarithm of the 'value' field. -field("value").ln(); - -``` - A new representing the natural logarithm of the numeric value. | -| [log10()](./firestore_lite_pipelines.expression.md#expressionlog10) | | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. -```typescript -// Compute the base-10 logarithm of the 'value' field. -field("value").log10(); - -``` - A new representing the base-10 logarithm of the numeric value. | -| [logicalMaximum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalmaximum) | | (Public Preview) Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. -```typescript -// Returns the larger value between the 'timestamp' field and the current timestamp. -field("timestamp").logicalMaximum(Function.currentTimestamp()); - -``` - | -| [logicalMinimum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalminimum) | | (Public Preview) Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. -```typescript -// Returns the smaller value between the 'timestamp' field and the current timestamp. -field("timestamp").logicalMinimum(Function.currentTimestamp()); - -``` - | -| [mapGet(subfield)](./firestore_lite_pipelines.expression.md#expressionmapget) | | (Public Preview) Accesses a value from a map (object) field using the provided key. -```typescript -// Get the 'city' value from the 'address' map field -field("address").mapGet("city"); - -``` - | -| [mapMerge(secondMap, otherMaps)](./firestore_lite_pipelines.expression.md#expressionmapmerge) | | (Public Preview) Creates an expression that merges multiple map values. -``` -// 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}, {}) - -``` - | -| [mapRemove(key)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. -``` -// Removes the key 'baz' from the input map. -map({foo: 'bar', baz: true}).mapRemove('baz'); - -``` - | -| [mapRemove(keyExpr)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. -``` -// Removes the key 'baz' from the input map. -map({foo: 'bar', baz: true}).mapRemove(constant('baz')); - -``` - | -| [maximum()](./firestore_lite_pipelines.expression.md#expressionmaximum) | | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. -```typescript -// Find the highest score in a leaderboard -field("score").maximum().as("highestScore"); - -``` - A new AggregateFunction representing the 'maximum' aggregation. | -| [minimum()](./firestore_lite_pipelines.expression.md#expressionminimum) | | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. -```typescript -// Find the lowest price of all products -field("price").minimum().as("lowestPrice"); - -``` - A new AggregateFunction representing the 'minimum' aggregation. | -| [mod(expression)](./firestore_lite_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. -```typescript -// Calculate the remainder of dividing the 'value' field by the 'divisor' field -field("value").mod(field("divisor")); - -``` - | -| [mod(value)](./firestore_lite_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. -```typescript -// Calculate the remainder of dividing the 'value' field by 10 -field("value").mod(10); - -``` - | -| [multiply(second)](./firestore_lite_pipelines.expression.md#expressionmultiply) | | (Public Preview) Creates an expression that multiplies this expression by another expression. -```typescript -// Multiply the 'quantity' field by the 'price' field -field("quantity").multiply(field("price")); - -``` - | -| [notEqual(expression)](./firestore_lite_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to another expression. -```typescript -// Check if the 'status' field is not equal to "completed" -field("status").notEqual("completed"); - -``` - | -| [notEqual(value)](./firestore_lite_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to a constant value. -```typescript -// Check if the 'country' field is not equal to "USA" -field("country").notEqual("USA"); - -``` - | -| [notEqualAny(values)](./firestore_lite_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the provided values or expressions. -```typescript -// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' -field("status").notEqualAny(["pending", field("rejectedStatus")]); - -``` - | -| [notEqualAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. -```typescript -// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' -field("status").notEqualAny(field('rejectedStatuses')); - -``` - | -| [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of another expression. -```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -field("base").pow(field("exponent")); - -``` - | -| [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of a constant value. -```typescript -// Raise the value of the 'base' field to the power of 2. -field("base").pow(2); - -``` - | -| [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. -```typescript -// Check if the 'description' field contains "example" (case-insensitive) -field("description").regexContains("(?i)example"); - -``` - | -| [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. -```typescript -// Check if the 'description' field contains the regular expression stored in field 'regex' -field("description").regexContains(field("regex")); - -``` - | -| [regexMatch(pattern)](./firestore_lite_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. -```typescript -// Check if the 'email' field matches a valid email pattern -field("email").regexMatch("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); - -``` - | -| [regexMatch(pattern)](./firestore_lite_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. -```typescript -// Check if the 'email' field matches a regular expression stored in field 'regex' -field("email").regexMatch(field("regex")); - -``` - | -| [reverse()](./firestore_lite_pipelines.expression.md#expressionreverse) | | (Public Preview) Creates an expression that reverses this string expression. -```typescript -// Reverse the value of the 'myString' field. -field("myString").reverse(); - -``` - A new representing the reversed string. | -| [round()](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. -```typescript -// Round the value of the 'price' field. -field("price").round(); - -``` - A new Expr representing the rounded value. | -| [round(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. -```typescript -// Round the value of the 'price' field to two decimal places. -field("price").round(2); - -``` - | -| [round(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. +| [abs()](./firestore_lite_pipelines.expression.md#expressionabs) | | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | +| [add(second)](./firestore_lite_pipelines.expression.md#expressionadd) | | (Public Preview) Creates an expression that adds this expression to another expression. | +| [arrayConcat(secondArray, otherArrays)](./firestore_lite_pipelines.expression.md#expressionarrayconcat) | | (Public Preview) Creates an expression that concatenates an array expression with one or more other arrays. | +| [arrayContains(expression)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific element. | +| [arrayContains(value)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific value. | +| [arrayContainsAll(values)](./firestore_lite_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. | +| [arrayContainsAll(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. | +| [arrayContainsAny(values)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. | +| [arrayContainsAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. | +| [arrayGet(offset)](./firestore_lite_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(offsetExpr)](./firestore_lite_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayLength()](./firestore_lite_pipelines.expression.md#expressionarraylength) | | (Public Preview) Creates an expression that calculates the length of an array. | +| [arrayReverse()](./firestore_lite_pipelines.expression.md#expressionarrayreverse) | | (Public Preview) Creates an expression that reverses an array. | +| [arraySum()](./firestore_lite_pipelines.expression.md#expressionarraysum) | | (Public Preview) Creates an expression that computes the sum of the elements in an array. | +| [as(name)](./firestore_lite_pipelines.expression.md#expressionas) | | (Public Preview) 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. | +| [asBoolean()](./firestore_lite_pipelines.expression.md#expressionasboolean) | | (Public Preview) Wraps the expression in a \[BooleanExpression\]. | +| [ascending()](./firestore_lite_pipelines.expression.md#expressionascending) | | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on this expression. | +| [average()](./firestore_lite_pipelines.expression.md#expressionaverage) | | (Public Preview) Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. | +| [byteLength()](./firestore_lite_pipelines.expression.md#expressionbytelength) | | (Public Preview) Creates an expression that calculates the length of this string expression in bytes. | +| [ceil()](./firestore_lite_pipelines.expression.md#expressionceil) | | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | +| [charLength()](./firestore_lite_pipelines.expression.md#expressioncharlength) | | (Public Preview) Creates an expression that calculates the character length of a string in UTF-8. | +| [collectionId()](./firestore_lite_pipelines.expression.md#expressioncollectionid) | | (Public Preview) Creates an expression that returns the collection ID from a path. | +| [concat(second, others)](./firestore_lite_pipelines.expression.md#expressionconcat) | | (Public Preview) Creates an expression that concatenates expression results together. | +| [cosineDistance(vectorExpression)](./firestore_lite_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the cosine distance between two vectors. | +| [cosineDistance(vector)](./firestore_lite_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the Cosine distance between two vectors. | +| [count()](./firestore_lite_pipelines.expression.md#expressioncount) | | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. | +| [countDistinct()](./firestore_lite_pipelines.expression.md#expressioncountdistinct) | | (Public Preview) Creates an aggregation that counts the number of distinct values of the expression or field. | +| [descending()](./firestore_lite_pipelines.expression.md#expressiondescending) | | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on this expression. | +| [divide(divisor)](./firestore_lite_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by another expression. | +| [divide(divisor)](./firestore_lite_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by a constant value. | +| [documentId()](./firestore_lite_pipelines.expression.md#expressiondocumentid) | | (Public Preview) Creates an expression that returns the document ID from a path. | +| [dotProduct(vectorExpression)](./firestore_lite_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. | +| [dotProduct(vector)](./firestore_lite_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. | +| [endsWith(suffix)](./firestore_lite_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix. | +| [endsWith(suffix)](./firestore_lite_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix (represented as an expression). | +| [equal(expression)](./firestore_lite_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to another expression. | +| [equal(value)](./firestore_lite_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to a constant value. | +| [equalAny(values)](./firestore_lite_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. | +| [equalAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. | +| [euclideanDistance(vectorExpression)](./firestore_lite_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. | +| [euclideanDistance(vector)](./firestore_lite_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. | +| [exists()](./firestore_lite_pipelines.expression.md#expressionexists) | | (Public Preview) Creates an expression that checks if a field exists in the document. | +| [exp()](./firestore_lite_pipelines.expression.md#expressionexp) | | (Public Preview) Creates an expression that computes e to the power of this expression. | +| [floor()](./firestore_lite_pipelines.expression.md#expressionfloor) | | (Public Preview) Creates an expression that computes the floor of a numeric value. | +| [greaterThan(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than another expression. | +| [greaterThan(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than a constant value. | +| [greaterThanOrEqual(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to another expression. | +| [greaterThanOrEqual(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to a constant value. | +| [ifAbsent(elseValue)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of the this expression evaluation. | +| [ifAbsent(elseExpression)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. ```typescript -// Round the value of the 'price' field to two decimal places. -field("price").round(constant(2)); +// Returns the value of the optional field 'optional_field', or if that is +// absent, then returns the value of the field ` +field("optional_field").ifAbsent(field('default_field')) ``` | +| [ifError(catchExpr)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [isAbsent()](./firestore_lite_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. | +| [isError()](./firestore_lite_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. | +| [join(delimiterExpression)](./firestore_lite_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array into a string. | +| [join(delimiter)](./firestore_lite_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array field into a string. | +| [length()](./firestore_lite_pipelines.expression.md#expressionlength) | | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | +| [lessThan(experession)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than another expression. | +| [lessThan(value)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than a constant value. | +| [lessThanOrEqual(expression)](./firestore_lite_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to another expression. | +| [lessThanOrEqual(value)](./firestore_lite_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to a constant value. | +| [like(pattern)](./firestore_lite_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. | +| [like(pattern)](./firestore_lite_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. | +| [ln()](./firestore_lite_pipelines.expression.md#expressionln) | | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. | +| [log10()](./firestore_lite_pipelines.expression.md#expressionlog10) | | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | +| [logicalMaximum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalmaximum) | | (Public Preview) Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. | +| [logicalMinimum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalminimum) | | (Public Preview) Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. | +| [mapGet(subfield)](./firestore_lite_pipelines.expression.md#expressionmapget) | | (Public Preview) Accesses a value from a map (object) field using the provided key. | +| [mapMerge(secondMap, otherMaps)](./firestore_lite_pipelines.expression.md#expressionmapmerge) | | (Public Preview) Creates an expression that merges multiple map values. | +| [mapRemove(key)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | +| [mapRemove(keyExpr)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | +| [maximum()](./firestore_lite_pipelines.expression.md#expressionmaximum) | | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | +| [minimum()](./firestore_lite_pipelines.expression.md#expressionminimum) | | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | +| [mod(expression)](./firestore_lite_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. | +| [mod(value)](./firestore_lite_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. | +| [multiply(second)](./firestore_lite_pipelines.expression.md#expressionmultiply) | | (Public Preview) Creates an expression that multiplies this expression by another expression. | +| [notEqual(expression)](./firestore_lite_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to another expression. | +| [notEqual(value)](./firestore_lite_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to a constant value. | +| [notEqualAny(values)](./firestore_lite_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the provided values or expressions. | +| [notEqualAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. | +| [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of another expression. | +| [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of a constant value. | +| [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. | +| [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. | +| [regexMatch(pattern)](./firestore_lite_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. | +| [regexMatch(pattern)](./firestore_lite_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. | +| [reverse()](./firestore_lite_pipelines.expression.md#expressionreverse) | | (Public Preview) Creates an expression that reverses this string expression. | +| [round()](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | +| [round(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [round(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | | [split(delimiter)](./firestore_lite_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | | [split(delimiter)](./firestore_lite_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | -| [sqrt()](./firestore_lite_pipelines.expression.md#expressionsqrt) | | (Public Preview) Creates an expression that computes the square root of a numeric value. -```typescript -// Compute the square root of the 'value' field. -field("value").sqrt(); - -``` - A new representing the square root of the numeric value. | -| [startsWith(prefix)](./firestore_lite_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix. -```typescript -// Check if the 'name' field starts with "Mr." -field("name").startsWith("Mr."); - -``` - | -| [startsWith(prefix)](./firestore_lite_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix (represented as an expression). -```typescript -// Check if the 'fullName' field starts with the value of the 'firstName' field -field("fullName").startsWith(field("firstName")); - -``` - | -| [stringConcat(secondString, otherStrings)](./firestore_lite_pipelines.expression.md#expressionstringconcat) | | (Public Preview) Creates an expression that concatenates string expressions together. -```typescript -// Combine the 'firstName', " ", and 'lastName' fields into a single string -field("firstName").stringConcat(constant(" "), field("lastName")); - -``` - | -| [stringContains(substring)](./firestore_lite_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified substring. -```typescript -// Check if the 'description' field contains "example". -field("description").stringContains("example"); - -``` - | -| [stringContains(expr)](./firestore_lite_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains the string represented by another expression. -```typescript -// Check if the 'description' field contains the value of the 'keyword' field. -field("description").stringContains(field("keyword")); - -``` - | -| [stringReverse()](./firestore_lite_pipelines.expression.md#expressionstringreverse) | | (Public Preview) Creates an expression that reverses a string. -```typescript -// Reverse the value of the 'myString' field. -field("myString").stringReverse(); - -``` - A new representing the reversed string. | +| [sqrt()](./firestore_lite_pipelines.expression.md#expressionsqrt) | | (Public Preview) Creates an expression that computes the square root of a numeric value. | +| [startsWith(prefix)](./firestore_lite_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix. | +| [startsWith(prefix)](./firestore_lite_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix (represented as an expression). | +| [stringConcat(secondString, otherStrings)](./firestore_lite_pipelines.expression.md#expressionstringconcat) | | (Public Preview) Creates an expression that concatenates string expressions together. | +| [stringContains(substring)](./firestore_lite_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified substring. | +| [stringContains(expr)](./firestore_lite_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains the string represented by another expression. | +| [stringReverse()](./firestore_lite_pipelines.expression.md#expressionstringreverse) | | (Public Preview) Creates an expression that reverses a string. | | [substring(position, length)](./firestore_lite_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | | [substring(position, length)](./firestore_lite_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | -| [subtract(subtrahend)](./firestore_lite_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts another expression from this expression. -```typescript -// Subtract the 'discount' field from the 'price' field -field("price").subtract(field("discount")); - -``` - | -| [subtract(subtrahend)](./firestore_lite_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts a constant value from this expression. -```typescript -// Subtract 20 from the value of the 'total' field -field("total").subtract(20); - -``` - | -| [sum()](./firestore_lite_pipelines.expression.md#expressionsum) | | (Public Preview) Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. -```typescript -// Calculate the total revenue from a set of orders -field("orderAmount").sum().as("totalRevenue"); - -``` - A new AggregateFunction representing the 'sum' aggregation. | -| [timestampAdd(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. -```typescript -// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. -field("timestamp").timestampAdd(field("unit"), field("amount")); - -``` - | -| [timestampAdd(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. -```typescript -// Add 1 day to the 'timestamp' field. -field("timestamp").timestampAdd("day", 1); - -``` - | -| [timestampSubtract(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. -```typescript -// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. -field("timestamp").timestampSubtract(field("unit"), field("amount")); - -``` - | -| [timestampSubtract(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. -```typescript -// Subtract 1 day from the 'timestamp' field. -field("timestamp").timestampSubtract("day", 1); - -``` - | -| [timestampToUnixMicros()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixmicros) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to microseconds since epoch. -field("timestamp").timestampToUnixMicros(); - -``` - A new representing the number of microseconds since epoch. | -| [timestampToUnixMillis()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixmillis) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -field("timestamp").timestampToUnixMillis(); - -``` - A new representing the number of milliseconds since epoch. | -| [timestampToUnixSeconds()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixseconds) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to seconds since epoch. -field("timestamp").timestampToUnixSeconds(); - -``` - A new representing the number of seconds since epoch. | +| [subtract(subtrahend)](./firestore_lite_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts another expression from this expression. | +| [subtract(subtrahend)](./firestore_lite_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts a constant value from this expression. | +| [sum()](./firestore_lite_pipelines.expression.md#expressionsum) | | (Public Preview) Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. | +| [timestampAdd(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. | +| [timestampAdd(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. | +| [timestampSubtract(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. | +| [timestampSubtract(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. | +| [timestampToUnixMicros()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixmicros) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixMillis()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixmillis) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixSeconds()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixseconds) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | | [timestampTruncate(granularity, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestamptruncate) | | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | | [timestampTruncate(granularity, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestamptruncate) | | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [toLower()](./firestore_lite_pipelines.expression.md#expressiontolower) | | (Public Preview) Creates an expression that converts a string to lowercase. -```typescript -// Convert the 'name' field to lowercase -field("name").toLower(); - -``` - A new Expr representing the lowercase string. | -| [toUpper()](./firestore_lite_pipelines.expression.md#expressiontoupper) | | (Public Preview) Creates an expression that converts a string to uppercase. -```typescript -// Convert the 'title' field to uppercase -field("title").toUpper(); - -``` - A new Expr representing the uppercase string. | -| [trim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressiontrim) | | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array. -```typescript -// Trim whitespace from the 'userInput' field -field("userInput").trim(); - -// Trim quotes from the 'userInput' field -field("userInput").trim('"'); - -``` - | +| [toLower()](./firestore_lite_pipelines.expression.md#expressiontolower) | | (Public Preview) Creates an expression that converts a string to lowercase. | +| [toUpper()](./firestore_lite_pipelines.expression.md#expressiontoupper) | | (Public Preview) Creates an expression that converts a string to uppercase. | +| [trim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressiontrim) | | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array. | | [type()](./firestore_lite_pipelines.expression.md#expressiontype) | | (Public Preview) Creates an expression that returns the data type of this expression's result, as a string. | -| [unixMicrosToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixmicrostotimestamp) | | (Public Preview) 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. -```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -field("microseconds").unixMicrosToTimestamp(); - -``` - A new representing the timestamp. | -| [unixMillisToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixmillistotimestamp) | | (Public Preview) 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. -```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -field("milliseconds").unixMillisToTimestamp(); - -``` - A new representing the timestamp. | -| [unixSecondsToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixsecondstotimestamp) | | (Public Preview) 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. -```typescript -// Interpret the 'seconds' field as seconds since epoch. -field("seconds").unixSecondsToTimestamp(); - -``` - A new representing the timestamp. | -| [vectorLength()](./firestore_lite_pipelines.expression.md#expressionvectorlength) | | (Public Preview) Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. -```typescript -// Get the vector length (dimension) of the field 'embedding'. -field("embedding").vectorLength(); - -``` - A new representing the length of the vector. | +| [unixMicrosToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixmicrostotimestamp) | | (Public Preview) 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. | +| [unixMillisToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixmillistotimestamp) | | (Public Preview) 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. | +| [unixSecondsToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixsecondstotimestamp) | | (Public Preview) 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. | +| [vectorLength()](./firestore_lite_pipelines.expression.md#expressionvectorlength) | | (Public Preview) Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. | ## Expression.expressionType @@ -871,28 +184,53 @@ abstract readonly expressionType: ExpressionType; Creates an expression that computes the absolute value of a numeric value. +Signature: + +```typescript +abs(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. + +### Example + + ```typescript // Compute the absolute value of the 'price' field. field("price").abs(); ``` - A new representing the absolute value of the numeric value. + +## Expression.add() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds this expression to another expression. Signature: ```typescript -abs(): FunctionExpression; +add(second: Expression | unknown): FunctionExpression; ``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The expression or literal to add to this expression. | + Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.add() +A new `Expression` representing the addition operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that adds this expression to another expression. ```typescript // Add the value of the 'quantity' field and the 'reserve' field. @@ -900,28 +238,34 @@ field("quantity").add(field("reserve")); ``` +## Expression.arrayConcat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates an array expression with one or more other arrays. + Signature: ```typescript -add(second: Expression | unknown): FunctionExpression; +arrayConcat(secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The expression or literal to add to this expression. | +| secondArray | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\] | Second array expression or array literal to concatenate. | +| otherArrays | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.arrayConcat() +A new `Expression` representing the concatenated array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that concatenates an array expression with one or more other arrays. ```typescript // Combine the 'items' array with another array field. @@ -929,29 +273,33 @@ field("items").arrayConcat(field("otherItems")); ``` +## Expression.arrayContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains a specific element. + Signature: ```typescript -arrayConcat(secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; +arrayContains(expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| secondArray | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\] | Second array expression or array literal to concatenate. | -| otherArrays | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. A new Expr representing the concatenated array. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The element to search for in the array. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.arrayContains() +A new `Expression` representing the 'array\_contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array contains a specific element. ```typescript // Check if the 'sizes' array contains the value from the 'selectedSize' field @@ -959,28 +307,33 @@ field("sizes").arrayContains(field("selectedSize")); ``` +## Expression.arrayContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains a specific value. + Signature: ```typescript -arrayContains(expression: Expression): BooleanExpression; +arrayContains(value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The element to search for in the array. A new Expr representing the 'array\_contains' comparison. | +| value | unknown | The element to search for in the array. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.arrayContains() +A new `Expression` representing the 'array\_contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array contains a specific value. ```typescript // Check if the 'colors' array contains "red" @@ -988,28 +341,33 @@ field("colors").arrayContains("red"); ``` +## Expression.arrayContainsAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains all the specified elements. + Signature: ```typescript -arrayContains(value: unknown): BooleanExpression; +arrayContainsAll(values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The element to search for in the array. A new Expr representing the 'array\_contains' comparison. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.arrayContainsAll() +A new `Expression` representing the 'array\_contains\_all' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array contains all the specified elements. ```typescript // Check if the 'tags' array contains both the value in field "tag1" and the literal value "tag2" @@ -1017,28 +375,33 @@ field("tags").arrayContainsAll([field("tag1"), "tag2"]); ``` +## Expression.arrayContainsAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains all the specified elements. + Signature: ```typescript -arrayContainsAll(values: Array): BooleanExpression; +arrayContainsAll(arrayExpression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new Expr representing the 'array\_contains\_all' comparison. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.arrayContainsAll() +A new `Expression` representing the 'array\_contains\_all' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array contains all the specified elements. ```typescript // Check if the 'tags' array contains both of the values from field "tag1" and the literal value "tag2" @@ -1046,28 +409,33 @@ field("tags").arrayContainsAll(array([field("tag1"), "tag2"])); ``` +## Expression.arrayContainsAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains any of the specified elements. + Signature: ```typescript -arrayContainsAll(arrayExpression: Expression): BooleanExpression; +arrayContainsAny(values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. A new Expr representing the 'array\_contains\_all' comparison. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.arrayContainsAny() +A new `Expression` representing the 'array\_contains\_any' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array contains any of the specified elements. ```typescript // Check if the 'categories' array contains either values from field "cate1" or "cate2" @@ -1075,28 +443,33 @@ field("categories").arrayContainsAny([field("cate1"), field("cate2")]); ``` +## Expression.arrayContainsAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains any of the specified elements. + Signature: ```typescript -arrayContainsAny(values: Array): BooleanExpression; +arrayContainsAny(arrayExpression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new Expr representing the 'array\_contains\_any' comparison. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.arrayContainsAny() +A new `Expression` representing the 'array\_contains\_any' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array contains any of the specified elements. ```typescript // Check if the 'groups' array contains either the value from the 'userGroup' field @@ -1105,28 +478,33 @@ field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); ``` +## Expression.arrayGet() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + Signature: ```typescript -arrayContainsAny(arrayExpression: Expression): BooleanExpression; +arrayGet(offset: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. A new Expr representing the 'array\_contains\_any' comparison. | +| offset | number | The index of the element to return. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.arrayGet() +A new `Expression` representing the 'arrayGet' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. ```typescript // Return the value in the 'tags' field array at index `1`. @@ -1134,28 +512,33 @@ field('tags').arrayGet(1); ``` +## Expression.arrayGet() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + Signature: ```typescript -arrayGet(offset: number): FunctionExpression; +arrayGet(offsetExpr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| offset | number | The index of the element to return. A new Expr representing the 'arrayGet' operation. | +| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.arrayGet() +A new `Expression` representing the 'arrayGet' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. ```typescript // Return the value in the tags field array at index specified by field @@ -1164,90 +547,86 @@ field('tags').arrayGet(field('favoriteTag')); ``` -Signature: +## Expression.arrayLength() -```typescript -arrayGet(offsetExpr: Expression): FunctionExpression; -``` +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> -#### Parameters +Creates an expression that calculates the length of an array. -| Parameter | Type | Description | -| --- | --- | --- | -| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expr evaluating to the index of the element to return. A new Expr representing the 'arrayGet' operation. | +Signature: +```typescript +arrayLength(): FunctionExpression; +``` Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.arrayLength() +A new `Expression` representing the length of the array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of an array. ```typescript // Get the number of items in the 'cart' array field("cart").arrayLength(); ``` - A new `Expr` representing the length of the array. + +## Expression.arrayReverse() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses an array. Signature: ```typescript -arrayLength(): FunctionExpression; +arrayReverse(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.arrayReverse() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses an array. ```typescript // Reverse the value of the 'myArray' field. field("myArray").arrayReverse(); ``` - A new representing the reversed array. + +## Expression.arraySum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. Signature: ```typescript -arrayReverse(): FunctionExpression; +arraySum(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.arraySum() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the sum of the elements in the array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the sum of the elements in an array. ```typescript // Compute the sum of the elements in the 'scores' field. field("scores").arraySum(); ``` - A new representing the sum of the elements in the array. - -Signature: - -```typescript -arraySum(): FunctionExpression; -``` -Returns: - -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) ## Expression.as() @@ -1258,13 +637,6 @@ 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. -```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")); - -``` - Signature: ```typescript @@ -1275,12 +647,24 @@ as(name: string): AliasedExpression; | Parameter | Type | Description | | --- | --- | --- | -| name | string | The alias to assign to this expression. A new that wraps this expression and associates it with the provided alias. | +| name | string | The alias to assign to this expression. | Returns: [AliasedExpression](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpression_class) +A new [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class) that wraps this expression and associates it with the provided alias. + +### 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")); + +``` + ## Expression.asBoolean() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1288,8 +672,6 @@ as(name: string): AliasedExpression; Wraps the expression in a \[BooleanExpression\]. - A \[BooleanExpression\] representing the same expression. - Signature: ```typescript @@ -1299,12 +681,28 @@ asBoolean(): BooleanExpression; [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +A \[BooleanExpression\] representing the same expression. + ## Expression.ascending() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an that sorts documents in ascending order based on this expression. +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on this expression. + +Signature: + +```typescript +ascending(): Ordering; +``` +Returns: + +[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) + +A new `Ordering` for ascending sorting. + +### Example + ```typescript // Sort documents by the 'name' field in ascending order @@ -1312,131 +710,141 @@ pipeline().collection("users") .sort(field("name").ascending()); ``` - A new `Ordering` for ascending sorting. + +## Expression.average() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. Signature: ```typescript -ascending(): Ordering; +average(): AggregateFunction; ``` Returns: -[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -## Expression.average() +A new `AggregateFunction` representing the 'average' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. ```typescript // Calculate the average age of users field("age").average().as("averageAge"); ``` - A new `AggregateFunction` representing the 'average' aggregation. + +## Expression.byteLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of this string expression in bytes. Signature: ```typescript -average(): AggregateFunction; +byteLength(): FunctionExpression; ``` Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.byteLength() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string in bytes. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of this string expression in bytes. ```typescript // Calculate the length of the 'myString' field in bytes. field("myString").byteLength(); ``` - A new representing the length of the string in bytes. + +## Expression.ceil() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. Signature: ```typescript -byteLength(): FunctionExpression; +ceil(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.ceil() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ceiling of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the ceiling of a numeric value. ```typescript // Compute the ceiling of the 'price' field. field("price").ceil(); ``` - A new representing the ceiling of the numeric value. + +## Expression.charLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the character length of a string in UTF-8. Signature: ```typescript -ceil(): FunctionExpression; +charLength(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.charLength() +A new `Expression` representing the length of the string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the character length of a string in UTF-8. ```typescript // Get the character length of the 'name' field in its UTF-8 form. field("name").charLength(); ``` - A new `Expr` representing the length of the string. + +## Expression.collectionId() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. Signature: ```typescript -charLength(): FunctionExpression; +collectionId(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.collectionId() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the collectionId operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the collection ID from a path. ```typescript // Get the collection ID from a path. field("__path__").collectionId(); ``` - A new representing the collectionId operation. - -Signature: - -```typescript -collectionId(): FunctionExpression; -``` -Returns: - -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) ## Expression.concat() @@ -1445,12 +853,6 @@ collectionId(): FunctionExpression; Creates an expression that concatenates expression results together. -```typescript -// Combine the 'firstName', ' ', and 'lastName' fields into a single value. -field("firstName").concat(constant(" "), field("lastName")); - -``` - Signature: ```typescript @@ -1462,25 +864,30 @@ concat(second: Expression | unknown, ...others: Array): Fu | Parameter | Type | Description | | --- | --- | --- | | second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The additional expression or literal to concatenate. | -| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals to concatenate. A new Expr representing the concatenated value. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals to concatenate. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.cosineDistance() +A new `Expression` representing the concatenated value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the cosine distance between two vectors. ```typescript -// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field -field("userVector").cosineDistance(field("itemVector")); +// Combine the 'firstName', ' ', and 'lastName' fields into a single value. +field("firstName").concat(constant(" "), field("lastName")); ``` +## Expression.cosineDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the cosine distance between two vectors. + Signature: ```typescript @@ -1491,25 +898,30 @@ cosineDistance(vectorExpression: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new Expr representing the cosine distance between the two vectors. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to compare against. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.cosineDistance() +A new `Expression` representing the cosine distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Cosine distance between two vectors. ```typescript -// Calculate the Cosine distance between the 'location' field and a target location -field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +field("userVector").cosineDistance(field("itemVector")); ``` +## Expression.cosineDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between two vectors. + Signature: ```typescript @@ -1520,25 +932,29 @@ cosineDistance(vector: VectorValue | number[]): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| vector | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as a VectorValue) to compare against. A new Expr representing the Cosine\* distance between the two vectors. | +| vector | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as a VectorValue) to compare against. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.count() +A new `Expression` representing the Cosine\* distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. ```typescript -// Count the total number of products -field("productId").count().as("totalProducts"); +// Calculate the Cosine distance between the 'location' field and a target location +field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); ``` - A new `AggregateFunction` representing the 'count' aggregation. + +## Expression.count() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. Signature: @@ -1549,19 +965,23 @@ count(): AggregateFunction; [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -## Expression.countDistinct() +A new `AggregateFunction` representing the 'count' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that counts the number of distinct values of the expression or field. ```typescript -// Count the distinct number of products -field("productId").countDistinct().as("distinctProducts"); +// Count the total number of products +field("productId").count().as("totalProducts"); ``` - A new `AggregateFunction` representing the 'count\_distinct' aggregation. + +## Expression.countDistinct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of distinct values of the expression or field. Signature: @@ -1572,20 +992,23 @@ countDistinct(): AggregateFunction; [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -## Expression.descending() +A new `AggregateFunction` representing the 'count\_distinct' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an that sorts documents in descending order based on this expression. ```typescript -// Sort documents by the 'createdAt' field in descending order -firestore.pipeline().collection("users") - .sort(field("createdAt").descending()); +// Count the distinct number of products +field("productId").countDistinct().as("distinctProducts"); ``` - A new `Ordering` for descending sorting. + +## Expression.descending() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on this expression. Signature: @@ -1596,19 +1019,25 @@ descending(): Ordering; [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) -## Expression.divide() +A new `Ordering` for descending sorting. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that divides this expression by another expression. ```typescript -// Divide the 'total' field by the 'count' field -field("total").divide(field("count")); +// Sort documents by the 'createdAt' field in descending order +firestore.pipeline().collection("users") + .sort(field("createdAt").descending()); ``` +## Expression.divide() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides this expression by another expression. + Signature: ```typescript @@ -1619,25 +1048,30 @@ divide(divisor: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| divisor | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to divide by. A new Expr representing the division operation. | +| divisor | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to divide by. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.divide() +A new `Expression` representing the division operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that divides this expression by a constant value. ```typescript -// Divide the 'value' field by 10 -field("value").divide(10); +// Divide the 'total' field by the 'count' field +field("total").divide(field("count")); ``` +## Expression.divide() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides this expression by a constant value. + Signature: ```typescript @@ -1648,12 +1082,23 @@ divide(divisor: number): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| divisor | number | The constant value to divide by. A new Expr representing the division operation. | +| divisor | number | The constant value to divide by. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the division operation. + +### Example + + +```typescript +// Divide the 'value' field by 10 +field("value").divide(10); + +``` + ## Expression.documentId() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1661,28 +1106,53 @@ divide(divisor: number): FunctionExpression; Creates an expression that returns the document ID from a path. +Signature: + +```typescript +documentId(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. + +### Example + + ```typescript // Get the document ID from a path. field("__path__").documentId(); ``` - A new representing the documentId operation. + +## Expression.dotProduct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between two vectors. Signature: ```typescript -documentId(): FunctionExpression; +dotProduct(vectorExpression: Expression): FunctionExpression; ``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (as an array of numbers) to calculate with. | + Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.dotProduct() +A new `Expression` representing the dot product between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the dot product between two vectors. ```typescript // Calculate the dot product between a feature vector and a target vector @@ -1690,28 +1160,33 @@ field("features").dotProduct([0.5, 0.8, 0.2]); ``` +## Expression.dotProduct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between two vectors. + Signature: ```typescript -dotProduct(vectorExpression: Expression): FunctionExpression; +dotProduct(vector: VectorValue | number[]): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (as an array of numbers) to calculate with. A new Expr representing the dot product between the two vectors. | +| vector | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as an array of numbers) to calculate with. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.dotProduct() +A new `Expression` representing the dot product between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the dot product between two vectors. ```typescript // Calculate the dot product between a feature vector and a target vector @@ -1719,28 +1194,33 @@ field("features").dotProduct(new VectorValue([0.5, 0.8, 0.2])); ``` +## Expression.endsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string ends with a given postfix. + Signature: ```typescript -dotProduct(vector: VectorValue | number[]): FunctionExpression; +endsWith(suffix: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| vector | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as an array of numbers) to calculate with. A new Expr representing the dot product between the two vectors. | +| suffix | string | The postfix to check for. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.endsWith() +A new `Expression` representing the 'ends with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string ends with a given postfix. ```typescript // Check if the 'filename' field ends with ".txt" @@ -1748,28 +1228,33 @@ field("filename").endsWith(".txt"); ``` +## Expression.endsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string ends with a given postfix (represented as an expression). + Signature: ```typescript -endsWith(suffix: string): BooleanExpression; +endsWith(suffix: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| suffix | string | The postfix to check for. A new Expr representing the 'ends with' comparison. | +| suffix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The postfix expression to check for. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.endsWith() +A new `Expression` representing the 'ends with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string ends with a given postfix (represented as an expression). ```typescript // Check if the 'url' field ends with the value of the 'extension' field @@ -1777,28 +1262,33 @@ field("url").endsWith(field("extension")); ``` +## Expression.equal() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to another expression. + Signature: ```typescript -endsWith(suffix: Expression): BooleanExpression; +equal(expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| suffix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The postfix expression to check for. A new Expr representing the 'ends with' comparison. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for equality. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.equal() +A new `Expression` representing the equality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is equal to another expression. ```typescript // Check if the 'age' field is equal to 21 @@ -1806,28 +1296,33 @@ field("age").equal(21); ``` +## Expression.equal() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to a constant value. + Signature: ```typescript -equal(expression: Expression): BooleanExpression; +equal(value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for equality. A new Expr representing the equality comparison. | +| value | unknown | The constant value to compare for equality. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.equal() +A new `Expression` representing the equality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is equal to a constant value. ```typescript // Check if the 'city' field is equal to "London" @@ -1835,28 +1330,33 @@ field("city").equal("London"); ``` +## Expression.equalAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to any of the provided values or expressions. + Signature: ```typescript -equal(value: unknown): BooleanExpression; +equalAny(values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The constant value to compare for equality. A new Expr representing the equality comparison. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values or expressions to check against. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.equalAny() +A new `Expression` representing the 'IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is equal to any of the provided values or expressions. ```typescript // Check if the 'category' field is either "Electronics" or value of field 'primaryType' @@ -1864,28 +1364,33 @@ field("category").equalAny("Electronics", field("primaryType")); ``` +## Expression.equalAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to any of the provided values or expressions. + Signature: ```typescript -equalAny(values: Array): BooleanExpression; +equalAny(arrayExpression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values or expressions to check against. A new Expr representing the 'IN' comparison. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array of values to check against. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.equalAny() +A new `Expression` representing the 'IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is equal to any of the provided values or expressions. ```typescript // Check if the 'category' field is either "Electronics" or value of field 'primaryType' @@ -1893,28 +1398,33 @@ field("category").equalAny(array(["Electronics", field("primaryType")])); ``` +## Expression.euclideanDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between two vectors. + Signature: ```typescript -equalAny(arrayExpression: Expression): BooleanExpression; +euclideanDistance(vectorExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array of values to check against. A new Expr representing the 'IN' comparison. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (as an array of numbers) to calculate with. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.euclideanDistance() +A new `Expression` representing the Euclidean distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Euclidean distance between two vectors. ```typescript // Calculate the Euclidean distance between the 'location' field and a target location @@ -1922,28 +1432,33 @@ field("location").euclideanDistance([37.7749, -122.4194]); ``` +## Expression.euclideanDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between two vectors. + Signature: ```typescript -euclideanDistance(vectorExpression: Expression): FunctionExpression; +euclideanDistance(vector: VectorValue | number[]): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (as an array of numbers) to calculate with. A new Expr representing the Euclidean distance between the two vectors. | +| vector | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as a VectorValue) to compare against. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.euclideanDistance() +A new `Expression` representing the Euclidean distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Euclidean distance between two vectors. ```typescript // Calculate the Euclidean distance between the 'location' field and a target location @@ -1951,90 +1466,86 @@ field("location").euclideanDistance(new VectorValue([37.7749, -122.4194])); ``` -Signature: +## Expression.exists() -```typescript -euclideanDistance(vector: VectorValue | number[]): FunctionExpression; -``` +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> -#### Parameters +Creates an expression that checks if a field exists in the document. -| Parameter | Type | Description | -| --- | --- | --- | -| vector | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as a VectorValue) to compare against. A new Expr representing the Euclidean distance between the two vectors. | +Signature: +```typescript +exists(): BooleanExpression; +``` Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.exists() +A new `Expression` representing the 'exists' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field exists in the document. ```typescript // Check if the document has a field named "phoneNumber" field("phoneNumber").exists(); ``` - A new `Expr` representing the 'exists' check. + +## Expression.exp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes e to the power of this expression. Signature: ```typescript -exists(): BooleanExpression; +exp(): FunctionExpression; ``` Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.exp() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the exp of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes e to the power of this expression. ```typescript // Compute e to the power of the 'value' field. field("value").exp(); ``` - A new representing the exp of the numeric value. + +## Expression.floor() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the floor of a numeric value. Signature: ```typescript -exp(): FunctionExpression; +floor(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.floor() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the floor of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the floor of a numeric value. ```typescript // Compute the floor of the 'price' field. field("price").floor(); ``` - A new representing the floor of the numeric value. - -Signature: - -```typescript -floor(): FunctionExpression; -``` -Returns: - -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) ## Expression.greaterThan() @@ -2043,12 +1554,6 @@ floor(): FunctionExpression; Creates an expression that checks if this expression is greater than another expression. -```typescript -// Check if the 'age' field is greater than the 'limit' field -field("age").greaterThan(field("limit")); - -``` - Signature: ```typescript @@ -2059,25 +1564,30 @@ greaterThan(expression: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for greater than. A new Expr representing the greater than comparison. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for greater than. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.greaterThan() +A new `Expression` representing the greater than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is greater than a constant value. ```typescript -// Check if the 'price' field is greater than 100 -field("price").greaterThan(100); +// Check if the 'age' field is greater than the 'limit' field +field("age").greaterThan(field("limit")); ``` +## Expression.greaterThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than a constant value. + Signature: ```typescript @@ -2088,25 +1598,30 @@ greaterThan(value: unknown): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The constant value to compare for greater than. A new Expr representing the greater than comparison. | +| value | unknown | The constant value to compare for greater than. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.greaterThanOrEqual() +A new `Expression` representing the greater than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is greater than or equal to another expression. ```typescript -// Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1 -field("quantity").greaterThanOrEqual(field('requirement').add(1)); +// Check if the 'price' field is greater than 100 +field("price").greaterThan(100); ``` +## Expression.greaterThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than or equal to another expression. + Signature: ```typescript @@ -2117,25 +1632,30 @@ greaterThanOrEqual(expression: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for greater than or equal to. A new Expr representing the greater than or equal to comparison. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for greater than or equal to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.greaterThanOrEqual() +A new `Expression` representing the greater than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is greater than or equal to a constant value. ```typescript -// Check if the 'score' field is greater than or equal to 80 -field("score").greaterThanOrEqual(80); +// Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1 +field("quantity").greaterThanOrEqual(field('requirement').add(1)); ``` +## Expression.greaterThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than or equal to a constant value. + Signature: ```typescript @@ -2146,26 +1666,30 @@ greaterThanOrEqual(value: unknown): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The constant value to compare for greater than or equal to. A new Expr representing the greater than or equal to comparison. | +| value | unknown | The constant value to compare for greater than or equal to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.ifAbsent() +A new `Expression` representing the greater than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of the this expression evaluation. ```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -field("optional_field").ifAbsent("default_value") +// Check if the 'score' field is greater than or equal to 80 +field("score").greaterThanOrEqual(80); ``` +## Expression.ifAbsent() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of the this expression evaluation. + Signature: ```typescript @@ -2176,12 +1700,24 @@ ifAbsent(elseValue: unknown): Expression; | Parameter | Type | Description | | --- | --- | --- | -| elseValue | unknown | The value that will be returned if this Expression evaluates to an absent value. A new \[Expression\] representing the ifAbsent operation. | +| elseValue | unknown | The value that will be returned if this Expression evaluates to an absent value. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new \[Expression\] representing the ifAbsent operation. + +### Example + + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +field("optional_field").ifAbsent("default_value") + +``` + ## Expression.ifAbsent() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2206,12 +1742,14 @@ ifAbsent(elseExpression: unknown): Expression; | Parameter | Type | Description | | --- | --- | --- | -| elseExpression | unknown | The Expression that will be evaluated if this Expression evaluates to an absent value. A new \[Expression\] representing the ifAbsent operation. | +| elseExpression | unknown | The Expression that will be evaluated if this Expression evaluates to an absent value. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new \[Expression\] representing the ifAbsent operation. + ## Expression.ifError() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2219,13 +1757,6 @@ ifAbsent(elseExpression: unknown): Expression; Creates an expression that returns the result of the `catchExpr` argument if there is an error, else return the result of this expression. -```typescript -// Returns the first item in the title field arrays, or returns -// the entire title field if the array is empty or the field is another type. -field("title").arrayGet(0).ifError(field("title")); - -``` - Signature: ```typescript @@ -2236,25 +1767,30 @@ ifError(catchExpr: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| catchExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The catch expression that will be evaluated and returned if this expression produces an error. A new representing the 'ifError' operation. | +| catchExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The catch expression that will be evaluated and returned if this expression produces an error. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.ifError() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. ```typescript // Returns the first item in the title field arrays, or returns -// "Default Title" -field("title").arrayGet(0).ifError("Default Title"); +// the entire title field if the array is empty or the field is another type. +field("title").arrayGet(0).ifError(field("title")); + +``` + +## Expression.ifError() -``` +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. Signature: @@ -2266,25 +1802,30 @@ ifError(catchValue: unknown): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| catchValue | unknown | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | +| catchValue | unknown | The value that will be returned if this expression produces an error. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.isAbsent() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns `true` if the result of this expression is absent. Otherwise, returns `false` even if the value is `null`. ```typescript -// Check if the field `value` is absent. -field("value").isAbsent(); +// Returns the first item in the title field arrays, or returns +// "Default Title" +field("title").arrayGet(0).ifError("Default Title"); ``` - A new representing the 'isAbsent' check. + +## Expression.isAbsent() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns `true` if the result of this expression is absent. Otherwise, returns `false` even if the value is `null`. Signature: @@ -2295,19 +1836,24 @@ isAbsent(): BooleanExpression; [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.isError() +A new [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) representing the 'isAbsent' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a given expression produces an error. ```typescript -// Check if the result of a calculation is an error -field("title").arrayContains(1).isError(); +// Check if the field `value` is absent. +field("value").isAbsent(); +@example ``` - A new representing the 'isError' check. + +## Expression.isError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a given expression produces an error. Signature: @@ -2318,19 +1864,24 @@ isError(): BooleanExpression; [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.join() +A new [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) representing the 'isError' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that joins the elements of an array into a string. ```typescript -// Join the elements of the 'tags' field with the delimiter from the 'separator' field. -field("tags").join(field("separator")) +// Check if the result of a calculation is an error +field("title").arrayContains(1).isError(); ``` +## Expression.join() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + Signature: ```typescript @@ -2341,25 +1892,30 @@ join(delimiterExpression: Expression): Expression; | Parameter | Type | Description | | --- | --- | --- | -| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. A new Expression representing the join operation. | +| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) -## Expression.join() +A new Expression representing the join operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that joins the elements of an array field into a string. ```typescript -// Join the elements of the 'tags' field with a comma and space. -field("tags").join(", ") +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +field("tags").join(field("separator")) ``` +## Expression.join() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array field into a string. + Signature: ```typescript @@ -2370,28 +1926,29 @@ join(delimiter: string): Expression; | Parameter | Type | Description | | --- | --- | --- | -| delimiter | string | The string to use as a delimiter. A new Expression representing the join operation. | +| delimiter | string | The string to use as a delimiter. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) -## Expression.length() +A new Expression representing the join operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of a string, array, map, vector, or bytes. ```typescript -// Get the length of the 'name' field. -field("name").length(); - -// Get the number of items in the 'cart' array. -field("cart").length(); +// Join the elements of the 'tags' field with a comma and space. +field("tags").join(", ") ``` - A new `Expr` representing the length of the string, array, map, vector, or bytes. + +## Expression.length() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string, array, map, vector, or bytes. Signature: @@ -2402,19 +1959,27 @@ length(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.lessThan() +A new `Expression` representing the length of the string, array, map, vector, or bytes. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is less than another expression. ```typescript -// Check if the 'age' field is less than 'limit' -field("age").lessThan(field('limit')); +// Get the length of the 'name' field. +field("name").length(); + +// Get the number of items in the 'cart' array. +field("cart").length(); ``` +## Expression.lessThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than another expression. + Signature: ```typescript @@ -2425,25 +1990,30 @@ lessThan(experession: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| experession | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for less than. A new Expr representing the less than comparison. | +| experession | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for less than. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.lessThan() +A new `Expression` representing the less than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is less than a constant value. ```typescript -// Check if the 'price' field is less than 50 -field("price").lessThan(50); +// Check if the 'age' field is less than 'limit' +field("age").lessThan(field('limit')); ``` +## Expression.lessThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than a constant value. + Signature: ```typescript @@ -2454,25 +2024,30 @@ lessThan(value: unknown): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The constant value to compare for less than. A new Expr representing the less than comparison. | +| value | unknown | The constant value to compare for less than. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.lessThanOrEqual() +A new `Expression` representing the less than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is less than or equal to another expression. ```typescript -// Check if the 'quantity' field is less than or equal to 20 -field("quantity").lessThan(constant(20)); +// Check if the 'price' field is less than 50 +field("price").lessThan(50); ``` +## Expression.lessThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than or equal to another expression. + Signature: ```typescript @@ -2483,25 +2058,30 @@ lessThanOrEqual(expression: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for less than or equal to. A new Expr representing the less than or equal to comparison. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for less than or equal to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.lessThanOrEqual() +A new `Expression` representing the less than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is less than or equal to a constant value. ```typescript -// Check if the 'score' field is less than or equal to 70 -field("score").lessThan(70); +// Check if the 'quantity' field is less than or equal to 20 +field("quantity").lessThan(constant(20)); ``` +## Expression.lessThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than or equal to a constant value. + Signature: ```typescript @@ -2512,25 +2092,30 @@ lessThanOrEqual(value: unknown): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The constant value to compare for less than or equal to. A new Expr representing the less than or equal to comparison. | +| value | unknown | The constant value to compare for less than or equal to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.like() +A new `Expression` representing the less than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a case-sensitive string comparison. ```typescript -// Check if the 'title' field contains the word "guide" (case-sensitive) -field("title").like("%guide%"); +// Check if the 'score' field is less than or equal to 70 +field("score").lessThan(70); ``` +## Expression.like() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive string comparison. + Signature: ```typescript @@ -2541,18 +2126,16 @@ like(pattern: string): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| pattern | string | The pattern to search for. You can use "%" as a wildcard character. A new Expr representing the 'like' comparison. | +| pattern | string | The pattern to search for. You can use "%" as a wildcard character. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.like() +A new `Expression` representing the 'like' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a case-sensitive string comparison. ```typescript // Check if the 'title' field contains the word "guide" (case-sensitive) @@ -2560,6 +2143,13 @@ field("title").like("%guide%"); ``` +## Expression.like() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive string comparison. + Signature: ```typescript @@ -2570,25 +2160,29 @@ like(pattern: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. A new Expr representing the 'like' comparison. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.ln() +A new `Expression` representing the 'like' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the natural logarithm of a numeric value. ```typescript -// Compute the natural logarithm of the 'value' field. -field("value").ln(); +// Check if the 'title' field contains the word "guide" (case-sensitive) +field("title").like("%guide%"); ``` - A new representing the natural logarithm of the numeric value. + +## Expression.ln() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the natural logarithm of a numeric value. Signature: @@ -2599,19 +2193,23 @@ ln(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.log10() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the natural logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the base-10 logarithm of a numeric value. ```typescript -// Compute the base-10 logarithm of the 'value' field. -field("value").log10(); +// Compute the natural logarithm of the 'value' field. +field("value").ln(); ``` - A new representing the base-10 logarithm of the numeric value. + +## Expression.log10() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the base-10 logarithm of a numeric value. Signature: @@ -2622,19 +2220,24 @@ log10(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.logicalMaximum() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the base-10 logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. ```typescript -// Returns the larger value between the 'timestamp' field and the current timestamp. -field("timestamp").logicalMaximum(Function.currentTimestamp()); +// Compute the base-10 logarithm of the 'value' field. +field("value").log10(); ``` +## Expression.logicalMaximum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. + Signature: ```typescript @@ -2646,25 +2249,30 @@ logicalMaximum(second: Expression | unknown, ...others: ArrayReturns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.logicalMinimum() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical maximum operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. ```typescript -// Returns the smaller value between the 'timestamp' field and the current timestamp. -field("timestamp").logicalMinimum(Function.currentTimestamp()); +// Returns the larger value between the 'timestamp' field and the current timestamp. +field("timestamp").logicalMaximum(Function.currentTimestamp()); ``` +## Expression.logicalMinimum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. + Signature: ```typescript @@ -2676,11 +2284,22 @@ logicalMinimum(second: Expression | unknown, ...others: ArrayReturns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical minimum operation. + +### Example + + +```typescript +// Returns the smaller value between the 'timestamp' field and the current timestamp. +field("timestamp").logicalMinimum(Function.currentTimestamp()); + +``` ## Expression.mapGet() @@ -2689,12 +2308,6 @@ logicalMinimum(second: Expression | unknown, ...others: ArraySignature: ```typescript @@ -2705,12 +2318,23 @@ mapGet(subfield: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| subfield | string | The key to access in the map. A new Expr representing the value associated with the given key in the map. | +| subfield | string | The key to access in the map. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the value associated with the given key in the map. + +### Example + + +```typescript +// Get the 'city' value from the 'address' map field +field("address").mapGet("city"); + +``` + ## Expression.mapMerge() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2718,13 +2342,6 @@ mapGet(subfield: string): FunctionExpression; Creates an expression that merges multiple map values. -``` -// 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}, {}) - -``` - Signature: ```typescript @@ -2742,7 +2359,17 @@ mapMerge(secondMap: Record | Expression, ...otherMaps: ArraySignature: ```typescript @@ -2773,21 +2394,24 @@ mapRemove(key: string): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new representing the 'mapRemove' operation. - -## Expression.mapRemove() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'mapRemove' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that removes a key from the map produced by evaluating this expression. ``` // Removes the key 'baz' from the input map. -map({foo: 'bar', baz: true}).mapRemove(constant('baz')); +map({foo: 'bar', baz: true}).mapRemove('baz'); ``` +## Expression.mapRemove() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map produced by evaluating this expression. + Signature: ```typescript @@ -2804,7 +2428,17 @@ mapRemove(keyExpr: Expression): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new representing the 'mapRemove' operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'mapRemove' operation. + +### Example + + +``` +// Removes the key 'baz' from the input map. +map({foo: 'bar', baz: true}).mapRemove(constant('baz')); +@example + +``` ## Expression.maximum() @@ -2813,51 +2447,80 @@ A new representing the 'mapRemove' operation. Creates an aggregation that finds the maximum value of a field across multiple stage inputs. +Signature: + +```typescript +maximum(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'maximum' aggregation. + +### Example + + ```typescript // Find the highest score in a leaderboard field("score").maximum().as("highestScore"); ``` - A new `AggregateFunction` representing the 'maximum' aggregation. + +## Expression.minimum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the minimum value of a field across multiple stage inputs. Signature: ```typescript -maximum(): AggregateFunction; +minimum(): AggregateFunction; ``` Returns: [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -## Expression.minimum() +A new `AggregateFunction` representing the 'minimum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that finds the minimum value of a field across multiple stage inputs. ```typescript // Find the lowest price of all products field("price").minimum().as("lowestPrice"); ``` - A new `AggregateFunction` representing the 'minimum' aggregation. + +## Expression.mod() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. Signature: ```typescript -minimum(): AggregateFunction; +mod(expression: Expression): FunctionExpression; ``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to divide by. | + Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.mod() +A new `Expression` representing the modulo operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. ```typescript // Calculate the remainder of dividing the 'value' field by the 'divisor' field @@ -2865,28 +2528,33 @@ field("value").mod(field("divisor")); ``` +## Expression.mod() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. + Signature: ```typescript -mod(expression: Expression): FunctionExpression; +mod(value: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to divide by. A new Expr representing the modulo operation. | +| value | number | The constant value to divide by. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.mod() +A new `Expression` representing the modulo operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. ```typescript // Calculate the remainder of dividing the 'value' field by 10 @@ -2894,28 +2562,33 @@ field("value").mod(10); ``` +## Expression.multiply() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that multiplies this expression by another expression. + Signature: ```typescript -mod(value: number): FunctionExpression; +multiply(second: Expression | number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| value | number | The constant value to divide by. A new Expr representing the modulo operation. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| number | The second expression or literal to multiply by. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.multiply() +A new `Expression` representing the multiplication operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that multiplies this expression by another expression. ```typescript // Multiply the 'quantity' field by the 'price' field @@ -2923,28 +2596,33 @@ field("quantity").multiply(field("price")); ``` +## Expression.notEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to another expression. + Signature: ```typescript -multiply(second: Expression | number): FunctionExpression; +notEqual(expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| number | The second expression or literal to multiply by. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for inequality. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.notEqual() +A new `Expression` representing the inequality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is not equal to another expression. ```typescript // Check if the 'status' field is not equal to "completed" @@ -2952,28 +2630,33 @@ field("status").notEqual("completed"); ``` +## Expression.notEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to a constant value. + Signature: ```typescript -notEqual(expression: Expression): BooleanExpression; +notEqual(value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare for inequality. A new Expr representing the inequality comparison. | +| value | unknown | The constant value to compare for inequality. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.notEqual() +A new `Expression` representing the inequality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is not equal to a constant value. ```typescript // Check if the 'country' field is not equal to "USA" @@ -2981,28 +2664,33 @@ field("country").notEqual("USA"); ``` +## Expression.notEqualAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to any of the provided values or expressions. + Signature: ```typescript -notEqual(value: unknown): BooleanExpression; +notEqualAny(values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The constant value to compare for inequality. A new Expr representing the inequality comparison. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values or expressions to check against. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.notEqualAny() +A new `Expression` representing the 'notEqualAny' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is not equal to any of the provided values or expressions. ```typescript // Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' @@ -3010,28 +2698,33 @@ field("status").notEqualAny(["pending", field("rejectedStatus")]); ``` +## Expression.notEqualAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. + Signature: ```typescript -notEqualAny(values: Array): BooleanExpression; +notEqualAny(arrayExpression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values or expressions to check against. A new Expr representing the 'notEqualAny' comparison. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The values or expressions to check against. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.notEqualAny() +A new `Expression` representing the 'notEqualAny' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. ```typescript // Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' @@ -3039,28 +2732,33 @@ field("status").notEqualAny(field('rejectedStatuses')); ``` +## Expression.pow() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of this expression raised to the power of another expression. + Signature: ```typescript -notEqualAny(arrayExpression: Expression): BooleanExpression; +pow(exponent: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The values or expressions to check against. A new Expr representing the 'notEqualAny' comparison. | +| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise this expression to the power of. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.pow() +A new `Expression` representing the power operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the value of this expression raised to the power of another expression. ```typescript // Raise the value of the 'base' field to the power of the 'exponent' field. @@ -3068,28 +2766,33 @@ field("base").pow(field("exponent")); ``` +## Expression.pow() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of this expression raised to the power of a constant value. + Signature: ```typescript -pow(exponent: Expression): FunctionExpression; +pow(exponent: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise this expression to the power of. A new Expr representing the power operation. | +| exponent | number | The constant value to raise this expression to the power of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.pow() +A new `Expression` representing the power operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the value of this expression raised to the power of a constant value. ```typescript // Raise the value of the 'base' field to the power of 2. @@ -3097,57 +2800,67 @@ field("base").pow(2); ``` +## Expression.regexContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains a specified regular expression as a substring. + Signature: ```typescript -pow(exponent: number): FunctionExpression; +regexContains(pattern: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| exponent | number | The constant value to raise this expression to the power of. A new Expr representing the power operation. | +| pattern | string | The regular expression to use for the search. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.regexContains() +A new `Expression` representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string contains a specified regular expression as a substring. ```typescript // Check if the 'description' field contains "example" (case-insensitive) field("description").regexContains("(?i)example"); -``` +``` + +## Expression.regexContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains a specified regular expression as a substring. Signature: ```typescript -regexContains(pattern: string): BooleanExpression; +regexContains(pattern: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| pattern | string | The regular expression to use for the search. A new Expr representing the 'contains' comparison. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the search. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.regexContains() +A new `Expression` representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string contains a specified regular expression as a substring. ```typescript // Check if the 'description' field contains the regular expression stored in field 'regex' @@ -3155,28 +2868,33 @@ field("description").regexContains(field("regex")); ``` +## Expression.regexMatch() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string matches a specified regular expression. + Signature: ```typescript -regexContains(pattern: Expression): BooleanExpression; +regexMatch(pattern: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the search. A new Expr representing the 'contains' comparison. | +| pattern | string | The regular expression to use for the match. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.regexMatch() +A new `Expression` representing the regular expression match. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string matches a specified regular expression. ```typescript // Check if the 'email' field matches a valid email pattern @@ -3184,28 +2902,33 @@ field("email").regexMatch("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); ``` +## Expression.regexMatch() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string matches a specified regular expression. + Signature: ```typescript -regexMatch(pattern: string): BooleanExpression; +regexMatch(pattern: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| pattern | string | The regular expression to use for the match. A new Expr representing the regular expression match. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the match. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.regexMatch() +A new `Expression` representing the regular expression match. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string matches a specified regular expression. ```typescript // Check if the 'email' field matches a regular expression stored in field 'regex' @@ -3213,67 +2936,59 @@ field("email").regexMatch(field("regex")); ``` -Signature: +## Expression.reverse() -```typescript -regexMatch(pattern: Expression): BooleanExpression; -``` +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> -#### Parameters +Creates an expression that reverses this string expression. -| Parameter | Type | Description | -| --- | --- | --- | -| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the match. A new Expr representing the regular expression match. | +Signature: +```typescript +reverse(): FunctionExpression; +``` Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.reverse() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses this string expression. ```typescript // Reverse the value of the 'myString' field. field("myString").reverse(); ``` - A new representing the reversed string. + +## Expression.round() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the nearest whole number. Signature: ```typescript -reverse(): FunctionExpression; +round(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.round() +A new `Expression` representing the rounded value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that rounds a numeric value to the nearest whole number. ```typescript // Round the value of the 'price' field. field("price").round(); ``` - A new `Expr` representing the rounded value. - -Signature: - -```typescript -round(): FunctionExpression; -``` -Returns: - -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) ## Expression.round() @@ -3282,12 +2997,6 @@ round(): FunctionExpression; Creates an expression that rounds a numeric value to the specified number of decimal places. -```typescript -// Round the value of the 'price' field to two decimal places. -field("price").round(2); - -``` - Signature: ```typescript @@ -3298,25 +3007,30 @@ round(decimalPlaces: number): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| decimalPlaces | number | A constant specifying the rounding precision in decimal places. A new Expr representing the rounded value. | +| decimalPlaces | number | A constant specifying the rounding precision in decimal places. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.round() +A new `Expression` representing the rounded value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that rounds a numeric value to the specified number of decimal places. ```typescript // Round the value of the 'price' field to two decimal places. -field("price").round(constant(2)); +field("price").round(2); ``` +## Expression.round() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + Signature: ```typescript @@ -3327,12 +3041,23 @@ round(decimalPlaces: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| decimalPlaces | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression specifying the rounding precision in decimal places. A new Expr representing the rounded value. | +| decimalPlaces | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression specifying the rounding precision in decimal places. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the rounded value. + +### Example + + +```typescript +// Round the value of the 'price' field to two decimal places. +field("price").round(constant(2)); + +``` + ## Expression.split() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3356,6 +3081,8 @@ split(delimiter: string): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. + ### Example @@ -3364,7 +3091,6 @@ split(delimiter: string): FunctionExpression; field('scoresCsv').split(',') ``` - A new representing the split function. ## Expression.split() @@ -3389,6 +3115,8 @@ split(delimiter: Expression): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. + ### Example @@ -3397,7 +3125,6 @@ split(delimiter: Expression): FunctionExpression; field('scores').split(conditional(field('format').equal('csv'), constant(','), constant(':')) ``` - A new representing the split function. ## Expression.sqrt() @@ -3406,13 +3133,6 @@ field('scores').split(conditional(field('format').equal('csv'), constant(','), c Creates an expression that computes the square root of a numeric value. -```typescript -// Compute the square root of the 'value' field. -field("value").sqrt(); - -``` - A new representing the square root of the numeric value. - Signature: ```typescript @@ -3422,19 +3142,24 @@ sqrt(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.startsWith() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the square root of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string starts with a given prefix. ```typescript -// Check if the 'name' field starts with "Mr." -field("name").startsWith("Mr."); +// Compute the square root of the 'value' field. +field("value").sqrt(); ``` +## Expression.startsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string starts with a given prefix. + Signature: ```typescript @@ -3445,25 +3170,30 @@ startsWith(prefix: string): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| prefix | string | The prefix to check for. A new Expr representing the 'starts with' comparison. | +| prefix | string | The prefix to check for. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.startsWith() +A new `Expression` representing the 'starts with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string starts with a given prefix (represented as an expression). ```typescript -// Check if the 'fullName' field starts with the value of the 'firstName' field -field("fullName").startsWith(field("firstName")); +// Check if the 'name' field starts with "Mr." +field("name").startsWith("Mr."); ``` +## Expression.startsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string starts with a given prefix (represented as an expression). + Signature: ```typescript @@ -3474,25 +3204,30 @@ startsWith(prefix: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| prefix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The prefix expression to check for. A new Expr representing the 'starts with' comparison. | +| prefix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The prefix expression to check for. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.stringConcat() +A new `Expression` representing the 'starts with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that concatenates string expressions together. ```typescript -// Combine the 'firstName', " ", and 'lastName' fields into a single string -field("firstName").stringConcat(constant(" "), field("lastName")); +// Check if the 'fullName' field starts with the value of the 'firstName' field +field("fullName").startsWith(field("firstName")); ``` +## Expression.stringConcat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates string expressions together. + Signature: ```typescript @@ -3504,25 +3239,30 @@ stringConcat(secondString: Expression | string, ...otherStrings: ArrayExpr representing the concatenated string. | +| otherStrings | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or string literals to concatenate. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.stringContains() +A new `Expression` representing the concatenated string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string contains a specified substring. ```typescript -// Check if the 'description' field contains "example". -field("description").stringContains("example"); +// Combine the 'firstName', " ", and 'lastName' fields into a single string +field("firstName").stringConcat(constant(" "), field("lastName")); ``` +## Expression.stringContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains a specified substring. + Signature: ```typescript @@ -3533,25 +3273,30 @@ stringContains(substring: string): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| substring | string | The substring to search for. A new Expr representing the 'contains' comparison. | +| substring | string | The substring to search for. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.stringContains() +A new `Expression` representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string contains the string represented by another expression. ```typescript -// Check if the 'description' field contains the value of the 'keyword' field. -field("description").stringContains(field("keyword")); +// Check if the 'description' field contains "example". +field("description").stringContains("example"); ``` +## Expression.stringContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains the string represented by another expression. + Signature: ```typescript @@ -3562,25 +3307,29 @@ stringContains(expr: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the substring to search for. A new Expr representing the 'contains' comparison. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the substring to search for. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.stringReverse() +A new `Expression` representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses a string. ```typescript -// Reverse the value of the 'myString' field. -field("myString").stringReverse(); +// Check if the 'description' field contains the value of the 'keyword' field. +field("description").stringContains(field("keyword")); ``` - A new representing the reversed string. + +## Expression.stringReverse() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string. Signature: @@ -3591,6 +3340,17 @@ stringReverse(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. + +### Example + + +```typescript +// Reverse the value of the 'myString' field. +field("myString").stringReverse(); + +``` + ## Expression.substring() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3646,12 +3406,6 @@ substring(position: Expression, length?: Expression): FunctionExpression; Creates an expression that subtracts another expression from this expression. -```typescript -// Subtract the 'discount' field from the 'price' field -field("price").subtract(field("discount")); - -``` - Signature: ```typescript @@ -3662,25 +3416,30 @@ subtract(subtrahend: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| subtrahend | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract from this expression. A new Expr representing the subtraction operation. | +| subtrahend | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract from this expression. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.subtract() +A new `Expression` representing the subtraction operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a constant value from this expression. ```typescript -// Subtract 20 from the value of the 'total' field -field("total").subtract(20); +// Subtract the 'discount' field from the 'price' field +field("price").subtract(field("discount")); ``` +## Expression.subtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a constant value from this expression. + Signature: ```typescript @@ -3691,11 +3450,22 @@ subtract(subtrahend: number): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| subtrahend | number | The constant value to subtract. A new Expr representing the subtraction operation. | +| subtrahend | number | The constant value to subtract. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the subtraction operation. + +### Example -Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +```typescript +// Subtract 20 from the value of the 'total' field +field("total").subtract(20); + +``` ## Expression.sum() @@ -3704,13 +3474,6 @@ subtract(subtrahend: number): FunctionExpression; Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. -```typescript -// Calculate the total revenue from a set of orders -field("orderAmount").sum().as("totalRevenue"); - -``` - A new `AggregateFunction` representing the 'sum' aggregation. - Signature: ```typescript @@ -3720,19 +3483,24 @@ sum(): AggregateFunction; [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -## Expression.timestampAdd() +A new `AggregateFunction` representing the 'sum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that adds a specified amount of time to this timestamp expression. ```typescript -// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. -field("timestamp").timestampAdd(field("unit"), field("amount")); +// Calculate the total revenue from a set of orders +field("orderAmount").sum().as("totalRevenue"); ``` +## Expression.timestampAdd() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to this timestamp expression. + Signature: ```typescript @@ -3744,25 +3512,30 @@ timestampAdd(unit: Expression, amount: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | | unit | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | -| amount | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | +| amount | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.timestampAdd() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that adds a specified amount of time to this timestamp expression. ```typescript -// Add 1 day to the 'timestamp' field. -field("timestamp").timestampAdd("day", 1); +// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. +field("timestamp").timestampAdd(field("unit"), field("amount")); ``` +## Expression.timestampAdd() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to this timestamp expression. + Signature: ```typescript @@ -3774,25 +3547,30 @@ timestampAdd(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | Parameter | Type | Description | | --- | --- | --- | | unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | -| amount | number | The amount of time to add. A new representing the resulting timestamp. | +| amount | number | The amount of time to add. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.timestampSubtract() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a specified amount of time from this timestamp expression. ```typescript -// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. -field("timestamp").timestampSubtract(field("unit"), field("amount")); +// Add 1 day to the 'timestamp' field. +field("timestamp").timestampAdd("day", 1); ``` +## Expression.timestampSubtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from this timestamp expression. + Signature: ```typescript @@ -3804,25 +3582,30 @@ timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | | unit | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | -| amount | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | +| amount | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.timestampSubtract() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a specified amount of time from this timestamp expression. ```typescript -// Subtract 1 day from the 'timestamp' field. -field("timestamp").timestampSubtract("day", 1); +// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. +field("timestamp").timestampSubtract(field("unit"), field("amount")); ``` +## Expression.timestampSubtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from this timestamp expression. + Signature: ```typescript @@ -3834,25 +3617,29 @@ timestampSubtract(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'h | Parameter | Type | Description | | --- | --- | --- | | unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | -| amount | number | The amount of time to subtract. A new representing the resulting timestamp. | +| amount | number | The amount of time to subtract. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.timestampToUnixMicros() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to microseconds since epoch. -field("timestamp").timestampToUnixMicros(); +// Subtract 1 day from the 'timestamp' field. +field("timestamp").timestampSubtract("day", 1); ``` - A new representing the number of microseconds since epoch. + +## Expression.timestampToUnixMicros() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -3863,19 +3650,23 @@ timestampToUnixMicros(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.timestampToUnixMillis() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of microseconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -field("timestamp").timestampToUnixMillis(); +// Convert the 'timestamp' field to microseconds since epoch. +field("timestamp").timestampToUnixMicros(); ``` - A new representing the number of milliseconds since epoch. + +## Expression.timestampToUnixMillis() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -3886,19 +3677,23 @@ timestampToUnixMillis(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.timestampToUnixSeconds() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of milliseconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to seconds since epoch. -field("timestamp").timestampToUnixSeconds(); +// Convert the 'timestamp' field to milliseconds since epoch. +field("timestamp").timestampToUnixMillis(); ``` - A new representing the number of seconds since epoch. + +## Expression.timestampToUnixSeconds() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -3909,6 +3704,17 @@ timestampToUnixSeconds(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of seconds since epoch. + +### Example + + +```typescript +// Convert the 'timestamp' field to seconds since epoch. +field("timestamp").timestampToUnixSeconds(); + +``` + ## Expression.timestampTruncate() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3927,12 +3733,14 @@ timestampTruncate(granularity: TimeGranularity, timezone?: string | Expression): | Parameter | Type | Description | | --- | --- | --- | | granularity | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | The granularity to truncate to. | -| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the truncated timestamp. + ### Example @@ -3960,12 +3768,14 @@ timestampTruncate(granularity: Expression, timezone?: string | Expression): Func | Parameter | Type | Description | | --- | --- | --- | | granularity | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The granularity to truncate to. | -| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the truncated timestamp. + ### Example @@ -3982,13 +3792,6 @@ field('createdAt').timestampTruncate(field('granularity')) Creates an expression that converts a string to lowercase. -```typescript -// Convert the 'name' field to lowercase -field("name").toLower(); - -``` - A new `Expr` representing the lowercase string. - Signature: ```typescript @@ -3998,19 +3801,23 @@ toLower(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.toUpper() +A new `Expression` representing the lowercase string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a string to uppercase. ```typescript -// Convert the 'title' field to uppercase -field("title").toUpper(); +// Convert the 'name' field to lowercase +field("name").toLower(); ``` - A new `Expr` representing the uppercase string. + +## Expression.toUpper() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string to uppercase. Signature: @@ -4021,22 +3828,24 @@ toUpper(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.trim() +A new `Expression` representing the uppercase string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that removes leading and trailing characters from a string or byte array. ```typescript -// Trim whitespace from the 'userInput' field -field("userInput").trim(); - -// Trim quotes from the 'userInput' field -field("userInput").trim('"'); +// Convert the 'title' field to uppercase +field("title").toUpper(); ``` +## Expression.trim() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes leading and trailing characters from a string or byte array. + Signature: ```typescript @@ -4047,12 +3856,26 @@ trim(valueToTrim?: string | Expression | Bytes): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | 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. A new Expr representing the trimmed string or byte array. | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | 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: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the trimmed string or byte array. + +### Example + + +```typescript +// Trim whitespace from the 'userInput' field +field("userInput").trim(); + +// Trim quotes from the 'userInput' field +field("userInput").trim('"'); + +``` + ## Expression.type() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4069,6 +3892,8 @@ type(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the data type. + ### Example @@ -4077,7 +3902,6 @@ type(): FunctionExpression; field('title').type() ``` - A new {Expression} representing the data type. ## Expression.unixMicrosToTimestamp() @@ -4086,13 +3910,6 @@ field('title').type() 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. -```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -field("microseconds").unixMicrosToTimestamp(); - -``` - A new representing the timestamp. - Signature: ```typescript @@ -4102,19 +3919,23 @@ unixMicrosToTimestamp(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.unixMillisToTimestamp() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -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. ```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -field("milliseconds").unixMillisToTimestamp(); +// Interpret the 'microseconds' field as microseconds since epoch. +field("microseconds").unixMicrosToTimestamp(); ``` - A new representing the timestamp. + +## Expression.unixMillisToTimestamp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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. Signature: @@ -4125,19 +3946,23 @@ unixMillisToTimestamp(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.unixSecondsToTimestamp() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -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. ```typescript -// Interpret the 'seconds' field as seconds since epoch. -field("seconds").unixSecondsToTimestamp(); +// Interpret the 'milliseconds' field as milliseconds since epoch. +field("milliseconds").unixMillisToTimestamp(); ``` - A new representing the timestamp. + +## Expression.unixSecondsToTimestamp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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. Signature: @@ -4148,19 +3973,23 @@ unixSecondsToTimestamp(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## Expression.vectorLength() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. ```typescript -// Get the vector length (dimension) of the field 'embedding'. -field("embedding").vectorLength(); +// Interpret the 'seconds' field as seconds since epoch. +field("seconds").unixSecondsToTimestamp(); ``` - A new representing the length of the vector. + +## Expression.vectorLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. Signature: @@ -4171,3 +4000,14 @@ vectorLength(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the vector. + +### Example + + +```typescript +// Get the vector length (dimension) of the field 'embedding'. +field("embedding").vectorLength(); + +``` + diff --git a/docs-devsite/firestore_lite_pipelines.field.md b/docs-devsite/firestore_lite_pipelines.field.md index 37ec1ea479..f3b7ad7288 100644 --- a/docs-devsite/firestore_lite_pipelines.field.md +++ b/docs-devsite/firestore_lite_pipelines.field.md @@ -13,21 +13,12 @@ https://github.com/firebase/firebase-js-sdk > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Represents a reference to a field in a Firestore document, or outputs of a stage. +Represents a reference to a field in a Firestore document, or outputs of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) stage.

Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines.

You can create a `Field` instance using the static method: -```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"); - -``` - Signature: ```typescript @@ -101,3 +92,16 @@ get fieldName(): string; ```typescript selectable: true; ``` + +### 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"); + +``` + diff --git a/docs-devsite/firestore_lite_pipelines.functionexpression.md b/docs-devsite/firestore_lite_pipelines.functionexpression.md index ef3a422c16..22f7670d2e 100644 --- a/docs-devsite/firestore_lite_pipelines.functionexpression.md +++ b/docs-devsite/firestore_lite_pipelines.functionexpression.md @@ -13,9 +13,9 @@ https://github.com/firebase/firebase-js-sdk > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -This class defines the base class for Firestore functions, which can be evaluated within pipeline execution. +This class defines the base class for Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) functions, which can be evaluated within pipeline execution. -Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_.md#and_e72c712), , or the methods on (, , etc.) to construct new Function instances. +Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_pipelines.md#and_e0c48bd), [equal()](./firestore_pipelines.md#equal_b3c3382), or the methods on [Expression](./firestore_pipelines.expression.md#expression_class) ([Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), etc.) to construct new Function instances. Signature: diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 8173c81da6..1f2599ce81 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -16,1618 +16,276 @@ https://github.com/firebase/firebase-js-sdk | Function | Description | | --- | --- | | function() | -| [countAll()](./firestore_lite_pipelines.md#countall) | (Public Preview) Creates an aggregation that counts the total number of stage inputs. -```typescript -// Count the total number of input documents -countAll().as("totalDocument"); - -``` - A new representing the 'countAll' aggregation. | -| [currentTimestamp()](./firestore_lite_pipelines.md#currenttimestamp) | (Public Preview) Creates an expression that evaluates to the current server timestamp. -```typescript -// Get the current server timestamp -currentTimestamp() - -``` - A new Expression representing the current server timestamp. | +| [countAll()](./firestore_lite_pipelines.md#countall) | (Public Preview) Creates an aggregation that counts the total number of stage inputs. | +| [currentTimestamp()](./firestore_lite_pipelines.md#currenttimestamp) | (Public Preview) Creates an expression that evaluates to the current server timestamp. | | function(array, ...) | -| [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_a00ea48) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. -```typescript -// Check if the 'colors' array contains the value of field 'selectedColor' -arrayContains(field("colors"), field("selectedColor")); - -``` - | -| [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_7328608) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. -```typescript -// Check if the 'colors' array contains "red" -arrayContains(field("colors"), "red"); - -``` - | -| [arrayContainsAll(array, values)](./firestore_lite_pipelines.md#arraycontainsall_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. -```typescript -// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" -arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); - -``` - | -| [arrayContainsAll(array, arrayExpression)](./firestore_lite_pipelines.md#arraycontainsall_7b535db) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. -```typescript -// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" -arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); - -``` - | -| [arrayContainsAny(array, values)](./firestore_lite_pipelines.md#arraycontainsany_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. -```typescript -// Check if the 'categories' array contains either values from field "cate1" or "Science" -arrayContainsAny(field("categories"), [field("cate1"), "Science"]); - -``` - | -| [arrayContainsAny(array, values)](./firestore_lite_pipelines.md#arraycontainsany_c381a96) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. -```typescript -// Check if the 'categories' array contains either values from field "cate1" or "Science" -arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); - -``` - | -| [arrayLength(array)](./firestore_lite_pipelines.md#arraylength_195e339) | (Public Preview) Creates an expression that calculates the length of an array expression. -```typescript -// Get the number of items in the 'cart' array -arrayLength(field("cart")); - -``` - | +| [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_a00ea48) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. | +| [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_7328608) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. | +| [arrayContainsAll(array, values)](./firestore_lite_pipelines.md#arraycontainsall_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. | +| [arrayContainsAll(array, arrayExpression)](./firestore_lite_pipelines.md#arraycontainsall_7b535db) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. | +| [arrayContainsAny(array, values)](./firestore_lite_pipelines.md#arraycontainsany_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. | +| [arrayContainsAny(array, values)](./firestore_lite_pipelines.md#arraycontainsany_c381a96) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. | +| [arrayLength(array)](./firestore_lite_pipelines.md#arraylength_195e339) | (Public Preview) Creates an expression that calculates the length of an array expression. | | function(arrayExpression, ...) | -| [arrayGet(arrayExpression, offset)](./firestore_lite_pipelines.md#arrayget_f2e27cc) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index 1. -arrayGet(field('tags'), 1); - -``` - | -| [arrayGet(arrayExpression, offsetExpr)](./firestore_lite_pipelines.md#arrayget_484550d) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -arrayGet(field('tags'), field('favoriteTag')); - -``` - | -| [join(arrayExpression, delimiterExpression)](./firestore_lite_pipelines.md#join_313e6aa) | (Public Preview) Creates an expression that joins the elements of an array into a string. -```typescript -// Join an array of string using the delimiter from the 'separator' field. -join(array(['foo', 'bar']), field("separator")) - -``` - | -| [join(arrayExpression, delimiter)](./firestore_lite_pipelines.md#join_d088d29) | (Public Preview) Creates an expression that joins the elements of an array into a string. -```typescript -// Join the elements of the 'tags' field with a comma and space. -join(field("tags"), ", ") - -``` - | +| [arrayGet(arrayExpression, offset)](./firestore_lite_pipelines.md#arrayget_f2e27cc) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(arrayExpression, offsetExpr)](./firestore_lite_pipelines.md#arrayget_484550d) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [join(arrayExpression, delimiterExpression)](./firestore_lite_pipelines.md#join_313e6aa) | (Public Preview) Creates an expression that joins the elements of an array into a string. | +| [join(arrayExpression, delimiter)](./firestore_lite_pipelines.md#join_d088d29) | (Public Preview) Creates an expression that joins the elements of an array into a string. | | function(arrayField, ...) | -| [arrayGet(arrayField, offset)](./firestore_lite_pipelines.md#arrayget_3f58471) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index 1. -arrayGet('tags', 1); - -``` - | -| [arrayGet(arrayField, offsetExpr)](./firestore_lite_pipelines.md#arrayget_1904c9a) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -arrayGet('tags', field('favoriteTag')); - -``` - | +| [arrayGet(arrayField, offset)](./firestore_lite_pipelines.md#arrayget_3f58471) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(arrayField, offsetExpr)](./firestore_lite_pipelines.md#arrayget_1904c9a) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | | function(arrayFieldName, ...) | -| [join(arrayFieldName, delimiter)](./firestore_lite_pipelines.md#join_478ef36) | (Public Preview) Creates an expression that joins the elements of an array into a string. -```typescript -// Join the elements of the 'tags' field with a comma and space. -join("tags", ", ") - -``` - | -| [join(arrayFieldName, delimiterExpression)](./firestore_lite_pipelines.md#join_829294c) | (Public Preview) Creates an expression that joins the elements of an array into a string. -```typescript -// Join the elements of the 'tags' field with the delimiter from the 'separator' field. -join('tags', field("separator")) - -``` - | +| [join(arrayFieldName, delimiter)](./firestore_lite_pipelines.md#join_478ef36) | (Public Preview) Creates an expression that joins the elements of an array into a string. | +| [join(arrayFieldName, delimiterExpression)](./firestore_lite_pipelines.md#join_829294c) | (Public Preview) Creates an expression that joins the elements of an array into a string. | | function(base, ...) | -| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_e4a9e64) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent expression. -```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -pow(field("base"), field("exponent")); - -``` - | -| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_93eae7f) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent. -```typescript -// Raise the value of the 'base' field to the power of 2. -pow(field("base"), 2); - -``` - | -| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_a237721) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent expression. -```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -pow("base", field("exponent")); - -``` - | -| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_f4d7908) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent. -```typescript -// Raise the value of the 'base' field to the power of 2. -pow("base", 2); - -``` - | +| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_e4a9e64) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent expression. | +| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_93eae7f) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent. | +| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_a237721) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent expression. | +| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_f4d7908) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent. | | function(booleanExpr, ...) | -| [countIf(booleanExpr)](./firestore_lite_pipelines.md#countif_c5b8fb1) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. -```typescript -// Count the number of documents where 'is_active' field equals true -countIf(field("is_active").equal(true)).as("numActiveDocuments"); - -``` - | -| [not(booleanExpr)](./firestore_lite_pipelines.md#not_c5b8fb1) | (Public Preview) Creates an expression that negates a filter condition. -```typescript -// Find documents where the 'completed' field is NOT true -not(equal("completed", true)); - -``` - | +| [countIf(booleanExpr)](./firestore_lite_pipelines.md#countif_c5b8fb1) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. | +| [not(booleanExpr)](./firestore_lite_pipelines.md#not_c5b8fb1) | (Public Preview) Creates an expression that negates a filter condition. | | function(condition, ...) | -| [conditional(condition, thenExpr, elseExpr)](./firestore_lite_pipelines.md#conditional_07a206d) | (Public Preview) Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. -```typescript -// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". -conditional( - greaterThan("age", 18), constant("Adult"), constant("Minor")); - -``` - | +| [conditional(condition, thenExpr, elseExpr)](./firestore_lite_pipelines.md#conditional_07a206d) | (Public Preview) Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. | | function(documentPath, ...) | -| [documentId(documentPath)](./firestore_lite_pipelines.md#documentid_cef293c) | (Public Preview) Creates an expression that returns the document ID from a path. -```typescript -// Get the document ID from a path. -documentId(myDocumentReference); - -``` - A new representing the documentId operation. | +| [documentId(documentPath)](./firestore_lite_pipelines.md#documentid_cef293c) | (Public Preview) Creates an expression that returns the document ID from a path. | | function(documentPathExpr, ...) | -| [documentId(documentPathExpr)](./firestore_lite_pipelines.md#documentid_9a69021) | (Public Preview) Creates an expression that returns the document ID from a path. -```typescript -// Get the document ID from a path. -documentId(field("__path__")); - -``` - A new representing the documentId operation. | +| [documentId(documentPathExpr)](./firestore_lite_pipelines.md#documentid_9a69021) | (Public Preview) Creates an expression that returns the document ID from a path. | | function(element, ...) | -| [notEqualAny(element, values)](./firestore_lite_pipelines.md#notequalany_c2c5bcb) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. -```typescript -// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' -notEqualAny(field("status"), ["pending", field("rejectedStatus")]); - -``` - | -| [notEqualAny(element, arrayExpression)](./firestore_lite_pipelines.md#notequalany_16b2851) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. -```typescript -// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' -notEqualAny(field("status"), ["pending", field("rejectedStatus")]); - -``` - | +| [notEqualAny(element, values)](./firestore_lite_pipelines.md#notequalany_c2c5bcb) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | +| [notEqualAny(element, arrayExpression)](./firestore_lite_pipelines.md#notequalany_16b2851) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | | function(elements, ...) | -| [array(elements)](./firestore_lite_pipelines.md#array_7d853aa) | (Public Preview) Creates an expression that creates a Firestore array value from an input array. -```typescript -// Create an array value from the input array and reference the 'baz' field value from the input document. -array(['bar', Field.of('baz')]).as('foo'); - -``` - | -| [map(elements)](./firestore_lite_pipelines.md#map_ce5dee1) | (Public Preview) Creates an expression that creates a Firestore map value from an input object. -```typescript -// Create a map from the input object and reference the 'baz' field value from the input document. -map({foo: 'bar', baz: Field.of('baz')}).as('data'); - -``` - | +| [array(elements)](./firestore_lite_pipelines.md#array_7d853aa) | (Public Preview) Creates an expression that creates a Firestore array value from an input array. | +| [map(elements)](./firestore_lite_pipelines.md#map_ce5dee1) | (Public Preview) Creates an expression that creates a Firestore map value from an input object. | | function(expr, ...) | | [abs(expr)](./firestore_lite_pipelines.md#abs_005f3d4) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | -| [ascending(expr)](./firestore_lite_pipelines.md#ascending_005f3d4) | (Public Preview) Creates an that sorts documents in ascending order based on an expression. -```typescript -// Sort documents by the 'name' field in lowercase in ascending order -firestore.pipeline().collection("users") - .sort(ascending(field("name").toLower())); - -``` - | -| [byteLength(expr)](./firestore_lite_pipelines.md#bytelength_005f3d4) | (Public Preview) Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. -```typescript -// Calculate the length of the 'myString' field in bytes. -byteLength(field("myString")); - -``` - | +| [ascending(expr)](./firestore_lite_pipelines.md#ascending_005f3d4) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. | +| [byteLength(expr)](./firestore_lite_pipelines.md#bytelength_005f3d4) | (Public Preview) Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. | | [countDistinct(expr)](./firestore_lite_pipelines.md#countdistinct_3c28b08) | (Public Preview) Creates an aggregation that counts the number of distinct values of a field. | -| [descending(expr)](./firestore_lite_pipelines.md#descending_005f3d4) | (Public Preview) Creates an that sorts documents in descending order based on an expression. -```typescript -// Sort documents by the 'name' field in lowercase in descending order -firestore.pipeline().collection("users") - .sort(descending(field("name").toLower())); - -``` - | +| [descending(expr)](./firestore_lite_pipelines.md#descending_005f3d4) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. | | [floor(expr)](./firestore_lite_pipelines.md#floor_005f3d4) | (Public Preview) Creates an expression that computes the floor of a numeric value. | -| [timestampToUnixMicros(expr)](./firestore_lite_pipelines.md#timestamptounixmicros_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to microseconds since epoch. -timestampToUnixMicros(field("timestamp")); - -``` - | -| [timestampToUnixMillis(expr)](./firestore_lite_pipelines.md#timestamptounixmillis_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -timestampToUnixMillis(field("timestamp")); - -``` - | -| [timestampToUnixSeconds(expr)](./firestore_lite_pipelines.md#timestamptounixseconds_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to seconds since epoch. -timestampToUnixSeconds(field("timestamp")); - -``` - | -| [unixMicrosToTimestamp(expr)](./firestore_lite_pipelines.md#unixmicrostotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -unixMicrosToTimestamp(field("microseconds")); - -``` - | -| [unixMillisToTimestamp(expr)](./firestore_lite_pipelines.md#unixmillistotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -unixMillisToTimestamp(field("milliseconds")); - -``` - | -| [unixSecondsToTimestamp(expr)](./firestore_lite_pipelines.md#unixsecondstotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'seconds' field as seconds since epoch. -unixSecondsToTimestamp(field("seconds")); - -``` - | +| [timestampToUnixMicros(expr)](./firestore_lite_pipelines.md#timestamptounixmicros_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixMillis(expr)](./firestore_lite_pipelines.md#timestamptounixmillis_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixSeconds(expr)](./firestore_lite_pipelines.md#timestamptounixseconds_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [unixMicrosToTimestamp(expr)](./firestore_lite_pipelines.md#unixmicrostotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixMillisToTimestamp(expr)](./firestore_lite_pipelines.md#unixmillistotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixSecondsToTimestamp(expr)](./firestore_lite_pipelines.md#unixsecondstotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | | function(expression, ...) | -| [arraySum(expression)](./firestore_lite_pipelines.md#arraysum_1138a27) | (Public Preview) Creates an expression that computes the sum of the elements in an array. -```typescript -// Compute the sum of the elements in the 'scores' field. -arraySum(field("scores")); - -``` - | -| [average(expression)](./firestore_lite_pipelines.md#average_1138a27) | (Public Preview) Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. -```typescript -// Calculate the average age of users -average(field("age")).as("averageAge"); - -``` - | -| [ceil(expression)](./firestore_lite_pipelines.md#ceil_1138a27) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. -```typescript -// Compute the ceiling of the 'price' field. -ceil(field("price")); - -``` - | -| [collectionId(expression)](./firestore_lite_pipelines.md#collectionid_1138a27) | (Public Preview) Creates an expression that returns the collection ID from a path. -```typescript -// Get the collection ID from a path. -collectionId(field("__name__")); - -``` - | -| [count(expression)](./firestore_lite_pipelines.md#count_1138a27) | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. -```typescript -// Count the number of items where the price is greater than 10 -count(field("price").greaterThan(10)).as("expensiveItemCount"); - -``` - | -| [divide(expression, value)](./firestore_lite_pipelines.md#divide_01df3cf) | (Public Preview) Creates an expression that divides an expression by a constant value. -```typescript -// Divide the 'value' field by 10 -divide(field("value"), 10); - -``` - | -| [equal(expression, value)](./firestore_lite_pipelines.md#equal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is equal to a constant value. -```typescript -// Check if the 'age' field is equal to 21 -equal(field("age"), 21); - -``` - | -| [equalAny(expression, values)](./firestore_lite_pipelines.md#equalany_7e759b5) | (Public Preview) Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. -```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -equalAny(field("category"), [constant("Electronics"), field("primaryType")]); - -``` - | -| [equalAny(expression, arrayExpression)](./firestore_lite_pipelines.md#equalany_214ce68) | (Public Preview) Creates an expression that checks if an expression is equal to any of the provided values. -```typescript -// Check if the 'category' field is set to a value in the disabledCategories field -equalAny(field("category"), field('disabledCategories')); - -``` - | -| [exp(expression)](./firestore_lite_pipelines.md#exp_1138a27) | (Public Preview) Creates an expression that computes e to the power of the expression's result. -```typescript -// Compute e to the power of 2. -exp(constant(2)); - -``` - A new representing the exp of the numeric value. | -| [greaterThan(expression, value)](./firestore_lite_pipelines.md#greaterthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than a constant value. -```typescript -// Check if the 'age' field is greater than 18 -greaterThan(field("age"), 18); - -``` - | -| [greaterThanOrEqual(expression, value)](./firestore_lite_pipelines.md#greaterthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than or equal to a constant value. -```typescript -// Check if the 'quantity' field is greater than or equal to 10 -greaterThanOrEqual(field("quantity"), 10); - -``` - | -| [length\_2(expression)](./firestore_lite_pipelines.md#length_2_1138a27) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. -```typescript -// Get the length of the 'name' field. -length(field("name")); - -// Get the number of items in the 'cart' array. -length(field("cart")); - -``` - | -| [lessThan(expression, value)](./firestore_lite_pipelines.md#lessthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than a constant value. -```typescript -// Check if the 'age' field is less than 30 -lessThan(field("age"), 30); - -``` - | -| [lessThanOrEqual(expression, value)](./firestore_lite_pipelines.md#lessthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than or equal to a constant value. -```typescript -// Check if the 'quantity' field is less than or equal to 20 -lessThan(field("quantity"), 20); - -``` - | -| [ln(expression)](./firestore_lite_pipelines.md#ln_1138a27) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. -```typescript -// Compute the natural logarithm of the 'value' field. -ln(field("value")); - -``` - | -| [log(expression, base)](./firestore_lite_pipelines.md#log_ac183e2) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. -```typescript -// Compute the logarithm of the 'value' field with base 10. -log(field("value"), 10); - -``` - | -| [log(expression, base)](./firestore_lite_pipelines.md#log_1894737) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. -```typescript -// Compute the logarithm of the 'value' field with the base in the 'base' field. -log(field("value"), field("base")); - -``` - | -| [log10(expression)](./firestore_lite_pipelines.md#log10_1138a27) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. -```typescript -// Compute the base-10 logarithm of the 'value' field. -log10(field("value")); - -``` - | -| [maximum(expression)](./firestore_lite_pipelines.md#maximum_1138a27) | (Public Preview) Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. -```typescript -// Find the highest score in a leaderboard -maximum(field("score")).as("highestScore"); - -``` - | -| [minimum(expression)](./firestore_lite_pipelines.md#minimum_1138a27) | (Public Preview) Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. -```typescript -// Find the lowest price of all products -minimum(field("price")).as("lowestPrice"); - -``` - | -| [mod(expression, value)](./firestore_lite_pipelines.md#mod_01df3cf) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. -```typescript -// Calculate the remainder of dividing 'field1' by 5. -mod(field("field1"), 5); - -``` - | -| [notEqual(expression, value)](./firestore_lite_pipelines.md#notequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is not equal to a constant value. -```typescript -// Check if the 'status' field is not equal to "completed" -notEqual(field("status"), "completed"); - -``` - | -| [round(expression)](./firestore_lite_pipelines.md#round_1138a27) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. -```typescript -// Round the value of the 'price' field. -round(field("price")); - -``` - | -| [round(expression, decimalPlaces)](./firestore_lite_pipelines.md#round_a3a92d0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. -```typescript -// Round the value of the 'price' field to two decimal places. -round(field("price"), constant(2)); - -``` - | +| [arraySum(expression)](./firestore_lite_pipelines.md#arraysum_1138a27) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | +| [average(expression)](./firestore_lite_pipelines.md#average_1138a27) | (Public Preview) Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. | +| [ceil(expression)](./firestore_lite_pipelines.md#ceil_1138a27) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | +| [collectionId(expression)](./firestore_lite_pipelines.md#collectionid_1138a27) | (Public Preview) Creates an expression that returns the collection ID from a path. | +| [count(expression)](./firestore_lite_pipelines.md#count_1138a27) | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. | +| [divide(expression, value)](./firestore_lite_pipelines.md#divide_01df3cf) | (Public Preview) Creates an expression that divides an expression by a constant value. | +| [equal(expression, value)](./firestore_lite_pipelines.md#equal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is equal to a constant value. | +| [equalAny(expression, values)](./firestore_lite_pipelines.md#equalany_7e759b5) | (Public Preview) Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. | +| [equalAny(expression, arrayExpression)](./firestore_lite_pipelines.md#equalany_214ce68) | (Public Preview) Creates an expression that checks if an expression is equal to any of the provided values. | +| [exp(expression)](./firestore_lite_pipelines.md#exp_1138a27) | (Public Preview) Creates an expression that computes e to the power of the expression's result. | +| [greaterThan(expression, value)](./firestore_lite_pipelines.md#greaterthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than a constant value. | +| [greaterThanOrEqual(expression, value)](./firestore_lite_pipelines.md#greaterthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than or equal to a constant value. | +| [length\_2(expression)](./firestore_lite_pipelines.md#length_2_1138a27) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | +| [lessThan(expression, value)](./firestore_lite_pipelines.md#lessthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than a constant value. | +| [lessThanOrEqual(expression, value)](./firestore_lite_pipelines.md#lessthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than or equal to a constant value. | +| [ln(expression)](./firestore_lite_pipelines.md#ln_1138a27) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. | +| [log(expression, base)](./firestore_lite_pipelines.md#log_ac183e2) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. | +| [log(expression, base)](./firestore_lite_pipelines.md#log_1894737) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. | +| [log10(expression)](./firestore_lite_pipelines.md#log10_1138a27) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | +| [maximum(expression)](./firestore_lite_pipelines.md#maximum_1138a27) | (Public Preview) Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. | +| [minimum(expression)](./firestore_lite_pipelines.md#minimum_1138a27) | (Public Preview) Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. | +| [mod(expression, value)](./firestore_lite_pipelines.md#mod_01df3cf) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. | +| [notEqual(expression, value)](./firestore_lite_pipelines.md#notequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is not equal to a constant value. | +| [round(expression)](./firestore_lite_pipelines.md#round_1138a27) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | +| [round(expression, decimalPlaces)](./firestore_lite_pipelines.md#round_a3a92d0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | | [split(expression, delimiter)](./firestore_lite_pipelines.md#split_5b5612b) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | | [split(expression, delimiter)](./firestore_lite_pipelines.md#split_5a171ed) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | -| [sqrt(expression)](./firestore_lite_pipelines.md#sqrt_1138a27) | (Public Preview) Creates an expression that computes the square root of a numeric value. -```typescript -// Compute the square root of the 'value' field. -sqrt(field("value")); - -``` - | -| [subtract(expression, value)](./firestore_lite_pipelines.md#subtract_01df3cf) | (Public Preview) Creates an expression that subtracts a constant value from an expression. -```typescript -// Subtract the constant value 2 from the 'value' field -subtract(field("value"), 2); - -``` - | -| [sum(expression)](./firestore_lite_pipelines.md#sum_1138a27) | (Public Preview) Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. -```typescript -// Calculate the total revenue from a set of orders -sum(field("orderAmount")).as("totalRevenue"); - -``` - | +| [sqrt(expression)](./firestore_lite_pipelines.md#sqrt_1138a27) | (Public Preview) Creates an expression that computes the square root of a numeric value. | +| [subtract(expression, value)](./firestore_lite_pipelines.md#subtract_01df3cf) | (Public Preview) Creates an expression that subtracts a constant value from an expression. | +| [sum(expression)](./firestore_lite_pipelines.md#sum_1138a27) | (Public Preview) Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. | | [type(expression)](./firestore_lite_pipelines.md#type_1138a27) | (Public Preview) Creates an expression that returns the data type of an expression's result. | | function(field, ...) | -| [isAbsent(field)](./firestore_lite_pipelines.md#isabsent_0fb8cd4) | (Public Preview) Creates an expression that returns true if a field is absent. Otherwise, returns false even if the field value is null. -```typescript -// Check if the field `value` is absent. -isAbsent("value"); - -``` - | -| [reverse(field)](./firestore_lite_pipelines.md#reverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. -```typescript -// Reverse the value of the 'myString' field. -reverse("myString"); - -``` - | -| [stringReverse(field)](./firestore_lite_pipelines.md#stringreverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. -```typescript -// Reverse the value of the 'myString' field. -strReverse("myString"); - -``` - | +| [isAbsent(field)](./firestore_lite_pipelines.md#isabsent_0fb8cd4) | (Public Preview) Creates an expression that returns true if a field is absent. Otherwise, returns false even if the field value is null. | +| [reverse(field)](./firestore_lite_pipelines.md#reverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. | +| [stringReverse(field)](./firestore_lite_pipelines.md#stringreverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. | | [substring(field, position, length)](./firestore_lite_pipelines.md#substring_0d9573a) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | | [substring(field, position, length)](./firestore_lite_pipelines.md#substring_05cb14e) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | | function(fieldName, ...) | | [abs(fieldName)](./firestore_lite_pipelines.md#abs_e5b0480) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | -| [add(fieldName, second)](./firestore_lite_pipelines.md#add_b75bb8b) | (Public Preview) Creates an expression that adds a field's value to an expression. -```typescript -// Add the value of the 'quantity' field and the 'reserve' field. -add("quantity", field("reserve")); - -``` - | -| [arrayContains(fieldName, element)](./firestore_lite_pipelines.md#arraycontains_aaace4a) | (Public Preview) Creates an expression that checks if a field's array value contains a specific element. -```typescript -// Check if the 'colors' array contains the value of field 'selectedColor' -arrayContains("colors", field("selectedColor")); - -``` - | -| [arrayContains(fieldName, element)](./firestore_lite_pipelines.md#arraycontains_999590f) | (Public Preview) Creates an expression that checks if a field's array value contains a specific value. -```typescript -// Check if the 'colors' array contains "red" -arrayContains("colors", "red"); - -``` - | -| [arrayContainsAll(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsall_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. -```typescript -// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" -arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); - -``` - | -| [arrayContainsAll(fieldName, arrayExpression)](./firestore_lite_pipelines.md#arraycontainsall_48da8d9) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. -```typescript -// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" -arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); - -``` - | -| [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. -```typescript -// Check if the 'groups' array contains either the value from the 'userGroup' field -// or the value "guest" -arrayContainsAny("categories", [field("cate1"), "Science"]); - -``` - | -| [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_1b4f7cd) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. -```typescript -// Check if the 'groups' array contains either the value from the 'userGroup' field -// or the value "guest" -arrayContainsAny("categories", array([field("cate1"), "Science"])); - -``` - | -| [arrayLength(fieldName)](./firestore_lite_pipelines.md#arraylength_e5b0480) | (Public Preview) Creates an expression that calculates the length of an array in a specified field. -```typescript -// Get the number of items in field 'cart' -arrayLength('cart'); - -``` - | -| [arraySum(fieldName)](./firestore_lite_pipelines.md#arraysum_e5b0480) | (Public Preview) Creates an expression that computes the sum of the elements in an array. -```typescript -// Compute the sum of the elements in the 'scores' field. -arraySum("scores"); - -``` - | -| [ascending(fieldName)](./firestore_lite_pipelines.md#ascending_e5b0480) | (Public Preview) Creates an that sorts documents in ascending order based on a field. -```typescript -// Sort documents by the 'name' field in ascending order -firestore.pipeline().collection("users") - .sort(ascending("name")); - -``` - | -| [average(fieldName)](./firestore_lite_pipelines.md#average_e5b0480) | (Public Preview) Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. -```typescript -// Calculate the average age of users -average("age").as("averageAge"); - -``` - | -| [byteLength(fieldName)](./firestore_lite_pipelines.md#bytelength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. -```typescript -// Calculate the length of the 'myString' field in bytes. -byteLength("myString"); - -``` - | -| [ceil(fieldName)](./firestore_lite_pipelines.md#ceil_e5b0480) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. -```typescript -// Compute the ceiling of the 'price' field. -ceil("price"); - -``` - | -| [charLength(fieldName)](./firestore_lite_pipelines.md#charlength_e5b0480) | (Public Preview) Creates an expression that calculates the character length of a string field in UTF8. -```typescript -// Get the character length of the 'name' field in UTF-8. -strLength("name"); - -``` - | -| [collectionId(fieldName)](./firestore_lite_pipelines.md#collectionid_e5b0480) | (Public Preview) Creates an expression that returns the collection ID from a path. -```typescript -// Get the collection ID from a path. -collectionId("__name__"); - -``` - | -| [concat(fieldName, second, others)](./firestore_lite_pipelines.md#concat_828272e) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. -```typescript -// Concatenate a field with a literal string. -concat(field("firstName"), "Doe") - -``` - | -| [cosineDistance(fieldName, vector)](./firestore_lite_pipelines.md#cosinedistance_463a23e) | (Public Preview) Calculates the Cosine distance between a field's vector value and a literal vector value. -```typescript -// Calculate the Cosine distance between the 'location' field and a target location -cosineDistance("location", [37.7749, -122.4194]); - -``` - | -| [cosineDistance(fieldName, vectorExpression)](./firestore_lite_pipelines.md#cosinedistance_ed766a1) | (Public Preview) Calculates the Cosine distance between a field's vector value and a vector expression. -```typescript -// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field -cosineDistance("userVector", field("itemVector")); - -``` - | -| [count(fieldName)](./firestore_lite_pipelines.md#count_e5b0480) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the input field exists. -```typescript -// Count the total number of products -count("productId").as("totalProducts"); - -``` - | -| [descending(fieldName)](./firestore_lite_pipelines.md#descending_e5b0480) | (Public Preview) Creates an that sorts documents in descending order based on a field. -```typescript -// Sort documents by the 'name' field in descending order -firestore.pipeline().collection("users") - .sort(descending("name")); - -``` - | -| [divide(fieldName, expressions)](./firestore_lite_pipelines.md#divide_cf36e43) | (Public Preview) Creates an expression that divides a field's value by an expression. -```typescript -// Divide the 'total' field by the 'count' field -divide("total", field("count")); - -``` - | -| [divide(fieldName, value)](./firestore_lite_pipelines.md#divide_65e2f32) | (Public Preview) Creates an expression that divides a field's value by a constant value. -```typescript -// Divide the 'value' field by 10 -divide("value", 10); - -``` - | -| [dotProduct(fieldName, vector)](./firestore_lite_pipelines.md#dotproduct_463a23e) | (Public Preview) Calculates the dot product between a field's vector value and a double array. -```typescript -// Calculate the dot product distance between a feature vector and a target vector -dotProduct("features", [0.5, 0.8, 0.2]); - -``` - | -| [dotProduct(fieldName, vectorExpression)](./firestore_lite_pipelines.md#dotproduct_ed766a1) | (Public Preview) Calculates the dot product between a field's vector value and a vector expression. -```typescript -// Calculate the dot product distance between two document vectors: 'docVector1' and 'docVector2' -dotProduct("docVector1", field("docVector2")); - -``` - | -| [endsWith(fieldName, suffix)](./firestore_lite_pipelines.md#endswith_05ca3b0) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. -```typescript -// Check if the 'filename' field ends with ".txt" -endsWith("filename", ".txt"); - -``` - | -| [endsWith(fieldName, suffix)](./firestore_lite_pipelines.md#endswith_8fc0ebc) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. -```typescript -// Check if the 'url' field ends with the value of the 'extension' field -endsWith("url", field("extension")); - -``` - | -| [equal(fieldName, expression)](./firestore_lite_pipelines.md#equal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is equal to an expression. -```typescript -// Check if the 'age' field is equal to the 'limit' field -equal("age", field("limit")); - -``` - | -| [equal(fieldName, value)](./firestore_lite_pipelines.md#equal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is equal to a constant value. -```typescript -// Check if the 'city' field is equal to string constant "London" -equal("city", "London"); - -``` - | -| [equalAny(fieldName, values)](./firestore_lite_pipelines.md#equalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. -```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -equalAny("category", [constant("Electronics"), field("primaryType")]); - -``` - | -| [equalAny(fieldName, arrayExpression)](./firestore_lite_pipelines.md#equalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. -```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -equalAny("category", ["Electronics", field("primaryType")]); - -``` - | -| [euclideanDistance(fieldName, vector)](./firestore_lite_pipelines.md#euclideandistance_463a23e) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a double array. -```typescript -// Calculate the Euclidean distance between the 'location' field and a target location -euclideanDistance("location", [37.7749, -122.4194]); - -``` - | -| [euclideanDistance(fieldName, vectorExpression)](./firestore_lite_pipelines.md#euclideandistance_ed766a1) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a vector expression. -```typescript -// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' -euclideanDistance("pointA", field("pointB")); - -``` - | -| [exists(fieldName)](./firestore_lite_pipelines.md#exists_e5b0480) | (Public Preview) Creates an expression that checks if a field exists. -```typescript -// Check if the document has a field named "phoneNumber" -exists("phoneNumber"); - -``` - | -| [exp(fieldName)](./firestore_lite_pipelines.md#exp_e5b0480) | (Public Preview) Creates an expression that computes e to the power of the expression's result. -```typescript -// Compute e to the power of the 'value' field. -exp('value'); - -``` - A new representing the exp of the numeric value. | +| [add(fieldName, second)](./firestore_lite_pipelines.md#add_b75bb8b) | (Public Preview) Creates an expression that adds a field's value to an expression. | +| [arrayContains(fieldName, element)](./firestore_lite_pipelines.md#arraycontains_aaace4a) | (Public Preview) Creates an expression that checks if a field's array value contains a specific element. | +| [arrayContains(fieldName, element)](./firestore_lite_pipelines.md#arraycontains_999590f) | (Public Preview) Creates an expression that checks if a field's array value contains a specific value. | +| [arrayContainsAll(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsall_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. | +| [arrayContainsAll(fieldName, arrayExpression)](./firestore_lite_pipelines.md#arraycontainsall_48da8d9) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. | +| [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. | +| [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_1b4f7cd) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. | +| [arrayLength(fieldName)](./firestore_lite_pipelines.md#arraylength_e5b0480) | (Public Preview) Creates an expression that calculates the length of an array in a specified field. | +| [arraySum(fieldName)](./firestore_lite_pipelines.md#arraysum_e5b0480) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | +| [ascending(fieldName)](./firestore_lite_pipelines.md#ascending_e5b0480) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. | +| [average(fieldName)](./firestore_lite_pipelines.md#average_e5b0480) | (Public Preview) Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. | +| [byteLength(fieldName)](./firestore_lite_pipelines.md#bytelength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. | +| [ceil(fieldName)](./firestore_lite_pipelines.md#ceil_e5b0480) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | +| [charLength(fieldName)](./firestore_lite_pipelines.md#charlength_e5b0480) | (Public Preview) Creates an expression that calculates the character length of a string field in UTF8. | +| [collectionId(fieldName)](./firestore_lite_pipelines.md#collectionid_e5b0480) | (Public Preview) Creates an expression that returns the collection ID from a path. | +| [concat(fieldName, second, others)](./firestore_lite_pipelines.md#concat_828272e) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | +| [cosineDistance(fieldName, vector)](./firestore_lite_pipelines.md#cosinedistance_463a23e) | (Public Preview) Calculates the Cosine distance between a field's vector value and a literal vector value. | +| [cosineDistance(fieldName, vectorExpression)](./firestore_lite_pipelines.md#cosinedistance_ed766a1) | (Public Preview) Calculates the Cosine distance between a field's vector value and a vector expression. | +| [count(fieldName)](./firestore_lite_pipelines.md#count_e5b0480) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the input field exists. | +| [descending(fieldName)](./firestore_lite_pipelines.md#descending_e5b0480) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on a field. | +| [divide(fieldName, expressions)](./firestore_lite_pipelines.md#divide_cf36e43) | (Public Preview) Creates an expression that divides a field's value by an expression. | +| [divide(fieldName, value)](./firestore_lite_pipelines.md#divide_65e2f32) | (Public Preview) Creates an expression that divides a field's value by a constant value. | +| [dotProduct(fieldName, vector)](./firestore_lite_pipelines.md#dotproduct_463a23e) | (Public Preview) Calculates the dot product between a field's vector value and a double array. | +| [dotProduct(fieldName, vectorExpression)](./firestore_lite_pipelines.md#dotproduct_ed766a1) | (Public Preview) Calculates the dot product between a field's vector value and a vector expression. | +| [endsWith(fieldName, suffix)](./firestore_lite_pipelines.md#endswith_05ca3b0) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. | +| [endsWith(fieldName, suffix)](./firestore_lite_pipelines.md#endswith_8fc0ebc) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. | +| [equal(fieldName, expression)](./firestore_lite_pipelines.md#equal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is equal to an expression. | +| [equal(fieldName, value)](./firestore_lite_pipelines.md#equal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is equal to a constant value. | +| [equalAny(fieldName, values)](./firestore_lite_pipelines.md#equalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. | +| [equalAny(fieldName, arrayExpression)](./firestore_lite_pipelines.md#equalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. | +| [euclideanDistance(fieldName, vector)](./firestore_lite_pipelines.md#euclideandistance_463a23e) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a double array. | +| [euclideanDistance(fieldName, vectorExpression)](./firestore_lite_pipelines.md#euclideandistance_ed766a1) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a vector expression. | +| [exists(fieldName)](./firestore_lite_pipelines.md#exists_e5b0480) | (Public Preview) Creates an expression that checks if a field exists. | +| [exp(fieldName)](./firestore_lite_pipelines.md#exp_e5b0480) | (Public Preview) Creates an expression that computes e to the power of the expression's result. | | [floor(fieldName)](./firestore_lite_pipelines.md#floor_e5b0480) | (Public Preview) Creates an expression that computes the floor of a numeric value. | -| [greaterThan(fieldName, expression)](./firestore_lite_pipelines.md#greaterthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is greater than an expression. -```typescript -// Check if the value of field 'age' is greater than the value of field 'limit' -greaterThan("age", field("limit")); - -``` - | -| [greaterThan(fieldName, value)](./firestore_lite_pipelines.md#greaterthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than a constant value. -```typescript -// Check if the 'price' field is greater than 100 -greaterThan("price", 100); - -``` - | -| [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_2e16acb) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to an expression. -```typescript -// Check if the value of field 'age' is greater than or equal to the value of field 'limit' -greaterThanOrEqual("age", field("limit")); - -``` - | -| [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to a constant value. -```typescript -// Check if the 'score' field is greater than or equal to 80 -greaterThanOrEqual("score", 80); - -``` - | -| [length\_2(fieldName)](./firestore_lite_pipelines.md#length_2_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. -```typescript -// Get the length of the 'name' field. -length("name"); - -// Get the number of items in the 'cart' array. -length("cart"); - -``` - | -| [lessThan(fieldName, expression)](./firestore_lite_pipelines.md#lessthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than an expression. -```typescript -// Check if the 'age' field is less than the 'limit' field -lessThan("age", field("limit")); - -``` - | -| [lessThan(fieldName, value)](./firestore_lite_pipelines.md#lessthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than a constant value. -```typescript -// Check if the 'price' field is less than 50 -lessThan("price", 50); - -``` - | -| [lessThanOrEqual(fieldName, expression)](./firestore_lite_pipelines.md#lessthanorequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to an expression. -```typescript -// Check if the 'quantity' field is less than or equal to the 'limit' field -lessThan("quantity", field("limit")); - -``` - | -| [lessThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#lessthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to a constant value. -```typescript -// Check if the 'score' field is less than or equal to 70 -lessThan("score", 70); - -``` - | -| [like(fieldName, pattern)](./firestore_lite_pipelines.md#like_67f7432) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. -```typescript -// Check if the 'title' field contains the string "guide" -like("title", "%guide%"); - -``` - | -| [like(fieldName, pattern)](./firestore_lite_pipelines.md#like_cb1318d) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. -```typescript -// Check if the 'title' field contains the string "guide" -like("title", field("pattern")); - -``` - | -| [ln(fieldName)](./firestore_lite_pipelines.md#ln_e5b0480) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. -```typescript -// Compute the natural logarithm of the 'value' field. -ln("value"); - -``` - | -| [log(fieldName, base)](./firestore_lite_pipelines.md#log_a89e21b) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. -```typescript -// Compute the logarithm of the 'value' field with base 10. -log("value", 10); - -``` - | -| [log(fieldName, base)](./firestore_lite_pipelines.md#log_805b11f) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. -```typescript -// Compute the logarithm of the 'value' field with the base in the 'base' field. -log("value", field("base")); - -``` - | -| [log10(fieldName)](./firestore_lite_pipelines.md#log10_e5b0480) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. -```typescript -// Compute the base-10 logarithm of the 'value' field. -log10("value"); - -``` - | -| [logicalMaximum(fieldName, second, others)](./firestore_lite_pipelines.md#logicalmaximum_828272e) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. -```typescript -// Returns the largest value between the 'field1' field, the 'field2' field, -// and 1000. -logicalMaximum("field1", field("field2"), 1000); - -``` - | -| [logicalMinimum(fieldName, second, others)](./firestore_lite_pipelines.md#logicalminimum_828272e) | (Public Preview) Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. -```typescript -// Returns the smallest value between the 'field1' field, the 'field2' field, -// and 1000. -logicalMinimum("field1", field("field2"), 1000); - -``` - | -| [mapGet(fieldName, subField)](./firestore_lite_pipelines.md#mapget_06663cf) | (Public Preview) Accesses a value from a map (object) field using the provided key. -```typescript -// Get the 'city' value from the 'address' map field -mapGet("address", "city"); - -``` - | -| [maximum(fieldName)](./firestore_lite_pipelines.md#maximum_e5b0480) | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. -```typescript -// Find the highest score in a leaderboard -maximum("score").as("highestScore"); - -``` - | -| [minimum(fieldName)](./firestore_lite_pipelines.md#minimum_e5b0480) | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. -```typescript -// Find the lowest price of all products -minimum("price").as("lowestPrice"); - -``` - | -| [mod(fieldName, expression)](./firestore_lite_pipelines.md#mod_1e91657) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. -```typescript -// Calculate the remainder of dividing 'field1' by 'field2'. -mod("field1", field("field2")); - -``` - | -| [mod(fieldName, value)](./firestore_lite_pipelines.md#mod_65e2f32) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. -```typescript -// Calculate the remainder of dividing 'field1' by 5. -mod("field1", 5); - -``` - | -| [multiply(fieldName, second)](./firestore_lite_pipelines.md#multiply_b75bb8b) | (Public Preview) Creates an expression that multiplies a field's value by an expression. -```typescript -// Multiply the 'quantity' field by the 'price' field -multiply("quantity", field("price")); - -``` - | -| [notEqual(fieldName, expression)](./firestore_lite_pipelines.md#notequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is not equal to an expression. -```typescript -// Check if the 'status' field is not equal to the value of 'expectedStatus' -notEqual("status", field("expectedStatus")); - -``` - | -| [notEqual(fieldName, value)](./firestore_lite_pipelines.md#notequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is not equal to a constant value. -```typescript -// Check if the 'country' field is not equal to "USA" -notEqual("country", "USA"); - -``` - | -| [notEqualAny(fieldName, values)](./firestore_lite_pipelines.md#notequalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. -```typescript -// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' -notEqualAny("status", [constant("pending"), field("rejectedStatus")]); - -``` - | -| [notEqualAny(fieldName, arrayExpression)](./firestore_lite_pipelines.md#notequalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. -```typescript -// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' -notEqualAny("status", field("rejectedStatuses")); - -``` - | -| [regexContains(fieldName, pattern)](./firestore_lite_pipelines.md#regexcontains_67f7432) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. -```typescript -// Check if the 'description' field contains "example" (case-insensitive) -regexContains("description", "(?i)example"); - -``` - | -| [regexContains(fieldName, pattern)](./firestore_lite_pipelines.md#regexcontains_cb1318d) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. -```typescript -// Check if the 'description' field contains "example" (case-insensitive) -regexContains("description", field("pattern")); - -``` - | -| [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_67f7432) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. -```typescript -// Check if the 'email' field matches a valid email pattern -regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); - -``` - | -| [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_cb1318d) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. -```typescript -// Check if the 'email' field matches a valid email pattern -regexMatch("email", field("pattern")); - -``` - | -| [round(fieldName)](./firestore_lite_pipelines.md#round_e5b0480) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. -```typescript -// Round the value of the 'price' field. -round("price"); - -``` - | -| [round(fieldName, decimalPlaces)](./firestore_lite_pipelines.md#round_07d0cf0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. -```typescript -// Round the value of the 'price' field to two decimal places. -round("price", 2); - -``` - | +| [greaterThan(fieldName, expression)](./firestore_lite_pipelines.md#greaterthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is greater than an expression. | +| [greaterThan(fieldName, value)](./firestore_lite_pipelines.md#greaterthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than a constant value. | +| [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_2e16acb) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to an expression. | +| [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to a constant value. | +| [length\_2(fieldName)](./firestore_lite_pipelines.md#length_2_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | +| [lessThan(fieldName, expression)](./firestore_lite_pipelines.md#lessthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than an expression. | +| [lessThan(fieldName, value)](./firestore_lite_pipelines.md#lessthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than a constant value. | +| [lessThanOrEqual(fieldName, expression)](./firestore_lite_pipelines.md#lessthanorequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to an expression. | +| [lessThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#lessthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to a constant value. | +| [like(fieldName, pattern)](./firestore_lite_pipelines.md#like_67f7432) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. | +| [like(fieldName, pattern)](./firestore_lite_pipelines.md#like_cb1318d) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. | +| [ln(fieldName)](./firestore_lite_pipelines.md#ln_e5b0480) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. | +| [log(fieldName, base)](./firestore_lite_pipelines.md#log_a89e21b) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. | +| [log(fieldName, base)](./firestore_lite_pipelines.md#log_805b11f) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. | +| [log10(fieldName)](./firestore_lite_pipelines.md#log10_e5b0480) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | +| [logicalMaximum(fieldName, second, others)](./firestore_lite_pipelines.md#logicalmaximum_828272e) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | +| [logicalMinimum(fieldName, second, others)](./firestore_lite_pipelines.md#logicalminimum_828272e) | (Public Preview) Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. | +| [mapGet(fieldName, subField)](./firestore_lite_pipelines.md#mapget_06663cf) | (Public Preview) Accesses a value from a map (object) field using the provided key. | +| [maximum(fieldName)](./firestore_lite_pipelines.md#maximum_e5b0480) | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | +| [minimum(fieldName)](./firestore_lite_pipelines.md#minimum_e5b0480) | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | +| [mod(fieldName, expression)](./firestore_lite_pipelines.md#mod_1e91657) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. | +| [mod(fieldName, value)](./firestore_lite_pipelines.md#mod_65e2f32) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. | +| [multiply(fieldName, second)](./firestore_lite_pipelines.md#multiply_b75bb8b) | (Public Preview) Creates an expression that multiplies a field's value by an expression. | +| [notEqual(fieldName, expression)](./firestore_lite_pipelines.md#notequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is not equal to an expression. | +| [notEqual(fieldName, value)](./firestore_lite_pipelines.md#notequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is not equal to a constant value. | +| [notEqualAny(fieldName, values)](./firestore_lite_pipelines.md#notequalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. | +| [notEqualAny(fieldName, arrayExpression)](./firestore_lite_pipelines.md#notequalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. | +| [regexContains(fieldName, pattern)](./firestore_lite_pipelines.md#regexcontains_67f7432) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. | +| [regexContains(fieldName, pattern)](./firestore_lite_pipelines.md#regexcontains_cb1318d) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. | +| [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_67f7432) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | +| [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_cb1318d) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | +| [round(fieldName)](./firestore_lite_pipelines.md#round_e5b0480) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | +| [round(fieldName, decimalPlaces)](./firestore_lite_pipelines.md#round_07d0cf0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | | [split(fieldName, delimiter)](./firestore_lite_pipelines.md#split_2cfdd37) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | -| [split(fieldName, delimiter)](./firestore_lite_pipelines.md#split_f4fe06a) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | -| [sqrt(fieldName)](./firestore_lite_pipelines.md#sqrt_e5b0480) | (Public Preview) Creates an expression that computes the square root of a numeric value. -```typescript -// Compute the square root of the 'value' field. -sqrt("value"); - -``` - | -| [startsWith(fieldName, prefix)](./firestore_lite_pipelines.md#startswith_89325cc) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. -```typescript -// Check if the 'name' field starts with "Mr." -startsWith("name", "Mr."); - -``` - | -| [startsWith(fieldName, prefix)](./firestore_lite_pipelines.md#startswith_266c338) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. -```typescript -// Check if the 'fullName' field starts with the value of the 'firstName' field -startsWith("fullName", field("firstName")); - -``` - | -| [stringConcat(fieldName, secondString, otherStrings)](./firestore_lite_pipelines.md#stringconcat_d80077e) | (Public Preview) Creates an expression that concatenates string functions, fields or constants together. -```typescript -// Combine the 'firstName', " ", and 'lastName' fields into a single string -stringConcat("firstName", " ", field("lastName")); - -``` - | -| [stringContains(fieldName, substring)](./firestore_lite_pipelines.md#stringcontains_5b94cfe) | (Public Preview) Creates an expression that checks if a string field contains a specified substring. -```typescript -// Check if the 'description' field contains "example". -stringContains("description", "example"); - -``` - | -| [stringContains(fieldName, substring)](./firestore_lite_pipelines.md#stringcontains_ac3ba47) | (Public Preview) Creates an expression that checks if a string field contains a substring specified by an expression. -```typescript -// Check if the 'description' field contains the value of the 'keyword' field. -stringContains("description", field("keyword")); - -``` - | -| [subtract(fieldName, expression)](./firestore_lite_pipelines.md#subtract_1e91657) | (Public Preview) Creates an expression that subtracts an expression from a field's value. -```typescript -// Subtract the 'discount' field from the 'price' field -subtract("price", field("discount")); - -``` - | -| [subtract(fieldName, value)](./firestore_lite_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. -```typescript -// Subtract 20 from the value of the 'total' field -subtract("total", 20); - -``` - | -| [sum(fieldName)](./firestore_lite_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. -```typescript -// Calculate the total revenue from a set of orders -sum("orderAmount").as("totalRevenue"); - -``` - | -| [timestampAdd(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampadd_341fe7d) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. -```typescript -// Add 1 day to the 'timestamp' field. -timestampAdd("timestamp", "day", 1); - -``` - | -| [timestampSubtract(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_341fe7d) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. -```typescript -// Subtract 1 day from the 'timestamp' field. -timestampSubtract("timestamp", "day", 1); - -``` - | -| [timestampToUnixMicros(fieldName)](./firestore_lite_pipelines.md#timestamptounixmicros_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to microseconds since epoch. -timestampToUnixMicros("timestamp"); - -``` - | -| [timestampToUnixMillis(fieldName)](./firestore_lite_pipelines.md#timestamptounixmillis_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -timestampToUnixMillis("timestamp"); - -``` - | -| [timestampToUnixSeconds(fieldName)](./firestore_lite_pipelines.md#timestamptounixseconds_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to seconds since epoch. -timestampToUnixSeconds("timestamp"); - -``` - | -| [timestampTruncate(fieldName, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_b6c7512) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [timestampTruncate(fieldName, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_ed83d46) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [toLower(fieldName)](./firestore_lite_pipelines.md#tolower_e5b0480) | (Public Preview) Creates an expression that converts a string field to lowercase. -```typescript -// Convert the 'name' field to lowercase -toLower("name"); - -``` - | -| [toUpper(fieldName)](./firestore_lite_pipelines.md#toupper_e5b0480) | (Public Preview) Creates an expression that converts a string field to uppercase. -```typescript -// Convert the 'title' field to uppercase -toUpper("title"); - -``` - | -| [trim(fieldName, valueToTrim)](./firestore_lite_pipelines.md#trim_c9f90ee) | (Public Preview) Creates an expression that removes leading and trailing whitespace from a string or byte array. -```typescript -// Trim whitespace from the 'userInput' field -trim("userInput"); - -// Trim quotes from the 'userInput' field -trim("userInput", '"'); - -``` - | -| [type(fieldName)](./firestore_lite_pipelines.md#type_e5b0480) | (Public Preview) Creates an expression that returns the data type of the data in the specified field. | -| [unixMicrosToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixmicrostotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -unixMicrosToTimestamp("microseconds"); - -``` - | -| [unixMillisToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixmillistotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -unixMillisToTimestamp("milliseconds"); - -``` - | -| [unixSecondsToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixsecondstotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'seconds' field as seconds since epoch. -unixSecondsToTimestamp("seconds"); - -``` - | -| [vectorLength(fieldName)](./firestore_lite_pipelines.md#vectorlength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector represented by a field. -```typescript -// Get the vector length (dimension) of the field 'embedding'. -vectorLength("embedding"); - -``` - | -| function(first, ...) | -| [add(first, second)](./firestore_lite_pipelines.md#add_846ca1b) | (Public Preview) Creates an expression that adds two expressions together. -```typescript -// Add the value of the 'quantity' field and the 'reserve' field. -add(field("quantity"), field("reserve")); - -``` - | -| [and(first, second, more)](./firestore_lite_pipelines.md#and_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'AND' operation on multiple filter conditions. -```typescript -// Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND -// the 'status' field is "active" -const condition = and(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); - -``` - | -| [concat(first, second, others)](./firestore_lite_pipelines.md#concat_83be015) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. -```typescript -// Concatenate the 'firstName' and 'lastName' fields with a space in between. -concat(field("firstName"), " ", field("lastName")) - -``` - | -| [logicalMaximum(first, second, others)](./firestore_lite_pipelines.md#logicalmaximum_83be015) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. -```typescript -// Returns the largest value between the 'field1' field, the 'field2' field, -// and 1000 -logicalMaximum(field("field1"), field("field2"), 1000); - -``` - | -| [logicalMinimum(first, second, others)](./firestore_lite_pipelines.md#logicalminimum_83be015) | (Public Preview) Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. -```typescript -// Returns the smallest value between the 'field1' field, the 'field2' field, -// and 1000. -logicalMinimum(field("field1"), field("field2"), 1000); - -``` - | -| [multiply(first, second)](./firestore_lite_pipelines.md#multiply_846ca1b) | (Public Preview) Creates an expression that multiplies two expressions together. -```typescript -// Multiply the 'quantity' field by the 'price' field -multiply(field("quantity"), field("price")); - -``` - | -| [or(first, second, more)](./firestore_lite_pipelines.md#or_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'OR' operation on multiple filter conditions. -```typescript -// Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR -// the 'status' field is "active" -const condition = or(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); - -``` - | -| [xor(first, second, additionalConditions)](./firestore_lite_pipelines.md#xor_8197113) | (Public Preview) Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. -```typescript -// Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London", -// or 'status' is "active". -const condition = xor( - greaterThan("age", 18), - equal("city", "London"), - equal("status", "active")); - -``` - | -| function(firstArray, ...) | -| [arrayConcat(firstArray, secondArray, otherArrays)](./firestore_lite_pipelines.md#arrayconcat_c00d5d7) | (Public Preview) Creates an expression that concatenates an array expression with other arrays. -```typescript -// Combine the 'items' array with two new item arrays -arrayConcat(field("items"), [field("newItems"), field("otherItems")]); - -``` - | -| function(firstArrayField, ...) | -| [arrayConcat(firstArrayField, secondArray, otherArrays)](./firestore_lite_pipelines.md#arrayconcat_f92063d) | (Public Preview) Creates an expression that concatenates a field's array value with other arrays. -```typescript -// Combine the 'items' array with two new item arrays -arrayConcat("items", [field("newItems"), field("otherItems")]); - -``` - | -| function(firstMap, ...) | -| [mapMerge(firstMap, secondMap, otherMaps)](./firestore_lite_pipelines.md#mapmerge_cfe77ce) | (Public Preview) Creates an expression that merges multiple map values. -``` -// Merges the map in the settings field with, a map literal, and a map in -// that is conditionally returned by another expression -mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) - -``` - | -| function(firstString, ...) | -| [stringConcat(firstString, secondString, otherStrings)](./firestore_lite_pipelines.md#stringconcat_8a8d1b6) | (Public Preview) Creates an expression that concatenates string expressions together. -```typescript -// Combine the 'firstName', " ", and 'lastName' fields into a single string -stringConcat(field("firstName"), " ", field("lastName")); - -``` - | -| function(ifExpr, ...) | -| [ifAbsent(ifExpr, elseExpr)](./firestore_lite_pipelines.md#ifabsent_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -ifAbsent(field("optional_field"), constant("default_value")) - -``` - | -| [ifAbsent(ifExpr, elseValue)](./firestore_lite_pipelines.md#ifabsent_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -ifAbsent(field("optional_field"), "default_value") - -``` - | -| function(ifFieldName, ...) | -| [ifAbsent(ifFieldName, elseExpr)](./firestore_lite_pipelines.md#ifabsent_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName is absent, else return the value of the field. -```typescript -// Returns the value of the optional field 'optional_field', or returns the value of -// 'default_field' if 'optional_field' is absent. -ifAbsent("optional_field", field("default_field")) - -``` - | -| [ifAbsent(ifFieldName, elseValue)](./firestore_lite_pipelines.md#ifabsent_d8f2823) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName is absent, else return the value of the field. -```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -ifAbsent("optional_field", "default_value") - -``` - | -| function(input, ...) | -| [substring(input, position, length)](./firestore_lite_pipelines.md#substring_e6e0aa3) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | -| [substring(input, position, length)](./firestore_lite_pipelines.md#substring_ab56dc6) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | -| function(left, ...) | -| [divide(left, right)](./firestore_lite_pipelines.md#divide_b3c3382) | (Public Preview) Creates an expression that divides two expressions. -```typescript -// Divide the 'total' field by the 'count' field -divide(field("total"), field("count")); - -``` - | -| [equal(left, right)](./firestore_lite_pipelines.md#equal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are equal. -```typescript -// Check if the 'age' field is equal to an expression -equal(field("age"), field("minAge").add(10)); - -``` - | -| [greaterThan(left, right)](./firestore_lite_pipelines.md#greaterthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than the second expression. -```typescript -// Check if the 'age' field is greater than 18 -greaterThan(field("age"), Constant(9).add(9)); - -``` - | -| [greaterThanOrEqual(left, right)](./firestore_lite_pipelines.md#greaterthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than or equal to the second expression. -```typescript -// Check if the 'quantity' field is greater than or equal to the field "threshold" -greaterThanOrEqual(field("quantity"), field("threshold")); - -``` - | -| [lessThan(left, right)](./firestore_lite_pipelines.md#lessthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than the second expression. -```typescript -// Check if the 'age' field is less than 30 -lessThan(field("age"), field("limit")); - -``` - | -| [lessThanOrEqual(left, right)](./firestore_lite_pipelines.md#lessthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than or equal to the second expression. -```typescript -// Check if the 'quantity' field is less than or equal to 20 -lessThan(field("quantity"), field("limit")); - -``` - | -| [mod(left, right)](./firestore_lite_pipelines.md#mod_b3c3382) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing two expressions. -```typescript -// Calculate the remainder of dividing 'field1' by 'field2'. -mod(field("field1"), field("field2")); - -``` - | -| [notEqual(left, right)](./firestore_lite_pipelines.md#notequal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are not equal. -```typescript -// Check if the 'status' field is not equal to field 'finalState' -notEqual(field("status"), field("finalState")); - -``` - | -| [subtract(left, right)](./firestore_lite_pipelines.md#subtract_b3c3382) | (Public Preview) Creates an expression that subtracts two expressions. -```typescript -// Subtract the 'discount' field from the 'price' field -subtract(field("price"), field("discount")); - -``` - | -| function(mapExpr, ...) | -| [mapRemove(mapExpr, key)](./firestore_lite_pipelines.md#mapremove_23c7d51) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. -``` -// Removes the key 'baz' from the input map. -mapRemove(map({foo: 'bar', baz: true}), 'baz'); - -``` - | -| [mapRemove(mapExpr, keyExpr)](./firestore_lite_pipelines.md#mapremove_9fbcaa3) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. -``` -// Removes the key 'baz' from the input map. -mapRemove(map({foo: 'bar', baz: true}), constant('baz')); - -``` - | -| function(mapExpression, ...) | -| [mapGet(mapExpression, subField)](./firestore_lite_pipelines.md#mapget_688c050) | (Public Preview) Accesses a value from a map (object) expression using the provided key. -```typescript -// Get the 'city' value from the 'address' map field -mapGet(field("address"), "city"); - -``` - | -| function(mapField, ...) | -| [mapMerge(mapField, secondMap, otherMaps)](./firestore_lite_pipelines.md#mapmerge_70a564b) | (Public Preview) Creates an expression that merges multiple map values. -``` -// Merges the map in the settings field with, a map literal, and a map in -// that is conditionally returned by another expression -mapMerge('settings', { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) - -``` - | -| [mapRemove(mapField, key)](./firestore_lite_pipelines.md#mapremove_bd5726e) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. -``` -// Removes the key 'city' field from the map in the address field of the input document. -mapRemove('address', 'city'); - -``` - | -| [mapRemove(mapField, keyExpr)](./firestore_lite_pipelines.md#mapremove_8406d13) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. -``` -// Removes the key 'city' field from the map in the address field of the input document. -mapRemove('address', constant('city')); - -``` - | -| function(name, ...) | -| [field(name)](./firestore_lite_pipelines.md#field_1eaaff4) | (Public Preview) Creates a instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). -```typescript -// Create a Field instance for the 'title' field -const titleField = field("title"); - -// Create a Field instance for a nested field 'author.firstName' -const authorFirstNameField = field("author.firstName"); - -``` - | -| function(path, ...) | -| [field(path)](./firestore_lite_pipelines.md#field_34ee07d) | (Public Preview) Creates a instance representing the field at the given path. | -| function(pipeline, ...) | -| [execute(pipeline)](./firestore_lite_pipelines.md#execute_01df620) | (Public Preview) Executes this pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a that contains a list of objects. Each typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:

  • If there are no stages or only transformation stages, each represents a single document.
  • If there is an aggregation, only a single is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each represents a distinct group and its associated aggregated values.

Example: -```typescript -const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") - .where(gt(field("rating"), 4.5)) - .select("title", "author", "rating")); - -const results: PipelineResults = snapshot.results; - -``` - | -| function(stringExpression, ...) | -| [charLength(stringExpression)](./firestore_lite_pipelines.md#charlength_c25a54a) | (Public Preview) Creates an expression that calculates the character length of a string expression in UTF-8. -```typescript -// Get the character length of the 'name' field in UTF-8. -strLength(field("name")); - -``` - | -| [endsWith(stringExpression, suffix)](./firestore_lite_pipelines.md#endswith_0a0b889) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. -```typescript -// Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." -endsWith(field("fullName"), "Jr."); - -``` - | -| [endsWith(stringExpression, suffix)](./firestore_lite_pipelines.md#endswith_13aee0d) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. -```typescript -// Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." -endsWith(field("fullName"), constant("Jr.")); - -``` - | -| [like(stringExpression, pattern)](./firestore_lite_pipelines.md#like_a84c581) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. -```typescript -// Check if the 'title' field contains the string "guide" -like(field("title"), "%guide%"); - -``` - | -| [like(stringExpression, pattern)](./firestore_lite_pipelines.md#like_b534848) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. -```typescript -// Check if the 'title' field contains the string "guide" -like(field("title"), field("pattern")); - -``` - | -| [regexContains(stringExpression, pattern)](./firestore_lite_pipelines.md#regexcontains_a84c581) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. -```typescript -// Check if the 'description' field contains "example" (case-insensitive) -regexContains(field("description"), "(?i)example"); - -``` - | -| [regexContains(stringExpression, pattern)](./firestore_lite_pipelines.md#regexcontains_b534848) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. -```typescript -// Check if the 'description' field contains "example" (case-insensitive) -regexContains(field("description"), field("pattern")); - -``` - | -| [regexMatch(stringExpression, pattern)](./firestore_lite_pipelines.md#regexmatch_a84c581) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. -```typescript -// Check if the 'email' field matches a valid email pattern -regexMatch(field("email"), "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); - -``` - | -| [regexMatch(stringExpression, pattern)](./firestore_lite_pipelines.md#regexmatch_b534848) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. -```typescript -// Check if the 'email' field matches a valid email pattern -regexMatch(field("email"), field("pattern")); - -``` - | -| [reverse(stringExpression)](./firestore_lite_pipelines.md#reverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. -```typescript -// Reverse the value of the 'myString' field. -reverse(field("myString")); - -``` - | -| [startsWith(stringExpression, prefix)](./firestore_lite_pipelines.md#startswith_75c3dbb) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. -```typescript -// Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." -startsWith(field("fullName"), "Mr."); - -``` - | -| [startsWith(stringExpression, prefix)](./firestore_lite_pipelines.md#startswith_52f218a) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. -```typescript -// Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." -startsWith(field("fullName"), field("prefix")); - -``` - | -| [stringContains(stringExpression, substring)](./firestore_lite_pipelines.md#stringcontains_3e9ff32) | (Public Preview) Creates an expression that checks if a string expression contains a specified substring. -```typescript -// Check if the 'description' field contains "example". -stringContains(field("description"), "example"); - -``` - | -| [stringContains(stringExpression, substring)](./firestore_lite_pipelines.md#stringcontains_cc6ee02) | (Public Preview) Creates an expression that checks if a string expression contains a substring specified by another expression. -```typescript -// Check if the 'description' field contains the value of the 'keyword' field. -stringContains(field("description"), field("keyword")); - -``` - | -| [stringReverse(stringExpression)](./firestore_lite_pipelines.md#stringreverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. -```typescript -// Reverse the value of the 'myString' field. -strReverse(field("myString")); - -``` - | -| [toLower(stringExpression)](./firestore_lite_pipelines.md#tolower_c25a54a) | (Public Preview) Creates an expression that converts a string expression to lowercase. -```typescript -// Convert the 'name' field to lowercase -toLower(field("name")); - -``` - | -| [toUpper(stringExpression)](./firestore_lite_pipelines.md#toupper_c25a54a) | (Public Preview) Creates an expression that converts a string expression to uppercase. -```typescript -// Convert the 'title' field to uppercase -toUppercase(field("title")); - -``` - | -| [trim(stringExpression, valueToTrim)](./firestore_lite_pipelines.md#trim_dd54322) | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array expression. -```typescript -// Trim whitespace from the 'userInput' field -trim(field("userInput")); - -// Trim quotes from the 'userInput' field -trim(field("userInput"), '"'); - -``` - | +| [split(fieldName, delimiter)](./firestore_lite_pipelines.md#split_f4fe06a) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | +| [sqrt(fieldName)](./firestore_lite_pipelines.md#sqrt_e5b0480) | (Public Preview) Creates an expression that computes the square root of a numeric value. | +| [startsWith(fieldName, prefix)](./firestore_lite_pipelines.md#startswith_89325cc) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. | +| [startsWith(fieldName, prefix)](./firestore_lite_pipelines.md#startswith_266c338) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. | +| [stringConcat(fieldName, secondString, otherStrings)](./firestore_lite_pipelines.md#stringconcat_d80077e) | (Public Preview) Creates an expression that concatenates string functions, fields or constants together. | +| [stringContains(fieldName, substring)](./firestore_lite_pipelines.md#stringcontains_5b94cfe) | (Public Preview) Creates an expression that checks if a string field contains a specified substring. | +| [stringContains(fieldName, substring)](./firestore_lite_pipelines.md#stringcontains_ac3ba47) | (Public Preview) Creates an expression that checks if a string field contains a substring specified by an expression. | +| [subtract(fieldName, expression)](./firestore_lite_pipelines.md#subtract_1e91657) | (Public Preview) Creates an expression that subtracts an expression from a field's value. | +| [subtract(fieldName, value)](./firestore_lite_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. | +| [sum(fieldName)](./firestore_lite_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. | +| [timestampAdd(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampadd_341fe7d) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. | +| [timestampSubtract(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_341fe7d) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. | +| [timestampToUnixMicros(fieldName)](./firestore_lite_pipelines.md#timestamptounixmicros_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixMillis(fieldName)](./firestore_lite_pipelines.md#timestamptounixmillis_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixSeconds(fieldName)](./firestore_lite_pipelines.md#timestamptounixseconds_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampTruncate(fieldName, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_b6c7512) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(fieldName, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_ed83d46) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [toLower(fieldName)](./firestore_lite_pipelines.md#tolower_e5b0480) | (Public Preview) Creates an expression that converts a string field to lowercase. | +| [toUpper(fieldName)](./firestore_lite_pipelines.md#toupper_e5b0480) | (Public Preview) Creates an expression that converts a string field to uppercase. | +| [trim(fieldName, valueToTrim)](./firestore_lite_pipelines.md#trim_c9f90ee) | (Public Preview) Creates an expression that removes leading and trailing whitespace from a string or byte array. | +| [type(fieldName)](./firestore_lite_pipelines.md#type_e5b0480) | (Public Preview) Creates an expression that returns the data type of the data in the specified field. | +| [unixMicrosToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixmicrostotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixMillisToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixmillistotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixSecondsToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixsecondstotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [vectorLength(fieldName)](./firestore_lite_pipelines.md#vectorlength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector represented by a field. | +| function(first, ...) | +| [add(first, second)](./firestore_lite_pipelines.md#add_846ca1b) | (Public Preview) Creates an expression that adds two expressions together. | +| [and(first, second, more)](./firestore_lite_pipelines.md#and_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'AND' operation on multiple filter conditions. | +| [concat(first, second, others)](./firestore_lite_pipelines.md#concat_83be015) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | +| [logicalMaximum(first, second, others)](./firestore_lite_pipelines.md#logicalmaximum_83be015) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | +| [logicalMinimum(first, second, others)](./firestore_lite_pipelines.md#logicalminimum_83be015) | (Public Preview) Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. | +| [multiply(first, second)](./firestore_lite_pipelines.md#multiply_846ca1b) | (Public Preview) Creates an expression that multiplies two expressions together. | +| [or(first, second, more)](./firestore_lite_pipelines.md#or_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'OR' operation on multiple filter conditions. | +| [xor(first, second, additionalConditions)](./firestore_lite_pipelines.md#xor_8197113) | (Public Preview) Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. | +| function(firstArray, ...) | +| [arrayConcat(firstArray, secondArray, otherArrays)](./firestore_lite_pipelines.md#arrayconcat_c00d5d7) | (Public Preview) Creates an expression that concatenates an array expression with other arrays. | +| function(firstArrayField, ...) | +| [arrayConcat(firstArrayField, secondArray, otherArrays)](./firestore_lite_pipelines.md#arrayconcat_f92063d) | (Public Preview) Creates an expression that concatenates a field's array value with other arrays. | +| function(firstMap, ...) | +| [mapMerge(firstMap, secondMap, otherMaps)](./firestore_lite_pipelines.md#mapmerge_cfe77ce) | (Public Preview) Creates an expression that merges multiple map values. | +| function(firstString, ...) | +| [stringConcat(firstString, secondString, otherStrings)](./firestore_lite_pipelines.md#stringconcat_8a8d1b6) | (Public Preview) Creates an expression that concatenates string expressions together. | +| function(ifExpr, ...) | +| [ifAbsent(ifExpr, elseExpr)](./firestore_lite_pipelines.md#ifabsent_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | +| [ifAbsent(ifExpr, elseValue)](./firestore_lite_pipelines.md#ifabsent_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | +| function(ifFieldName, ...) | +| [ifAbsent(ifFieldName, elseExpr)](./firestore_lite_pipelines.md#ifabsent_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName is absent, else return the value of the field. | +| [ifAbsent(ifFieldName, elseValue)](./firestore_lite_pipelines.md#ifabsent_d8f2823) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName is absent, else return the value of the field. | +| function(input, ...) | +| [substring(input, position, length)](./firestore_lite_pipelines.md#substring_e6e0aa3) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| [substring(input, position, length)](./firestore_lite_pipelines.md#substring_ab56dc6) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| function(left, ...) | +| [divide(left, right)](./firestore_lite_pipelines.md#divide_b3c3382) | (Public Preview) Creates an expression that divides two expressions. | +| [equal(left, right)](./firestore_lite_pipelines.md#equal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are equal. | +| [greaterThan(left, right)](./firestore_lite_pipelines.md#greaterthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than the second expression. | +| [greaterThanOrEqual(left, right)](./firestore_lite_pipelines.md#greaterthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than or equal to the second expression. | +| [lessThan(left, right)](./firestore_lite_pipelines.md#lessthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than the second expression. | +| [lessThanOrEqual(left, right)](./firestore_lite_pipelines.md#lessthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than or equal to the second expression. | +| [mod(left, right)](./firestore_lite_pipelines.md#mod_b3c3382) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing two expressions. | +| [notEqual(left, right)](./firestore_lite_pipelines.md#notequal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are not equal. | +| [subtract(left, right)](./firestore_lite_pipelines.md#subtract_b3c3382) | (Public Preview) Creates an expression that subtracts two expressions. | +| function(mapExpr, ...) | +| [mapRemove(mapExpr, key)](./firestore_lite_pipelines.md#mapremove_23c7d51) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. | +| [mapRemove(mapExpr, keyExpr)](./firestore_lite_pipelines.md#mapremove_9fbcaa3) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. | +| function(mapExpression, ...) | +| [mapGet(mapExpression, subField)](./firestore_lite_pipelines.md#mapget_688c050) | (Public Preview) Accesses a value from a map (object) expression using the provided key. | +| function(mapField, ...) | +| [mapMerge(mapField, secondMap, otherMaps)](./firestore_lite_pipelines.md#mapmerge_70a564b) | (Public Preview) Creates an expression that merges multiple map values. | +| [mapRemove(mapField, key)](./firestore_lite_pipelines.md#mapremove_bd5726e) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. | +| [mapRemove(mapField, keyExpr)](./firestore_lite_pipelines.md#mapremove_8406d13) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. | +| function(name, ...) | +| [field(name)](./firestore_lite_pipelines.md#field_1eaaff4) | (Public Preview) Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). | +| function(path, ...) | +| [field(path)](./firestore_lite_pipelines.md#field_34ee07d) | (Public Preview) Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. | +| function(pipeline, ...) | +| [execute(pipeline)](./firestore_lite_pipelines.md#execute_01df620) | (Public Preview) Executes this pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:

  • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
  • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
| +| function(stringExpression, ...) | +| [charLength(stringExpression)](./firestore_lite_pipelines.md#charlength_c25a54a) | (Public Preview) Creates an expression that calculates the character length of a string expression in UTF-8. | +| [endsWith(stringExpression, suffix)](./firestore_lite_pipelines.md#endswith_0a0b889) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. | +| [endsWith(stringExpression, suffix)](./firestore_lite_pipelines.md#endswith_13aee0d) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. | +| [like(stringExpression, pattern)](./firestore_lite_pipelines.md#like_a84c581) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. | +| [like(stringExpression, pattern)](./firestore_lite_pipelines.md#like_b534848) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. | +| [regexContains(stringExpression, pattern)](./firestore_lite_pipelines.md#regexcontains_a84c581) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. | +| [regexContains(stringExpression, pattern)](./firestore_lite_pipelines.md#regexcontains_b534848) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. | +| [regexMatch(stringExpression, pattern)](./firestore_lite_pipelines.md#regexmatch_a84c581) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. | +| [regexMatch(stringExpression, pattern)](./firestore_lite_pipelines.md#regexmatch_b534848) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. | +| [reverse(stringExpression)](./firestore_lite_pipelines.md#reverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. | +| [startsWith(stringExpression, prefix)](./firestore_lite_pipelines.md#startswith_75c3dbb) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. | +| [startsWith(stringExpression, prefix)](./firestore_lite_pipelines.md#startswith_52f218a) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. | +| [stringContains(stringExpression, substring)](./firestore_lite_pipelines.md#stringcontains_3e9ff32) | (Public Preview) Creates an expression that checks if a string expression contains a specified substring. | +| [stringContains(stringExpression, substring)](./firestore_lite_pipelines.md#stringcontains_cc6ee02) | (Public Preview) Creates an expression that checks if a string expression contains a substring specified by another expression. | +| [stringReverse(stringExpression)](./firestore_lite_pipelines.md#stringreverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. | +| [toLower(stringExpression)](./firestore_lite_pipelines.md#tolower_c25a54a) | (Public Preview) Creates an expression that converts a string expression to lowercase. | +| [toUpper(stringExpression)](./firestore_lite_pipelines.md#toupper_c25a54a) | (Public Preview) Creates an expression that converts a string expression to uppercase. | +| [trim(stringExpression, valueToTrim)](./firestore_lite_pipelines.md#trim_dd54322) | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array expression. | | function(timestamp, ...) | -| [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_98418f9) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. -```typescript -// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. -timestampAdd(field("timestamp"), field("unit"), field("amount")); - -``` - | -| [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_ffe8e57) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. -```typescript -// Add 1 day to the 'timestamp' field. -timestampAdd(field("timestamp"), "day", 1); - -``` - | -| [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_98418f9) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. -```typescript -// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. -timestampSubtract(field("timestamp"), field("unit"), field("amount")); - -``` - | -| [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_ffe8e57) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. -```typescript -// Subtract 1 day from the 'timestamp' field. -timestampSubtract(field("timestamp"), "day", 1); - -``` - | +| [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_98418f9) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | +| [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_ffe8e57) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | +| [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_98418f9) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | +| [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_ffe8e57) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | | function(timestampExpression, ...) | | [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_ad5d843) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | | [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_d6ab2a4) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | | function(tryExpr, ...) | -| [ifError(tryExpr, catchExpr)](./firestore_lite_pipelines.md#iferror_a99a327) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation.This overload is useful when a BooleanExpression is required. -```typescript -// Create an expression that protects against a divide by zero error -// but always returns a boolean expression. -ifError(constant(50).divide('length').gt(1), constant(false)); - -``` - | -| [ifError(tryExpr, catchExpr)](./firestore_lite_pipelines.md#iferror_756c12e) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. -```typescript -// Returns the first item in the title field arrays, or returns -// the entire title field if the array is empty or the field is another type. -ifError(field("title").arrayGet(0), field("title")); - -``` - | -| [ifError(tryExpr, catchValue)](./firestore_lite_pipelines.md#iferror_dc532f9) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. -```typescript -// Returns the first item in the title field arrays, or returns -// "Default Title" -ifError(field("title").arrayGet(0), "Default Title"); - -``` - | +| [ifError(tryExpr, catchExpr)](./firestore_lite_pipelines.md#iferror_a99a327) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation.This overload is useful when a BooleanExpression is required. | +| [ifError(tryExpr, catchExpr)](./firestore_lite_pipelines.md#iferror_756c12e) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. | +| [ifError(tryExpr, catchValue)](./firestore_lite_pipelines.md#iferror_dc532f9) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. | | function(value, ...) | | [constant(value)](./firestore_lite_pipelines.md#constant_0c00f91) | (Public Preview) Creates a Constant instance for a number value. | | [constant(value)](./firestore_lite_pipelines.md#constant_6dac335) | (Public Preview) Creates a Constant instance for a VectorValue value. | @@ -1639,78 +297,17 @@ ifError(field("title").arrayGet(0), "Default Title"); | [constant(value)](./firestore_lite_pipelines.md#constant_5131bf7) | (Public Preview) Creates a Constant instance for a Date value. | | [constant(value)](./firestore_lite_pipelines.md#constant_fdf565d) | (Public Preview) Creates a Constant instance for a Bytes value. | | [constant(value)](./firestore_lite_pipelines.md#constant_bcd2b0b) | (Public Preview) Creates a Constant instance for a DocumentReference value. | -| [exists(value)](./firestore_lite_pipelines.md#exists_f3daf14) | (Public Preview) Creates an expression that checks if a field exists. -```typescript -// Check if the document has a field named "phoneNumber" -exists(field("phoneNumber")); - -``` - | -| [isAbsent(value)](./firestore_lite_pipelines.md#isabsent_f3daf14) | (Public Preview) Creates an expression that returns true if a value is absent. Otherwise, returns false even if the value is null. -```typescript -// Check if the field `value` is absent. -isAbsent(field("value")); - -``` - | -| [isError(value)](./firestore_lite_pipelines.md#iserror_f3daf14) | (Public Preview) Creates an expression that checks if a given expression produces an error. -```typescript -// Check if the result of a calculation is an error -isError(field("title").arrayContains(1)); - -``` - | +| [exists(value)](./firestore_lite_pipelines.md#exists_f3daf14) | (Public Preview) Creates an expression that checks if a field exists. | +| [isAbsent(value)](./firestore_lite_pipelines.md#isabsent_f3daf14) | (Public Preview) Creates an expression that returns true if a value is absent. Otherwise, returns false even if the value is null. | +| [isError(value)](./firestore_lite_pipelines.md#iserror_f3daf14) | (Public Preview) Creates an expression that checks if a given expression produces an error. | | function(vectorExpression, ...) | -| [cosineDistance(vectorExpression, vector)](./firestore_lite_pipelines.md#cosinedistance_3a80317) | (Public Preview) Calculates the Cosine distance between a vector expression and a vector literal. -```typescript -// Calculate the cosine distance between the 'location' field and a target location -cosineDistance(field("location"), [37.7749, -122.4194]); - -``` - | -| [cosineDistance(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#cosinedistance_17b5bcc) | (Public Preview) Calculates the Cosine distance between two vector expressions. -```typescript -// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field -cosineDistance(field("userVector"), field("itemVector")); - -``` - | -| [dotProduct(vectorExpression, vector)](./firestore_lite_pipelines.md#dotproduct_3a80317) | (Public Preview) Calculates the dot product between a vector expression and a double array. -```typescript -// Calculate the dot product between a feature vector and a target vector -dotProduct(field("features"), [0.5, 0.8, 0.2]); - -``` - | -| [dotProduct(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#dotproduct_17b5bcc) | (Public Preview) Calculates the dot product between two vector expressions. -```typescript -// Calculate the dot product between two document vectors: 'docVector1' and 'docVector2' -dotProduct(field("docVector1"), field("docVector2")); - -``` - | -| [euclideanDistance(vectorExpression, vector)](./firestore_lite_pipelines.md#euclideandistance_3a80317) | (Public Preview) Calculates the Euclidean distance between a vector expression and a double array. -```typescript -// Calculate the Euclidean distance between the 'location' field and a target location - -euclideanDistance(field("location"), [37.7749, -122.4194]); - -``` - | -| [euclideanDistance(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#euclideandistance_17b5bcc) | (Public Preview) Calculates the Euclidean distance between two vector expressions. -```typescript -// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' -euclideanDistance(field("pointA"), field("pointB")); - -``` - | -| [vectorLength(vectorExpression)](./firestore_lite_pipelines.md#vectorlength_58a039b) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector. -```typescript -// Get the vector length (dimension) of the field 'embedding'. -vectorLength(field("embedding")); - -``` - | +| [cosineDistance(vectorExpression, vector)](./firestore_lite_pipelines.md#cosinedistance_3a80317) | (Public Preview) Calculates the Cosine distance between a vector expression and a vector literal. | +| [cosineDistance(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#cosinedistance_17b5bcc) | (Public Preview) Calculates the Cosine distance between two vector expressions. | +| [dotProduct(vectorExpression, vector)](./firestore_lite_pipelines.md#dotproduct_3a80317) | (Public Preview) Calculates the dot product between a vector expression and a double array. | +| [dotProduct(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#dotproduct_17b5bcc) | (Public Preview) Calculates the dot product between two vector expressions. | +| [euclideanDistance(vectorExpression, vector)](./firestore_lite_pipelines.md#euclideandistance_3a80317) | (Public Preview) Calculates the Euclidean distance between a vector expression and a double array. | +| [euclideanDistance(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#euclideandistance_17b5bcc) | (Public Preview) Calculates the Euclidean distance between two vector expressions. | +| [vectorLength(vectorExpression)](./firestore_lite_pipelines.md#vectorlength_58a039b) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector. | ## Classes @@ -1724,52 +321,22 @@ vectorLength(field("embedding")); | [CollectionReference](./firestore_lite_pipelines.collectionreference.md#collectionreference_class) | A CollectionReference object can be used for adding documents, getting document references, and querying for documents (using [query()](./firestore_.md#query_9f7b0f4)). | | [DocumentReference](./firestore_lite_pipelines.documentreference.md#documentreference_class) | A DocumentReference refers to a document location in a Firestore database and can be used to write, read, or listen to the location. The document at the referenced location may or may not exist. | | [DocumentSnapshot](./firestore_lite_pipelines.documentsnapshot.md#documentsnapshot_class) | A DocumentSnapshot contains data read from a document in your Firestore database. The data can be extracted with .data() or .get(<field>) to get a specific field.For a DocumentSnapshot that points to a non-existing document, any data access will return 'undefined'. You can use the exists() method to explicitly verify a document's existence. | -| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | (Public Preview) Represents an expression that can be evaluated to a value within the execution of a .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 Expr class provides a fluent API for building expressions. You can chain together method calls to create complex expressions. | -| [Field](./firestore_lite_pipelines.field.md#field_class) | (Public Preview) Represents a reference to a field in a Firestore document, or outputs of a stage.

Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines.

You can create a Field instance using the static method: -```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"); - -``` - | +| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | (Public Preview) Represents an expression that can be evaluated to a value within the execution of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class).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. | +| [Field](./firestore_lite_pipelines.field.md#field_class) | (Public Preview) Represents a reference to a field in a Firestore document, or outputs of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) stage.

Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines.

You can create a Field instance using the static method: | | [FieldPath](./firestore_lite_pipelines.fieldpath.md#fieldpath_class) | A FieldPath refers to a field in a document. The path may consist of a single field name (referring to a top-level field in the document), or a list of field names (referring to a nested field in the document).Create a FieldPath by providing field names. If more than one field name is provided, the path will point to a nested field in a document. | | [FieldValue](./firestore_lite_pipelines.fieldvalue.md#fieldvalue_class) | Sentinel values that can be used when writing document fields with set() or update(). | | [Firestore](./firestore_lite_pipelines.firestore.md#firestore_class) | The Cloud Firestore service interface.Do not call this constructor directly. Instead, use [getFirestore()](./firestore_.md#getfirestore). | -| [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) | (Public Preview) This class defines the base class for Firestore functions, which can be evaluated within pipeline execution.Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_.md#and_e72c712), , or the methods on (, , etc.) to construct new Function instances. | +| [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) | (Public Preview) This class defines the base class for Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) functions, which can be evaluated within pipeline execution.Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_pipelines.md#and_e0c48bd), [equal()](./firestore_pipelines.md#equal_b3c3382), or the methods on [Expression](./firestore_pipelines.expression.md#expression_class) ([Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), etc.) to construct new Function instances. | | [GeoPoint](./firestore_lite_pipelines.geopoint.md#geopoint_class) | An immutable object representing a geographic location in Firestore. The location is represented as latitude/longitude pair.Latitude values are in the range of \[-90, 90\]. Longitude values are in the range of \[-180, 180\]. | | [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) | (Public Preview) Represents an ordering criterion for sorting documents in a Firestore pipeline.You create Ordering instances using the ascending and descending helper functions. | -| [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) | (Public Preview) The Pipeline class provides a flexible and expressive framework for building complex data transformation and query pipelines for Firestore.A pipeline takes data sources, such as Firestore collections or collection groups, and applies a series of stages that are chained together. Each stage takes the output from the previous stage (or the data source) and produces an output for the next stage (or as the final output of the pipeline).Expressions can be used within each stage to filter and transform data through the stage.NOTE: The chained stages do not prescribe exactly how Firestore will execute the pipeline. Instead, Firestore only guarantees that the result is the same as if the chained stages were executed in order.Usage Examples: -```typescript -const db: Firestore; // Assumes a valid firestore instance. - -// Example 1: Select specific fields and rename 'rating' to 'bookRating' -const results1 = await execute(db.pipeline() - .collection("books") - .select("title", "author", field("rating").as("bookRating"))); - -// Example 2: Filter documents where 'genre' is "Science Fiction" and 'published' is after 1950 -const results2 = await execute(db.pipeline() - .collection("books") - .where(and(field("genre").eq("Science Fiction"), field("published").gt(1950)))); - -// Example 3: Calculate the average rating of books published after 1980 -const results3 = await execute(db.pipeline() - .collection("books") - .where(field("published").gt(1980)) - .aggregate(avg(field("rating")).as("averageRating"))); - -``` - | -| [PipelineResult](./firestore_lite_pipelines.pipelineresult.md#pipelineresult_class) | (Public Preview) A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the or methods.

If the PipelineResult represents a non-document result, ref will return a undefined value. | -| [PipelineSnapshot](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) | (Public Preview) Represents the results of a Firestore pipeline execution.A PipelineSnapshot contains zero or more objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. | -| [PipelineSource](./firestore_lite_pipelines.pipelinesource.md#pipelinesource_class) | (Public Preview) Provides the entry point for defining the data source of a Firestore .Use the methods of this class (e.g., , , , or ) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. | +| [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) | (Public Preview) The Pipeline class provides a flexible and expressive framework for building complex data transformation and query pipelines for Firestore.A pipeline takes data sources, such as Firestore collections or collection groups, and applies a series of stages that are chained together. Each stage takes the output from the previous stage (or the data source) and produces an output for the next stage (or as the final output of the pipeline).Expressions can be used within each stage to filter and transform data through the stage.NOTE: The chained stages do not prescribe exactly how Firestore will execute the pipeline. Instead, Firestore only guarantees that the result is the same as if the chained stages were executed in order.Usage Examples: | +| [PipelineResult](./firestore_lite_pipelines.pipelineresult.md#pipelineresult_class) | (Public Preview) A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the [PipelineResult.data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) or [PipelineResult.get()](./firestore_pipelines.pipelineresult.md#pipelineresultget) methods.

If the PipelineResult represents a non-document result, ref will return a undefined value. | +| [PipelineSnapshot](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) | (Public Preview) Represents the results of a Firestore pipeline execution.A PipelineSnapshot contains zero or more [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. | +| [PipelineSource](./firestore_lite_pipelines.pipelinesource.md#pipelinesource_class) | (Public Preview) Provides the entry point for defining the data source of a Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class).Use the methods of this class (e.g., [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection), [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup), [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase), or [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments)) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. | | [Query](./firestore_lite_pipelines.query.md#query_class) | A Query refers to a query which you can read or listen to. You can also construct refined Query objects by adding filters and ordering. | | [QueryDocumentSnapshot](./firestore_lite_pipelines.querydocumentsnapshot.md#querydocumentsnapshot_class) | A QueryDocumentSnapshot contains data read from a document in your Firestore database as part of a query. The document is guaranteed to exist and its data can be extracted with .data() or .get(<field>) to get a specific field.A QueryDocumentSnapshot offers the same API surface as a DocumentSnapshot. Since query results contain only existing documents, the exists property will always be true and data() will never return 'undefined'. | | [Timestamp](./firestore_lite_pipelines.timestamp.md#timestamp_class) | A Timestamp represents a point in time independent of any time zone or calendar, represented as seconds and fractions of seconds at nanosecond resolution in UTC Epoch time.It is encoded using the Proleptic Gregorian Calendar which extends the Gregorian calendar backwards to year one. It is encoded assuming all minutes are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.For examples and further specifications, refer to the [Timestamp definition](https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto). | -| [VectorValue](./firestore_lite_pipelines.vectorvalue.md#vectorvalue_class) | Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). VectorValue | +| [VectorValue](./firestore_lite_pipelines.vectorvalue.md#vectorvalue_class) | Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). | ## Interfaces @@ -1784,30 +351,30 @@ const results3 = await execute(db.pipeline() | Type Alias | Description | | --- | --- | -| [AddFieldsStageOptions](./firestore_lite_pipelines.md#addfieldsstageoptions) | (Public Preview) Options defining how an AddFieldsStage is evaluated. See . | -| [AggregateStageOptions](./firestore_lite_pipelines.md#aggregatestageoptions) | (Public Preview) Options defining how an AggregateStage is evaluated. See . | -| [CollectionGroupStageOptions](./firestore_lite_pipelines.md#collectiongroupstageoptions) | (Public Preview) Defines the configuration options for a within a pipeline. This type extends and provides specific settings for how a collection group is identified and processed during pipeline execution. | -| [CollectionStageOptions](./firestore_lite_pipelines.md#collectionstageoptions) | (Public Preview) Options defining how a CollectionStage is evaluated. See . | -| [DatabaseStageOptions](./firestore_lite_pipelines.md#databasestageoptions) | (Public Preview) Options defining how a DatabaseStage is evaluated. See . | -| [DistinctStageOptions](./firestore_lite_pipelines.md#distinctstageoptions) | (Public Preview) Options defining how a DistinctStage is evaluated. See . | -| [DocumentsStageOptions](./firestore_lite_pipelines.md#documentsstageoptions) | (Public Preview) Options defining how a DocumentsStage is evaluated. See . | +| [AddFieldsStageOptions](./firestore_lite_pipelines.md#addfieldsstageoptions) | (Public Preview) Options defining how an AddFieldsStage is evaluated. See [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields). | +| [AggregateStageOptions](./firestore_lite_pipelines.md#aggregatestageoptions) | (Public Preview) Options defining how an AggregateStage is evaluated. See [Pipeline.aggregate()](./firestore_pipelines.pipeline.md#pipelineaggregate). | +| [CollectionGroupStageOptions](./firestore_lite_pipelines.md#collectiongroupstageoptions) | (Public Preview) Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution.See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. | +| [CollectionStageOptions](./firestore_lite_pipelines.md#collectionstageoptions) | (Public Preview) Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). | +| [DatabaseStageOptions](./firestore_lite_pipelines.md#databasestageoptions) | (Public Preview) Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). | +| [DistinctStageOptions](./firestore_lite_pipelines.md#distinctstageoptions) | (Public Preview) Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). | +| [DocumentsStageOptions](./firestore_lite_pipelines.md#documentsstageoptions) | (Public Preview) Options defining how a DocumentsStage is evaluated. See [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments). | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) An enumeration of the different types of expressions. | -| [FindNearestStageOptions](./firestore_lite_pipelines.md#findneareststageoptions) | (Public Preview) Options defining how a FindNearestStage is evaluated. See . | -| [LimitStageOptions](./firestore_lite_pipelines.md#limitstageoptions) | (Public Preview) Options defining how a LimitStage is evaluated. See . | -| [OffsetStageOptions](./firestore_lite_pipelines.md#offsetstageoptions) | (Public Preview) Options defining how an OffsetStage is evaluated. See . | -| [OneOf](./firestore_lite_pipelines.md#oneof) | (Public Preview) Utility type to create an type that only allows one property of the Type param T to be set.type XorY = OneOf<{ x: unknown, y: unknown}> let a = { x: "foo" } // OK let b = { y: "foo" } // OK let c = { a: "foo", y: "foo" } // Not OK | +| [FindNearestStageOptions](./firestore_lite_pipelines.md#findneareststageoptions) | (Public Preview) Options defining how a FindNearestStage is evaluated. See [Pipeline.findNearest()](./firestore_pipelines.pipeline.md#pipelinefindnearest). | +| [LimitStageOptions](./firestore_lite_pipelines.md#limitstageoptions) | (Public Preview) Options defining how a LimitStage is evaluated. See [Pipeline.limit()](./firestore_pipelines.pipeline.md#pipelinelimit). | +| [OffsetStageOptions](./firestore_lite_pipelines.md#offsetstageoptions) | (Public Preview) Options defining how an OffsetStage is evaluated. See [Pipeline.offset()](./firestore_pipelines.pipeline.md#pipelineoffset). | +| [OneOf](./firestore_lite_pipelines.md#oneof) | (Public Preview) Utility type to create an type that only allows one property of the Type param T to be set. | | [PartialWithFieldValue](./firestore_lite_pipelines.md#partialwithfieldvalue) | Similar to TypeScript's Partial<T>, but allows nested fields to be omitted and FieldValues to be passed in as property values. | | [Primitive](./firestore_lite_pipelines.md#primitive) | Primitive types. | -| [RemoveFieldsStageOptions](./firestore_lite_pipelines.md#removefieldsstageoptions) | (Public Preview) Options defining how a RemoveFieldsStage is evaluated. See . | -| [ReplaceWithStageOptions](./firestore_lite_pipelines.md#replacewithstageoptions) | (Public Preview) Options defining how a ReplaceWithStage is evaluated. See . | -| [SampleStageOptions](./firestore_lite_pipelines.md#samplestageoptions) | (Public Preview) Defines the options for evaluating a sample stage within a pipeline. This type combines common with a specific configuration where only one of the defined sampling methods can be applied.See to create a sample stage.. | -| [SelectStageOptions](./firestore_lite_pipelines.md#selectstageoptions) | (Public Preview) Options defining how a SelectStage is evaluated. See . | +| [RemoveFieldsStageOptions](./firestore_lite_pipelines.md#removefieldsstageoptions) | (Public Preview) Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). | +| [ReplaceWithStageOptions](./firestore_lite_pipelines.md#replacewithstageoptions) | (Public Preview) Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). | +| [SampleStageOptions](./firestore_lite_pipelines.md#samplestageoptions) | (Public Preview) Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied.See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. | +| [SelectStageOptions](./firestore_lite_pipelines.md#selectstageoptions) | (Public Preview) Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). | | [SetOptions](./firestore_lite_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | -| [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See . | +| [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | (Public Preview) Specify time granularity for expressions. | -| [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See . | +| [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | | [UnnestStageOptions](./firestore_lite_pipelines.md#unneststageoptions) | (Public Preview) Represents the specific options available for configuring an UnnestStage within a pipeline. | -| [WhereStageOptions](./firestore_lite_pipelines.md#wherestageoptions) | (Public Preview) Options defining how a WhereStage is evaluated. See . | +| [WhereStageOptions](./firestore_lite_pipelines.md#wherestageoptions) | (Public Preview) Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). | | [WithFieldValue](./firestore_lite_pipelines.md#withfieldvalue) | Allows FieldValues to be passed in as a property value while maintaining type safety. | ## function() @@ -1819,13 +386,6 @@ const results3 = await execute(db.pipeline() Creates an aggregation that counts the total number of stage inputs. -```typescript -// Count the total number of input documents -countAll().as("totalDocument"); - -``` - A new representing the 'countAll' aggregation. - Signature: ```typescript @@ -1835,19 +395,23 @@ export declare function countAll(): AggregateFunction; [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -### currentTimestamp() {:#currenttimestamp} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'countAll' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that evaluates to the current server timestamp. ```typescript -// Get the current server timestamp -currentTimestamp() +// Count the total number of input documents +countAll().as("totalDocument"); ``` - A new Expression representing the current server timestamp. + +### currentTimestamp() {:#currenttimestamp} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to the current server timestamp. Signature: @@ -1858,6 +422,17 @@ export declare function currentTimestamp(): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new Expression representing the current server timestamp. + +### Example + + +```typescript +// Get the current server timestamp +currentTimestamp() + +``` + ## function(array, ...) ### arrayContains(array, element) {:#arraycontains_a00ea48} @@ -1867,12 +442,6 @@ export declare function currentTimestamp(): FunctionExpression; Creates an expression that checks if an array expression contains a specific element. -```typescript -// Check if the 'colors' array contains the value of field 'selectedColor' -arrayContains(field("colors"), field("selectedColor")); - -``` - Signature: ```typescript @@ -1884,25 +453,30 @@ export declare function arrayContains(array: Expression, element: Expression): B | Parameter | Type | Description | | --- | --- | --- | | array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to check. | -| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The element to search for in the array. A new representing the 'array\_contains' comparison. | +| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The element to search for in the array. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContains(array, element) {:#arraycontains_7328608} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array expression contains a specific element. ```typescript -// Check if the 'colors' array contains "red" -arrayContains(field("colors"), "red"); +// Check if the 'colors' array contains the value of field 'selectedColor' +arrayContains(field("colors"), field("selectedColor")); ``` +### arrayContains(array, element) {:#arraycontains_7328608} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains a specific element. + Signature: ```typescript @@ -1914,25 +488,30 @@ export declare function arrayContains(array: Expression, element: unknown): Bool | Parameter | Type | Description | | --- | --- | --- | | array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to check. | -| element | unknown | The element to search for in the array. A new representing the 'array\_contains' comparison. | +| element | unknown | The element to search for in the array. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAll(array, values) {:#arraycontainsall_c658ad5} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array expression contains all the specified elements. ```typescript -// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" -arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); +// Check if the 'colors' array contains "red" +arrayContains(field("colors"), "red"); ``` +### arrayContainsAll(array, values) {:#arraycontainsall_c658ad5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains all the specified elements. + Signature: ```typescript @@ -1944,18 +523,16 @@ export declare function arrayContainsAll(array: Expression, values: ArrayReturns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAll(array, arrayExpression) {:#arraycontainsall_7b535db} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array expression contains all the specified elements. ```typescript // Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" @@ -1963,6 +540,13 @@ arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]) ``` +### arrayContainsAll(array, arrayExpression) {:#arraycontainsall_7b535db} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains all the specified elements. + Signature: ```typescript @@ -1974,25 +558,30 @@ export declare function arrayContainsAll(array: Expression, arrayExpression: Exp | Parameter | Type | Description | | --- | --- | --- | | array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to check. | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. A new representing the 'array\_contains\_all' comparison. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAny(array, values) {:#arraycontainsany_c658ad5} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array expression contains any of the specified elements. ```typescript -// Check if the 'categories' array contains either values from field "cate1" or "Science" -arrayContainsAny(field("categories"), [field("cate1"), "Science"]); +// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" +arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); ``` +### arrayContainsAny(array, values) {:#arraycontainsany_c658ad5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains any of the specified elements. + Signature: ```typescript @@ -2004,25 +593,30 @@ export declare function arrayContainsAny(array: Expression, values: ArrayReturns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAny(array, values) {:#arraycontainsany_c381a96} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array expression contains any of the specified elements. ```typescript // Check if the 'categories' array contains either values from field "cate1" or "Science" -arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); +arrayContainsAny(field("categories"), [field("cate1"), "Science"]); ``` +### arrayContainsAny(array, values) {:#arraycontainsany_c381a96} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains any of the specified elements. + Signature: ```typescript @@ -2034,25 +628,30 @@ export declare function arrayContainsAny(array: Expression, values: Expression): | Parameter | Type | Description | | --- | --- | --- | | array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to check. | -| values | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array. A new representing the 'array\_contains\_any' comparison. | +| values | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### arrayLength(array) {:#arraylength_195e339} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of an array expression. ```typescript -// Get the number of items in the 'cart' array -arrayLength(field("cart")); +// Check if the 'categories' array contains either values from field "cate1" or "Science" +arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); ``` +### arrayLength(array) {:#arraylength_195e339} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of an array expression. + Signature: ```typescript @@ -2063,11 +662,22 @@ export declare function arrayLength(array: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to calculate the length of. A new representing the length of the array. | +| array | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The array expression to calculate the length of. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the array. + +### Example + + +```typescript +// Get the number of items in the 'cart' array +arrayLength(field("cart")); + +``` ## function(arrayExpression, ...) @@ -2078,12 +688,6 @@ export declare function arrayLength(array: Expression): FunctionExpression; Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index 1. -arrayGet(field('tags'), 1); - -``` - Signature: ```typescript @@ -2094,27 +698,31 @@ export declare function arrayGet(arrayExpression: Expression, offset: number): F | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expr evaluating to an array. | -| offset | number | The index of the element to return. A new Expr representing the 'arrayGet' operation. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to an array. | +| offset | number | The index of the element to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### arrayGet(arrayExpression, offsetExpr) {:#arrayget_484550d} +A new `Expression` representing the 'arrayGet' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. ```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -arrayGet(field('tags'), field('favoriteTag')); +// Return the value in the tags field array at index 1. +arrayGet(field('tags'), 1); ``` +### arrayGet(arrayExpression, offsetExpr) {:#arrayget_484550d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + Signature: ```typescript @@ -2125,26 +733,32 @@ export declare function arrayGet(arrayExpression: Expression, offsetExpr: Expres | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expr evaluating to an array. | -| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expr evaluating to the index of the element to return. A new Expr representing the 'arrayGet' operation. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to an array. | +| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### join(arrayExpression, delimiterExpression) {:#join_313e6aa} +A new `Expression` representing the 'arrayGet' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that joins the elements of an array into a string. ```typescript -// Join an array of string using the delimiter from the 'separator' field. -join(array(['foo', 'bar']), field("separator")) +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet(field('tags'), field('favoriteTag')); ``` +### join(arrayExpression, delimiterExpression) {:#join_313e6aa} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + Signature: ```typescript @@ -2156,25 +770,30 @@ export declare function join(arrayExpression: Expression, delimiterExpression: E | Parameter | Type | Description | | --- | --- | --- | | arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | -| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. A new Expression representing the join operation. | +| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) -### join(arrayExpression, delimiter) {:#join_d088d29} +A new Expression representing the join operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that joins the elements of an array into a string. ```typescript -// Join the elements of the 'tags' field with a comma and space. -join(field("tags"), ", ") +// Join an array of string using the delimiter from the 'separator' field. +join(array(['foo', 'bar']), field("separator")) ``` +### join(arrayExpression, delimiter) {:#join_d088d29} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + Signature: ```typescript @@ -2186,12 +805,23 @@ export declare function join(arrayExpression: Expression, delimiter: string): Ex | Parameter | Type | Description | | --- | --- | --- | | arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | -| delimiter | string | The string to use as a delimiter. A new Expression representing the join operation. | +| delimiter | string | The string to use as a delimiter. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new Expression representing the join operation. + +### Example + + +```typescript +// Join the elements of the 'tags' field with a comma and space. +join(field("tags"), ", ") + +``` + ## function(arrayField, ...) ### arrayGet(arrayField, offset) {:#arrayget_3f58471} @@ -2201,12 +831,6 @@ export declare function join(arrayExpression: Expression, delimiter: string): Ex Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index 1. -arrayGet('tags', 1); - -``` - Signature: ```typescript @@ -2218,26 +842,30 @@ export declare function arrayGet(arrayField: string, offset: number): FunctionEx | Parameter | Type | Description | | --- | --- | --- | | arrayField | string | The name of the array field. | -| offset | number | The index of the element to return. A new Expr representing the 'arrayGet' operation. | +| offset | number | The index of the element to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### arrayGet(arrayField, offsetExpr) {:#arrayget_1904c9a} +A new `Expression` representing the 'arrayGet' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. ```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -arrayGet('tags', field('favoriteTag')); +// Return the value in the tags field array at index 1. +arrayGet('tags', 1); ``` +### arrayGet(arrayField, offsetExpr) {:#arrayget_1904c9a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + Signature: ```typescript @@ -2249,12 +877,24 @@ export declare function arrayGet(arrayField: string, offsetExpr: Expression): Fu | Parameter | Type | Description | | --- | --- | --- | | arrayField | string | The name of the array field. | -| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expr evaluating to the index of the element to return. A new Expr representing the 'arrayGet' operation. | +| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the 'arrayGet' operation. + +### Example + + +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet('tags', field('favoriteTag')); + +``` + ## function(arrayFieldName, ...) ### join(arrayFieldName, delimiter) {:#join_478ef36} @@ -2264,12 +904,6 @@ export declare function arrayGet(arrayField: string, offsetExpr: Expression): Fu Creates an expression that joins the elements of an array into a string. -```typescript -// Join the elements of the 'tags' field with a comma and space. -join("tags", ", ") - -``` - Signature: ```typescript @@ -2281,25 +915,30 @@ export declare function join(arrayFieldName: string, delimiter: string): Express | Parameter | Type | Description | | --- | --- | --- | | arrayFieldName | string | The name of the field containing the array. | -| delimiter | string | The string to use as a delimiter. A new Expression representing the join operation. | +| delimiter | string | The string to use as a delimiter. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) -### join(arrayFieldName, delimiterExpression) {:#join_829294c} +A new Expression representing the join operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that joins the elements of an array into a string. ```typescript -// Join the elements of the 'tags' field with the delimiter from the 'separator' field. -join('tags', field("separator")) +// Join the elements of the 'tags' field with a comma and space. +join("tags", ", ") ``` +### join(arrayFieldName, delimiterExpression) {:#join_829294c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + Signature: ```typescript @@ -2311,12 +950,23 @@ export declare function join(arrayFieldName: string, delimiterExpression: Expres | Parameter | Type | Description | | --- | --- | --- | | arrayFieldName | string | The name of the field containing the array. | -| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. A new Expression representing the join operation. | +| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new Expression representing the join operation. + +### Example + + +```typescript +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +join('tags', field("separator")) + +``` + ## function(base, ...) ### pow(base, exponent) {:#pow_e4a9e64} @@ -2326,12 +976,6 @@ export declare function join(arrayFieldName: string, delimiterExpression: Expres Creates an expression that returns the value of the base expression raised to the power of the exponent expression. -```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -pow(field("base"), field("exponent")); - -``` - Signature: ```typescript @@ -2343,25 +987,30 @@ export declare function pow(base: Expression, exponent: Expression): FunctionExp | Parameter | Type | Description | | --- | --- | --- | | base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | -| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. A new Expr representing the power operation. | +| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### pow(base, exponent) {:#pow_93eae7f} +A new `Expression` representing the power operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the value of the base expression raised to the power of the exponent. ```typescript -// Raise the value of the 'base' field to the power of 2. -pow(field("base"), 2); +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow(field("base"), field("exponent")); ``` +### pow(base, exponent) {:#pow_93eae7f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base expression raised to the power of the exponent. + Signature: ```typescript @@ -2373,25 +1022,30 @@ export declare function pow(base: Expression, exponent: number): FunctionExpress | Parameter | Type | Description | | --- | --- | --- | | base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | -| exponent | number | The constant value to raise the base to the power of. A new Expr representing the power operation. | +| exponent | number | The constant value to raise the base to the power of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### pow(base, exponent) {:#pow_a237721} +A new `Expression` representing the power operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the value of the base field raised to the power of the exponent expression. ```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -pow("base", field("exponent")); +// Raise the value of the 'base' field to the power of 2. +pow(field("base"), 2); ``` +### pow(base, exponent) {:#pow_a237721} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base field raised to the power of the exponent expression. + Signature: ```typescript @@ -2403,25 +1057,30 @@ export declare function pow(base: string, exponent: Expression): FunctionExpress | Parameter | Type | Description | | --- | --- | --- | | base | string | The name of the field to raise to the power of the exponent. | -| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. A new Expr representing the power operation. | +| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### pow(base, exponent) {:#pow_f4d7908} +A new `Expression` representing the power operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the value of the base field raised to the power of the exponent. ```typescript -// Raise the value of the 'base' field to the power of 2. -pow("base", 2); +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow("base", field("exponent")); ``` +### pow(base, exponent) {:#pow_f4d7908} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base field raised to the power of the exponent. + Signature: ```typescript @@ -2433,12 +1092,23 @@ export declare function pow(base: string, exponent: number): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | | base | string | The name of the field to raise to the power of the exponent. | -| exponent | number | The constant value to raise the base to the power of. A new Expr representing the power operation. | +| exponent | number | The constant value to raise the base to the power of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the power operation. + +### Example + + +```typescript +// Raise the value of the 'base' field to the power of 2. +pow("base", 2); + +``` + ## function(booleanExpr, ...) ### countIf(booleanExpr) {:#countif_c5b8fb1} @@ -2448,12 +1118,6 @@ export declare function pow(base: string, exponent: number): FunctionExpression; Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. -```typescript -// Count the number of documents where 'is_active' field equals true -countIf(field("is_active").equal(true)).as("numActiveDocuments"); - -``` - Signature: ```typescript @@ -2472,6 +1136,15 @@ export declare function countIf(booleanExpr: BooleanExpression): AggregateFuncti A new `AggregateFunction` representing the 'countIf' aggregation. +### Example + + +```typescript +// Count the number of documents where 'is_active' field equals true +countIf(field("is_active").equal(true)).as("numActiveDocuments"); + +``` + ### not(booleanExpr) {:#not_c5b8fb1} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2479,12 +1152,6 @@ A new `AggregateFunction` representing the 'countIf' aggregation. Creates an expression that negates a filter condition. -```typescript -// Find documents where the 'completed' field is NOT true -not(equal("completed", true)); - -``` - Signature: ```typescript @@ -2495,12 +1162,23 @@ export declare function not(booleanExpr: BooleanExpression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| booleanExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The filter condition to negate. A new representing the negated filter condition. | +| booleanExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The filter condition to negate. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the negated filter condition. + +### Example + + +```typescript +// Find documents where the 'completed' field is NOT true +not(equal("completed", true)); + +``` + ## function(condition, ...) ### conditional(condition, thenExpr, elseExpr) {:#conditional_07a206d} @@ -2510,13 +1188,6 @@ export declare function not(booleanExpr: BooleanExpression): BooleanExpression; Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. -```typescript -// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". -conditional( - greaterThan("age", 18), constant("Adult"), constant("Minor")); - -``` - Signature: ```typescript @@ -2529,12 +1200,24 @@ export declare function conditional(condition: BooleanExpression, thenExpr: Expr | --- | --- | --- | | condition | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The condition to evaluate. | | thenExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is true. | -| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. A new representing the conditional expression. | +| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the conditional expression. + +### Example + + +```typescript +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +conditional( + greaterThan("age", 18), constant("Adult"), constant("Minor")); + +``` + ## function(documentPath, ...) ### documentId(documentPath) {:#documentid_cef293c} @@ -2544,13 +1227,6 @@ export declare function conditional(condition: BooleanExpression, thenExpr: Expr Creates an expression that returns the document ID from a path. -```typescript -// Get the document ID from a path. -documentId(myDocumentReference); - -``` - A new representing the documentId operation. - Signature: ```typescript @@ -2567,6 +1243,17 @@ export declare function documentId(documentPath: string | DocumentReference): Fu [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. + +### Example + + +```typescript +// Get the document ID from a path. +documentId(myDocumentReference); + +``` + ## function(documentPathExpr, ...) ### documentId(documentPathExpr) {:#documentid_9a69021} @@ -2576,13 +1263,6 @@ export declare function documentId(documentPath: string | DocumentReference): Fu Creates an expression that returns the document ID from a path. -```typescript -// Get the document ID from a path. -documentId(field("__path__")); - -``` - A new representing the documentId operation. - Signature: ```typescript @@ -2599,6 +1279,17 @@ export declare function documentId(documentPathExpr: Expression): FunctionExpres [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. + +### Example + + +```typescript +// Get the document ID from a path. +documentId(field("__path__")); + +``` + ## function(element, ...) ### notEqualAny(element, values) {:#notequalany_c2c5bcb} @@ -2608,12 +1299,6 @@ export declare function documentId(documentPathExpr: Expression): FunctionExpres Creates an expression that checks if an expression is not equal to any of the provided values or expressions. -```typescript -// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' -notEqualAny(field("status"), ["pending", field("rejectedStatus")]); - -``` - Signature: ```typescript @@ -2625,25 +1310,30 @@ export declare function notEqualAny(element: Expression, values: ArrayReturns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### notEqualAny(element, arrayExpression) {:#notequalany_16b2851} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is not equal to any of the provided values or expressions. ```typescript -// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' notEqualAny(field("status"), ["pending", field("rejectedStatus")]); ``` +### notEqualAny(element, arrayExpression) {:#notequalany_16b2851} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to any of the provided values or expressions. + Signature: ```typescript @@ -2655,12 +1345,23 @@ export declare function notEqualAny(element: Expression, arrayExpression: Expres | Parameter | Type | Description | | --- | --- | --- | | element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The values to check against. A new representing the 'NOT IN' comparison. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The values to check against. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. + +### Example + + +```typescript +// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + ## function(elements, ...) ### array(elements) {:#array_7d853aa} @@ -2670,12 +1371,6 @@ export declare function notEqualAny(element: Expression, arrayExpression: Expres Creates an expression that creates a Firestore array value from an input array. -```typescript -// Create an array value from the input array and reference the 'baz' field value from the input document. -array(['bar', Field.of('baz')]).as('foo'); - -``` - Signature: ```typescript @@ -2686,25 +1381,30 @@ export declare function array(elements: unknown[]): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| elements | unknown\[\] | The input array to evaluate in the expression. A new representing the array function. | +| elements | unknown\[\] | The input array to evaluate in the expression. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### map(elements) {:#map_ce5dee1} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the array function. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that creates a Firestore map value from an input object. ```typescript -// Create a map from the input object and reference the 'baz' field value from the input document. -map({foo: 'bar', baz: Field.of('baz')}).as('data'); +// Create an array value from the input array and reference the 'baz' field value from the input document. +array(['bar', Field.of('baz')]).as('foo'); ``` +### map(elements) {:#map_ce5dee1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that creates a Firestore map value from an input object. + Signature: ```typescript @@ -2715,12 +1415,23 @@ export declare function map(elements: Record): FunctionExpressi | Parameter | Type | Description | | --- | --- | --- | -| elements | Record<string, unknown> | The input map to evaluate in the expression. A new representing the map function. | +| elements | Record<string, unknown> | The input map to evaluate in the expression. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the map function. + +### Example + + +```typescript +// Create a map from the input object and reference the 'baz' field value from the input document. +map({foo: 'bar', baz: Field.of('baz')}).as('data'); + +``` + ## function(expr, ...) ### abs(expr) {:#abs_005f3d4} @@ -2740,25 +1451,20 @@ export declare function abs(expr: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compute the absolute value of. A new representing the absolute value of the numeric value. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compute the absolute value of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. + ### ascending(expr) {:#ascending_005f3d4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an that sorts documents in ascending order based on an expression. - -```typescript -// Sort documents by the 'name' field in lowercase in ascending order -firestore.pipeline().collection("users") - .sort(ascending(field("name").toLower())); - -``` +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. Signature: @@ -2770,25 +1476,31 @@ export declare function ascending(expr: Expression): Ordering; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to create an ascending ordering for. A new Ordering for ascending sorting. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to create an ascending ordering for. | Returns: [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) -### byteLength(expr) {:#bytelength_005f3d4} +A new `Ordering` for ascending sorting. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. ```typescript -// Calculate the length of the 'myString' field in bytes. -byteLength(field("myString")); +// Sort documents by the 'name' field in lowercase in ascending order +firestore.pipeline().collection("users") + .sort(ascending(field("name").toLower())); ``` +### byteLength(expr) {:#bytelength_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. + Signature: ```typescript @@ -2799,12 +1511,23 @@ export declare function byteLength(expr: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string. A new representing the length of the string in bytes. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string in bytes. + +### Example + + +```typescript +// Calculate the length of the 'myString' field in bytes. +byteLength(field("myString")); + +``` + ### countDistinct(expr) {:#countdistinct_3c28b08} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2822,25 +1545,20 @@ export declare function countDistinct(expr: Expression | string): AggregateFunct | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string | The expression or field to count distinct values of. A new AggregateFunction representing the 'count\_distinct' aggregation. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string | The expression or field to count distinct values of. | Returns: [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +A new `AggregateFunction` representing the 'count\_distinct' aggregation. + ### descending(expr) {:#descending_005f3d4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an that sorts documents in descending order based on an expression. - -```typescript -// Sort documents by the 'name' field in lowercase in descending order -firestore.pipeline().collection("users") - .sort(descending(field("name").toLower())); - -``` +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. Signature: @@ -2852,12 +1570,24 @@ export declare function descending(expr: Expression): Ordering; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to create a descending ordering for. A new Ordering for descending sorting. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to create a descending ordering for. | Returns: [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) +A new `Ordering` for descending sorting. + +### Example + + +```typescript +// Sort documents by the 'name' field in lowercase in descending order +firestore.pipeline().collection("users") + .sort(descending(field("name").toLower())); + +``` + ### floor(expr) {:#floor_005f3d4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2875,12 +1605,14 @@ export declare function floor(expr: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compute the floor of. A new representing the floor of the numeric value. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compute the floor of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the floor of the numeric value. + ### timestampToUnixMicros(expr) {:#timestamptounixmicros_005f3d4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2888,34 +1620,60 @@ export declare function floor(expr: Expression): FunctionExpression; Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +Signature: + +```typescript +export declare function timestampToUnixMicros(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of microseconds since epoch. + +### Example + + ```typescript // Convert the 'timestamp' field to microseconds since epoch. timestampToUnixMicros(field("timestamp")); ``` +### timestampToUnixMillis(expr) {:#timestamptounixmillis_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + Signature: ```typescript -export declare function timestampToUnixMicros(expr: Expression): FunctionExpression; +export declare function timestampToUnixMillis(expr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. A new representing the number of microseconds since epoch. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### timestampToUnixMillis(expr) {:#timestamptounixmillis_005f3d4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of milliseconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript // Convert the 'timestamp' field to milliseconds since epoch. @@ -2923,28 +1681,33 @@ timestampToUnixMillis(field("timestamp")); ``` +### timestampToUnixSeconds(expr) {:#timestamptounixseconds_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + Signature: ```typescript -export declare function timestampToUnixMillis(expr: Expression): FunctionExpression; +export declare function timestampToUnixSeconds(expr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. A new representing the number of milliseconds since epoch. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### timestampToUnixSeconds(expr) {:#timestamptounixseconds_005f3d4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of seconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript // Convert the 'timestamp' field to seconds since epoch. @@ -2952,28 +1715,33 @@ timestampToUnixSeconds(field("timestamp")); ``` +### unixMicrosToTimestamp(expr) {:#unixmicrostotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + Signature: ```typescript -export declare function timestampToUnixSeconds(expr: Expression): FunctionExpression; +export declare function unixMicrosToTimestamp(expr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. A new representing the number of seconds since epoch. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of microseconds since epoch. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### unixMicrosToTimestamp(expr) {:#unixmicrostotimestamp_005f3d4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. ```typescript // Interpret the 'microseconds' field as microseconds since epoch. @@ -2981,28 +1749,33 @@ unixMicrosToTimestamp(field("microseconds")); ``` +### unixMillisToTimestamp(expr) {:#unixmillistotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + Signature: ```typescript -export declare function unixMicrosToTimestamp(expr: Expression): FunctionExpression; +export declare function unixMillisToTimestamp(expr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of microseconds since epoch. A new representing the timestamp. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of milliseconds since epoch. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### unixMillisToTimestamp(expr) {:#unixmillistotimestamp_005f3d4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. ```typescript // Interpret the 'milliseconds' field as milliseconds since epoch. @@ -3010,28 +1783,33 @@ unixMillisToTimestamp(field("milliseconds")); ``` +### unixSecondsToTimestamp(expr) {:#unixsecondstotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + Signature: ```typescript -export declare function unixMillisToTimestamp(expr: Expression): FunctionExpression; +export declare function unixSecondsToTimestamp(expr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of milliseconds since epoch. A new representing the timestamp. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of seconds since epoch. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### unixSecondsToTimestamp(expr) {:#unixsecondstotimestamp_005f3d4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. ```typescript // Interpret the 'seconds' field as seconds since epoch. @@ -3039,30 +1817,35 @@ unixSecondsToTimestamp(field("seconds")); ``` +## function(expression, ...) + +### arraySum(expression) {:#arraysum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. + Signature: ```typescript -export declare function unixSecondsToTimestamp(expr: Expression): FunctionExpression; +export declare function arraySum(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of seconds since epoch. A new representing the timestamp. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric array, which the sum will be computed for. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -## function(expression, ...) - -### arraySum(expression) {:#arraysum_1138a27} +A new `Expression` representing the sum of the elements in the array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the sum of the elements in an array. ```typescript // Compute the sum of the elements in the 'scores' field. @@ -3070,28 +1853,33 @@ arraySum(field("scores")); ``` +### average(expression) {:#average_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. + Signature: ```typescript -export declare function arraySum(expression: Expression): FunctionExpression; +export declare function average(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric array, which the sum will be computed for. A new Expr representing the sum of the elements in the array. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the values to average. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -### average(expression) {:#average_1138a27} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'average' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. ```typescript // Calculate the average age of users @@ -3099,28 +1887,33 @@ average(field("age")).as("averageAge"); ``` +### ceil(expression) {:#ceil_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. + Signature: ```typescript -export declare function average(expression: Expression): AggregateFunction; +export declare function ceil(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the values to average. A new representing the 'average' aggregation. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the ceiling will be computed for. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### ceil(expression) {:#ceil_1138a27} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ceiling of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the ceiling of a numeric value. ```typescript // Compute the ceiling of the 'price' field. @@ -3128,28 +1921,33 @@ ceil(field("price")); ``` +### collectionId(expression) {:#collectionid_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. + Signature: ```typescript -export declare function ceil(expression: Expression): FunctionExpression; +export declare function collectionId(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the ceiling will be computed for. A new representing the ceiling of the numeric value. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a path, which the collection ID will be extracted from. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### collectionId(expression) {:#collectionid_1138a27} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the collectionId operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the collection ID from a path. ```typescript // Get the collection ID from a path. @@ -3157,28 +1955,33 @@ collectionId(field("__name__")); ``` +### count(expression) {:#count_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. + Signature: ```typescript -export declare function collectionId(expression: Expression): FunctionExpression; +export declare function count(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a path, which the collection ID will be extracted from. A new representing the collectionId operation. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to count. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -### count(expression) {:#count_1138a27} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'count' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. ```typescript // Count the number of items where the price is greater than 10 @@ -3186,28 +1989,34 @@ count(field("price").greaterThan(10)).as("expensiveItemCount"); ``` +### divide(expression, value) {:#divide_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides an expression by a constant value. + Signature: ```typescript -export declare function count(expression: Expression): AggregateFunction; +export declare function divide(expression: Expression, value: unknown): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to count. A new representing the 'count' aggregation. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to be divided. | +| value | unknown | The constant value to divide by. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### divide(expression, value) {:#divide_01df3cf} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the division operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that divides an expression by a constant value. ```typescript // Divide the 'value' field by 10 @@ -3215,29 +2024,34 @@ divide(field("value"), 10); ``` +### equal(expression, value) {:#equal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is equal to a constant value. + Signature: ```typescript -export declare function divide(expression: Expression, value: unknown): FunctionExpression; +export declare function equal(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to be divided. | -| value | unknown | The constant value to divide by. A new representing the division operation. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### equal(expression, value) {:#equal_01df3cf} +A new `Expression` representing the equality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is equal to a constant value. ```typescript // Check if the 'age' field is equal to 21 @@ -3245,29 +2059,34 @@ equal(field("age"), 21); ``` +### equalAny(expression, values) {:#equalany_7e759b5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. + Signature: ```typescript -export declare function equal(expression: Expression, value: unknown): BooleanExpression; +export declare function equalAny(expression: Expression, values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the equality comparison. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression whose results to compare. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values to check against. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### equalAny(expression, values) {:#equalany_7e759b5} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. ```typescript // Check if the 'category' field is either "Electronics" or value of field 'primaryType' @@ -3275,10 +2094,17 @@ equalAny(field("category"), [constant("Electronics"), field("primaryType")]); ``` +### equalAny(expression, arrayExpression) {:#equalany_214ce68} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is equal to any of the provided values. + Signature: ```typescript -export declare function equalAny(expression: Expression, values: Array): BooleanExpression; +export declare function equalAny(expression: Expression, arrayExpression: Expression): BooleanExpression; ``` #### Parameters @@ -3286,18 +2112,16 @@ export declare function equalAny(expression: Expression, values: ArrayReturns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### equalAny(expression, arrayExpression) {:#equalany_214ce68} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is equal to any of the provided values. ```typescript // Check if the 'category' field is set to a value in the disabledCategories field @@ -3305,59 +2129,68 @@ equalAny(field("category"), field('disabledCategories')); ``` +### exp(expression) {:#exp_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes e to the power of the expression's result. + Signature: ```typescript -export declare function equalAny(expression: Expression, arrayExpression: Expression): BooleanExpression; +export declare function exp(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression whose results to compare. | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input. A new representing the 'IN' comparison. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### exp(expression) {:#exp_1138a27} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the exp of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes e to the power of the expression's result. ```typescript // Compute e to the power of 2. exp(constant(2)); ``` - A new representing the exp of the numeric value. + +### greaterThan(expression, value) {:#greaterthan_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is greater than a constant value. Signature: ```typescript -export declare function exp(expression: Expression): FunctionExpression; +export declare function greaterThan(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThan(expression, value) {:#greaterthan_01df3cf} +A new `Expression` representing the greater than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is greater than a constant value. ```typescript // Check if the 'age' field is greater than 18 @@ -3365,10 +2198,17 @@ greaterThan(field("age"), 18); ``` +### greaterThanOrEqual(expression, value) {:#greaterthanorequal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is greater than or equal to a constant value. + Signature: ```typescript -export declare function greaterThan(expression: Expression, value: unknown): BooleanExpression; +export declare function greaterThanOrEqual(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters @@ -3376,18 +2216,16 @@ export declare function greaterThan(expression: Expression, value: unknown): Boo | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the greater than comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThanOrEqual(expression, value) {:#greaterthanorequal_01df3cf} +A new `Expression` representing the greater than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is greater than or equal to a constant value. ```typescript // Check if the 'quantity' field is greater than or equal to 10 @@ -3395,29 +2233,33 @@ greaterThanOrEqual(field("quantity"), 10); ``` +### length\_2(expression) {:#length_2_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string, array, map, vector, or bytes. + Signature: ```typescript -export declare function greaterThanOrEqual(expression: Expression, value: unknown): BooleanExpression; +declare function length_2(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the greater than or equal to comparison. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### length\_2(expression) {:#length_2_1138a27} +A new `Expression` representing the length of the string, array, map, vector, or bytes. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of a string, array, map, vector, or bytes. ```typescript // Get the length of the 'name' field. @@ -3428,28 +2270,34 @@ length(field("cart")); ``` +### lessThan(expression, value) {:#lessthan_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is less than a constant value. + Signature: ```typescript -declare function length_2(expression: Expression): FunctionExpression; +export declare function lessThan(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. A new Expr representing the length of the string, array, map, vector, or bytes. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### lessThan(expression, value) {:#lessthan_01df3cf} +A new `Expression` representing the less than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is less than a constant value. ```typescript // Check if the 'age' field is less than 30 @@ -3457,10 +2305,17 @@ lessThan(field("age"), 30); ``` +### lessThanOrEqual(expression, value) {:#lessthanorequal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is less than or equal to a constant value. + Signature: ```typescript -export declare function lessThan(expression: Expression, value: unknown): BooleanExpression; +export declare function lessThanOrEqual(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters @@ -3468,18 +2323,16 @@ export declare function lessThan(expression: Expression, value: unknown): Boolea | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the less than comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### lessThanOrEqual(expression, value) {:#lessthanorequal_01df3cf} +A new `Expression` representing the less than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is less than or equal to a constant value. ```typescript // Check if the 'quantity' field is less than or equal to 20 @@ -3487,29 +2340,33 @@ lessThan(field("quantity"), 20); ``` +### ln(expression) {:#ln_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the natural logarithm of a numeric value. + Signature: ```typescript -export declare function lessThanOrEqual(expression: Expression, value: unknown): BooleanExpression; +export declare function ln(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the less than or equal to comparison. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the natural logarithm will be computed for. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### ln(expression) {:#ln_1138a27} +A new `Expression` representing the natural logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the natural logarithm of a numeric value. ```typescript // Compute the natural logarithm of the 'value' field. @@ -3517,39 +2374,52 @@ ln(field("value")); ``` +### log(expression, base) {:#log_ac183e2} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of an expression to a given base. + Signature: ```typescript -export declare function ln(expression: Expression): FunctionExpression; +export declare function log(expression: Expression, base: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the natural logarithm will be computed for. A new Expr representing the natural logarithm of the numeric value. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | +| base | number | The base of the logarithm. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### log(expression, base) {:#log_ac183e2} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the logarithm of an expression to a given base. ```typescript // Compute the logarithm of the 'value' field with base 10. log(field("value"), 10); -``` +``` + +### log(expression, base) {:#log_1894737} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of an expression to a given base. Signature: ```typescript -export declare function log(expression: Expression, base: number): FunctionExpression; +export declare function log(expression: Expression, base: Expression): FunctionExpression; ``` #### Parameters @@ -3557,18 +2427,16 @@ export declare function log(expression: Expression, base: number): FunctionExpre | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | -| base | number | The base of the logarithm. A new representing the logarithm of the numeric value. | +| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The base of the logarithm. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### log(expression, base) {:#log_1894737} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the logarithm of an expression to a given base. ```typescript // Compute the logarithm of the 'value' field with the base in the 'base' field. @@ -3576,29 +2444,33 @@ log(field("value"), field("base")); ``` +### log10(expression) {:#log10_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the base-10 logarithm of a numeric value. + Signature: ```typescript -export declare function log(expression: Expression, base: Expression): FunctionExpression; +export declare function log10(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | -| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The base of the logarithm. A new representing the logarithm of the numeric value. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### log10(expression) {:#log10_1138a27} +A new `Expression` representing the base-10 logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the base-10 logarithm of a numeric value. ```typescript // Compute the base-10 logarithm of the 'value' field. @@ -3606,28 +2478,33 @@ log10(field("value")); ``` +### maximum(expression) {:#maximum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. + Signature: ```typescript -export declare function log10(expression: Expression): FunctionExpression; +export declare function maximum(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. A new Expr representing the base-10 logarithm of the numeric value. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the maximum value of. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -### maximum(expression) {:#maximum_1138a27} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'maximum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. ```typescript // Find the highest score in a leaderboard @@ -3635,28 +2512,33 @@ maximum(field("score")).as("highestScore"); ``` +### minimum(expression) {:#minimum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. + Signature: ```typescript -export declare function maximum(expression: Expression): AggregateFunction; +export declare function minimum(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the maximum value of. A new representing the 'maximum' aggregation. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the minimum value of. | Returns: [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -### minimum(expression) {:#minimum_1138a27} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'minimum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. ```typescript // Find the lowest price of all products @@ -3664,22 +2546,6 @@ minimum(field("price")).as("lowestPrice"); ``` -Signature: - -```typescript -export declare function minimum(expression: Expression): AggregateFunction; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the minimum value of. A new representing the 'minimum' aggregation. | - -Returns: - -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) - ### mod(expression, value) {:#mod_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3687,12 +2553,6 @@ export declare function minimum(expression: Expression): AggregateFunction; Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. -```typescript -// Calculate the remainder of dividing 'field1' by 5. -mod(field("field1"), 5); - -``` - Signature: ```typescript @@ -3704,25 +2564,30 @@ export declare function mod(expression: Expression, value: unknown): FunctionExp | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The dividend expression. | -| value | unknown | The divisor constant. A new representing the modulo operation. | +| value | unknown | The divisor constant. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### notEqual(expression, value) {:#notequal_01df3cf} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the modulo operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is not equal to a constant value. ```typescript -// Check if the 'status' field is not equal to "completed" -notEqual(field("status"), "completed"); +// Calculate the remainder of dividing 'field1' by 5. +mod(field("field1"), 5); ``` +### notEqual(expression, value) {:#notequal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to a constant value. + Signature: ```typescript @@ -3734,25 +2599,30 @@ export declare function notEqual(expression: Expression, value: unknown): Boolea | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the inequality comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### round(expression) {:#round_1138a27} +A new `Expression` representing the inequality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that rounds a numeric value to the nearest whole number. ```typescript -// Round the value of the 'price' field. -round(field("price")); +// Check if the 'status' field is not equal to "completed" +notEqual(field("status"), "completed"); ``` +### round(expression) {:#round_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the nearest whole number. + Signature: ```typescript @@ -3763,25 +2633,30 @@ export declare function round(expression: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. A new Expr representing the rounded value. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### round(expression, decimalPlaces) {:#round_a3a92d0} +A new `Expression` representing the rounded value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that rounds a numeric value to the specified number of decimal places. ```typescript -// Round the value of the 'price' field to two decimal places. -round(field("price"), constant(2)); +// Round the value of the 'price' field. +round(field("price")); ``` +### round(expression, decimalPlaces) {:#round_a3a92d0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + Signature: ```typescript @@ -3793,12 +2668,23 @@ export declare function round(expression: Expression, decimalPlaces: number | Ex | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | -| decimalPlaces | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. A new Expr representing the rounded value. | +| decimalPlaces | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the rounded value. + +### Example + + +```typescript +// Round the value of the 'price' field to two decimal places. +round(field("price"), constant(2)); + +``` + ### split(expression, delimiter) {:#split_5b5612b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3817,12 +2703,14 @@ export declare function split(expression: Expression, delimiter: string): Functi | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split the result of this expression. | -| delimiter | string | Split on this delimiter. A new representing the split function. | +| delimiter | string | Split on this delimiter. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. + ### Example @@ -3850,12 +2738,14 @@ export declare function split(expression: Expression, delimiter: Expression): Fu | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split the result of this expression. | -| delimiter | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. A new representing the split function. | +| delimiter | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. + ### Example @@ -3872,12 +2762,6 @@ split(field('scores'), conditional(field('format').equal('csv'), constant(','), Creates an expression that computes the square root of a numeric value. -```typescript -// Compute the square root of the 'value' field. -sqrt(field("value")); - -``` - Signature: ```typescript @@ -3888,25 +2772,30 @@ export declare function sqrt(expression: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the square root will be computed for. A new representing the square root of the numeric value. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the square root will be computed for. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### subtract(expression, value) {:#subtract_01df3cf} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the square root of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a constant value from an expression. ```typescript -// Subtract the constant value 2 from the 'value' field -subtract(field("value"), 2); +// Compute the square root of the 'value' field. +sqrt(field("value")); ``` +### subtract(expression, value) {:#subtract_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a constant value from an expression. + Signature: ```typescript @@ -3918,25 +2807,30 @@ export declare function subtract(expression: Expression, value: unknown): Functi | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract from. | -| value | unknown | The constant value to subtract. A new representing the subtraction operation. | +| value | unknown | The constant value to subtract. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### sum(expression) {:#sum_1138a27} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the subtraction operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. ```typescript -// Calculate the total revenue from a set of orders -sum(field("orderAmount")).as("totalRevenue"); +// Subtract the constant value 2 from the 'value' field +subtract(field("value"), 2); ``` +### sum(expression) {:#sum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. + Signature: ```typescript @@ -3947,12 +2841,23 @@ export declare function sum(expression: Expression): AggregateFunction; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to sum up. A new representing the 'sum' aggregation. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to sum up. | Returns: [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'sum' aggregation. + +### Example + + +```typescript +// Calculate the total revenue from a set of orders +sum(field("orderAmount")).as("totalRevenue"); + +``` + ### type(expression) {:#type_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3976,6 +2881,8 @@ export declare function type(expression: Expression): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the data type. + ### Example @@ -3984,7 +2891,6 @@ export declare function type(expression: Expression): FunctionExpression; type(conditional(exists('foo'), constant(1), constant(true))) ``` - A new {Expression} representing the data type. ## function(field, ...) @@ -3995,12 +2901,6 @@ type(conditional(exists('foo'), constant(1), constant(true))) Creates an expression that returns `true` if a field is absent. Otherwise, returns `false` even if the field value is `null`. -```typescript -// Check if the field `value` is absent. -isAbsent("value"); - -``` - Signature: ```typescript @@ -4011,25 +2911,30 @@ export declare function isAbsent(field: string): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| field | string | The field to check. A new representing the 'isAbsent' check. | +| field | string | The field to check. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### reverse(field) {:#reverse_0fb8cd4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'isAbsent' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses a string value in the specified field. ```typescript -// Reverse the value of the 'myString' field. -reverse("myString"); +// Check if the field `value` is absent. +isAbsent("value"); ``` +### reverse(field) {:#reverse_0fb8cd4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string value in the specified field. + Signature: ```typescript @@ -4040,25 +2945,30 @@ export declare function reverse(field: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| field | string | The name of the field representing the string to reverse. A new representing the reversed string. | +| field | string | The name of the field representing the string to reverse. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### stringReverse(field) {:#stringreverse_0fb8cd4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses a string value in the specified field. ```typescript // Reverse the value of the 'myString' field. -strReverse("myString"); +reverse("myString"); ``` +### stringReverse(field) {:#stringreverse_0fb8cd4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string value in the specified field. + Signature: ```typescript @@ -4069,12 +2979,23 @@ export declare function stringReverse(field: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| field | string | The name of the field representing the string to reverse. A new representing the reversed string. | +| field | string | The name of the field representing the string to reverse. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. + +### Example + + +```typescript +// Reverse the value of the 'myString' field. +strReverse("myString"); + +``` + ### substring(field, position, length) {:#substring_0d9573a} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4144,18 +3065,42 @@ export declare function abs(fieldName: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field to compute the absolute value of. A new representing the absolute value of the numeric value. | +| fieldName | string | The field to compute the absolute value of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. + ### add(fieldName, second) {:#add_b75bb8b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that adds a field's value to an expression. +Creates an expression that adds a field's value to an expression. + +Signature: + +```typescript +export declare function add(fieldName: string, second: Expression | unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the value to add. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the addition operation. + +### Example + ```typescript // Add the value of the 'quantity' field and the 'reserve' field. @@ -4163,29 +3108,34 @@ add("quantity", field("reserve")); ``` +### arrayContains(fieldName, element) {:#arraycontains_aaace4a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains a specific element. + Signature: ```typescript -export declare function add(fieldName: string, second: Expression | unknown): FunctionExpression; +export declare function arrayContains(fieldName: string, element: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the value to add. | -| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | +| fieldName | string | The field name to check. | +| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The element to search for in the array. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContains(fieldName, element) {:#arraycontains_aaace4a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's array value contains a specific element. ```typescript // Check if the 'colors' array contains the value of field 'selectedColor' @@ -4193,10 +3143,17 @@ arrayContains("colors", field("selectedColor")); ``` +### arrayContains(fieldName, element) {:#arraycontains_999590f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains a specific value. + Signature: ```typescript -export declare function arrayContains(fieldName: string, element: Expression): BooleanExpression; +export declare function arrayContains(fieldName: string, element: unknown): BooleanExpression; ``` #### Parameters @@ -4204,18 +3161,16 @@ export declare function arrayContains(fieldName: string, element: Expression): B | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to check. | -| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The element to search for in the array. A new representing the 'array\_contains' comparison. | +| element | unknown | The element to search for in the array. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContains(fieldName, element) {:#arraycontains_999590f} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's array value contains a specific value. ```typescript // Check if the 'colors' array contains "red" @@ -4223,10 +3178,17 @@ arrayContains("colors", "red"); ``` +### arrayContainsAll(fieldName, values) {:#arraycontainsall_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains all the specified values or expressions. + Signature: ```typescript -export declare function arrayContains(fieldName: string, element: unknown): BooleanExpression; +export declare function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; ``` #### Parameters @@ -4234,18 +3196,16 @@ export declare function arrayContains(fieldName: string, element: unknown): Bool | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to check. | -| element | unknown | The element to search for in the array. A new representing the 'array\_contains' comparison. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAll(fieldName, values) {:#arraycontainsall_8060b23} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's array value contains all the specified values or expressions. ```typescript // Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" @@ -4253,10 +3213,17 @@ arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); ``` +### arrayContainsAll(fieldName, arrayExpression) {:#arraycontainsall_48da8d9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains all the specified values or expressions. + Signature: ```typescript -export declare function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; +export declare function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; ``` #### Parameters @@ -4264,18 +3231,16 @@ export declare function arrayContainsAll(fieldName: string, values: ArrayReturns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAll(fieldName, arrayExpression) {:#arraycontainsall_48da8d9} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's array value contains all the specified values or expressions. ```typescript // Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" @@ -4283,10 +3248,17 @@ arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); ``` +### arrayContainsAny(fieldName, values) {:#arraycontainsany_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains any of the specified elements. + Signature: ```typescript -export declare function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; +export declare function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; ``` #### Parameters @@ -4294,18 +3266,16 @@ export declare function arrayContainsAll(fieldName: string, arrayExpression: Exp | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to check. | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. A new representing the 'array\_contains\_all' comparison. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAny(fieldName, values) {:#arraycontainsany_8060b23} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's array value contains any of the specified elements. ```typescript // Check if the 'groups' array contains either the value from the 'userGroup' field @@ -4314,10 +3284,17 @@ arrayContainsAny("categories", [field("cate1"), "Science"]); ``` +### arrayContainsAny(fieldName, values) {:#arraycontainsany_1b4f7cd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains any of the specified elements. + Signature: ```typescript -export declare function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; +export declare function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; ``` #### Parameters @@ -4325,18 +3302,16 @@ export declare function arrayContainsAny(fieldName: string, values: ArrayReturns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAny(fieldName, values) {:#arraycontainsany_1b4f7cd} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's array value contains any of the specified elements. ```typescript // Check if the 'groups' array contains either the value from the 'userGroup' field @@ -4345,29 +3320,33 @@ arrayContainsAny("categories", array([field("cate1"), "Science"])); ``` +### arrayLength(fieldName) {:#arraylength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of an array in a specified field. + Signature: ```typescript -export declare function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; +export declare function arrayLength(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| values | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array field. A new representing the 'array\_contains\_any' comparison. | +| fieldName | string | The name of the field containing an array to calculate the length of. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### arrayLength(fieldName) {:#arraylength_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of an array in a specified field. ```typescript // Get the number of items in field 'cart' @@ -4375,28 +3354,33 @@ arrayLength('cart'); ``` +### arraySum(fieldName) {:#arraysum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. + Signature: ```typescript -export declare function arrayLength(fieldName: string): FunctionExpression; +export declare function arraySum(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing an array to calculate the length of. A new representing the length of the array. | +| fieldName | string | The name of the field to compute the sum of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### arraySum(fieldName) {:#arraysum_e5b0480} +A new `Expression` representing the sum of the elements in the array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the sum of the elements in an array. ```typescript // Compute the sum of the elements in the 'scores' field. @@ -4404,28 +3388,33 @@ arraySum("scores"); ``` +### ascending(fieldName) {:#ascending_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. + Signature: ```typescript -export declare function arraySum(fieldName: string): FunctionExpression; +export declare function ascending(fieldName: string): Ordering; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the sum of. A new Expr representing the sum of the elements in the array. | +| fieldName | string | The field to create an ascending ordering for. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) -### ascending(fieldName) {:#ascending_e5b0480} +A new `Ordering` for ascending sorting. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an that sorts documents in ascending order based on a field. ```typescript // Sort documents by the 'name' field in ascending order @@ -4434,28 +3423,33 @@ firestore.pipeline().collection("users") ``` +### average(fieldName) {:#average_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. + Signature: ```typescript -export declare function ascending(fieldName: string): Ordering; +export declare function average(fieldName: string): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field to create an ascending ordering for. A new Ordering for ascending sorting. | +| fieldName | string | The name of the field containing numeric values to average. | Returns: -[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -### average(fieldName) {:#average_e5b0480} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'average' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. ```typescript // Calculate the average age of users @@ -4463,28 +3457,33 @@ average("age").as("averageAge"); ``` +### byteLength(fieldName) {:#bytelength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. + Signature: ```typescript -export declare function average(fieldName: string): AggregateFunction; +export declare function byteLength(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing numeric values to average. A new representing the 'average' aggregation. | +| fieldName | string | The name of the field containing the string. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### byteLength(fieldName) {:#bytelength_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string in bytes. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. ```typescript // Calculate the length of the 'myString' field in bytes. @@ -4492,28 +3491,33 @@ byteLength("myString"); ``` +### ceil(fieldName) {:#ceil_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. + Signature: ```typescript -export declare function byteLength(fieldName: string): FunctionExpression; +export declare function ceil(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the string. A new representing the length of the string in bytes. | +| fieldName | string | The name of the field to compute the ceiling of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### ceil(fieldName) {:#ceil_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ceiling of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the ceiling of a numeric value. ```typescript // Compute the ceiling of the 'price' field. @@ -4521,28 +3525,33 @@ ceil("price"); ``` +### charLength(fieldName) {:#charlength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the character length of a string field in UTF8. + Signature: ```typescript -export declare function ceil(fieldName: string): FunctionExpression; +export declare function charLength(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the ceiling of. A new representing the ceiling of the numeric value. | +| fieldName | string | The name of the field containing the string. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### charLength(fieldName) {:#charlength_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the character length of a string field in UTF8. ```typescript // Get the character length of the 'name' field in UTF-8. @@ -4550,28 +3559,33 @@ strLength("name"); ``` +### collectionId(fieldName) {:#collectionid_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. + Signature: ```typescript -export declare function charLength(fieldName: string): FunctionExpression; +export declare function collectionId(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the string. A new representing the length of the string. | +| fieldName | string | The name of the field to get the collection ID from. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### collectionId(fieldName) {:#collectionid_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the collectionId operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the collection ID from a path. ```typescript // Get the collection ID from a path. @@ -4579,28 +3593,35 @@ collectionId("__name__"); ``` +### concat(fieldName, second, others) {:#concat_828272e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. + Signature: ```typescript -export declare function collectionId(fieldName: string): FunctionExpression; +export declare function concat(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to get the collection ID from. A new representing the collectionId operation. | +| fieldName | string | The name of a field to concatenate. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second literal or expression to concatenate. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Additional literal or expressions to concatenate. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### concat(fieldName, second, others) {:#concat_828272e} +A new `Expression` representing the concatenation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. ```typescript // Concatenate a field with a literal string. @@ -4608,30 +3629,34 @@ concat(field("firstName"), "Doe") ``` +### cosineDistance(fieldName, vector) {:#cosinedistance_463a23e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between a field's vector value and a literal vector value. + Signature: ```typescript -export declare function concat(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +export declare function cosineDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of a field to concatenate. | -| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second literal or expression to concatenate. | -| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Additional literal or expressions to concatenate. A new Expression representing the concatenation. | +| fieldName | string | The name of the field containing the first vector. | +| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles) or [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) to compare against. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### cosineDistance(fieldName, vector) {:#cosinedistance_463a23e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the Cosine distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Cosine distance between a field's vector value and a literal vector value. ```typescript // Calculate the Cosine distance between the 'location' field and a target location @@ -4639,10 +3664,17 @@ cosineDistance("location", [37.7749, -122.4194]); ``` +### cosineDistance(fieldName, vectorExpression) {:#cosinedistance_ed766a1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between a field's vector value and a vector expression. + Signature: ```typescript -export declare function cosineDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; +export declare function cosineDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; ``` #### Parameters @@ -4650,18 +3682,16 @@ export declare function cosineDistance(fieldName: string, vector: number[] | Vec | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the first vector. | -| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles) or [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) to compare against. A new representing the Cosine distance between the two vectors. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to compare against. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### cosineDistance(fieldName, vectorExpression) {:#cosinedistance_ed766a1} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the cosine distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Cosine distance between a field's vector value and a vector expression. ```typescript // Calculate the cosine distance between the 'userVector' field and the 'itemVector' field @@ -4669,29 +3699,33 @@ cosineDistance("userVector", field("itemVector")); ``` +### count(fieldName) {:#count_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs where the input field exists. + Signature: ```typescript -export declare function cosineDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; +export declare function count(fieldName: string): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the first vector. | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the cosine distance between the two vectors. | +| fieldName | string | The name of the field to count. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -### count(fieldName) {:#count_e5b0480} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'count' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that counts the number of stage inputs where the input field exists. ```typescript // Count the total number of products @@ -4699,28 +3733,33 @@ count("productId").as("totalProducts"); ``` +### descending(fieldName) {:#descending_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on a field. + Signature: ```typescript -export declare function count(fieldName: string): AggregateFunction; +export declare function descending(fieldName: string): Ordering; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to count. A new representing the 'count' aggregation. | +| fieldName | string | The field to create a descending ordering for. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) -### descending(fieldName) {:#descending_e5b0480} +A new `Ordering` for descending sorting. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an that sorts documents in descending order based on a field. ```typescript // Sort documents by the 'name' field in descending order @@ -4729,28 +3768,34 @@ firestore.pipeline().collection("users") ``` +### divide(fieldName, expressions) {:#divide_cf36e43} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides a field's value by an expression. + Signature: ```typescript -export declare function descending(fieldName: string): Ordering; +export declare function divide(fieldName: string, expressions: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field to create a descending ordering for. A new Ordering for descending sorting. | +| fieldName | string | The field name to be divided. | +| expressions | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to divide by. | Returns: -[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### divide(fieldName, expressions) {:#divide_cf36e43} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the division operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that divides a field's value by an expression. ```typescript // Divide the 'total' field by the 'count' field @@ -4758,10 +3803,17 @@ divide("total", field("count")); ``` +### divide(fieldName, value) {:#divide_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides a field's value by a constant value. + Signature: ```typescript -export declare function divide(fieldName: string, expressions: Expression): FunctionExpression; +export declare function divide(fieldName: string, value: unknown): FunctionExpression; ``` #### Parameters @@ -4769,18 +3821,16 @@ export declare function divide(fieldName: string, expressions: Expression): Func | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to be divided. | -| expressions | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to divide by. A new representing the division operation. | +| value | unknown | The constant value to divide by. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### divide(fieldName, value) {:#divide_65e2f32} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the division operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that divides a field's value by a constant value. ```typescript // Divide the 'value' field by 10 @@ -4788,29 +3838,34 @@ divide("value", 10); ``` +### dotProduct(fieldName, vector) {:#dotproduct_463a23e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between a field's vector value and a double array. + Signature: ```typescript -export declare function divide(fieldName: string, value: unknown): FunctionExpression; +export declare function dotProduct(fieldName: string, vector: number[] | VectorValue): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to be divided. | -| value | unknown | The constant value to divide by. A new representing the division operation. | +| fieldName | string | The name of the field containing the first vector. | +| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to calculate with. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### dotProduct(fieldName, vector) {:#dotproduct_463a23e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the dot product between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the dot product between a field's vector value and a double array. ```typescript // Calculate the dot product distance between a feature vector and a target vector @@ -4818,10 +3873,17 @@ dotProduct("features", [0.5, 0.8, 0.2]); ``` +### dotProduct(fieldName, vectorExpression) {:#dotproduct_ed766a1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between a field's vector value and a vector expression. + Signature: ```typescript -export declare function dotProduct(fieldName: string, vector: number[] | VectorValue): FunctionExpression; +export declare function dotProduct(fieldName: string, vectorExpression: Expression): FunctionExpression; ``` #### Parameters @@ -4829,18 +3891,16 @@ export declare function dotProduct(fieldName: string, vector: number[] | VectorV | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the first vector. | -| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to calculate with. A new representing the dot product between the two vectors. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to calculate with. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### dotProduct(fieldName, vectorExpression) {:#dotproduct_ed766a1} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the dot product between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the dot product between a field's vector value and a vector expression. ```typescript // Calculate the dot product distance between two document vectors: 'docVector1' and 'docVector2' @@ -4848,29 +3908,34 @@ dotProduct("docVector1", field("docVector2")); ``` +### endsWith(fieldName, suffix) {:#endswith_05ca3b0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value ends with a given postfix. + Signature: ```typescript -export declare function dotProduct(fieldName: string, vectorExpression: Expression): FunctionExpression; +export declare function endsWith(fieldName: string, suffix: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the first vector. | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to calculate with. A new representing the dot product between the two vectors. | +| fieldName | string | The field name to check. | +| suffix | string | The postfix to check for. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### endsWith(fieldName, suffix) {:#endswith_05ca3b0} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ends with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value ends with a given postfix. ```typescript // Check if the 'filename' field ends with ".txt" @@ -4878,10 +3943,17 @@ endsWith("filename", ".txt"); ``` +### endsWith(fieldName, suffix) {:#endswith_8fc0ebc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value ends with a given postfix. + Signature: ```typescript -export declare function endsWith(fieldName: string, suffix: string): BooleanExpression; +export declare function endsWith(fieldName: string, suffix: Expression): BooleanExpression; ``` #### Parameters @@ -4889,18 +3961,16 @@ export declare function endsWith(fieldName: string, suffix: string): BooleanExpr | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to check. | -| suffix | string | The postfix to check for. A new representing the 'ends with' comparison. | +| suffix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the postfix. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### endsWith(fieldName, suffix) {:#endswith_8fc0ebc} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ends with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value ends with a given postfix. ```typescript // Check if the 'url' field ends with the value of the 'extension' field @@ -4908,29 +3978,34 @@ endsWith("url", field("extension")); ``` +### equal(fieldName, expression) {:#equal_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to an expression. + Signature: ```typescript -export declare function endsWith(fieldName: string, suffix: Expression): BooleanExpression; +export declare function equal(fieldName: string, expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| suffix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the postfix. A new representing the 'ends with' comparison. | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### equal(fieldName, expression) {:#equal_1e91657} +A new `Expression` representing the equality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is equal to an expression. ```typescript // Check if the 'age' field is equal to the 'limit' field @@ -4938,10 +4013,17 @@ equal("age", field("limit")); ``` +### equal(fieldName, value) {:#equal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to a constant value. + Signature: ```typescript -export declare function equal(fieldName: string, expression: Expression): BooleanExpression; +export declare function equal(fieldName: string, value: unknown): BooleanExpression; ``` #### Parameters @@ -4949,18 +4031,16 @@ export declare function equal(fieldName: string, expression: Expression): Boolea | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the equality comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### equal(fieldName, value) {:#equal_65e2f32} +A new `Expression` representing the equality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is equal to a constant value. ```typescript // Check if the 'city' field is equal to string constant "London" @@ -4968,29 +4048,34 @@ equal("city", "London"); ``` +### equalAny(fieldName, values) {:#equalany_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to any of the provided values or expressions. + Signature: ```typescript -export declare function equal(fieldName: string, value: unknown): BooleanExpression; +export declare function equalAny(fieldName: string, values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the equality comparison. | +| fieldName | string | The field to compare. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values to check against. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### equalAny(fieldName, values) {:#equalany_8060b23} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is equal to any of the provided values or expressions. ```typescript // Check if the 'category' field is either "Electronics" or value of field 'primaryType' @@ -4998,10 +4083,17 @@ equalAny("category", [constant("Electronics"), field("primaryType")]); ``` +### equalAny(fieldName, arrayExpression) {:#equalany_48da8d9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to any of the provided values or expressions. + Signature: ```typescript -export declare function equalAny(fieldName: string, values: Array): BooleanExpression; +export declare function equalAny(fieldName: string, arrayExpression: Expression): BooleanExpression; ``` #### Parameters @@ -5009,18 +4101,16 @@ export declare function equalAny(fieldName: string, values: ArrayReturns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### equalAny(fieldName, arrayExpression) {:#equalany_48da8d9} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is equal to any of the provided values or expressions. ```typescript // Check if the 'category' field is either "Electronics" or value of field 'primaryType' @@ -5028,29 +4118,34 @@ equalAny("category", ["Electronics", field("primaryType")]); ``` +### euclideanDistance(fieldName, vector) {:#euclideandistance_463a23e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between a field's vector value and a double array. + Signature: ```typescript -export declare function equalAny(fieldName: string, arrayExpression: Expression): BooleanExpression; +export declare function euclideanDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field to compare. | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input field. A new representing the 'IN' comparison. | +| fieldName | string | The name of the field containing the first vector. | +| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### euclideanDistance(fieldName, vector) {:#euclideandistance_463a23e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the Euclidean distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Euclidean distance between a field's vector value and a double array. ```typescript // Calculate the Euclidean distance between the 'location' field and a target location @@ -5058,10 +4153,17 @@ euclideanDistance("location", [37.7749, -122.4194]); ``` +### euclideanDistance(fieldName, vectorExpression) {:#euclideandistance_ed766a1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between a field's vector value and a vector expression. + Signature: ```typescript -export declare function euclideanDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; +export declare function euclideanDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; ``` #### Parameters @@ -5069,18 +4171,16 @@ export declare function euclideanDistance(fieldName: string, vector: number[] | | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the first vector. | -| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. A new representing the Euclidean distance between the two vectors. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to compare against. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### euclideanDistance(fieldName, vectorExpression) {:#euclideandistance_ed766a1} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the Euclidean distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Euclidean distance between a field's vector value and a vector expression. ```typescript // Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' @@ -5088,29 +4188,33 @@ euclideanDistance("pointA", field("pointB")); ``` +### exists(fieldName) {:#exists_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field exists. + Signature: ```typescript -export declare function euclideanDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; +export declare function exists(fieldName: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the first vector. | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the Euclidean distance between the two vectors. | +| fieldName | string | The field name to check. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### exists(fieldName) {:#exists_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'exists' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field exists. ```typescript // Check if the document has a field named "phoneNumber" @@ -5118,81 +4222,93 @@ exists("phoneNumber"); ``` +### exp(fieldName) {:#exp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes e to the power of the expression's result. + Signature: ```typescript -export declare function exists(fieldName: string): BooleanExpression; +export declare function exp(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. A new representing the 'exists' check. | +| fieldName | string | | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### exp(fieldName) {:#exp_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the exp of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes e to the power of the expression's result. ```typescript // Compute e to the power of the 'value' field. exp('value'); -``` - A new representing the exp of the numeric value. +``` + +### floor(fieldName) {:#floor_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the floor of a numeric value. Signature: ```typescript -export declare function exp(fieldName: string): FunctionExpression; +export declare function floor(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | | +| fieldName | string | The name of the field to compute the floor of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### floor(fieldName) {:#floor_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the floor of the numeric value. + +### greaterThan(fieldName, expression) {:#greaterthan_1e91657} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the floor of a numeric value. +Creates an expression that checks if a field's value is greater than an expression. Signature: ```typescript -export declare function floor(fieldName: string): FunctionExpression; +export declare function greaterThan(fieldName: string, expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the floor of. A new representing the floor of the numeric value. | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThan(fieldName, expression) {:#greaterthan_1e91657} +A new `Expression` representing the greater than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is greater than an expression. ```typescript // Check if the value of field 'age' is greater than the value of field 'limit' @@ -5200,10 +4316,17 @@ greaterThan("age", field("limit")); ``` +### greaterThan(fieldName, value) {:#greaterthan_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than a constant value. + Signature: ```typescript -export declare function greaterThan(fieldName: string, expression: Expression): BooleanExpression; +export declare function greaterThan(fieldName: string, value: unknown): BooleanExpression; ``` #### Parameters @@ -5211,18 +4334,16 @@ export declare function greaterThan(fieldName: string, expression: Expression): | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the greater than comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThan(fieldName, value) {:#greaterthan_65e2f32} +A new `Expression` representing the greater than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is greater than a constant value. ```typescript // Check if the 'price' field is greater than 100 @@ -5230,10 +4351,17 @@ greaterThan("price", 100); ``` +### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_2e16acb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than or equal to an expression. + Signature: ```typescript -export declare function greaterThan(fieldName: string, value: unknown): BooleanExpression; +export declare function greaterThanOrEqual(fieldName: string, value: Expression): BooleanExpression; ``` #### Parameters @@ -5241,18 +4369,16 @@ export declare function greaterThan(fieldName: string, value: unknown): BooleanE | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the greater than comparison. | +| value | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_2e16acb} +A new `Expression` representing the greater than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is greater than or equal to an expression. ```typescript // Check if the value of field 'age' is greater than or equal to the value of field 'limit' @@ -5260,10 +4386,17 @@ greaterThanOrEqual("age", field("limit")); ``` +### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than or equal to a constant value. + Signature: ```typescript -export declare function greaterThanOrEqual(fieldName: string, value: Expression): BooleanExpression; +export declare function greaterThanOrEqual(fieldName: string, value: unknown): BooleanExpression; ``` #### Parameters @@ -5271,18 +4404,16 @@ export declare function greaterThanOrEqual(fieldName: string, value: Expression) | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| value | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the greater than or equal to comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_65e2f32} +A new `Expression` representing the greater than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is greater than or equal to a constant value. ```typescript // Check if the 'score' field is greater than or equal to 80 @@ -5290,29 +4421,33 @@ greaterThanOrEqual("score", 80); ``` +### length\_2(fieldName) {:#length_2_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string, array, map, vector, or bytes. + Signature: ```typescript -export declare function greaterThanOrEqual(fieldName: string, value: unknown): BooleanExpression; +declare function length_2(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the greater than or equal to comparison. | +| fieldName | string | The name of the field to calculate the length of. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### length\_2(fieldName) {:#length_2_e5b0480} +A new `Expression` representing the length of the string, array, map, vector, or bytes. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of a string, array, map, vector, or bytes. ```typescript // Get the length of the 'name' field. @@ -5323,28 +4458,34 @@ length("cart"); ``` +### lessThan(fieldName, expression) {:#lessthan_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than an expression. + Signature: ```typescript -declare function length_2(fieldName: string): FunctionExpression; +export declare function lessThan(fieldName: string, expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to calculate the length of. A new Expr representing the length of the string, array, map, vector, or bytes. | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### lessThan(fieldName, expression) {:#lessthan_1e91657} +A new `Expression` representing the less than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is less than an expression. ```typescript // Check if the 'age' field is less than the 'limit' field @@ -5352,10 +4493,17 @@ lessThan("age", field("limit")); ``` +### lessThan(fieldName, value) {:#lessthan_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than a constant value. + Signature: ```typescript -export declare function lessThan(fieldName: string, expression: Expression): BooleanExpression; +export declare function lessThan(fieldName: string, value: unknown): BooleanExpression; ``` #### Parameters @@ -5363,18 +4511,16 @@ export declare function lessThan(fieldName: string, expression: Expression): Boo | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the less than comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### lessThan(fieldName, value) {:#lessthan_65e2f32} +A new `Expression` representing the less than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is less than a constant value. ```typescript // Check if the 'price' field is less than 50 @@ -5382,10 +4528,17 @@ lessThan("price", 50); ``` +### lessThanOrEqual(fieldName, expression) {:#lessthanorequal_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than or equal to an expression. + Signature: ```typescript -export declare function lessThan(fieldName: string, value: unknown): BooleanExpression; +export declare function lessThanOrEqual(fieldName: string, expression: Expression): BooleanExpression; ``` #### Parameters @@ -5393,18 +4546,16 @@ export declare function lessThan(fieldName: string, value: unknown): BooleanExpr | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the less than comparison. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### lessThanOrEqual(fieldName, expression) {:#lessthanorequal_1e91657} +A new `Expression` representing the less than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is less than or equal to an expression. ```typescript // Check if the 'quantity' field is less than or equal to the 'limit' field @@ -5412,10 +4563,17 @@ lessThan("quantity", field("limit")); ``` +### lessThanOrEqual(fieldName, value) {:#lessthanorequal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than or equal to a constant value. + Signature: ```typescript -export declare function lessThanOrEqual(fieldName: string, expression: Expression): BooleanExpression; +export declare function lessThanOrEqual(fieldName: string, value: unknown): BooleanExpression; ``` #### Parameters @@ -5423,18 +4581,16 @@ export declare function lessThanOrEqual(fieldName: string, expression: Expressio | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the less than or equal to comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### lessThanOrEqual(fieldName, value) {:#lessthanorequal_65e2f32} +A new `Expression` representing the less than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is less than or equal to a constant value. ```typescript // Check if the 'score' field is less than or equal to 70 @@ -5442,29 +4598,34 @@ lessThan("score", 70); ``` +### like(fieldName, pattern) {:#like_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison against a field. + Signature: ```typescript -export declare function lessThanOrEqual(fieldName: string, value: unknown): BooleanExpression; +export declare function like(fieldName: string, pattern: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the less than or equal to comparison. | +| fieldName | string | The name of the field containing the string. | +| pattern | string | The pattern to search for. You can use "%" as a wildcard character. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### like(fieldName, pattern) {:#like_67f7432} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'like' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a case-sensitive wildcard string comparison against a field. ```typescript // Check if the 'title' field contains the string "guide" @@ -5472,10 +4633,17 @@ like("title", "%guide%"); ``` +### like(fieldName, pattern) {:#like_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison against a field. + Signature: ```typescript -export declare function like(fieldName: string, pattern: string): BooleanExpression; +export declare function like(fieldName: string, pattern: Expression): BooleanExpression; ``` #### Parameters @@ -5483,18 +4651,16 @@ export declare function like(fieldName: string, pattern: string): BooleanExpress | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| pattern | string | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### like(fieldName, pattern) {:#like_cb1318d} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'like' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a case-sensitive wildcard string comparison against a field. ```typescript // Check if the 'title' field contains the string "guide" @@ -5502,29 +4668,33 @@ like("title", field("pattern")); ``` +### ln(fieldName) {:#ln_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the natural logarithm of a numeric value. + Signature: ```typescript -export declare function like(fieldName: string, pattern: Expression): BooleanExpression; +export declare function ln(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the string. | -| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | +| fieldName | string | The name of the field to compute the natural logarithm of. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### ln(fieldName) {:#ln_e5b0480} +A new `Expression` representing the natural logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the natural logarithm of a numeric value. ```typescript // Compute the natural logarithm of the 'value' field. @@ -5532,28 +4702,34 @@ ln("value"); ``` +### log(fieldName, base) {:#log_a89e21b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of a field to a given base. + Signature: ```typescript -export declare function ln(fieldName: string): FunctionExpression; +export declare function log(fieldName: string, base: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the natural logarithm of. A new Expr representing the natural logarithm of the numeric value. | +| fieldName | string | The name of the field to compute the logarithm of. | +| base | number | The base of the logarithm. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### log(fieldName, base) {:#log_a89e21b} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the logarithm of a field to a given base. ```typescript // Compute the logarithm of the 'value' field with base 10. @@ -5561,10 +4737,17 @@ log("value", 10); ``` +### log(fieldName, base) {:#log_805b11f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of a field to a given base. + Signature: ```typescript -export declare function log(fieldName: string, base: number): FunctionExpression; +export declare function log(fieldName: string, base: Expression): FunctionExpression; ``` #### Parameters @@ -5572,18 +4755,16 @@ export declare function log(fieldName: string, base: number): FunctionExpression | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field to compute the logarithm of. | -| base | number | The base of the logarithm. A new representing the logarithm of the numeric value. | +| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The base of the logarithm. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### log(fieldName, base) {:#log_805b11f} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the logarithm of a field to a given base. ```typescript // Compute the logarithm of the 'value' field with the base in the 'base' field. @@ -5591,29 +4772,33 @@ log("value", field("base")); ``` +### log10(fieldName) {:#log10_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the base-10 logarithm of a numeric value. + Signature: ```typescript -export declare function log(fieldName: string, base: Expression): FunctionExpression; +export declare function log10(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the logarithm of. | -| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The base of the logarithm. A new representing the logarithm of the numeric value. | +| fieldName | string | The name of the field to compute the base-10 logarithm of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### log10(fieldName) {:#log10_e5b0480} +A new `Expression` representing the base-10 logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the base-10 logarithm of a numeric value. ```typescript // Compute the base-10 logarithm of the 'value' field. @@ -5621,40 +4806,54 @@ log10("value"); ``` +### logicalMaximum(fieldName, second, others) {:#logicalmaximum_828272e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. + Signature: ```typescript -export declare function log10(fieldName: string): FunctionExpression; +export declare function logicalMaximum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the base-10 logarithm of. A new Expr representing the base-10 logarithm of the numeric value. | +| fieldName | string | The first operand field name. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### logicalMaximum(fieldName, second, others) {:#logicalmaximum_828272e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical maximum operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. ```typescript // Returns the largest value between the 'field1' field, the 'field2' field, // and 1000. logicalMaximum("field1", field("field2"), 1000); -``` +``` + +### logicalMinimum(fieldName, second, others) {:#logicalminimum_828272e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. Signature: ```typescript -export declare function logicalMaximum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +export declare function logicalMinimum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; ``` #### Parameters @@ -5663,18 +4862,16 @@ export declare function logicalMaximum(fieldName: string, second: Expression | u | --- | --- | --- | | fieldName | string | The first operand field name. | | second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | -| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical maximum operation. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### logicalMinimum(fieldName, second, others) {:#logicalminimum_828272e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical minimum operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. ```typescript // Returns the smallest value between the 'field1' field, the 'field2' field, @@ -5683,30 +4880,34 @@ logicalMinimum("field1", field("field2"), 1000); ``` +### mapGet(fieldName, subField) {:#mapget_06663cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Accesses a value from a map (object) field using the provided key. + Signature: ```typescript -export declare function logicalMinimum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +export declare function mapGet(fieldName: string, subField: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The first operand field name. | -| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | -| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical minimum operation. | +| fieldName | string | The field name of the map field. | +| subField | string | The key to access in the map. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### mapGet(fieldName, subField) {:#mapget_06663cf} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the value associated with the given key in the map. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Accesses a value from a map (object) field using the provided key. ```typescript // Get the 'city' value from the 'address' map field @@ -5714,29 +4915,33 @@ mapGet("address", "city"); ``` +### maximum(fieldName) {:#maximum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the maximum value of a field across multiple stage inputs. + Signature: ```typescript -export declare function mapGet(fieldName: string, subField: string): FunctionExpression; +export declare function maximum(fieldName: string): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name of the map field. | -| subField | string | The key to access in the map. A new representing the value associated with the given key in the map. | +| fieldName | string | The name of the field to find the maximum value of. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -### maximum(fieldName) {:#maximum_e5b0480} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'maximum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that finds the maximum value of a field across multiple stage inputs. ```typescript // Find the highest score in a leaderboard @@ -5744,28 +4949,33 @@ maximum("score").as("highestScore"); ``` +### minimum(fieldName) {:#minimum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the minimum value of a field across multiple stage inputs. + Signature: ```typescript -export declare function maximum(fieldName: string): AggregateFunction; +export declare function minimum(fieldName: string): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to find the maximum value of. A new representing the 'maximum' aggregation. | +| fieldName | string | The name of the field to find the minimum value of. | Returns: [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -### minimum(fieldName) {:#minimum_e5b0480} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'minimum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that finds the minimum value of a field across multiple stage inputs. ```typescript // Find the lowest price of all products @@ -5773,28 +4983,34 @@ minimum("price").as("lowestPrice"); ``` +### mod(fieldName, expression) {:#mod_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. + Signature: ```typescript -export declare function minimum(fieldName: string): AggregateFunction; +export declare function mod(fieldName: string, expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to find the minimum value of. A new representing the 'minimum' aggregation. | +| fieldName | string | The dividend field name. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The divisor expression. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### mod(fieldName, expression) {:#mod_1e91657} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the modulo operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. ```typescript // Calculate the remainder of dividing 'field1' by 'field2'. @@ -5802,10 +5018,17 @@ mod("field1", field("field2")); ``` +### mod(fieldName, value) {:#mod_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. + Signature: ```typescript -export declare function mod(fieldName: string, expression: Expression): FunctionExpression; +export declare function mod(fieldName: string, value: unknown): FunctionExpression; ``` #### Parameters @@ -5813,18 +5036,16 @@ export declare function mod(fieldName: string, expression: Expression): Function | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The dividend field name. | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The divisor expression. A new representing the modulo operation. | +| value | unknown | The divisor constant. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### mod(fieldName, value) {:#mod_65e2f32} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the modulo operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. ```typescript // Calculate the remainder of dividing 'field1' by 5. @@ -5832,29 +5053,34 @@ mod("field1", 5); ``` +### multiply(fieldName, second) {:#multiply_b75bb8b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that multiplies a field's value by an expression. + Signature: ```typescript -export declare function mod(fieldName: string, value: unknown): FunctionExpression; +export declare function multiply(fieldName: string, second: Expression | unknown): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The dividend field name. | -| value | unknown | The divisor constant. A new representing the modulo operation. | +| fieldName | string | The name of the field containing the value to add. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### multiply(fieldName, second) {:#multiply_b75bb8b} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the multiplication operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that multiplies a field's value by an expression. ```typescript // Multiply the 'quantity' field by the 'price' field @@ -5862,29 +5088,34 @@ multiply("quantity", field("price")); ``` +### notEqual(fieldName, expression) {:#notequal_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to an expression. + Signature: ```typescript -export declare function multiply(fieldName: string, second: Expression | unknown): FunctionExpression; +export declare function notEqual(fieldName: string, expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the value to add. | -| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### notEqual(fieldName, expression) {:#notequal_1e91657} +A new `Expression` representing the inequality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is not equal to an expression. ```typescript // Check if the 'status' field is not equal to the value of 'expectedStatus' @@ -5892,10 +5123,17 @@ notEqual("status", field("expectedStatus")); ``` +### notEqual(fieldName, value) {:#notequal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to a constant value. + Signature: ```typescript -export declare function notEqual(fieldName: string, expression: Expression): BooleanExpression; +export declare function notEqual(fieldName: string, value: unknown): BooleanExpression; ``` #### Parameters @@ -5903,18 +5141,16 @@ export declare function notEqual(fieldName: string, expression: Expression): Boo | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the inequality comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### notEqual(fieldName, value) {:#notequal_65e2f32} +A new `Expression` representing the inequality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is not equal to a constant value. ```typescript // Check if the 'country' field is not equal to "USA" @@ -5922,10 +5158,17 @@ notEqual("country", "USA"); ``` +### notEqualAny(fieldName, values) {:#notequalany_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. + Signature: ```typescript -export declare function notEqual(fieldName: string, value: unknown): BooleanExpression; +export declare function notEqualAny(fieldName: string, values: Array): BooleanExpression; ``` #### Parameters @@ -5933,18 +5176,16 @@ export declare function notEqual(fieldName: string, value: unknown): BooleanExpr | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the inequality comparison. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values to check against. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### notEqualAny(fieldName, values) {:#notequalany_8060b23} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. ```typescript // Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' @@ -5952,10 +5193,17 @@ notEqualAny("status", [constant("pending"), field("rejectedStatus")]); ``` +### notEqualAny(fieldName, arrayExpression) {:#notequalany_48da8d9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. + Signature: ```typescript -export declare function notEqualAny(fieldName: string, values: Array): BooleanExpression; +export declare function notEqualAny(fieldName: string, arrayExpression: Expression): BooleanExpression; ``` #### Parameters @@ -5963,18 +5211,16 @@ export declare function notEqualAny(fieldName: string, values: ArrayReturns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### notEqualAny(fieldName, arrayExpression) {:#notequalany_48da8d9} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. ```typescript // Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' @@ -5982,29 +5228,34 @@ notEqualAny("status", field("rejectedStatuses")); ``` +### regexContains(fieldName, pattern) {:#regexcontains_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a specified regular expression as a substring. + Signature: ```typescript -export declare function notEqualAny(fieldName: string, arrayExpression: Expression): BooleanExpression; +export declare function regexContains(fieldName: string, pattern: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to compare. | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The values to check against. A new representing the 'NOT IN' comparison. | +| fieldName | string | The name of the field containing the string. | +| pattern | string | The regular expression to use for the search. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### regexContains(fieldName, pattern) {:#regexcontains_67f7432} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string field contains a specified regular expression as a substring. ```typescript // Check if the 'description' field contains "example" (case-insensitive) @@ -6012,10 +5263,17 @@ regexContains("description", "(?i)example"); ``` +### regexContains(fieldName, pattern) {:#regexcontains_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a specified regular expression as a substring. + Signature: ```typescript -export declare function regexContains(fieldName: string, pattern: string): BooleanExpression; +export declare function regexContains(fieldName: string, pattern: Expression): BooleanExpression; ``` #### Parameters @@ -6023,18 +5281,16 @@ export declare function regexContains(fieldName: string, pattern: string): Boole | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| pattern | string | The regular expression to use for the search. A new representing the 'contains' comparison. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the search. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### regexContains(fieldName, pattern) {:#regexcontains_cb1318d} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string field contains a specified regular expression as a substring. ```typescript // Check if the 'description' field contains "example" (case-insensitive) @@ -6042,10 +5298,17 @@ regexContains("description", field("pattern")); ``` +### regexMatch(fieldName, pattern) {:#regexmatch_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field matches a specified regular expression. + Signature: ```typescript -export declare function regexContains(fieldName: string, pattern: Expression): BooleanExpression; +export declare function regexMatch(fieldName: string, pattern: string): BooleanExpression; ``` #### Parameters @@ -6053,18 +5316,16 @@ export declare function regexContains(fieldName: string, pattern: Expression): B | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the search. A new representing the 'contains' comparison. | +| pattern | string | The regular expression to use for the match. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### regexMatch(fieldName, pattern) {:#regexmatch_67f7432} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression match. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string field matches a specified regular expression. ```typescript // Check if the 'email' field matches a valid email pattern @@ -6072,10 +5333,17 @@ regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); ``` +### regexMatch(fieldName, pattern) {:#regexmatch_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field matches a specified regular expression. + Signature: ```typescript -export declare function regexMatch(fieldName: string, pattern: string): BooleanExpression; +export declare function regexMatch(fieldName: string, pattern: Expression): BooleanExpression; ``` #### Parameters @@ -6083,18 +5351,16 @@ export declare function regexMatch(fieldName: string, pattern: string): BooleanE | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| pattern | string | The regular expression to use for the match. A new representing the regular expression match. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the match. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### regexMatch(fieldName, pattern) {:#regexmatch_cb1318d} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression match. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string field matches a specified regular expression. ```typescript // Check if the 'email' field matches a valid email pattern @@ -6102,23 +5368,6 @@ regexMatch("email", field("pattern")); ``` -Signature: - -```typescript -export declare function regexMatch(fieldName: string, pattern: Expression): BooleanExpression; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| fieldName | string | The name of the field containing the string. | -| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the match. A new representing the regular expression match. | - -Returns: - -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) - ### round(fieldName) {:#round_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -6126,12 +5375,6 @@ export declare function regexMatch(fieldName: string, pattern: Expression): Bool Creates an expression that rounds a numeric value to the nearest whole number. -```typescript -// Round the value of the 'price' field. -round("price"); - -``` - Signature: ```typescript @@ -6140,13 +5383,24 @@ export declare function round(fieldName: string): FunctionExpression; #### Parameters -| Parameter | Type | Description | -| --- | --- | --- | -| fieldName | string | The name of the field to round. A new Expr representing the rounded value. | +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to round. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the rounded value. + +### Example + -Returns: +```typescript +// Round the value of the 'price' field. +round("price"); -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +``` ### round(fieldName, decimalPlaces) {:#round_07d0cf0} @@ -6155,12 +5409,6 @@ export declare function round(fieldName: string): FunctionExpression; Creates an expression that rounds a numeric value to the specified number of decimal places. -```typescript -// Round the value of the 'price' field to two decimal places. -round("price", 2); - -``` - Signature: ```typescript @@ -6172,12 +5420,23 @@ export declare function round(fieldName: string, decimalPlaces: number | Express | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field to round. | -| decimalPlaces | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. A new Expr representing the rounded value. | +| decimalPlaces | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the rounded value. + +### Example + + +```typescript +// Round the value of the 'price' field to two decimal places. +round("price", 2); + +``` + ### split(fieldName, delimiter) {:#split_2cfdd37} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -6196,12 +5455,14 @@ export declare function split(fieldName: string, delimiter: string): FunctionExp | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | Split the value in this field. | -| delimiter | string | Split on this delimiter. A new representing the split function. | +| delimiter | string | Split on this delimiter. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. + ### Example @@ -6229,12 +5490,14 @@ export declare function split(fieldName: string, delimiter: Expression): Functio | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | Split the value in this field. | -| delimiter | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. A new representing the split function. | +| delimiter | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. + ### Example @@ -6251,12 +5514,6 @@ split('scores', conditional(field('format').equal('csv'), constant(','), constan Creates an expression that computes the square root of a numeric value. -```typescript -// Compute the square root of the 'value' field. -sqrt("value"); - -``` - Signature: ```typescript @@ -6267,25 +5524,30 @@ export declare function sqrt(fieldName: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the square root of. A new representing the square root of the numeric value. | +| fieldName | string | The name of the field to compute the square root of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### startsWith(fieldName, prefix) {:#startswith_89325cc} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the square root of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value starts with a given prefix. ```typescript -// Check if the 'name' field starts with "Mr." -startsWith("name", "Mr."); +// Compute the square root of the 'value' field. +sqrt("value"); ``` +### startsWith(fieldName, prefix) {:#startswith_89325cc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value starts with a given prefix. + Signature: ```typescript @@ -6297,25 +5559,30 @@ export declare function startsWith(fieldName: string, prefix: string): BooleanEx | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to check. | -| prefix | string | The prefix to check for. A new representing the 'starts with' comparison. | +| prefix | string | The prefix to check for. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### startsWith(fieldName, prefix) {:#startswith_266c338} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'starts with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value starts with a given prefix. ```typescript -// Check if the 'fullName' field starts with the value of the 'firstName' field -startsWith("fullName", field("firstName")); +// Check if the 'name' field starts with "Mr." +startsWith("name", "Mr."); ``` +### startsWith(fieldName, prefix) {:#startswith_266c338} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value starts with a given prefix. + Signature: ```typescript @@ -6327,25 +5594,30 @@ export declare function startsWith(fieldName: string, prefix: Expression): Boole | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to check. | -| prefix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the prefix. A new representing the 'starts with' comparison. | +| prefix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the prefix. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### stringConcat(fieldName, secondString, otherStrings) {:#stringconcat_d80077e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'starts with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that concatenates string functions, fields or constants together. ```typescript -// Combine the 'firstName', " ", and 'lastName' fields into a single string -stringConcat("firstName", " ", field("lastName")); +// Check if the 'fullName' field starts with the value of the 'firstName' field +startsWith("fullName", field("firstName")); ``` +### stringConcat(fieldName, secondString, otherStrings) {:#stringconcat_d80077e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates string functions, fields or constants together. + Signature: ```typescript @@ -6358,25 +5630,30 @@ export declare function stringConcat(fieldName: string, secondString: Expression | --- | --- | --- | | fieldName | string | The field name containing the initial string value. | | secondString | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string | An expression or string literal to concatenate. | -| otherStrings | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or literals (typically strings) to concatenate. A new representing the concatenated string. | +| otherStrings | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or literals (typically strings) to concatenate. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### stringContains(fieldName, substring) {:#stringcontains_5b94cfe} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the concatenated string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string field contains a specified substring. ```typescript -// Check if the 'description' field contains "example". -stringContains("description", "example"); +// Combine the 'firstName', " ", and 'lastName' fields into a single string +stringConcat("firstName", " ", field("lastName")); ``` +### stringContains(fieldName, substring) {:#stringcontains_5b94cfe} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a specified substring. + Signature: ```typescript @@ -6388,25 +5665,30 @@ export declare function stringContains(fieldName: string, substring: string): Bo | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| substring | string | The substring to search for. A new representing the 'contains' comparison. | +| substring | string | The substring to search for. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### stringContains(fieldName, substring) {:#stringcontains_ac3ba47} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string field contains a substring specified by an expression. ```typescript -// Check if the 'description' field contains the value of the 'keyword' field. -stringContains("description", field("keyword")); +// Check if the 'description' field contains "example". +stringContains("description", "example"); ``` +### stringContains(fieldName, substring) {:#stringcontains_ac3ba47} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a substring specified by an expression. + Signature: ```typescript @@ -6418,25 +5700,30 @@ export declare function stringContains(fieldName: string, substring: Expression) | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| substring | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the substring to search for. A new representing the 'contains' comparison. | +| substring | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the substring to search for. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### subtract(fieldName, expression) {:#subtract_1e91657} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts an expression from a field's value. ```typescript -// Subtract the 'discount' field from the 'price' field -subtract("price", field("discount")); +// Check if the 'description' field contains the value of the 'keyword' field. +stringContains("description", field("keyword")); ``` +### subtract(fieldName, expression) {:#subtract_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts an expression from a field's value. + Signature: ```typescript @@ -6448,25 +5735,30 @@ export declare function subtract(fieldName: string, expression: Expression): Fun | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to subtract from. | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract. A new representing the subtraction operation. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### subtract(fieldName, value) {:#subtract_65e2f32} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the subtraction operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a constant value from a field's value. ```typescript -// Subtract 20 from the value of the 'total' field -subtract("total", 20); +// Subtract the 'discount' field from the 'price' field +subtract("price", field("discount")); ``` +### subtract(fieldName, value) {:#subtract_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a constant value from a field's value. + Signature: ```typescript @@ -6478,25 +5770,30 @@ export declare function subtract(fieldName: string, value: unknown): FunctionExp | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to subtract from. | -| value | unknown | The constant value to subtract. A new representing the subtraction operation. | +| value | unknown | The constant value to subtract. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### sum(fieldName) {:#sum_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the subtraction operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. ```typescript -// Calculate the total revenue from a set of orders -sum("orderAmount").as("totalRevenue"); +// Subtract 20 from the value of the 'total' field +subtract("total", 20); ``` +### sum(fieldName) {:#sum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. + Signature: ```typescript @@ -6507,25 +5804,30 @@ export declare function sum(fieldName: string): AggregateFunction; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing numeric values to sum up. A new representing the 'sum' aggregation. | +| fieldName | string | The name of the field containing numeric values to sum up. | Returns: [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -### timestampAdd(fieldName, unit, amount) {:#timestampadd_341fe7d} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'sum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that adds a specified amount of time to a timestamp represented by a field. ```typescript -// Add 1 day to the 'timestamp' field. -timestampAdd("timestamp", "day", 1); +// Calculate the total revenue from a set of orders +sum("orderAmount").as("totalRevenue"); ``` +### timestampAdd(fieldName, unit, amount) {:#timestampadd_341fe7d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to a timestamp represented by a field. + Signature: ```typescript @@ -6538,25 +5840,30 @@ export declare function timestampAdd(fieldName: string, unit: 'microsecond' | 'm | --- | --- | --- | | fieldName | string | The name of the field representing the timestamp. | | unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | -| amount | number | The amount of time to add. A new representing the resulting timestamp. | +| amount | number | The amount of time to add. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_341fe7d} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. ```typescript -// Subtract 1 day from the 'timestamp' field. -timestampSubtract("timestamp", "day", 1); +// Add 1 day to the 'timestamp' field. +timestampAdd("timestamp", "day", 1); ``` +### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_341fe7d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. + Signature: ```typescript @@ -6569,25 +5876,30 @@ export declare function timestampSubtract(fieldName: string, unit: 'microsecond' | --- | --- | --- | | fieldName | string | The name of the field representing the timestamp. | | unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | -| amount | number | The amount of time to subtract. A new representing the resulting timestamp. | +| amount | number | The amount of time to subtract. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### timestampToUnixMicros(fieldName) {:#timestamptounixmicros_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to microseconds since epoch. -timestampToUnixMicros("timestamp"); +// Subtract 1 day from the 'timestamp' field. +timestampSubtract("timestamp", "day", 1); ``` +### timestampToUnixMicros(fieldName) {:#timestamptounixmicros_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + Signature: ```typescript @@ -6598,25 +5910,30 @@ export declare function timestampToUnixMicros(fieldName: string): FunctionExpres | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the timestamp. A new representing the number of microseconds since epoch. | +| fieldName | string | The name of the field representing the timestamp. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### timestampToUnixMillis(fieldName) {:#timestamptounixmillis_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of microseconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -timestampToUnixMillis("timestamp"); +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros("timestamp"); ``` +### timestampToUnixMillis(fieldName) {:#timestamptounixmillis_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + Signature: ```typescript @@ -6627,25 +5944,30 @@ export declare function timestampToUnixMillis(fieldName: string): FunctionExpres | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the timestamp. A new representing the number of milliseconds since epoch. | +| fieldName | string | The name of the field representing the timestamp. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### timestampToUnixSeconds(fieldName) {:#timestamptounixseconds_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of milliseconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to seconds since epoch. -timestampToUnixSeconds("timestamp"); +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis("timestamp"); ``` +### timestampToUnixSeconds(fieldName) {:#timestamptounixseconds_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + Signature: ```typescript @@ -6656,12 +5978,23 @@ export declare function timestampToUnixSeconds(fieldName: string): FunctionExpre | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the timestamp. A new representing the number of seconds since epoch. | +| fieldName | string | The name of the field representing the timestamp. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of seconds since epoch. + +### Example + + +```typescript +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds("timestamp"); + +``` + ### timestampTruncate(fieldName, granularity, timezone) {:#timestamptruncate_b6c7512} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -6681,12 +6014,14 @@ export declare function timestampTruncate(fieldName: string, granularity: TimeGr | --- | --- | --- | | fieldName | string | Truncate the timestamp value contained in this field. | | granularity | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | The granularity to truncate to. | -| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the truncated timestamp. + ### Example @@ -6715,12 +6050,14 @@ export declare function timestampTruncate(fieldName: string, granularity: Expres | --- | --- | --- | | fieldName | string | Truncate the timestamp value contained in this field. | | granularity | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The granularity to truncate to. | -| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the truncated timestamp. + ### Example @@ -6737,12 +6074,6 @@ field('createdAt').timestampTruncate(field('granularity')) Creates an expression that converts a string field to lowercase. -```typescript -// Convert the 'name' field to lowercase -toLower("name"); - -``` - Signature: ```typescript @@ -6753,25 +6084,30 @@ export declare function toLower(fieldName: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the string. A new representing the lowercase string. | +| fieldName | string | The name of the field containing the string. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### toUpper(fieldName) {:#toupper_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the lowercase string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a string field to uppercase. ```typescript -// Convert the 'title' field to uppercase -toUpper("title"); +// Convert the 'name' field to lowercase +toLower("name"); ``` +### toUpper(fieldName) {:#toupper_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string field to uppercase. + Signature: ```typescript @@ -6782,28 +6118,30 @@ export declare function toUpper(fieldName: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the string. A new representing the uppercase string. | +| fieldName | string | The name of the field containing the string. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### trim(fieldName, valueToTrim) {:#trim_c9f90ee} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the uppercase string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that removes leading and trailing whitespace from a string or byte array. ```typescript -// Trim whitespace from the 'userInput' field -trim("userInput"); - -// Trim quotes from the 'userInput' field -trim("userInput", '"'); +// Convert the 'title' field to uppercase +toUpper("title"); ``` +### trim(fieldName, valueToTrim) {:#trim_c9f90ee} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes leading and trailing whitespace from a string or byte array. + Signature: ```typescript @@ -6815,12 +6153,26 @@ export declare function trim(fieldName: string, valueToTrim?: string | Expressio | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string or byte array. | -| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | 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. A new representing the trimmed string. | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | 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: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string. + +### Example + + +```typescript +// Trim whitespace from the 'userInput' field +trim("userInput"); + +// Trim quotes from the 'userInput' field +trim("userInput", '"'); + +``` + ### type(fieldName) {:#type_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -6844,6 +6196,8 @@ export declare function type(fieldName: string): FunctionExpression; [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the data type. + ### Example @@ -6852,7 +6206,6 @@ export declare function type(fieldName: string): FunctionExpression; type('title') ``` - A new {Expression} representing the data type. ### unixMicrosToTimestamp(fieldName) {:#unixmicrostotimestamp_e5b0480} @@ -6861,12 +6214,6 @@ type('title') Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -unixMicrosToTimestamp("microseconds"); - -``` - Signature: ```typescript @@ -6877,25 +6224,30 @@ export declare function unixMicrosToTimestamp(fieldName: string): FunctionExpres | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the number of microseconds since epoch. A new representing the timestamp. | +| fieldName | string | The name of the field representing the number of microseconds since epoch. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### unixMillisToTimestamp(fieldName) {:#unixmillistotimestamp_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. ```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -unixMillisToTimestamp("milliseconds"); +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp("microseconds"); ``` +### unixMillisToTimestamp(fieldName) {:#unixmillistotimestamp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + Signature: ```typescript @@ -6906,25 +6258,30 @@ export declare function unixMillisToTimestamp(fieldName: string): FunctionExpres | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the number of milliseconds since epoch. A new representing the timestamp. | +| fieldName | string | The name of the field representing the number of milliseconds since epoch. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### unixSecondsToTimestamp(fieldName) {:#unixsecondstotimestamp_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. ```typescript -// Interpret the 'seconds' field as seconds since epoch. -unixSecondsToTimestamp("seconds"); +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp("milliseconds"); ``` +### unixSecondsToTimestamp(fieldName) {:#unixsecondstotimestamp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + Signature: ```typescript @@ -6935,25 +6292,30 @@ export declare function unixSecondsToTimestamp(fieldName: string): FunctionExpre | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the number of seconds since epoch. A new representing the timestamp. | +| fieldName | string | The name of the field representing the number of seconds since epoch. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### vectorLength(fieldName) {:#vectorlength_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of a Firestore Vector represented by a field. ```typescript -// Get the vector length (dimension) of the field 'embedding'. -vectorLength("embedding"); +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp("seconds"); ``` +### vectorLength(fieldName) {:#vectorlength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a Firestore Vector represented by a field. + Signature: ```typescript @@ -6964,12 +6326,23 @@ export declare function vectorLength(fieldName: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the Firestore Vector. A new representing the length of the array. | +| fieldName | string | The name of the field representing the Firestore Vector. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the array. + +### Example + + +```typescript +// Get the vector length (dimension) of the field 'embedding'. +vectorLength("embedding"); + +``` + ## function(first, ...) ### add(first, second) {:#add_846ca1b} @@ -6979,12 +6352,6 @@ export declare function vectorLength(fieldName: string): FunctionExpression; Creates an expression that adds two expressions together. -```typescript -// Add the value of the 'quantity' field and the 'reserve' field. -add(field("quantity"), field("reserve")); - -``` - Signature: ```typescript @@ -7002,20 +6369,24 @@ export declare function add(first: Expression, second: Expression | unknown): Fu [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### and(first, second, more) {:#and_e0c48bd} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the addition operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a logical 'AND' operation on multiple filter conditions. ```typescript -// Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND -// the 'status' field is "active" -const condition = and(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); +// Add the value of the 'quantity' field and the 'reserve' field. +add(field("quantity"), field("reserve")); ``` +### and(first, second, more) {:#and_e0c48bd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'AND' operation on multiple filter conditions. + Signature: ```typescript @@ -7028,25 +6399,31 @@ export declare function and(first: BooleanExpression, second: BooleanExpression, | --- | --- | --- | | first | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The first filter condition. | | second | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The second filter condition. | -| more | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'AND' together. A new representing the logical 'AND' operation. | +| more | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'AND' together. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### concat(first, second, others) {:#concat_83be015} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical 'AND' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. ```typescript -// Concatenate the 'firstName' and 'lastName' fields with a space in between. -concat(field("firstName"), " ", field("lastName")) +// Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND +// the 'status' field is "active" +const condition = and(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); ``` +### concat(first, second, others) {:#concat_83be015} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. + Signature: ```typescript @@ -7059,26 +6436,30 @@ export declare function concat(first: Expression, second: Expression | unknown, | --- | --- | --- | | first | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expressions to concatenate. | | second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second literal or expression to concatenate. | -| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Additional literals or expressions to concatenate. A new Expression representing the concatenation. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Additional literals or expressions to concatenate. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### logicalMaximum(first, second, others) {:#logicalmaximum_83be015} +A new `Expression` representing the concatenation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. ```typescript -// Returns the largest value between the 'field1' field, the 'field2' field, -// and 1000 -logicalMaximum(field("field1"), field("field2"), 1000); +// Concatenate the 'firstName' and 'lastName' fields with a space in between. +concat(field("firstName"), " ", field("lastName")) ``` +### logicalMaximum(first, second, others) {:#logicalmaximum_83be015} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. + Signature: ```typescript @@ -7091,26 +6472,31 @@ export declare function logicalMaximum(first: Expression, second: Expression | u | --- | --- | --- | | first | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first operand expression. | | second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | -| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical maximum operation. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### logicalMinimum(first, second, others) {:#logicalminimum_83be015} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical maximum operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. ```typescript -// Returns the smallest value between the 'field1' field, the 'field2' field, -// and 1000. -logicalMinimum(field("field1"), field("field2"), 1000); +// Returns the largest value between the 'field1' field, the 'field2' field, +// and 1000 +logicalMaximum(field("field1"), field("field2"), 1000); ``` +### logicalMinimum(first, second, others) {:#logicalminimum_83be015} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. + Signature: ```typescript @@ -7123,25 +6509,31 @@ export declare function logicalMinimum(first: Expression, second: Expression | u | --- | --- | --- | | first | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first operand expression. | | second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | -| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical minimum operation. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### multiply(first, second) {:#multiply_846ca1b} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical minimum operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that multiplies two expressions together. ```typescript -// Multiply the 'quantity' field by the 'price' field -multiply(field("quantity"), field("price")); +// Returns the smallest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMinimum(field("field1"), field("field2"), 1000); ``` +### multiply(first, second) {:#multiply_846ca1b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that multiplies two expressions together. + Signature: ```typescript @@ -7159,20 +6551,24 @@ export declare function multiply(first: Expression, second: Expression | unknown [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### or(first, second, more) {:#or_e0c48bd} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the multiplication operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a logical 'OR' operation on multiple filter conditions. ```typescript -// Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR -// the 'status' field is "active" -const condition = or(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); +// Multiply the 'quantity' field by the 'price' field +multiply(field("quantity"), field("price")); ``` +### or(first, second, more) {:#or_e0c48bd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'OR' operation on multiple filter conditions. + Signature: ```typescript @@ -7185,29 +6581,31 @@ export declare function or(first: BooleanExpression, second: BooleanExpression, | --- | --- | --- | | first | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The first filter condition. | | second | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The second filter condition. | -| more | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'OR' together. A new representing the logical 'OR' operation. | +| more | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'OR' together. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### xor(first, second, additionalConditions) {:#xor_8197113} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical 'OR' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. ```typescript -// Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London", -// or 'status' is "active". -const condition = xor( - greaterThan("age", 18), - equal("city", "London"), - equal("status", "active")); +// Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR +// the 'status' field is "active" +const condition = or(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); ``` +### xor(first, second, additionalConditions) {:#xor_8197113} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. + Signature: ```typescript @@ -7220,11 +6618,26 @@ export declare function xor(first: BooleanExpression, second: BooleanExpression, | --- | --- | --- | | first | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The first condition. | | second | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The second condition. | -| additionalConditions | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional conditions to 'XOR' together. A new representing the logical 'XOR' operation. | +| additionalConditions | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional conditions to 'XOR' together. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical 'XOR' operation. -Returns: +### Example -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +```typescript +// Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London", +// or 'status' is "active". +const condition = xor( + greaterThan("age", 18), + equal("city", "London"), + equal("status", "active")); + +``` ## function(firstArray, ...) @@ -7235,12 +6648,6 @@ export declare function xor(first: BooleanExpression, second: BooleanExpression, Creates an expression that concatenates an array expression with other arrays. -```typescript -// Combine the 'items' array with two new item arrays -arrayConcat(field("items"), [field("newItems"), field("otherItems")]); - -``` - Signature: ```typescript @@ -7253,12 +6660,23 @@ export declare function arrayConcat(firstArray: Expression, secondArray: Express | --- | --- | --- | | firstArray | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first array expression to concatenate to. | | secondArray | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\] | The second array expression or array literal to concatenate to. | -| otherArrays | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. A new representing the concatenated array. | +| otherArrays | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the concatenated array. + +### Example + + +```typescript +// Combine the 'items' array with two new item arrays +arrayConcat(field("items"), [field("newItems"), field("otherItems")]); + +``` + ## function(firstArrayField, ...) ### arrayConcat(firstArrayField, secondArray, otherArrays) {:#arrayconcat_f92063d} @@ -7268,12 +6686,6 @@ export declare function arrayConcat(firstArray: Expression, secondArray: Express Creates an expression that concatenates a field's array value with other arrays. -```typescript -// Combine the 'items' array with two new item arrays -arrayConcat("items", [field("newItems"), field("otherItems")]); - -``` - Signature: ```typescript @@ -7286,12 +6698,23 @@ export declare function arrayConcat(firstArrayField: string, secondArray: Expres | --- | --- | --- | | firstArrayField | string | The first array to concatenate to. | | secondArray | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\] | The second array expression or array literal to concatenate to. | -| otherArrays | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. A new representing the concatenated array. | +| otherArrays | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the concatenated array. + +### Example + + +```typescript +// Combine the 'items' array with two new item arrays +arrayConcat("items", [field("newItems"), field("otherItems")]); + +``` + ## function(firstMap, ...) ### mapMerge(firstMap, secondMap, otherMaps) {:#mapmerge_cfe77ce} @@ -7301,13 +6724,6 @@ export declare function arrayConcat(firstArrayField: string, secondArray: Expres Creates an expression that merges multiple map values. -``` -// Merges the map in the settings field with, a map literal, and a map in -// that is conditionally returned by another expression -mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) - -``` - Signature: ```typescript @@ -7326,6 +6742,16 @@ export declare function mapMerge(firstMap: Record | Expression, [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +### Example + + +``` +// Merges the map in the settings field with, a map literal, and a map in +// that is conditionally returned by another expression +mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) + +``` + ## function(firstString, ...) ### stringConcat(firstString, secondString, otherStrings) {:#stringconcat_8a8d1b6} @@ -7335,12 +6761,6 @@ export declare function mapMerge(firstMap: Record | Expression, Creates an expression that concatenates string expressions together. -```typescript -// Combine the 'firstName', " ", and 'lastName' fields into a single string -stringConcat(field("firstName"), " ", field("lastName")); - -``` - Signature: ```typescript @@ -7353,12 +6773,23 @@ export declare function stringConcat(firstString: Expression, secondString: Expr | --- | --- | --- | | firstString | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The initial string expression to concatenate to. | | secondString | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string | An expression or string literal to concatenate. | -| otherStrings | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or literals (typically strings) to concatenate. A new representing the concatenated string. | +| otherStrings | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or literals (typically strings) to concatenate. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the concatenated string. + +### Example + + +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +stringConcat(field("firstName"), " ", field("lastName")); + +``` + ## function(ifExpr, ...) ### ifAbsent(ifExpr, elseExpr) {:#ifabsent_0e6d161} @@ -7368,13 +6799,6 @@ export declare function stringConcat(firstString: Expression, secondString: Expr Creates an expression that returns the `elseExpr` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -ifAbsent(field("optional_field"), constant("default_value")) - -``` - Signature: ```typescript @@ -7386,26 +6810,31 @@ export declare function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expr | Parameter | Type | Description | | --- | --- | --- | | ifExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check for absence. | -| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if \[ifExpr\] is absent. A new Expression representing the ifAbsent operation. | +| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if \[ifExpr\] is absent. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) -### ifAbsent(ifExpr, elseValue) {:#ifabsent_c34e5ed} +A new Expression representing the ifAbsent operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `elseValue` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. ```typescript // Returns the value of the optional field 'optional_field', or returns 'default_value' // if the field is absent. -ifAbsent(field("optional_field"), "default_value") +ifAbsent(field("optional_field"), constant("default_value")) ``` +### ifAbsent(ifExpr, elseValue) {:#ifabsent_c34e5ed} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. + Signature: ```typescript @@ -7417,12 +6846,24 @@ export declare function ifAbsent(ifExpr: Expression, elseValue: unknown): Expres | Parameter | Type | Description | | --- | --- | --- | | ifExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check for absence. | -| elseValue | unknown | The value that will be returned if ifExpr evaluates to an absent value. A new \[Expression\] representing the ifAbsent operation. | +| elseValue | unknown | The value that will be returned if ifExpr evaluates to an absent value. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new \[Expression\] representing the ifAbsent operation. + +### Example + + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent(field("optional_field"), "default_value") + +``` + ## function(ifFieldName, ...) ### ifAbsent(ifFieldName, elseExpr) {:#ifabsent_e6dabea} @@ -7432,13 +6873,6 @@ export declare function ifAbsent(ifExpr: Expression, elseValue: unknown): Expres Creates an expression that returns the `elseExpr` argument if `ifFieldName` is absent, else return the value of the field. -```typescript -// Returns the value of the optional field 'optional_field', or returns the value of -// 'default_field' if 'optional_field' is absent. -ifAbsent("optional_field", field("default_field")) - -``` - Signature: ```typescript @@ -7450,26 +6884,31 @@ export declare function ifAbsent(ifFieldName: string, elseExpr: Expression): Exp | Parameter | Type | Description | | --- | --- | --- | | ifFieldName | string | The field to check for absence. | -| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if ifFieldName is absent. A new Expression representing the ifAbsent operation. | +| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if ifFieldName is absent. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) -### ifAbsent(ifFieldName, elseValue) {:#ifabsent_d8f2823} +A new Expression representing the ifAbsent operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `elseValue` argument if `ifFieldName` is absent, else return the value of the field. ```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -ifAbsent("optional_field", "default_value") +// Returns the value of the optional field 'optional_field', or returns the value of +// 'default_field' if 'optional_field' is absent. +ifAbsent("optional_field", field("default_field")) ``` +### ifAbsent(ifFieldName, elseValue) {:#ifabsent_d8f2823} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if `ifFieldName` is absent, else return the value of the field. + Signature: ```typescript @@ -7481,12 +6920,24 @@ export declare function ifAbsent(ifFieldName: string | Expression, elseValue: Ex | Parameter | Type | Description | | --- | --- | --- | | ifFieldName | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The field to check for absence. | -| elseValue | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The value that will be returned if \[ifFieldName\] is absent. A new Expression representing the ifAbsent operation. | +| elseValue | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The value that will be returned if \[ifFieldName\] is absent. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new Expression representing the ifAbsent operation. + +### Example + + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent("optional_field", "default_value") + +``` + ## function(input, ...) ### substring(input, position, length) {:#substring_e6e0aa3} @@ -7548,12 +6999,6 @@ export declare function substring(input: Expression, position: Expression, lengt Creates an expression that divides two expressions. -```typescript -// Divide the 'total' field by the 'count' field -divide(field("total"), field("count")); - -``` - Signature: ```typescript @@ -7565,25 +7010,30 @@ export declare function divide(left: Expression, right: Expression): FunctionExp | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to be divided. | -| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to divide by. A new representing the division operation. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to divide by. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### equal(left, right) {:#equal_b3c3382} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the division operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if two expressions are equal. ```typescript -// Check if the 'age' field is equal to an expression -equal(field("age"), field("minAge").add(10)); +// Divide the 'total' field by the 'count' field +divide(field("total"), field("count")); ``` +### equal(left, right) {:#equal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if two expressions are equal. + Signature: ```typescript @@ -7595,25 +7045,30 @@ export declare function equal(left: Expression, right: Expression): BooleanExpre | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to compare. | -| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the equality comparison. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThan(left, right) {:#greaterthan_b3c3382} +A new `Expression` representing the equality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if the first expression is greater than the second expression. ```typescript -// Check if the 'age' field is greater than 18 -greaterThan(field("age"), Constant(9).add(9)); +// Check if the 'age' field is equal to an expression +equal(field("age"), field("minAge").add(10)); ``` +### greaterThan(left, right) {:#greaterthan_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is greater than the second expression. + Signature: ```typescript @@ -7625,25 +7080,30 @@ export declare function greaterThan(left: Expression, right: Expression): Boolea | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to compare. | -| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the greater than comparison. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThanOrEqual(left, right) {:#greaterthanorequal_b3c3382} +A new `Expression` representing the greater than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if the first expression is greater than or equal to the second expression. ```typescript -// Check if the 'quantity' field is greater than or equal to the field "threshold" -greaterThanOrEqual(field("quantity"), field("threshold")); +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), Constant(9).add(9)); ``` +### greaterThanOrEqual(left, right) {:#greaterthanorequal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is greater than or equal to the second expression. + Signature: ```typescript @@ -7655,25 +7115,30 @@ export declare function greaterThanOrEqual(left: Expression, right: Expression): | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to compare. | -| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the greater than or equal to comparison. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### lessThan(left, right) {:#lessthan_b3c3382} +A new `Expression` representing the greater than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if the first expression is less than the second expression. ```typescript -// Check if the 'age' field is less than 30 -lessThan(field("age"), field("limit")); +// Check if the 'quantity' field is greater than or equal to the field "threshold" +greaterThanOrEqual(field("quantity"), field("threshold")); ``` +### lessThan(left, right) {:#lessthan_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is less than the second expression. + Signature: ```typescript @@ -7685,25 +7150,30 @@ export declare function lessThan(left: Expression, right: Expression): BooleanEx | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to compare. | -| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the less than comparison. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### lessThanOrEqual(left, right) {:#lessthanorequal_b3c3382} +A new `Expression` representing the less than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if the first expression is less than or equal to the second expression. ```typescript -// Check if the 'quantity' field is less than or equal to 20 -lessThan(field("quantity"), field("limit")); +// Check if the 'age' field is less than 30 +lessThan(field("age"), field("limit")); ``` +### lessThanOrEqual(left, right) {:#lessthanorequal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is less than or equal to the second expression. + Signature: ```typescript @@ -7715,25 +7185,30 @@ export declare function lessThanOrEqual(left: Expression, right: Expression): Bo | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to compare. | -| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the less than or equal to comparison. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### mod(left, right) {:#mod_b3c3382} +A new `Expression` representing the less than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the modulo (remainder) of dividing two expressions. ```typescript -// Calculate the remainder of dividing 'field1' by 'field2'. -mod(field("field1"), field("field2")); +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), field("limit")); ``` +### mod(left, right) {:#mod_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing two expressions. + Signature: ```typescript @@ -7745,11 +7220,22 @@ export declare function mod(left: Expression, right: Expression): FunctionExpres | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The dividend expression. | -| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The divisor expression. A new representing the modulo operation. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The divisor expression. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the modulo operation. + +### Example + -Returns: +```typescript +// Calculate the remainder of dividing 'field1' by 'field2'. +mod(field("field1"), field("field2")); -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +``` ### notEqual(left, right) {:#notequal_b3c3382} @@ -7758,12 +7244,6 @@ export declare function mod(left: Expression, right: Expression): FunctionExpres Creates an expression that checks if two expressions are not equal. -```typescript -// Check if the 'status' field is not equal to field 'finalState' -notEqual(field("status"), field("finalState")); - -``` - Signature: ```typescript @@ -7775,25 +7255,30 @@ export declare function notEqual(left: Expression, right: Expression): BooleanEx | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to compare. | -| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the inequality comparison. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The second expression to compare. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### subtract(left, right) {:#subtract_b3c3382} +A new `Expression` representing the inequality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts two expressions. ```typescript -// Subtract the 'discount' field from the 'price' field -subtract(field("price"), field("discount")); +// Check if the 'status' field is not equal to field 'finalState' +notEqual(field("status"), field("finalState")); ``` +### subtract(left, right) {:#subtract_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts two expressions. + Signature: ```typescript @@ -7805,12 +7290,23 @@ export declare function subtract(left: Expression, right: Expression): FunctionE | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract from. | -| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract. A new representing the subtraction operation. | +| right | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the subtraction operation. + +### Example + + +```typescript +// Subtract the 'discount' field from the 'price' field +subtract(field("price"), field("discount")); + +``` + ## function(mapExpr, ...) ### mapRemove(mapExpr, key) {:#mapremove_23c7d51} @@ -7820,12 +7316,6 @@ export declare function subtract(left: Expression, right: Expression): FunctionE Creates an expression that removes a key from the map produced by evaluating an expression. -``` -// Removes the key 'baz' from the input map. -mapRemove(map({foo: 'bar', baz: true}), 'baz'); - -``` - Signature: ```typescript @@ -7843,19 +7333,23 @@ export declare function mapRemove(mapExpr: Expression, key: string): FunctionExp [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### mapRemove(mapExpr, keyExpr) {:#mapremove_9fbcaa3} - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that removes a key from the map produced by evaluating an expression. ``` // Removes the key 'baz' from the input map. -mapRemove(map({foo: 'bar', baz: true}), constant('baz')); +mapRemove(map({foo: 'bar', baz: true}), 'baz'); +@example ``` +### mapRemove(mapExpr, keyExpr) {:#mapremove_9fbcaa3} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map produced by evaluating an expression. + Signature: ```typescript @@ -7873,6 +7367,16 @@ export declare function mapRemove(mapExpr: Expression, keyExpr: Expression): Fun [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +### Example + + +``` +// Removes the key 'baz' from the input map. +mapRemove(map({foo: 'bar', baz: true}), constant('baz')); +@example + +``` + ## function(mapExpression, ...) ### mapGet(mapExpression, subField) {:#mapget_688c050} @@ -7882,12 +7386,6 @@ export declare function mapRemove(mapExpr: Expression, keyExpr: Expression): Fun Accesses a value from a map (object) expression using the provided key. -```typescript -// Get the 'city' value from the 'address' map field -mapGet(field("address"), "city"); - -``` - Signature: ```typescript @@ -7899,12 +7397,23 @@ export declare function mapGet(mapExpression: Expression, subField: string): Fun | Parameter | Type | Description | | --- | --- | --- | | mapExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the map. | -| subField | string | The key to access in the map. A new representing the value associated with the given key in the map. | +| subField | string | The key to access in the map. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the value associated with the given key in the map. + +### Example + + +```typescript +// Get the 'city' value from the 'address' map field +mapGet(field("address"), "city"); + +``` + ## function(mapField, ...) ### mapMerge(mapField, secondMap, otherMaps) {:#mapmerge_70a564b} @@ -7914,13 +7423,6 @@ export declare function mapGet(mapExpression: Expression, subField: string): Fun Creates an expression that merges multiple map values. -``` -// Merges the map in the settings field with, a map literal, and a map in -// that is conditionally returned by another expression -mapMerge('settings', { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) - -``` - Signature: ```typescript @@ -7939,6 +7441,16 @@ export declare function mapMerge(mapField: string, secondMap: Record This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -7946,12 +7458,6 @@ export declare function mapMerge(mapField: string, secondMap: RecordSignature: ```typescript @@ -7969,19 +7475,22 @@ export declare function mapRemove(mapField: string, key: string): FunctionExpres [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### mapRemove(mapField, keyExpr) {:#mapremove_8406d13} - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that removes a key from the map at the specified field name. ``` // Removes the key 'city' field from the map in the address field of the input document. -mapRemove('address', constant('city')); +mapRemove('address', 'city'); ``` +### mapRemove(mapField, keyExpr) {:#mapremove_8406d13} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map at the specified field name. + Signature: ```typescript @@ -7999,6 +7508,15 @@ export declare function mapRemove(mapField: string, keyExpr: Expression): Functi [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +### Example + + +``` +// Removes the key 'city' field from the map in the address field of the input document. +mapRemove('address', constant('city')); + +``` + ## function(name, ...) ### field(name) {:#field_1eaaff4} @@ -8006,19 +7524,10 @@ export declare function mapRemove(mapField: string, keyExpr: Expression): Functi > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates a instance representing the field at the given path. +Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). -```typescript -// Create a Field instance for the 'title' field -const titleField = field("title"); - -// Create a Field instance for a nested field 'author.firstName' -const authorFirstNameField = field("author.firstName"); - -``` - Signature: ```typescript @@ -8029,12 +7538,26 @@ export declare function field(name: string): Field; | Parameter | Type | Description | | --- | --- | --- | -| name | string | The path to the field. A new instance representing the specified field. | +| name | string | The path to the field. | Returns: [Field](./firestore_lite_pipelines.field.md#field_class) +A new [Field](./firestore_pipelines.field.md#field_class) instance representing the specified field. + +### Example + + +```typescript +// Create a Field instance for the 'title' field +const titleField = field("title"); + +// Create a Field instance for a nested field 'author.firstName' +const authorFirstNameField = field("author.firstName"); + +``` + ## function(path, ...) ### field(path) {:#field_34ee07d} @@ -8042,7 +7565,7 @@ export declare function field(name: string): Field; > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates a instance representing the field at the given path. +Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. Signature: @@ -8054,12 +7577,14 @@ export declare function field(path: FieldPath): Field; | Parameter | Type | Description | | --- | --- | --- | -| path | [FieldPath](./firestore_lite.fieldpath.md#fieldpath_class) | A FieldPath specifying the field. A new instance representing the specified field. | +| path | [FieldPath](./firestore_lite.fieldpath.md#fieldpath_class) | A FieldPath specifying the field. | Returns: [Field](./firestore_lite_pipelines.field.md#field_class) +A new [Field](./firestore_pipelines.field.md#field_class) instance representing the specified field. + ## function(pipeline, ...) ### execute(pipeline) {:#execute_01df620} @@ -8071,11 +7596,30 @@ Executes this pipeline and returns a Promise to represent the asynchronous opera The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously. -The pipeline results are returned as a that contains a list of objects. Each typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example: +The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example: + +

  • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
  • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
+ +Signature: + +```typescript +export declare function execute(pipeline: Pipeline): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pipeline | [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) | The pipeline to execute. | + +Returns: + +Promise<[PipelineSnapshot](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshot_class)> + +A Promise representing the asynchronous pipeline execution. -
  • If there are no stages or only transformation stages, each represents a single document.
  • If there is an aggregation, only a single is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each represents a distinct group and its associated aggregated values.
+### Example -

Example: ```typescript const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") @@ -8086,30 +7630,35 @@ const results: PipelineResults = snapshot.results; ``` +## function(stringExpression, ...) + +### charLength(stringExpression) {:#charlength_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the character length of a string expression in UTF-8. + Signature: ```typescript -export declare function execute(pipeline: Pipeline): Promise; +export declare function charLength(stringExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| pipeline | [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) | The pipeline to execute. A Promise representing the asynchronous pipeline execution. | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to calculate the length of. | Returns: -Promise<[PipelineSnapshot](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshot_class)> - -## function(stringExpression, ...) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### charLength(stringExpression) {:#charlength_c25a54a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the character length of a string expression in UTF-8. ```typescript // Get the character length of the 'name' field in UTF-8. @@ -8117,28 +7666,34 @@ strLength(field("name")); ``` +### endsWith(stringExpression, suffix) {:#endswith_0a0b889} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression ends with a given postfix. + Signature: ```typescript -export declare function charLength(stringExpression: Expression): FunctionExpression; +export declare function endsWith(stringExpression: Expression, suffix: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to calculate the length of. A new representing the length of the string. | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | +| suffix | string | The postfix to check for. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### endsWith(stringExpression, suffix) {:#endswith_0a0b889} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ends with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression ends with a given postfix. ```typescript // Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." @@ -8146,10 +7701,17 @@ endsWith(field("fullName"), "Jr."); ``` +### endsWith(stringExpression, suffix) {:#endswith_13aee0d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression ends with a given postfix. + Signature: ```typescript -export declare function endsWith(stringExpression: Expression, suffix: string): BooleanExpression; +export declare function endsWith(stringExpression: Expression, suffix: Expression): BooleanExpression; ``` #### Parameters @@ -8157,18 +7719,16 @@ export declare function endsWith(stringExpression: Expression, suffix: string): | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | -| suffix | string | The postfix to check for. A new representing the 'ends with' comparison. | +| suffix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The postfix to check for. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### endsWith(stringExpression, suffix) {:#endswith_13aee0d} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ends with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression ends with a given postfix. ```typescript // Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." @@ -8176,29 +7736,34 @@ endsWith(field("fullName"), constant("Jr.")); ``` +### like(stringExpression, pattern) {:#like_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison. + Signature: ```typescript -export declare function endsWith(stringExpression: Expression, suffix: Expression): BooleanExpression; +export declare function like(stringExpression: Expression, pattern: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | -| suffix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The postfix to check for. A new representing the 'ends with' comparison. | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| pattern | string | The pattern to search for. You can use "%" as a wildcard character. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### like(stringExpression, pattern) {:#like_a84c581} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'like' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a case-sensitive wildcard string comparison. ```typescript // Check if the 'title' field contains the string "guide" @@ -8206,10 +7771,17 @@ like(field("title"), "%guide%"); ``` +### like(stringExpression, pattern) {:#like_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison. + Signature: ```typescript -export declare function like(stringExpression: Expression, pattern: string): BooleanExpression; +export declare function like(stringExpression: Expression, pattern: Expression): BooleanExpression; ``` #### Parameters @@ -8217,29 +7789,34 @@ export declare function like(stringExpression: Expression, pattern: string): Boo | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | -| pattern | string | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### like(stringExpression, pattern) {:#like_b534848} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'like' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a case-sensitive wildcard string comparison. ```typescript // Check if the 'title' field contains the string "guide" like(field("title"), field("pattern")); -``` +``` + +### regexContains(stringExpression, pattern) {:#regexcontains_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a specified regular expression as a substring. Signature: ```typescript -export declare function like(stringExpression: Expression, pattern: Expression): BooleanExpression; +export declare function regexContains(stringExpression: Expression, pattern: string): BooleanExpression; ``` #### Parameters @@ -8247,18 +7824,16 @@ export declare function like(stringExpression: Expression, pattern: Expression): | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | -| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | +| pattern | string | The regular expression to use for the search. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### regexContains(stringExpression, pattern) {:#regexcontains_a84c581} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression contains a specified regular expression as a substring. ```typescript // Check if the 'description' field contains "example" (case-insensitive) @@ -8266,10 +7841,17 @@ regexContains(field("description"), "(?i)example"); ``` +### regexContains(stringExpression, pattern) {:#regexcontains_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a specified regular expression as a substring. + Signature: ```typescript -export declare function regexContains(stringExpression: Expression, pattern: string): BooleanExpression; +export declare function regexContains(stringExpression: Expression, pattern: Expression): BooleanExpression; ``` #### Parameters @@ -8277,18 +7859,16 @@ export declare function regexContains(stringExpression: Expression, pattern: str | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | -| pattern | string | The regular expression to use for the search. A new representing the 'contains' comparison. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the search. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### regexContains(stringExpression, pattern) {:#regexcontains_b534848} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression contains a specified regular expression as a substring. ```typescript // Check if the 'description' field contains "example" (case-insensitive) @@ -8296,29 +7876,34 @@ regexContains(field("description"), field("pattern")); ``` +### regexMatch(stringExpression, pattern) {:#regexmatch_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression matches a specified regular expression. + Signature: ```typescript -export declare function regexContains(stringExpression: Expression, pattern: Expression): BooleanExpression; +export declare function regexMatch(stringExpression: Expression, pattern: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | -| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the search. A new representing the 'contains' comparison. | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to match against. | +| pattern | string | The regular expression to use for the match. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### regexMatch(stringExpression, pattern) {:#regexmatch_a84c581} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression match. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression matches a specified regular expression. ```typescript // Check if the 'email' field matches a valid email pattern @@ -8326,10 +7911,17 @@ regexMatch(field("email"), "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); ``` +### regexMatch(stringExpression, pattern) {:#regexmatch_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression matches a specified regular expression. + Signature: ```typescript -export declare function regexMatch(stringExpression: Expression, pattern: string): BooleanExpression; +export declare function regexMatch(stringExpression: Expression, pattern: Expression): BooleanExpression; ``` #### Parameters @@ -8337,18 +7929,16 @@ export declare function regexMatch(stringExpression: Expression, pattern: string | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to match against. | -| pattern | string | The regular expression to use for the match. A new representing the regular expression match. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the match. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### regexMatch(stringExpression, pattern) {:#regexmatch_b534848} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression match. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression matches a specified regular expression. ```typescript // Check if the 'email' field matches a valid email pattern @@ -8356,29 +7946,33 @@ regexMatch(field("email"), field("pattern")); ``` +### reverse(stringExpression) {:#reverse_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string. + Signature: ```typescript -export declare function regexMatch(stringExpression: Expression, pattern: Expression): BooleanExpression; +export declare function reverse(stringExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to match against. | -| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to use for the match. A new representing the regular expression match. | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a string value, which will be reversed. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### reverse(stringExpression) {:#reverse_c25a54a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses a string. ```typescript // Reverse the value of the 'myString' field. @@ -8386,28 +7980,34 @@ reverse(field("myString")); ``` +### startsWith(stringExpression, prefix) {:#startswith_75c3dbb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression starts with a given prefix. + Signature: ```typescript -export declare function reverse(stringExpression: Expression): FunctionExpression; +export declare function startsWith(stringExpression: Expression, prefix: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a string value, which will be reversed. A new representing the reversed string. | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | +| prefix | string | The prefix to check for. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### startsWith(stringExpression, prefix) {:#startswith_75c3dbb} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'starts with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression starts with a given prefix. ```typescript // Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." @@ -8415,10 +8015,17 @@ startsWith(field("fullName"), "Mr."); ``` +### startsWith(stringExpression, prefix) {:#startswith_52f218a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression starts with a given prefix. + Signature: ```typescript -export declare function startsWith(stringExpression: Expression, prefix: string): BooleanExpression; +export declare function startsWith(stringExpression: Expression, prefix: Expression): BooleanExpression; ``` #### Parameters @@ -8426,18 +8033,16 @@ export declare function startsWith(stringExpression: Expression, prefix: string) | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | -| prefix | string | The prefix to check for. A new representing the 'starts with' comparison. | +| prefix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The prefix to check for. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### startsWith(stringExpression, prefix) {:#startswith_52f218a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'starts with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression starts with a given prefix. ```typescript // Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." @@ -8445,29 +8050,34 @@ startsWith(field("fullName"), field("prefix")); ``` +### stringContains(stringExpression, substring) {:#stringcontains_3e9ff32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a specified substring. + Signature: ```typescript -export declare function startsWith(stringExpression: Expression, prefix: Expression): BooleanExpression; +export declare function stringContains(stringExpression: Expression, substring: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | -| prefix | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The prefix to check for. A new representing the 'starts with' comparison. | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| substring | string | The substring to search for. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### stringContains(stringExpression, substring) {:#stringcontains_3e9ff32} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression contains a specified substring. ```typescript // Check if the 'description' field contains "example". @@ -8475,10 +8085,17 @@ stringContains(field("description"), "example"); ``` +### stringContains(stringExpression, substring) {:#stringcontains_cc6ee02} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a substring specified by another expression. + Signature: ```typescript -export declare function stringContains(stringExpression: Expression, substring: string): BooleanExpression; +export declare function stringContains(stringExpression: Expression, substring: Expression): BooleanExpression; ``` #### Parameters @@ -8486,18 +8103,16 @@ export declare function stringContains(stringExpression: Expression, substring: | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | -| substring | string | The substring to search for. A new representing the 'contains' comparison. | +| substring | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the substring to search for. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### stringContains(stringExpression, substring) {:#stringcontains_cc6ee02} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression contains a substring specified by another expression. ```typescript // Check if the 'description' field contains the value of the 'keyword' field. @@ -8505,29 +8120,33 @@ stringContains(field("description"), field("keyword")); ``` +### stringReverse(stringExpression) {:#stringreverse_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string. + Signature: ```typescript -export declare function stringContains(stringExpression: Expression, substring: Expression): BooleanExpression; +export declare function stringReverse(stringExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | -| substring | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the substring to search for. A new representing the 'contains' comparison. | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a string value, which will be reversed. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### stringReverse(stringExpression) {:#stringreverse_c25a54a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses a string. ```typescript // Reverse the value of the 'myString' field. @@ -8535,28 +8154,33 @@ strReverse(field("myString")); ``` +### toLower(stringExpression) {:#tolower_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string expression to lowercase. + Signature: ```typescript -export declare function stringReverse(stringExpression: Expression): FunctionExpression; +export declare function toLower(stringExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a string value, which will be reversed. A new representing the reversed string. | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to convert to lowercase. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### toLower(stringExpression) {:#tolower_c25a54a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the lowercase string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a string expression to lowercase. ```typescript // Convert the 'name' field to lowercase @@ -8564,28 +8188,33 @@ toLower(field("name")); ``` +### toUpper(stringExpression) {:#toupper_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string expression to uppercase. + Signature: ```typescript -export declare function toLower(stringExpression: Expression): FunctionExpression; +export declare function toUpper(stringExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to convert to lowercase. A new representing the lowercase string. | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to convert to uppercase. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### toUpper(stringExpression) {:#toupper_c25a54a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the uppercase string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a string expression to uppercase. ```typescript // Convert the 'title' field to uppercase @@ -8593,28 +8222,34 @@ toUppercase(field("title")); ``` +### trim(stringExpression, valueToTrim) {:#trim_dd54322} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes leading and trailing characters from a string or byte array expression. + Signature: ```typescript -export declare function toUpper(stringExpression: Expression): FunctionExpression; +export declare function trim(stringExpression: Expression, valueToTrim?: string | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to convert to uppercase. A new representing the uppercase string. | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array to trim. | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | 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: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### trim(stringExpression, valueToTrim) {:#trim_dd54322} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that removes leading and trailing characters from a string or byte array expression. ```typescript // Trim whitespace from the 'userInput' field @@ -8625,23 +8260,6 @@ trim(field("userInput"), '"'); ``` -Signature: - -```typescript -export declare function trim(stringExpression: Expression, valueToTrim?: string | Expression): FunctionExpression; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array to trim. | -| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | 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. A new representing the trimmed string or byte array. | - -Returns: - -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) - ## function(timestamp, ...) ### timestampAdd(timestamp, unit, amount) {:#timestampadd_98418f9} @@ -8651,12 +8269,6 @@ export declare function trim(stringExpression: Expression, valueToTrim?: string Creates an expression that adds a specified amount of time to a timestamp. -```typescript -// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. -timestampAdd(field("timestamp"), field("unit"), field("amount")); - -``` - Signature: ```typescript @@ -8669,25 +8281,30 @@ export declare function timestampAdd(timestamp: Expression, unit: Expression, am | --- | --- | --- | | timestamp | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | | unit | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | -| amount | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | +| amount | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### timestampAdd(timestamp, unit, amount) {:#timestampadd_ffe8e57} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that adds a specified amount of time to a timestamp. ```typescript -// Add 1 day to the 'timestamp' field. -timestampAdd(field("timestamp"), "day", 1); +// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. +timestampAdd(field("timestamp"), field("unit"), field("amount")); ``` +### timestampAdd(timestamp, unit, amount) {:#timestampadd_ffe8e57} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to a timestamp. + Signature: ```typescript @@ -8700,25 +8317,30 @@ export declare function timestampAdd(timestamp: Expression, unit: 'microsecond' | --- | --- | --- | | timestamp | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | | unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | -| amount | number | The amount of time to add. A new representing the resulting timestamp. | +| amount | number | The amount of time to add. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_98418f9} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a specified amount of time from a timestamp. ```typescript -// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. -timestampSubtract(field("timestamp"), field("unit"), field("amount")); +// Add 1 day to the 'timestamp' field. +timestampAdd(field("timestamp"), "day", 1); ``` +### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_98418f9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from a timestamp. + Signature: ```typescript @@ -8731,11 +8353,22 @@ export declare function timestampSubtract(timestamp: Expression, unit: Expressio | --- | --- | --- | | timestamp | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | | unit | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | -| amount | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | +| amount | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. + +### Example + + +```typescript +// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. +timestampSubtract(field("timestamp"), field("unit"), field("amount")); + +``` ### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_ffe8e57} @@ -8744,12 +8377,6 @@ export declare function timestampSubtract(timestamp: Expression, unit: Expressio Creates an expression that subtracts a specified amount of time from a timestamp. -```typescript -// Subtract 1 day from the 'timestamp' field. -timestampSubtract(field("timestamp"), "day", 1); - -``` - Signature: ```typescript @@ -8762,12 +8389,23 @@ export declare function timestampSubtract(timestamp: Expression, unit: 'microsec | --- | --- | --- | | timestamp | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | | unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | -| amount | number | The amount of time to subtract. A new representing the resulting timestamp. | +| amount | number | The amount of time to subtract. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. + +### Example + + +```typescript +// Subtract 1 day from the 'timestamp' field. +timestampSubtract(field("timestamp"), "day", 1); + +``` + ## function(timestampExpression, ...) ### timestampTruncate(timestampExpression, granularity, timezone) {:#timestamptruncate_ad5d843} @@ -8789,12 +8427,14 @@ export declare function timestampTruncate(timestampExpression: Expression, granu | --- | --- | --- | | timestampExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Truncate the timestamp value that is returned by this expression. | | granularity | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | The granularity to truncate to. | -| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the truncated timestamp. + ### Example @@ -8823,12 +8463,14 @@ export declare function timestampTruncate(timestampExpression: Expression, granu | --- | --- | --- | | timestampExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Truncate the timestamp value that is returned by this expression. | | granularity | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The granularity to truncate to. | -| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the truncated timestamp. + ### Example @@ -8849,13 +8491,6 @@ Creates an expression that returns the `catch` argument if there is an error, el This overload is useful when a BooleanExpression is required. -```typescript -// Create an expression that protects against a divide by zero error -// but always returns a boolean expression. -ifError(constant(50).divide('length').gt(1), constant(false)); - -``` - Signature: ```typescript @@ -8867,26 +8502,31 @@ export declare function ifError(tryExpr: BooleanExpression, catchExpr: BooleanEx | Parameter | Type | Description | | --- | --- | --- | | tryExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The try expression. | -| catchExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The catch expression that will be evaluated and returned if the tryExpr produces an error. A new representing the 'ifError' operation. | +| catchExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The catch expression that will be evaluated and returned if the tryExpr produces an error. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### ifError(tryExpr, catchExpr) {:#iferror_756c12e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. ```typescript -// Returns the first item in the title field arrays, or returns -// the entire title field if the array is empty or the field is another type. -ifError(field("title").arrayGet(0), field("title")); +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +ifError(constant(50).divide('length').gt(1), constant(false)); ``` +### ifError(tryExpr, catchExpr) {:#iferror_756c12e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. + Signature: ```typescript @@ -8898,26 +8538,31 @@ export declare function ifError(tryExpr: Expression, catchExpr: Expression): Fun | Parameter | Type | Description | | --- | --- | --- | | tryExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The try expression. | -| catchExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The catch expression that will be evaluated and returned if the tryExpr produces an error. A new representing the 'ifError' operation. | +| catchExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The catch expression that will be evaluated and returned if the tryExpr produces an error. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### ifError(tryExpr, catchValue) {:#iferror_dc532f9} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. ```typescript // Returns the first item in the title field arrays, or returns -// "Default Title" -ifError(field("title").arrayGet(0), "Default Title"); +// the entire title field if the array is empty or the field is another type. +ifError(field("title").arrayGet(0), field("title")); ``` +### ifError(tryExpr, catchValue) {:#iferror_dc532f9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. + Signature: ```typescript @@ -8929,12 +8574,24 @@ export declare function ifError(tryExpr: Expression, catchValue: unknown): Funct | Parameter | Type | Description | | --- | --- | --- | | tryExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The try expression. | -| catchValue | unknown | The value that will be returned if the tryExpr produces an error. A new representing the 'ifError' operation. | +| catchValue | unknown | The value that will be returned if the tryExpr produces an error. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. + +### Example + + +```typescript +// Returns the first item in the title field arrays, or returns +// "Default Title" +ifError(field("title").arrayGet(0), "Default Title"); + +``` + ## function(value, ...) ### constant(value) {:#constant_0c00f91} @@ -8954,12 +8611,14 @@ export declare function constant(value: number): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | number | The number value. A new Constant instance. | +| value | number | The number value. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_6dac335} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -8977,12 +8636,14 @@ export declare function constant(value: VectorValue): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The VectorValue value. A new Constant instance. | +| value | [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The VectorValue value. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_7c807cd} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9000,12 +8661,14 @@ export declare function constant(value: string): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | string | The string value. A new Constant instance. | +| value | string | The string value. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_b2e4f8d} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9023,12 +8686,14 @@ export declare function constant(value: boolean): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | boolean | The boolean value. A new Constant instance. | +| value | boolean | The boolean value. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +A new `Constant` instance. + ### constant(value) {:#constant_73ebd84} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9046,12 +8711,14 @@ export declare function constant(value: null): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | null | The null value. A new Constant instance. | +| value | null | The null value. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_72a76cb} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9069,12 +8736,14 @@ export declare function constant(value: GeoPoint): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | [GeoPoint](./firestore_lite.geopoint.md#geopoint_class) | The GeoPoint value. A new Constant instance. | +| value | [GeoPoint](./firestore_lite.geopoint.md#geopoint_class) | The GeoPoint value. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_000477d} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9092,12 +8761,14 @@ export declare function constant(value: Timestamp): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) | The Timestamp value. A new Constant instance. | +| value | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) | The Timestamp value. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_5131bf7} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9115,12 +8786,14 @@ export declare function constant(value: Date): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | Date | The Date value. A new Constant instance. | +| value | Date | The Date value. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_fdf565d} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9138,12 +8811,14 @@ export declare function constant(value: Bytes): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | [Bytes](./firestore_lite.bytes.md#bytes_class) | The Bytes value. A new Constant instance. | +| value | [Bytes](./firestore_lite.bytes.md#bytes_class) | The Bytes value. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_bcd2b0b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9161,12 +8836,14 @@ export declare function constant(value: DocumentReference): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | [DocumentReference](./firestore_lite.documentreference.md#documentreference_class) | The DocumentReference value. A new Constant instance. | +| value | [DocumentReference](./firestore_lite.documentreference.md#documentreference_class) | The DocumentReference value. | Returns: [Expression](./firestore_lite_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### exists(value) {:#exists_f3daf14} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9174,12 +8851,6 @@ export declare function constant(value: DocumentReference): Expression; Creates an expression that checks if a field exists. -```typescript -// Check if the document has a field named "phoneNumber" -exists(field("phoneNumber")); - -``` - Signature: ```typescript @@ -9190,25 +8861,30 @@ export declare function exists(value: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluates to the name of the field to check. A new representing the 'exists' check. | +| value | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluates to the name of the field to check. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### isAbsent(value) {:#isabsent_f3daf14} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'exists' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns `true` if a value is absent. Otherwise, returns `false` even if the value is `null`. ```typescript -// Check if the field `value` is absent. -isAbsent(field("value")); +// Check if the document has a field named "phoneNumber" +exists(field("phoneNumber")); ``` +### isAbsent(value) {:#isabsent_f3daf14} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns `true` if a value is absent. Otherwise, returns `false` even if the value is `null`. + Signature: ```typescript @@ -9219,25 +8895,30 @@ export declare function isAbsent(value: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. A new representing the 'isAbsent' check. | +| value | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -### isError(value) {:#iserror_f3daf14} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'isAbsent' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a given expression produces an error. ```typescript -// Check if the result of a calculation is an error -isError(field("title").arrayContains(1)); +// Check if the field `value` is absent. +isAbsent(field("value")); ``` +### isError(value) {:#iserror_f3daf14} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a given expression produces an error. + Signature: ```typescript @@ -9248,12 +8929,23 @@ export declare function isError(value: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. A new representing the 'isError' check. | +| value | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | Returns: [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'isError' check. + +### Example + + +```typescript +// Check if the result of a calculation is an error +isError(field("title").arrayContains(1)); + +``` + ## function(vectorExpression, ...) ### cosineDistance(vectorExpression, vector) {:#cosinedistance_3a80317} @@ -9263,12 +8955,6 @@ export declare function isError(value: Expression): BooleanExpression; Calculates the Cosine distance between a vector expression and a vector literal. -```typescript -// Calculate the cosine distance between the 'location' field and a target location -cosineDistance(field("location"), [37.7749, -122.4194]); - -``` - Signature: ```typescript @@ -9279,26 +8965,31 @@ export declare function cosineDistance(vectorExpression: Expression, vector: num | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | -| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. A new representing the cosine distance between the two vectors. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expression) to compare against. | +| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### cosineDistance(vectorExpression, otherVectorExpression) {:#cosinedistance_17b5bcc} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the cosine distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Cosine distance between two vector expressions. ```typescript -// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field -cosineDistance(field("userVector"), field("itemVector")); +// Calculate the cosine distance between the 'location' field and a target location +cosineDistance(field("location"), [37.7749, -122.4194]); ``` +### cosineDistance(vectorExpression, otherVectorExpression) {:#cosinedistance_17b5bcc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between two vector expressions. + Signature: ```typescript @@ -9309,26 +9000,31 @@ export declare function cosineDistance(vectorExpression: Expression, otherVector | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | -| otherVectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the cosine distance between the two vectors. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expression) to compare against. | +| otherVectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to compare against. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### dotProduct(vectorExpression, vector) {:#dotproduct_3a80317} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the cosine distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the dot product between a vector expression and a double array. ```typescript -// Calculate the dot product between a feature vector and a target vector -dotProduct(field("features"), [0.5, 0.8, 0.2]); +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +cosineDistance(field("userVector"), field("itemVector")); ``` +### dotProduct(vectorExpression, vector) {:#dotproduct_3a80317} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between a vector expression and a double array. + Signature: ```typescript @@ -9339,26 +9035,31 @@ export declare function dotProduct(vectorExpression: Expression, vector: number[ | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to calculate with. | -| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to calculate with. A new representing the dot product between the two vectors. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expression) to calculate with. | +| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to calculate with. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### dotProduct(vectorExpression, otherVectorExpression) {:#dotproduct_17b5bcc} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the dot product between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the dot product between two vector expressions. ```typescript -// Calculate the dot product between two document vectors: 'docVector1' and 'docVector2' -dotProduct(field("docVector1"), field("docVector2")); +// Calculate the dot product between a feature vector and a target vector +dotProduct(field("features"), [0.5, 0.8, 0.2]); ``` +### dotProduct(vectorExpression, otherVectorExpression) {:#dotproduct_17b5bcc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between two vector expressions. + Signature: ```typescript @@ -9369,27 +9070,31 @@ export declare function dotProduct(vectorExpression: Expression, otherVectorExpr | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to calculate with. | -| otherVectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to calculate with. A new representing the dot product between the two vectors. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expression) to calculate with. | +| otherVectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to calculate with. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### euclideanDistance(vectorExpression, vector) {:#euclideandistance_3a80317} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the dot product between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Euclidean distance between a vector expression and a double array. ```typescript -// Calculate the Euclidean distance between the 'location' field and a target location - -euclideanDistance(field("location"), [37.7749, -122.4194]); +// Calculate the dot product between two document vectors: 'docVector1' and 'docVector2' +dotProduct(field("docVector1"), field("docVector2")); ``` +### euclideanDistance(vectorExpression, vector) {:#euclideandistance_3a80317} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between a vector expression and a double array. + Signature: ```typescript @@ -9400,26 +9105,32 @@ export declare function euclideanDistance(vectorExpression: Expression, vector: | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | -| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. A new representing the Euclidean distance between the two vectors. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expression) to compare against. | +| vector | number\[\] \| [VectorValue](./firestore_lite.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### euclideanDistance(vectorExpression, otherVectorExpression) {:#euclideandistance_17b5bcc} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the Euclidean distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Euclidean distance between two vector expressions. ```typescript -// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' -euclideanDistance(field("pointA"), field("pointB")); +// Calculate the Euclidean distance between the 'location' field and a target location + +euclideanDistance(field("location"), [37.7749, -122.4194]); ``` +### euclideanDistance(vectorExpression, otherVectorExpression) {:#euclideandistance_17b5bcc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between two vector expressions. + Signature: ```typescript @@ -9430,26 +9141,31 @@ export declare function euclideanDistance(vectorExpression: Expression, otherVec | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | -| otherVectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the Euclidean distance between the two vectors. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first vector (represented as an Expression) to compare against. | +| otherVectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to compare against. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### vectorLength(vectorExpression) {:#vectorlength_58a039b} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the Euclidean distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of a Firestore Vector. ```typescript -// Get the vector length (dimension) of the field 'embedding'. -vectorLength(field("embedding")); +// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' +euclideanDistance(field("pointA"), field("pointB")); ``` +### vectorLength(vectorExpression) {:#vectorlength_58a039b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a Firestore Vector. + Signature: ```typescript @@ -9460,18 +9176,29 @@ export declare function vectorLength(vectorExpression: Expression): FunctionExpr | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the Firestore Vector. A new representing the length of the array. | +| vectorExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the Firestore Vector. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the array. + +### Example + + +```typescript +// Get the vector length (dimension) of the field 'embedding'. +vectorLength(field("embedding")); + +``` + ## AddFieldsStageOptions > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how an AddFieldsStage is evaluated. See . +Options defining how an AddFieldsStage is evaluated. See [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields). Signature: @@ -9486,7 +9213,7 @@ export declare type AddFieldsStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how an AggregateStage is evaluated. See . +Options defining how an AggregateStage is evaluated. See [Pipeline.aggregate()](./firestore_pipelines.pipeline.md#pipelineaggregate). Signature: @@ -9502,7 +9229,9 @@ export declare type AggregateStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Defines the configuration options for a within a pipeline. This type extends and provides specific settings for how a collection group is identified and processed during pipeline execution. +Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution. + +See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. Signature: @@ -9518,7 +9247,7 @@ export declare type CollectionGroupStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a CollectionStage is evaluated. See . +Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). Signature: @@ -9534,7 +9263,7 @@ export declare type CollectionStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a DatabaseStage is evaluated. See . +Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). Signature: @@ -9547,7 +9276,7 @@ export declare type DatabaseStageOptions = StageOptions & {}; > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a DistinctStage is evaluated. See . +Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). Signature: @@ -9562,7 +9291,7 @@ export declare type DistinctStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a DocumentsStage is evaluated. See . +Options defining how a DocumentsStage is evaluated. See [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments). Signature: @@ -9590,7 +9319,7 @@ export declare type ExpressionType = 'Field' | 'Constant' | 'Function' | 'Aggreg > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a FindNearestStage is evaluated. See . +Options defining how a FindNearestStage is evaluated. See [Pipeline.findNearest()](./firestore_pipelines.pipeline.md#pipelinefindnearest). Signature: @@ -9609,7 +9338,7 @@ export declare type FindNearestStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a LimitStage is evaluated. See . +Options defining how a LimitStage is evaluated. See [Pipeline.limit()](./firestore_pipelines.pipeline.md#pipelinelimit). Signature: @@ -9624,7 +9353,7 @@ export declare type LimitStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how an OffsetStage is evaluated. See . +Options defining how an OffsetStage is evaluated. See [Pipeline.offset()](./firestore_pipelines.pipeline.md#pipelineoffset). Signature: @@ -9641,8 +9370,6 @@ export declare type OffsetStageOptions = StageOptions & { Utility type to create an type that only allows one property of the Type param T to be set. -type XorY = OneOf<{ x: unknown, y: unknown}> let a = { x: "foo" } // OK let b = { y: "foo" } // OK let c = { a: "foo", y: "foo" } // Not OK - Signature: ```typescript @@ -9653,6 +9380,17 @@ export declare type OneOf = { }[keyof T]; ``` +### Example + + +``` +type XorY = OneOf<{ x: unknown, y: unknown }> +let a = { x: "foo" } // OK +let b = { y: "foo" } // OK +let c = { a: "foo", y: "foo" } // Not OK + +``` + ## PartialWithFieldValue Similar to TypeScript's `Partial`, but allows nested fields to be omitted and FieldValues to be passed in as property values. @@ -9680,7 +9418,7 @@ export declare type Primitive = string | number | boolean | undefined | null; > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a RemoveFieldsStage is evaluated. See . +Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). Signature: @@ -9695,7 +9433,7 @@ export declare type RemoveFieldsStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a ReplaceWithStage is evaluated. See . +Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). Signature: @@ -9710,9 +9448,9 @@ export declare type ReplaceWithStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Defines the options for evaluating a sample stage within a pipeline. This type combines common with a specific configuration where only one of the defined sampling methods can be applied. +Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied. -See to create a sample stage.. +See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. Signature: @@ -9728,7 +9466,7 @@ export declare type SampleStageOptions = StageOptions & OneOf<{ > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a SelectStage is evaluated. See . +Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). Signature: @@ -9757,7 +9495,7 @@ export declare type SetOptions = { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a SortStage is evaluated. See . +Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). Signature: @@ -9785,7 +9523,7 @@ export declare type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a UnionStage is evaluated. See . +Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). Signature: @@ -9816,7 +9554,7 @@ export declare type UnnestStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a WhereStage is evaluated. See . +Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). Signature: diff --git a/docs-devsite/firestore_lite_pipelines.pipeline.md b/docs-devsite/firestore_lite_pipelines.pipeline.md index 9c3f65e046..e68ad20767 100644 --- a/docs-devsite/firestore_lite_pipelines.pipeline.md +++ b/docs-devsite/firestore_lite_pipelines.pipeline.md @@ -23,27 +23,6 @@ NOTE: The chained stages do not prescribe exactly how Firestore will execute the Usage Examples: -```typescript -const db: Firestore; // Assumes a valid firestore instance. - -// Example 1: Select specific fields and rename 'rating' to 'bookRating' -const results1 = await execute(db.pipeline() - .collection("books") - .select("title", "author", field("rating").as("bookRating"))); - -// Example 2: Filter documents where 'genre' is "Science Fiction" and 'published' is after 1950 -const results2 = await execute(db.pipeline() - .collection("books") - .where(and(field("genre").eq("Science Fiction"), field("published").gt(1950)))); - -// Example 3: Calculate the average rating of books published after 1980 -const results3 = await execute(db.pipeline() - .collection("books") - .where(field("published").gt(1980)) - .aggregate(avg(field("rating")).as("averageRating"))); - -``` - Signature: ```typescript @@ -54,66 +33,12 @@ export declare class Pipeline | Method | Modifiers | Description | | --- | --- | --- | -| [addFields(field, additionalFields)](./firestore_lite_pipelines.pipeline.md#pipelineaddfields) | | (Public Preview) Adds new fields to outputs from previous stages.This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps).The added fields are defined using s, which can be:- : References an existing document field. - : Either a literal value (see ) or a computed value (see ) with an assigned alias using .Example: -```typescript -firestore.pipeline().collection("books") - .addFields( - field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' - add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' - ); - -``` - | -| [addFields(options)](./firestore_lite_pipelines.pipeline.md#pipelineaddfields) | | (Public Preview) Adds new fields to outputs from previous stages.This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps).The added fields are defined using s, which can be:- : References an existing document field. - : Either a literal value (see ) or a computed value (see ) with an assigned alias using .Example: -```typescript -firestore.pipeline().collection("books") - .addFields( - field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' - add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' - ); - -``` - | -| [aggregate(accumulator, additionalAccumulators)](./firestore_lite_pipelines.pipeline.md#pipelineaggregate) | | (Public Preview) Performs aggregation operations on the documents from previous stages.

This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using expressions which are typically results of calling on instances.

Example: -```typescript -// Calculate the average rating and the total number of books -firestore.pipeline().collection("books") - .aggregate( - field("rating").avg().as("averageRating"), - countAll().as("totalBooks") - ); - -``` - | -| [aggregate(options)](./firestore_lite_pipelines.pipeline.md#pipelineaggregate) | | (Public Preview) Performs optionally grouped aggregation operations on the documents from previous stages.

This stage allows you to calculate aggregate values over a set of documents, optionally grouped by one or more fields or functions. You can specify:

  • \*\*Grouping Fields or Functions:\*\* One or more fields or functions to group the documents by. For each distinct combination of values in these fields, a separate group is created. If no grouping fields are provided, a single group containing all documents is used. Not specifying groups is the same as putting the entire inputs into one group.
  • \*\*Accumulators:\*\* One or more accumulation operations to perform within each group. These are defined using expressions, which are typically created by calling on instances. Each aggregation calculates a value (e.g., sum, average, count) based on the documents within its group.

Example: -```typescript -// Calculate the average rating for each genre. -firestore.pipeline().collection("books") - .aggregate({ - accumulators: [avg(field("rating")).as("avg_rating")] - groups: ["genre"] - }); - -``` - | -| [distinct(group, additionalGroups)](./firestore_lite_pipelines.pipeline.md#pipelinedistinct) | | (Public Preview) Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of values (, , etc).The parameters to this stage are defined using expressions or strings:- : Name of an existing field - : References an existing document field. - : Represents the result of a function with an assigned alias name using .Example: -```typescript -// Get a list of unique author names in uppercase and genre combinations. -firestore.pipeline().collection("books") - .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") - .select("authorName"); - -``` - | -| [distinct(options)](./firestore_lite_pipelines.pipeline.md#pipelinedistinct) | | (Public Preview) Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of values (, , etc).The parameters to this stage are defined using expressions or strings:- : Name of an existing field - : References an existing document field. - : Represents the result of a function with an assigned alias name using .Example: -```typescript -// Get a list of unique author names in uppercase and genre combinations. -firestore.pipeline().collection("books") - .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") - .select("authorName"); - -``` - | +| [addFields(field, additionalFields)](./firestore_lite_pipelines.pipeline.md#pipelineaddfields) | | (Public Preview) Adds new fields to outputs from previous stages.This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps).The added fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s, which can be:- [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [Expression](./firestore_pipelines.expression.md#expression_class): Either a literal value (see [constant()](./firestore_pipelines.md#constant_0c00f91)) or a computed value with an assigned alias using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | +| [addFields(options)](./firestore_lite_pipelines.pipeline.md#pipelineaddfields) | | (Public Preview) Adds new fields to outputs from previous stages.This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps).The added fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s, which can be:- [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [Expression](./firestore_pipelines.expression.md#expression_class): Either a literal value (see [constant()](./firestore_pipelines.md#constant_0c00f91)) or a computed value with an assigned alias using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | +| [aggregate(accumulator, additionalAccumulators)](./firestore_lite_pipelines.pipeline.md#pipelineaggregate) | | (Public Preview) Performs aggregation operations on the documents from previous stages.

This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions which are typically results of calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances.

Example: | +| [aggregate(options)](./firestore_lite_pipelines.pipeline.md#pipelineaggregate) | | (Public Preview) Performs optionally grouped aggregation operations on the documents from previous stages.

This stage allows you to calculate aggregate values over a set of documents, optionally grouped by one or more fields or functions. You can specify:

  • \*\*Grouping Fields or Functions:\*\* One or more fields or functions to group the documents by. For each distinct combination of values in these fields, a separate group is created. If no grouping fields are provided, a single group containing all documents is used. Not specifying groups is the same as putting the entire inputs into one group.
  • \*\*Accumulators:\*\* One or more accumulation operations to perform within each group. These are defined using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions, which are typically created by calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances. Each aggregation calculates a value (e.g., sum, average, count) based on the documents within its group.

Example: | +| [distinct(group, additionalGroups)](./firestore_lite_pipelines.pipeline.md#pipelinedistinct) | | (Public Preview) Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc).The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings:- string: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | +| [distinct(options)](./firestore_lite_pipelines.pipeline.md#pipelinedistinct) | | (Public Preview) Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc).The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings:- string: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | | [findNearest(options)](./firestore_lite_pipelines.pipeline.md#pipelinefindnearest) | | (Public Preview) Performs a vector proximity search on the documents from the previous stage, returning the K-nearest documents based on the specified query vectorValue and distanceMeasure. The returned documents will be sorted in order from nearest to furthest from the query vectorValue.

Example: ```typescript // Find the 10 most similar books based on the book description. @@ -131,278 +56,74 @@ firestore.pipeline().collection("books") ``` | -| [limit(limit)](./firestore_lite_pipelines.pipeline.md#pipelinelimit) | | (Public Preview) Limits the maximum number of documents returned by previous stages to limit.

This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for:

  • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
  • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.

Example: -```typescript -// Limit the results to the top 10 highest-rated books -firestore.pipeline().collection('books') - .sort(field('rating').descending()) - .limit(10); - -``` - | -| [limit(options)](./firestore_lite_pipelines.pipeline.md#pipelinelimit) | | (Public Preview) Limits the maximum number of documents returned by previous stages to limit.

This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for:

  • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
  • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.

Example: -```typescript -// Limit the results to the top 10 highest-rated books -firestore.pipeline().collection('books') - .sort(field('rating').descending()) - .limit(10); +| [limit(limit)](./firestore_lite_pipelines.pipeline.md#pipelinelimit) | | (Public Preview) Limits the maximum number of documents returned by previous stages to limit.

This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for:

  • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
  • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.

Example: | +| [limit(options)](./firestore_lite_pipelines.pipeline.md#pipelinelimit) | | (Public Preview) Limits the maximum number of documents returned by previous stages to limit.

This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for:

  • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
  • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.

Example: | +| [offset(offset)](./firestore_lite_pipelines.pipeline.md#pipelineoffset) | | (Public Preview) Skips the first offset number of documents from the results of previous stages.

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page.

Example: | +| [offset(options)](./firestore_lite_pipelines.pipeline.md#pipelineoffset) | | (Public Preview) Skips the first offset number of documents from the results of previous stages.

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page.

Example: | +| [rawStage(name, params, options)](./firestore_lite_pipelines.pipeline.md#pipelinerawstage) | | (Public Preview) Adds a raw stage to the pipeline.

This method provides a flexible way to extend the pipeline's functionality by adding custom stages. Each raw stage is defined by a unique name and a set of params that control its behavior.

Example (Assuming there is no 'where' stage available in SDK): | +| [removeFields(fieldValue, additionalFields)](./firestore_lite_pipelines.pipeline.md#pipelineremovefields) | | (Public Preview) Remove fields from outputs of previous stages.Example: | +| [removeFields(options)](./firestore_lite_pipelines.pipeline.md#pipelineremovefields) | | (Public Preview) Remove fields from outputs of previous stages.Example: | +| [replaceWith(fieldName)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) Fully overwrites all fields in a document with those coming from a nested map.

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

Example: | +| [replaceWith(expr)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) Fully overwrites all fields in a document with those coming from a map.

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

Example: | +| [replaceWith(options)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) Fully overwrites all fields in a document with those coming from a map.

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

Example: | +| [sample(documents)](./firestore_lite_pipelines.pipeline.md#pipelinesample) | | (Public Preview) Performs a pseudo-random sampling of the documents from the previous stage.

This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned.

Examples: | +| [sample(options)](./firestore_lite_pipelines.pipeline.md#pipelinesample) | | (Public Preview) Performs a pseudo-random sampling of the documents from the previous stage.

This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) for more information. | +| [select(selection, additionalSelections)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | (Public Preview) Selects or creates a set of fields from the outputs of previous stages.

The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

  • string : Name of an existing field
  • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
  • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

Example: | +| [select(options)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | (Public Preview) Selects or creates a set of fields from the outputs of previous stages.

The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

  • string: Name of an existing field
  • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
  • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

Example: | +| [sort(ordering, additionalOrderings)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | (Public Preview) Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

Example: | +| [sort(options)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | (Public Preview) Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

Example: | +| [union(other)](./firestore_lite_pipelines.pipeline.md#pipelineunion) | | (Public Preview) Performs union of all documents from two pipelines, including duplicates.

This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined.

Example: | +| [union(options)](./firestore_lite_pipelines.pipeline.md#pipelineunion) | | (Public Preview) Performs union of all documents from two pipelines, including duplicates.

This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined.

Example: | +| [unnest(selectable, indexField)](./firestore_lite_pipelines.pipeline.md#pipelineunnest) | | (Public Preview) Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: | +| [unnest(options)](./firestore_lite_pipelines.pipeline.md#pipelineunnest) | | (Public Preview) Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: | +| [where(condition)](./firestore_lite_pipelines.pipeline.md#pipelinewhere) | | (Public Preview) Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class).

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to:

  • field comparators: [Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), [Expression.greaterThan()](./firestore_pipelines.expression.md#expressiongreaterthan), etc.
  • logical operators: , , , etc.
  • advanced functions: [Expression.regexMatch()](./firestore_pipelines.expression.md#expressionregexmatch), [Expression.arrayContains()](./firestore_pipelines.expression.md#expressionarraycontains), etc.

Example: | +| [where(options)](./firestore_lite_pipelines.pipeline.md#pipelinewhere) | | (Public Preview) Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class).

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to:

  • field comparators: , (less than), [Expression.greaterThan()](./firestore_pipelines.expression.md#expressiongreaterthan), etc.
  • logical operators: , , , etc.
  • advanced functions: [Expression.regexMatch()](./firestore_pipelines.expression.md#expressionregexmatch), [Expression.arrayContains()](./firestore_pipelines.expression.md#expressionarraycontains), etc.

Example: | -``` - | -| [offset(offset)](./firestore_lite_pipelines.pipeline.md#pipelineoffset) | | (Public Preview) Skips the first offset number of documents from the results of previous stages.

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page.

Example: -```typescript -// Retrieve the second page of 20 results -firestore.pipeline().collection('books') - .sort(field('published').descending()) - .offset(20) // Skip the first 20 results - .limit(20); // Take the next 20 results - -``` - | -| [offset(options)](./firestore_lite_pipelines.pipeline.md#pipelineoffset) | | (Public Preview) Skips the first offset number of documents from the results of previous stages.

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page.

Example: -```typescript -// Retrieve the second page of 20 results -firestore.pipeline().collection('books') - .sort(field('published').descending()) - .offset(20) // Skip the first 20 results - .limit(20); // Take the next 20 results - -``` - | -| [rawStage(name, params, options)](./firestore_lite_pipelines.pipeline.md#pipelinerawstage) | | (Public Preview) Adds a raw stage to the pipeline.

This method provides a flexible way to extend the pipeline's functionality by adding custom stages. Each raw stage is defined by a unique name and a set of params that control its behavior.

Example (Assuming there is no 'where' stage available in SDK): -```typescript -// Assume we don't have a built-in 'where' stage -firestore.pipeline().collection('books') - .rawStage('where', [field('published').lt(1900)]) // Custom 'where' stage - .select('title', 'author'); - -``` - | -| [removeFields(fieldValue, additionalFields)](./firestore_lite_pipelines.pipeline.md#pipelineremovefields) | | (Public Preview) Remove fields from outputs of previous stages.Example: -```typescript -firestore.pipeline().collection('books') - // removes field 'rating' and 'cost' from the previous stage outputs. - .removeFields( - field('rating'), - 'cost' - ); - -``` - | -| [removeFields(options)](./firestore_lite_pipelines.pipeline.md#pipelineremovefields) | | (Public Preview) Remove fields from outputs of previous stages.Example: -```typescript -firestore.pipeline().collection('books') - // removes field 'rating' and 'cost' from the previous stage outputs. - .removeFields( - field('rating'), - 'cost' - ); - -``` - | -| [replaceWith(fieldName)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) Fully overwrites all fields in a document with those coming from a nested map.

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

Example: -```typescript -// Input. -// { -// 'name': 'John Doe Jr.', -// 'parents': { -// 'father': 'John Doe Sr.', -// 'mother': 'Jane Doe' -// } -// } - -// Emit parents as document. -firestore.pipeline().collection('people').replaceWith('parents'); - -// Output -// { -// 'father': 'John Doe Sr.', -// 'mother': 'Jane Doe' -// } - -``` - | -| [replaceWith(expr)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) Fully overwrites all fields in a document with those coming from a map.

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

Example: -```typescript -// Input. -// { -// 'name': 'John Doe Jr.', -// 'parents': { -// 'father': 'John Doe Sr.', -// 'mother': 'Jane Doe' -// } -// } - -// Emit parents as document. -firestore.pipeline().collection('people').replaceWith(map({ - foo: 'bar', - info: { - name: field('name') - } -})); - -// Output -// { -// 'father': 'John Doe Sr.', -// 'mother': 'Jane Doe' -// } - -``` - | -| [replaceWith(options)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) Fully overwrites all fields in a document with those coming from a map.

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

Example: -```typescript -// Input. -// { -// 'name': 'John Doe Jr.', -// 'parents': { -// 'father': 'John Doe Sr.', -// 'mother': 'Jane Doe' -// } -// } +## Pipeline.addFields() -// Emit parents as document. -firestore.pipeline().collection('people').replaceWith(map({ - foo: 'bar', - info: { - name: field('name') - } -})); +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> -// Output -// { -// 'father': 'John Doe Sr.', -// 'mother': 'Jane Doe' -// } +Adds new fields to outputs from previous stages. -``` - | -| [sample(documents)](./firestore_lite_pipelines.pipeline.md#pipelinesample) | | (Public Preview) Performs a pseudo-random sampling of the documents from the previous stage.

This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned.

Examples: -```typescript -// Sample 25 books, if available. -firestore.pipeline().collection('books') - .sample(25); +This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps). -``` - | -| [sample(options)](./firestore_lite_pipelines.pipeline.md#pipelinesample) | | (Public Preview) Performs a pseudo-random sampling of the documents from the previous stage.

This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See for more information.

Examples:// Sample 10 books, if available. firestore.pipeline().collection("books") .sample({ documents: 10 });// Sample 50% of books. firestore.pipeline().collection("books") .sample({ percentage: 0.5 }); | -| [select(selection, additionalSelections)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | (Public Preview) Selects or creates a set of fields from the outputs of previous stages.

The selected fields are defined using expressions, which can be:

  • : Name of an existing field
  • : References an existing field.
  • : Represents the result of a function with an assigned alias name using

If no selections are provided, the output of this stage is empty. Use instead if only additions are desired.

Example: -```typescript -db.pipeline().collection("books") - .select( - "firstName", - field("lastName"), - field("address").toUppercase().as("upperAddress"), - ); +The added fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s, which can be: -``` - | -| [select(options)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | (Public Preview) Selects or creates a set of fields from the outputs of previous stages.

The selected fields are defined using expressions, which can be:

  • : Name of an existing field
  • : References an existing field.
  • : Represents the result of a function with an assigned alias name using

If no selections are provided, the output of this stage is empty. Use instead if only additions are desired.

Example: -```typescript -db.pipeline().collection("books") - .select( - "firstName", - field("lastName"), - field("address").toUppercase().as("upperAddress"), - ); +- [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [Expression](./firestore_pipelines.expression.md#expression_class): Either a literal value (see [constant()](./firestore_pipelines.md#constant_0c00f91)) or a computed value with an assigned alias using [Expression.as()](./firestore_pipelines.expression.md#expressionas). -``` - | -| [sort(ordering, additionalOrderings)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | (Public Preview) Sorts the documents from previous stages based on one or more criteria.

This stage allows you to order the results of your pipeline. You can specify multiple instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

Example: -```typescript -// Sort books by rating in descending order, and then by title in ascending order for books -// with the same rating -firestore.pipeline().collection("books") - .sort( - Ordering.of(field("rating")).descending(), - Ordering.of(field("title")) // Ascending order is the default - ); +Example: -``` - | -| [sort(options)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | (Public Preview) Sorts the documents from previous stages based on one or more criteria.

This stage allows you to order the results of your pipeline. You can specify multiple instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

Example: -```typescript -// Sort books by rating in descending order, and then by title in ascending order for books -// with the same rating -firestore.pipeline().collection("books") - .sort( - Ordering.of(field("rating")).descending(), - Ordering.of(field("title")) // Ascending order is the default - ); +Signature: -``` - | -| [union(other)](./firestore_lite_pipelines.pipeline.md#pipelineunion) | | (Public Preview) Performs union of all documents from two pipelines, including duplicates.

This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other given in parameter. The order of documents emitted from this stage is undefined.

Example: ```typescript -// Emit documents from books collection and magazines collection. -firestore.pipeline().collection('books') - .union(firestore.pipeline().collection('magazines')); - +addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; ``` - | -| [union(options)](./firestore_lite_pipelines.pipeline.md#pipelineunion) | | (Public Preview) Performs union of all documents from two pipelines, including duplicates.

This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other given in parameter. The order of documents emitted from this stage is undefined.

Example: -```typescript -// Emit documents from books collection and magazines collection. -firestore.pipeline().collection('books') - .union(firestore.pipeline().collection('magazines')); -``` - | -| [unnest(selectable, indexField)](./firestore_lite_pipelines.pipeline.md#pipelineunnest) | | (Public Preview) Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: -```typescript -// Input: -// { "title": "The Hitchhiker's Guide to the Galaxy", "tags": [ "comedy", "space", "adventure" ], ... } +#### Parameters -// Emit a book document for each tag of the book. -firestore.pipeline().collection("books") - .unnest(field("tags").as('tag'), 'tagIndex'); +| Parameter | Type | Description | +| --- | --- | --- | +| field | [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) | The first field to add to the documents, specified as a [Selectable](./firestore_pipelines.selectable.md#selectable_interface). | +| additionalFields | [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface)\[\] | Optional additional fields to add to the documents, specified as [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s. | -// Output: -// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "comedy", "tagIndex": 0, ... } -// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "space", "tagIndex": 1, ... } -// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "adventure", "tagIndex": 2, ... } +Returns: -``` - | -| [unnest(options)](./firestore_lite_pipelines.pipeline.md#pipelineunnest) | | (Public Preview) Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: -```typescript -// Input: -// { "title": "The Hitchhiker's Guide to the Galaxy", "tags": [ "comedy", "space", "adventure" ], ... } +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -// Emit a book document for each tag of the book. -firestore.pipeline().collection("books") - .unnest(field("tags").as('tag'), 'tagIndex'); +A new Pipeline object with this stage appended to the stage list. -// Output: -// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "comedy", "tagIndex": 0, ... } -// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "space", "tagIndex": 1, ... } -// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "adventure", "tagIndex": 2, ... } +### Example -``` - | -| [where(condition)](./firestore_lite_pipelines.pipeline.md#pipelinewhere) | | (Public Preview) Filters the documents from previous stages to only include those matching the specified .

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of , typically including but not limited to:

  • field comparators: , (less than), (greater than), etc.
  • logical operators: , , , etc.
  • advanced functions: , , etc.

Example: -```typescript -firestore.pipeline().collection("books") - .where( - and( - gt(field("rating"), 4.0), // Filter for ratings greater than 4.0 - field("genre").eq("Science Fiction") // Equivalent to gt("genre", "Science Fiction") - ) - ); -``` - | -| [where(options)](./firestore_lite_pipelines.pipeline.md#pipelinewhere) | | (Public Preview) Filters the documents from previous stages to only include those matching the specified .

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of , typically including but not limited to:

  • field comparators: , (less than), (greater than), etc.
  • logical operators: , , , etc.
  • advanced functions: , , etc.

Example: ```typescript firestore.pipeline().collection("books") - .where( - and( - gt(field("rating"), 4.0), // Filter for ratings greater than 4.0 - field("genre").eq("Science Fiction") // Equivalent to gt("genre", "Science Fiction") - ) + .addFields( + field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' + add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' ); ``` - | ## Pipeline.addFields() @@ -413,52 +134,32 @@ Adds new fields to outputs from previous stages. This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps). -The added fields are defined using s, which can be: +The added fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s, which can be: -- : References an existing document field. - : Either a literal value (see ) or a computed value (see ) with an assigned alias using . +- [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [Expression](./firestore_pipelines.expression.md#expression_class): Either a literal value (see [constant()](./firestore_pipelines.md#constant_0c00f91)) or a computed value with an assigned alias using [Expression.as()](./firestore_pipelines.expression.md#expressionas). Example: -```typescript -firestore.pipeline().collection("books") - .addFields( - field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' - add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' - ); - -``` - Signature: ```typescript -addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; +addFields(options: AddFieldsStageOptions): Pipeline; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| field | [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) | The first field to add to the documents, specified as a . | -| additionalFields | [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface)\[\] | Optional additional fields to add to the documents, specified as s. A new Pipeline object with this stage appended to the stage list. | +| options | [AddFieldsStageOptions](./firestore_lite_pipelines.md#addfieldsstageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -## Pipeline.addFields() +A new Pipeline object with this stage appended to the stage list. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Adds new fields to outputs from previous stages. - -This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps). - -The added fields are defined using s, which can be: - -- : References an existing document field. - : Either a literal value (see ) or a computed value (see ) with an assigned alias using . - -Example: ```typescript firestore.pipeline().collection("books") @@ -469,32 +170,38 @@ firestore.pipeline().collection("books") ``` +## Pipeline.aggregate() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Performs aggregation operations on the documents from previous stages. + +

This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions which are typically results of calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances. + +

Example: + Signature: ```typescript -addFields(options: AddFieldsStageOptions): Pipeline; +aggregate(accumulator: AliasedAggregate, ...additionalAccumulators: AliasedAggregate[]): Pipeline; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| options | [AddFieldsStageOptions](./firestore_lite_pipelines.md#addfieldsstageoptions) | An object that specifies required and optional parameters for the stage. A new Pipeline object with this stage appended to the stage list. | +| accumulator | [AliasedAggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregate_class) | The first [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class), wrapping an [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) and providing a name for the accumulated results. | +| additionalAccumulators | [AliasedAggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregate_class)\[\] | Optional additional [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class), each wrapping an [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) and providing a name for the accumulated results. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -## Pipeline.aggregate() +A new Pipeline object with this stage appended to the stage list. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Performs aggregation operations on the documents from previous stages. - -

This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using expressions which are typically results of calling on instances. - -

Example: ```typescript // Calculate the average rating and the total number of books @@ -506,23 +213,6 @@ firestore.pipeline().collection("books") ``` -Signature: - -```typescript -aggregate(accumulator: AliasedAggregate, ...additionalAccumulators: AliasedAggregate[]): Pipeline; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| accumulator | [AliasedAggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregate_class) | The first , wrapping an and providing a name for the accumulated results. | -| additionalAccumulators | [AliasedAggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregate_class)\[\] | Optional additional , each wrapping an and providing a name for the accumulated results. A new Pipeline object with this stage appended to the stage list. | - -Returns: - -[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) - ## Pipeline.aggregate() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -532,20 +222,10 @@ Performs optionally grouped aggregation operations on the documents from previou

This stage allows you to calculate aggregate values over a set of documents, optionally grouped by one or more fields or functions. You can specify: -

  • \*\*Grouping Fields or Functions:\*\* One or more fields or functions to group the documents by. For each distinct combination of values in these fields, a separate group is created. If no grouping fields are provided, a single group containing all documents is used. Not specifying groups is the same as putting the entire inputs into one group.
  • \*\*Accumulators:\*\* One or more accumulation operations to perform within each group. These are defined using expressions, which are typically created by calling on instances. Each aggregation calculates a value (e.g., sum, average, count) based on the documents within its group.
+
  • \*\*Grouping Fields or Functions:\*\* One or more fields or functions to group the documents by. For each distinct combination of values in these fields, a separate group is created. If no grouping fields are provided, a single group containing all documents is used. Not specifying groups is the same as putting the entire inputs into one group.
  • \*\*Accumulators:\*\* One or more accumulation operations to perform within each group. These are defined using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions, which are typically created by calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances. Each aggregation calculates a value (e.g., sum, average, count) based on the documents within its group.

Example: -```typescript -// Calculate the average rating for each genre. -firestore.pipeline().collection("books") - .aggregate({ - accumulators: [avg(field("rating")).as("avg_rating")] - groups: ["genre"] - }); - -``` - Signature: ```typescript @@ -556,12 +236,27 @@ aggregate(options: AggregateStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [AggregateStageOptions](./firestore_lite_pipelines.md#aggregatestageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | +| options | [AggregateStageOptions](./firestore_lite_pipelines.md#aggregatestageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Calculate the average rating for each genre. +firestore.pipeline().collection("books") + .aggregate({ + accumulators: [avg(field("rating")).as("avg_rating")] + groups: ["genre"] + }); + +``` + ## Pipeline.distinct() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -569,21 +264,13 @@ aggregate(options: AggregateStageOptions): Pipeline; Returns a set of distinct values from the inputs to this stage. -This stage runs through the results from previous stages to include only results with unique combinations of values (, , etc). +This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc). -The parameters to this stage are defined using expressions or strings: - -- : Name of an existing field - : References an existing document field. - : Represents the result of a function with an assigned alias name using . - -Example: +The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings: -```typescript -// Get a list of unique author names in uppercase and genre combinations. -firestore.pipeline().collection("books") - .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") - .select("authorName"); +- `string`: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas). -``` +Example: Signature: @@ -595,13 +282,26 @@ distinct(group: string | Selectable, ...additionalGroups: Array> | Optional additional expressions to consider when determining distinct value combinations or strings representing field names. A new object with this stage appended to the stage list. | +| group | string \| [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) | The [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expression or field name to consider when determining distinct value combinations. | +| additionalGroups | Array<string \| [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface)> | Optional additional [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions to consider when determining distinct value combinations or strings representing field names. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Get a list of unique author names in uppercase and genre combinations. +firestore.pipeline().collection("books") + .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") + .select("authorName"); + +``` + ## Pipeline.distinct() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -609,22 +309,14 @@ distinct(group: string | Selectable, ...additionalGroups: Array, , etc). +This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc). -The parameters to this stage are defined using expressions or strings: +The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings: -- : Name of an existing field - : References an existing document field. - : Represents the result of a function with an assigned alias name using . +- `string`: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas). Example: -```typescript -// Get a list of unique author names in uppercase and genre combinations. -firestore.pipeline().collection("books") - .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") - .select("authorName"); - -``` - Signature: ```typescript @@ -635,12 +327,25 @@ distinct(options: DistinctStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [DistinctStageOptions](./firestore_lite_pipelines.md#distinctstageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | +| options | [DistinctStageOptions](./firestore_lite_pipelines.md#distinctstageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Get a list of unique author names in uppercase and genre combinations. +firestore.pipeline().collection("books") + .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") + .select("authorName"); + +``` + ## Pipeline.findNearest() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -676,12 +381,14 @@ findNearest(options: FindNearestStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [FindNearestStageOptions](./firestore_lite_pipelines.md#findneareststageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | +| options | [FindNearestStageOptions](./firestore_lite_pipelines.md#findneareststageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + ## Pipeline.limit() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -695,14 +402,6 @@ Limits the maximum number of documents returned by previous stages to `limit`Example: -```typescript -// Limit the results to the top 10 highest-rated books -firestore.pipeline().collection('books') - .sort(field('rating').descending()) - .limit(10); - -``` - Signature: ```typescript @@ -713,12 +412,25 @@ limit(limit: number): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| limit | number | The maximum number of documents to return. A new Pipeline object with this stage appended to the stage list. | +| limit | number | The maximum number of documents to return. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +// Limit the results to the top 10 highest-rated books +firestore.pipeline().collection('books') + .sort(field('rating').descending()) + .limit(10); + +``` + ## Pipeline.limit() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -732,14 +444,6 @@ Limits the maximum number of documents returned by previous stages to `limit`Example: -```typescript -// Limit the results to the top 10 highest-rated books -firestore.pipeline().collection('books') - .sort(field('rating').descending()) - .limit(10); - -``` - Signature: ```typescript @@ -750,12 +454,25 @@ limit(options: LimitStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [LimitStageOptions](./firestore_lite_pipelines.md#limitstageoptions) | An object that specifies required and optional parameters for the stage. A new Pipeline object with this stage appended to the stage list. | +| options | [LimitStageOptions](./firestore_lite_pipelines.md#limitstageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +// Limit the results to the top 10 highest-rated books +firestore.pipeline().collection('books') + .sort(field('rating').descending()) + .limit(10); + +``` + ## Pipeline.offset() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -767,15 +484,6 @@ Skips the first `offset` number of documents from the results of previous stages

Example: -```typescript -// Retrieve the second page of 20 results -firestore.pipeline().collection('books') - .sort(field('published').descending()) - .offset(20) // Skip the first 20 results - .limit(20); // Take the next 20 results - -``` - Signature: ```typescript @@ -786,22 +494,16 @@ offset(offset: number): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| offset | number | The number of documents to skip. A new Pipeline object with this stage appended to the stage list. | +| offset | number | The number of documents to skip. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -## Pipeline.offset() - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Skips the first `offset` number of documents from the results of previous stages. +A new Pipeline object with this stage appended to the stage list. -

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page. +### Example -

Example: ```typescript // Retrieve the second page of 20 results @@ -812,6 +514,17 @@ firestore.pipeline().collection('books') ``` +## Pipeline.offset() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Skips the first `offset` number of documents from the results of previous stages. + +

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page. + +

Example: + Signature: ```typescript @@ -822,12 +535,26 @@ offset(options: OffsetStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [OffsetStageOptions](./firestore_lite_pipelines.md#offsetstageoptions) | An object that specifies required and optional parameters for the stage. A new Pipeline object with this stage appended to the stage list. | +| options | [OffsetStageOptions](./firestore_lite_pipelines.md#offsetstageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +// Retrieve the second page of 20 results +firestore.pipeline().collection('books') + .sort(field('published').descending()) + .offset(20) // Skip the first 20 results + .limit(20); // Take the next 20 results + +``` + ## Pipeline.rawStage() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -839,14 +566,6 @@ Adds a raw stage to the pipeline.

Example (Assuming there is no 'where' stage available in SDK): -```typescript -// Assume we don't have a built-in 'where' stage -firestore.pipeline().collection('books') - .rawStage('where', [field('published').lt(1900)]) // Custom 'where' stage - .select('title', 'author'); - -``` - Signature: ```typescript @@ -861,12 +580,25 @@ rawStage(name: string, params: unknown[], options?: { | --- | --- | --- | | name | string | The unique name of the raw stage to add. | | params | unknown\[\] | A list of parameters to configure the raw stage's behavior. | -| options | { \[key: string\]: [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown; } | An object of key value pairs that specifies optional parameters for the stage. A new object with this stage appended to the stage list. | +| options | { \[key: string\]: [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown; } | An object of key value pairs that specifies optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Assume we don't have a built-in 'where' stage +firestore.pipeline().collection('books') + .rawStage('where', [field('published').lt(1900)]) // Custom 'where' stage + .select('title', 'author'); + +``` + ## Pipeline.removeFields() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -876,16 +608,6 @@ Remove fields from outputs of previous stages. Example: -```typescript -firestore.pipeline().collection('books') - // removes field 'rating' and 'cost' from the previous stage outputs. - .removeFields( - field('rating'), - 'cost' - ); - -``` - Signature: ```typescript @@ -897,20 +619,16 @@ removeFields(fieldValue: Field | string, ...additionalFields: ArrayReturns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -## Pipeline.removeFields() - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +A new Pipeline object with this stage appended to the stage list. -Remove fields from outputs of previous stages. +### Example -Example: ```typescript firestore.pipeline().collection('books') @@ -922,6 +640,15 @@ firestore.pipeline().collection('books') ``` +## Pipeline.removeFields() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Remove fields from outputs of previous stages. + +Example: + Signature: ```typescript @@ -932,12 +659,27 @@ removeFields(options: RemoveFieldsStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [RemoveFieldsStageOptions](./firestore_lite_pipelines.md#removefieldsstageoptions) | An object that specifies required and optional parameters for the stage. A new Pipeline object with this stage appended to the stage list. | +| options | [RemoveFieldsStageOptions](./firestore_lite_pipelines.md#removefieldsstageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +firestore.pipeline().collection('books') + // removes field 'rating' and 'cost' from the previous stage outputs. + .removeFields( + field('rating'), + 'cost' + ); + +``` + ## Pipeline.replaceWith() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -949,6 +691,27 @@ Fully overwrites all fields in a document with those coming from a nested map.

Example: +Signature: + +```typescript +replaceWith(fieldName: string): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The [Field](./firestore_pipelines.field.md#field_class) field containing the nested map. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + ```typescript // Input. // { @@ -970,32 +733,37 @@ firestore.pipeline().collection('people').replaceWith('parents'); ``` +## Pipeline.replaceWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Fully overwrites all fields in a document with those coming from a map. + +

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value. + +

Example: + Signature: ```typescript -replaceWith(fieldName: string): Pipeline; +replaceWith(expr: Expression): Pipeline; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field containing the nested map. A new object with this stage appended to the stage list. | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An [Expression](./firestore_pipelines.expression.md#expression_class) that when returned evaluates to a map. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -## Pipeline.replaceWith() - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Fully overwrites all fields in a document with those coming from a map. +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. -

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value. +### Example -

Example: ```typescript // Input. @@ -1023,32 +791,37 @@ firestore.pipeline().collection('people').replaceWith(map({ ``` +## Pipeline.replaceWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Fully overwrites all fields in a document with those coming from a map. + +

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value. + +

Example: + Signature: ```typescript -replaceWith(expr: Expression): Pipeline; +replaceWith(options: ReplaceWithStageOptions): Pipeline; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An that when returned evaluates to a map. A new object with this stage appended to the stage list. | +| options | [ReplaceWithStageOptions](./firestore_lite_pipelines.md#replacewithstageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -## Pipeline.replaceWith() - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Fully overwrites all fields in a document with those coming from a map. +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. -

This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value. +### Example -

Example: ```typescript // Input. @@ -1076,22 +849,6 @@ firestore.pipeline().collection('people').replaceWith(map({ ``` -Signature: - -```typescript -replaceWith(options: ReplaceWithStageOptions): Pipeline; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| options | [ReplaceWithStageOptions](./firestore_lite_pipelines.md#replacewithstageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | - -Returns: - -[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) - ## Pipeline.sample() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1099,16 +856,9 @@ replaceWith(options: ReplaceWithStageOptions): Pipeline; Performs a pseudo-random sampling of the documents from the previous stage. -

This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned. - -

Examples: - -```typescript -// Sample 25 books, if available. -firestore.pipeline().collection('books') - .sample(25); +

This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned. -``` +

Examples: Signature: @@ -1120,12 +870,24 @@ sample(documents: number): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| documents | number | The number of documents to sample. A new object with this stage appended to the stage list. | +| documents | number | The number of documents to sample. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Sample 25 books, if available. +firestore.pipeline().collection('books') + .sample(25); + +``` + ## Pipeline.sample() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1133,13 +895,7 @@ sample(documents: number): Pipeline; Performs a pseudo-random sampling of the documents from the previous stage. -

This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See for more information. - -

Examples: - -// Sample 10 books, if available. firestore.pipeline().collection("books") .sample({ documents: 10 }); - -// Sample 50% of books. firestore.pipeline().collection("books") .sample({ percentage: 0.5 }); +

This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) for more information. Signature: @@ -1151,12 +907,28 @@ sample(options: SampleStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [SampleStageOptions](./firestore_lite_pipelines.md#samplestageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | +| options | [SampleStageOptions](./firestore_lite_pipelines.md#samplestageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Sample 10 books, if available. +firestore.pipeline().collection("books") + .sample({ documents: 10 }); + +// Sample 50% of books. +firestore.pipeline().collection("books") + .sample({ percentage: 0.5 }); + +``` + ## Pipeline.select() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1164,24 +936,14 @@ sample(options: SampleStageOptions): Pipeline; Selects or creates a set of fields from the outputs of previous stages. -

The selected fields are defined using expressions, which can be: +

The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be: -

  • : Name of an existing field
  • : References an existing field.
  • : Represents the result of a function with an assigned alias name using
+
  • `string` : Name of an existing field
  • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
  • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)
-

If no selections are provided, the output of this stage is empty. Use instead if only additions are desired. +

If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

Example: -```typescript -db.pipeline().collection("books") - .select( - "firstName", - field("lastName"), - field("address").toUppercase().as("upperAddress"), - ); - -``` - Signature: ```typescript @@ -1192,27 +954,17 @@ select(selection: Selectable | string, ...additionalSelections: Arraystring values representing field names. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -## Pipeline.select() - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Selects or creates a set of fields from the outputs of previous stages. - -

The selected fields are defined using expressions, which can be: +A new Pipeline object with this stage appended to the stage list. -

  • : Name of an existing field
  • : References an existing field.
  • : Represents the result of a function with an assigned alias name using
+### Example -

If no selections are provided, the output of this stage is empty. Use instead if only additions are desired. - -

Example: ```typescript db.pipeline().collection("books") @@ -1224,6 +976,21 @@ db.pipeline().collection("books") ``` +## Pipeline.select() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Selects or creates a set of fields from the outputs of previous stages. + +

The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be: + +

  • `string`: Name of an existing field
  • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
  • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)
+ +

If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired. + +

Example: + Signature: ```typescript @@ -1234,34 +1001,38 @@ select(options: SelectStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [SelectStageOptions](./firestore_lite_pipelines.md#selectstageoptions) | An object that specifies required and optional parameters for the stage. A new Pipeline object with this stage appended to the stage list. | +| options | [SelectStageOptions](./firestore_lite_pipelines.md#selectstageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +db.pipeline().collection("books") + .select( + "firstName", + field("lastName"), + field("address").toUppercase().as("upperAddress"), + ); + +``` + ## Pipeline.sort() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Sorts the documents from previous stages based on one or more criteria. +Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria. -

This stage allows you to order the results of your pipeline. You can specify multiple instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified. +

This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

Example: -```typescript -// Sort books by rating in descending order, and then by title in ascending order for books -// with the same rating -firestore.pipeline().collection("books") - .sort( - Ordering.of(field("rating")).descending(), - Ordering.of(field("title")) // Ascending order is the default - ); - -``` - Signature: ```typescript @@ -1272,23 +1043,17 @@ sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| ordering | [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) | The first instance specifying the sorting criteria. | -| additionalOrderings | [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class)\[\] | Optional additional instances specifying the additional sorting criteria. A new object with this stage appended to the stage list. | +| ordering | [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) | The first [Ordering](./firestore_pipelines.ordering.md#ordering_class) instance specifying the sorting criteria. | +| additionalOrderings | [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class)\[\] | Optional additional [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances specifying the additional sorting criteria. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -## Pipeline.sort() - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. -Sorts the documents from previous stages based on one or more criteria. +### Example -

This stage allows you to order the results of your pipeline. You can specify multiple instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified. - -

Example: ```typescript // Sort books by rating in descending order, and then by title in ascending order for books @@ -1301,6 +1066,17 @@ firestore.pipeline().collection("books") ``` +## Pipeline.sort() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria. + +

This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified. + +

Example: + Signature: ```typescript @@ -1311,12 +1087,28 @@ sort(options: SortStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | +| options | [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Sort books by rating in descending order, and then by title in ascending order for books +// with the same rating +firestore.pipeline().collection("books") + .sort( + Ordering.of(field("rating")).descending(), + Ordering.of(field("title")) // Ascending order is the default + ); + +``` + ## Pipeline.union() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1324,17 +1116,10 @@ sort(options: SortStageOptions): Pipeline; Performs union of all documents from two pipelines, including duplicates. -

This stage will pass through documents from previous stage, and also pass through documents from previous stage of the `other` given in parameter. The order of documents emitted from this stage is undefined. +

This stage will pass through documents from previous stage, and also pass through documents from previous stage of the `other` [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined.

Example: -```typescript -// Emit documents from books collection and magazines collection. -firestore.pipeline().collection('books') - .union(firestore.pipeline().collection('magazines')); - -``` - Signature: ```typescript @@ -1345,22 +1130,16 @@ union(other: Pipeline): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| other | [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) | The other that is part of union. A new object with this stage appended to the stage list. | +| other | [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) | The other [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) that is part of union. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -## Pipeline.union() - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Performs union of all documents from two pipelines, including duplicates. +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. -

This stage will pass through documents from previous stage, and also pass through documents from previous stage of the `other` given in parameter. The order of documents emitted from this stage is undefined. +### Example -

Example: ```typescript // Emit documents from books collection and magazines collection. @@ -1369,6 +1148,17 @@ firestore.pipeline().collection('books') ``` +## Pipeline.union() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Performs union of all documents from two pipelines, including duplicates. + +

This stage will pass through documents from previous stage, and also pass through documents from previous stage of the `other` [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined. + +

Example: + Signature: ```typescript @@ -1379,12 +1169,24 @@ union(options: UnionStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | +| options | [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Emit documents from books collection and magazines collection. +firestore.pipeline().collection('books') + .union(firestore.pipeline().collection('magazines')); + +``` + ## Pipeline.unnest() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1400,6 +1202,28 @@ No documents are emitted when `selectable` evaluates to an empty array. Example: +Signature: + +```typescript +unnest(selectable: Selectable, indexField?: string): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| selectable | [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) | A selectable expression defining the field to unnest and the alias to use for each un-nested element in the output documents. | +| indexField | string | An optional string value specifying the field path to write the offset (starting at zero) into the array the un-nested element is from | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + ```typescript // Input: // { "title": "The Hitchhiker's Guide to the Galaxy", "tags": [ "comedy", "space", "adventure" ], ... } @@ -1415,37 +1239,41 @@ firestore.pipeline().collection("books") ``` +## Pipeline.unnest() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Produces a document for each element in an input array. + +For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the `selectable` parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the `alias` field with the array element value. + +When `selectable` evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the `alias` field absent. + +No documents are emitted when `selectable` evaluates to an empty array. + +Example: + Signature: ```typescript -unnest(selectable: Selectable, indexField?: string): Pipeline; +unnest(options: UnnestStageOptions): Pipeline; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| selectable | [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) | A selectable expression defining the field to unnest and the alias to use for each un-nested element in the output documents. | -| indexField | string | An optional string value specifying the field path to write the offset (starting at zero) into the array the un-nested element is from A new object with this stage appended to the stage list. | +| options | [UnnestStageOptions](./firestore_lite_pipelines.md#unneststageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -## Pipeline.unnest() - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Produces a document for each element in an input array. - -For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the `selectable` parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the `alias` field with the array element value. - -When `selectable` evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the `alias` field absent. +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. -No documents are emitted when `selectable` evaluates to an empty array. +### Example -Example: ```typescript // Input: @@ -1462,34 +1290,39 @@ firestore.pipeline().collection("books") ``` +## Pipeline.where() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class). + +

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to: + +

  • field comparators: [Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), [Expression.greaterThan()](./firestore_pipelines.expression.md#expressiongreaterthan), etc.
  • logical operators: , , , etc.
  • advanced functions: [Expression.regexMatch()](./firestore_pipelines.expression.md#expressionregexmatch), [Expression.arrayContains()](./firestore_pipelines.expression.md#expressionarraycontains), etc.
+ +

Example: + Signature: ```typescript -unnest(options: UnnestStageOptions): Pipeline; +where(condition: BooleanExpression): Pipeline; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| options | [UnnestStageOptions](./firestore_lite_pipelines.md#unneststageoptions) | An object that specifies required and optional parameters for the stage. A new object with this stage appended to the stage list. | +| condition | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) to apply. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -## Pipeline.where() - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Filters the documents from previous stages to only include those matching the specified . - -

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of , typically including but not limited to: +A new Pipeline object with this stage appended to the stage list. -

  • field comparators: , (less than), (greater than), etc.
  • logical operators: , , , etc.
  • advanced functions: , , etc.
+### Example -

Example: ```typescript firestore.pipeline().collection("books") @@ -1502,34 +1335,39 @@ firestore.pipeline().collection("books") ``` +## Pipeline.where() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class). + +

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to: + +

  • field comparators: , (less than), [Expression.greaterThan()](./firestore_pipelines.expression.md#expressiongreaterthan), etc.
  • logical operators: , , , etc.
  • advanced functions: [Expression.regexMatch()](./firestore_pipelines.expression.md#expressionregexmatch), [Expression.arrayContains()](./firestore_pipelines.expression.md#expressionarraycontains), etc.
+ +

Example: + Signature: ```typescript -where(condition: BooleanExpression): Pipeline; +where(options: WhereStageOptions): Pipeline; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| condition | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The to apply. A new Pipeline object with this stage appended to the stage list. | +| options | [WhereStageOptions](./firestore_lite_pipelines.md#wherestageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) -## Pipeline.where() - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Filters the documents from previous stages to only include those matching the specified . +A new Pipeline object with this stage appended to the stage list. -

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of , typically including but not limited to: +### Example -

  • field comparators: , (less than), (greater than), etc.
  • logical operators: , , , etc.
  • advanced functions: , , etc.
- -

Example: ```typescript firestore.pipeline().collection("books") @@ -1542,19 +1380,27 @@ firestore.pipeline().collection("books") ``` -Signature: +### Example + ```typescript -where(options: WhereStageOptions): Pipeline; -``` +const db: Firestore; // Assumes a valid firestore instance. -#### Parameters +// Example 1: Select specific fields and rename 'rating' to 'bookRating' +const results1 = await execute(db.pipeline() + .collection("books") + .select("title", "author", field("rating").as("bookRating"))); -| Parameter | Type | Description | -| --- | --- | --- | -| options | [WhereStageOptions](./firestore_lite_pipelines.md#wherestageoptions) | An object that specifies required and optional parameters for the stage. A new Pipeline object with this stage appended to the stage list. | +// Example 2: Filter documents where 'genre' is "Science Fiction" and 'published' is after 1950 +const results2 = await execute(db.pipeline() + .collection("books") + .where(and(field("genre").eq("Science Fiction"), field("published").gt(1950)))); -Returns: +// Example 3: Calculate the average rating of books published after 1980 +const results3 = await execute(db.pipeline() + .collection("books") + .where(field("published").gt(1980)) + .aggregate(avg(field("rating")).as("averageRating"))); -[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) +``` diff --git a/docs-devsite/firestore_lite_pipelines.pipelineresult.md b/docs-devsite/firestore_lite_pipelines.pipelineresult.md index a2ac28a984..7dde1ef068 100644 --- a/docs-devsite/firestore_lite_pipelines.pipelineresult.md +++ b/docs-devsite/firestore_lite_pipelines.pipelineresult.md @@ -13,7 +13,7 @@ https://github.com/firebase/firebase-js-sdk > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the or methods. +A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the [PipelineResult.data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) or [PipelineResult.get()](./firestore_pipelines.pipelineresult.md#pipelineresultget) methods.

If the PipelineResult represents a non-document result, `ref` will return a undefined value. @@ -27,10 +27,10 @@ export declare class PipelineResult | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [createTime](./firestore_lite_pipelines.pipelineresult.md#pipelineresultcreatetime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was created. Undefined if this result is not a document. {Timestamp\|undefined} | -| [id](./firestore_lite_pipelines.pipelineresult.md#pipelineresultid) | | string \| undefined | (Public Preview) The ID of the document for which this PipelineResult contains data, if it is a document; otherwise undefined. {string} | +| [createTime](./firestore_lite_pipelines.pipelineresult.md#pipelineresultcreatetime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was created. Undefined if this result is not a document. | +| [id](./firestore_lite_pipelines.pipelineresult.md#pipelineresultid) | | string \| undefined | (Public Preview) The ID of the document for which this PipelineResult contains data, if it is a document; otherwise undefined. | | [ref](./firestore_lite_pipelines.pipelineresult.md#pipelineresultref) | | [DocumentReference](./firestore_lite.documentreference.md#documentreference_class) \| undefined | (Public Preview) The reference of the document, if it is a document; otherwise undefined. | -| [updateTime](./firestore_lite_pipelines.pipelineresult.md#pipelineresultupdatetime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. {Timestamp\|undefined} | +| [updateTime](./firestore_lite_pipelines.pipelineresult.md#pipelineresultupdatetime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. | ## Methods @@ -46,8 +46,6 @@ export declare class PipelineResult The time the document was created. Undefined if this result is not a document. - {Timestamp\|undefined} - Signature: ```typescript @@ -61,8 +59,6 @@ get createTime(): Timestamp | undefined; The ID of the document for which this PipelineResult contains data, if it is a document; otherwise `undefined`. - {string} - Signature: ```typescript @@ -89,8 +85,6 @@ get ref(): DocumentReference | undefined; The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. - {Timestamp\|undefined} - Signature: ```typescript @@ -113,7 +107,7 @@ data(): AppModelType; AppModelType -{T} An object containing all fields in the document or 'undefined' if the document doesn't exist. +An object containing all fields in the document or 'undefined' if the document doesn't exist. ### Example @@ -151,7 +145,7 @@ get(fieldPath: string | FieldPath | Field): any; any -{\*} The data at the specified field location or undefined if no such field exists. +The data at the specified field location or `undefined` if no such field exists. ### Example diff --git a/docs-devsite/firestore_lite_pipelines.pipelinesnapshot.md b/docs-devsite/firestore_lite_pipelines.pipelinesnapshot.md index e5370fc1d0..d8e2f8f5bf 100644 --- a/docs-devsite/firestore_lite_pipelines.pipelinesnapshot.md +++ b/docs-devsite/firestore_lite_pipelines.pipelinesnapshot.md @@ -15,7 +15,7 @@ https://github.com/firebase/firebase-js-sdk Represents the results of a Firestore pipeline execution. -A `PipelineSnapshot` contains zero or more objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. +A `PipelineSnapshot` contains zero or more [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. Signature: @@ -33,7 +33,7 @@ export declare class PipelineSnapshot | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [executionTime](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshotexecutiontime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) | (Public Preview) The time at which the pipeline producing this result is executed. {Timestamp} | +| [executionTime](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshotexecutiontime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) | (Public Preview) The time at which the pipeline producing this result is executed. | | [results](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshotresults) | | [PipelineResult](./firestore_lite_pipelines.pipelineresult.md#pipelineresult_class)\[\] | (Public Preview) An array of all the results in the PipelineSnapshot. | ## PipelineSnapshot.(constructor) @@ -64,8 +64,6 @@ constructor(pipeline: Pipeline, results: PipelineResult[], executionTime?: Times The time at which the pipeline producing this result is executed. - {Timestamp} - Signature: ```typescript diff --git a/docs-devsite/firestore_lite_pipelines.pipelinesource.md b/docs-devsite/firestore_lite_pipelines.pipelinesource.md index 6ec4d729fa..e42b7b66ec 100644 --- a/docs-devsite/firestore_lite_pipelines.pipelinesource.md +++ b/docs-devsite/firestore_lite_pipelines.pipelinesource.md @@ -13,9 +13,9 @@ https://github.com/firebase/firebase-js-sdk > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Provides the entry point for defining the data source of a Firestore . +Provides the entry point for defining the data source of a Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class). -Use the methods of this class (e.g., , , , or ) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. +Use the methods of this class (e.g., [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection), [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup), [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase), or [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments)) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. Signature: @@ -154,7 +154,7 @@ createFrom(query: Query): Pipeline; #### Exceptions - Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. +`FirestoreError` Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. ## PipelineSource.database() @@ -220,7 +220,7 @@ PipelineType #### Exceptions - Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. +`FirestoreError` Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. ## PipelineSource.documents() @@ -247,5 +247,5 @@ PipelineType #### Exceptions - Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. +`FirestoreError` Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. diff --git a/docs-devsite/firestore_lite_pipelines.vectorvalue.md b/docs-devsite/firestore_lite_pipelines.vectorvalue.md index 19a69f0bc2..3afe1d51f3 100644 --- a/docs-devsite/firestore_lite_pipelines.vectorvalue.md +++ b/docs-devsite/firestore_lite_pipelines.vectorvalue.md @@ -12,8 +12,6 @@ https://github.com/firebase/firebase-js-sdk # VectorValue class Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). - VectorValue - Signature: ```typescript diff --git a/docs-devsite/firestore_pipelines.aggregatefunction.md b/docs-devsite/firestore_pipelines.aggregatefunction.md index 5373c05e5a..37b927d28d 100644 --- a/docs-devsite/firestore_pipelines.aggregatefunction.md +++ b/docs-devsite/firestore_pipelines.aggregatefunction.md @@ -37,14 +37,7 @@ export declare class AggregateFunction | Method | Modifiers | Description | | --- | --- | --- | -| [as(name)](./firestore_pipelines.aggregatefunction.md#aggregatefunctionas) | | (Public Preview) Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. -```typescript -// Calculate the average price of all items and assign it the alias "averagePrice". -firestore.pipeline().collection("items") - .aggregate(field("price").average().as("averagePrice")); - -``` - | +| [as(name)](./firestore_pipelines.aggregatefunction.md#aggregatefunctionas) | | (Public Preview) Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. | ## AggregateFunction.(constructor) @@ -84,13 +77,6 @@ exprType: ExpressionType; Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. -```typescript -// Calculate the average price of all items and assign it the alias "averagePrice". -firestore.pipeline().collection("items") - .aggregate(field("price").average().as("averagePrice")); - -``` - Signature: ```typescript @@ -101,9 +87,21 @@ as(name: string): AliasedAggregate; | Parameter | Type | Description | | --- | --- | --- | -| name | string | The alias to assign to this AggregateFunction. A new that wraps this AggregateFunction and associates it with the provided alias. | +| name | string | The alias to assign to this AggregateFunction. | Returns: [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) +A new [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) that wraps this AggregateFunction and associates it with the provided alias. + +### 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")); + +``` + diff --git a/docs-devsite/firestore_pipelines.booleanexpression.md b/docs-devsite/firestore_pipelines.booleanexpression.md index b4855ea111..4717d34e96 100644 --- a/docs-devsite/firestore_pipelines.booleanexpression.md +++ b/docs-devsite/firestore_pipelines.booleanexpression.md @@ -26,57 +26,13 @@ export declare abstract class BooleanExpression extends Expression | Method | Modifiers | Description | | --- | --- | --- | -| [conditional(thenExpr, elseExpr)](./firestore_pipelines.booleanexpression.md#booleanexpressionconditional) | | (Public Preview) Creates a conditional expression that evaluates to the 'then' expression if this expression evaluates to true, or evaluates to the 'else' expression if this expressions evaluates false. -```typescript -// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". -field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor")); - -``` - | -| [countIf()](./firestore_pipelines.booleanexpression.md#booleanexpressioncountif) | | (Public Preview) Creates an aggregation that finds the count of input documents satisfying this boolean expression. -```typescript -// Find the count of documents with a score greater than 90 -field("score").greaterThan(90).countIf().as("highestScore"); - -``` - A new AggregateFunction representing the 'countIf' aggregation. | -| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. -```typescript -// Create an expression that protects against a divide by zero error -// but always returns a boolean expression. -constant(50).divide('length').gt(1).ifError(constant(false)); - -``` - | -| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. -```typescript -// Create an expression that protects against a divide by zero error -// but always returns a boolean expression. -constant(50).divide('length').gt(1).ifError(false); - -``` - | -| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. -```typescript -// Create an expression that protects against a divide by zero error. -constant(50).divide('length').gt(1).ifError(constant(0)); - -``` - | -| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. -```typescript -// Create an expression that protects against a divide by zero error. -constant(50).divide('length').gt(1).ifError(0); - -``` - | -| [not()](./firestore_pipelines.booleanexpression.md#booleanexpressionnot) | | (Public Preview) Creates an expression that negates this boolean expression. -```typescript -// Find documents where the 'tags' field does not contain 'completed' -field("tags").arrayContains("completed").not(); - -``` - A new representing the negated filter condition. | +| [conditional(thenExpr, elseExpr)](./firestore_pipelines.booleanexpression.md#booleanexpressionconditional) | | (Public Preview) Creates a conditional expression that evaluates to the 'then' expression if this expression evaluates to true, or evaluates to the 'else' expression if this expressions evaluates false. | +| [countIf()](./firestore_pipelines.booleanexpression.md#booleanexpressioncountif) | | (Public Preview) Creates an aggregation that finds the count of input documents satisfying this boolean expression. | +| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [not()](./firestore_pipelines.booleanexpression.md#booleanexpressionnot) | | (Public Preview) Creates an expression that negates this boolean expression. | ## BooleanExpression.conditional() @@ -85,12 +41,6 @@ field("tags").arrayContains("completed").not(); Creates a conditional expression that evaluates to the 'then' expression if `this` expression evaluates to `true`, or evaluates to the 'else' expression if `this` expressions evaluates `false`. -```typescript -// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". -field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor")); - -``` - Signature: ```typescript @@ -102,25 +52,29 @@ conditional(thenExpr: Expression, elseExpr: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | | thenExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is true. | -| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. A new representing the conditional expression. | +| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## BooleanExpression.countIf() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the conditional expression. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that finds the count of input documents satisfying this boolean expression. ```typescript -// Find the count of documents with a score greater than 90 -field("score").greaterThan(90).countIf().as("highestScore"); +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor")); ``` - A new `AggregateFunction` representing the 'countIf' aggregation. + +## BooleanExpression.countIf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the count of input documents satisfying this boolean expression. Signature: @@ -131,20 +85,24 @@ countIf(): AggregateFunction; [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -## BooleanExpression.ifError() +A new `AggregateFunction` representing the 'countIf' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. ```typescript -// Create an expression that protects against a divide by zero error -// but always returns a boolean expression. -constant(50).divide('length').gt(1).ifError(constant(false)); +// Find the count of documents with a score greater than 90 +field("score").greaterThan(90).countIf().as("highestScore"); ``` +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + Signature: ```typescript @@ -155,26 +113,31 @@ ifError(catchValue: BooleanExpression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| catchValue | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | +| catchValue | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The value that will be returned if this expression produces an error. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## BooleanExpression.ifError() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. ```typescript // Create an expression that protects against a divide by zero error // but always returns a boolean expression. -constant(50).divide('length').gt(1).ifError(false); +constant(50).divide('length').gt(1).ifError(constant(false)); ``` +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + Signature: ```typescript @@ -185,25 +148,31 @@ ifError(catchValue: boolean): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| catchValue | boolean | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | +| catchValue | boolean | The value that will be returned if this expression produces an error. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## BooleanExpression.ifError() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. ```typescript -// Create an expression that protects against a divide by zero error. -constant(50).divide('length').gt(1).ifError(constant(0)); +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +constant(50).divide('length').gt(1).ifError(false); ``` +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + Signature: ```typescript @@ -214,25 +183,30 @@ ifError(catchValue: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| catchValue | [Expression](./firestore_pipelines.expression.md#expression_class) | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | +| catchValue | [Expression](./firestore_pipelines.expression.md#expression_class) | The value that will be returned if this expression produces an error. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## BooleanExpression.ifError() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. ```typescript // Create an expression that protects against a divide by zero error. -constant(50).divide('length').gt(1).ifError(0); +constant(50).divide('length').gt(1).ifError(constant(0)); ``` +## BooleanExpression.ifError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. + Signature: ```typescript @@ -243,25 +217,29 @@ ifError(catchValue: unknown): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| catchValue | unknown | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | +| catchValue | unknown | The value that will be returned if this expression produces an error. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## BooleanExpression.not() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that negates this boolean expression. ```typescript -// Find documents where the 'tags' field does not contain 'completed' -field("tags").arrayContains("completed").not(); +// Create an expression that protects against a divide by zero error. +constant(50).divide('length').gt(1).ifError(0); ``` - A new representing the negated filter condition. + +## BooleanExpression.not() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that negates this boolean expression. Signature: @@ -272,3 +250,14 @@ not(): BooleanExpression; [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the negated filter condition. + +### Example + + +```typescript +// Find documents where the 'tags' field does not contain 'completed' +field("tags").arrayContains("completed").not(); + +``` + diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index c082bbfd5f..5c74487ae5 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -13,13 +13,13 @@ https://github.com/firebase/firebase-js-sdk > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Represents an expression that can be evaluated to a value within the execution of a . +Represents an expression that can be evaluated to a value within the execution of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class). 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 `Expr` class provides a fluent API for building expressions. You can chain together method calls to create complex expressions. +The `Expression` class provides a fluent API for building expressions. You can chain together method calls to create complex expressions. Signature: @@ -37,821 +37,134 @@ export declare abstract class Expression | Method | Modifiers | Description | | --- | --- | --- | -| [abs()](./firestore_pipelines.expression.md#expressionabs) | | (Public Preview) Creates an expression that computes the absolute value of a numeric value. -```typescript -// Compute the absolute value of the 'price' field. -field("price").abs(); - -``` - A new representing the absolute value of the numeric value. | -| [add(second)](./firestore_pipelines.expression.md#expressionadd) | | (Public Preview) Creates an expression that adds this expression to another expression. -```typescript -// Add the value of the 'quantity' field and the 'reserve' field. -field("quantity").add(field("reserve")); - -``` - | -| [arrayConcat(secondArray, otherArrays)](./firestore_pipelines.expression.md#expressionarrayconcat) | | (Public Preview) Creates an expression that concatenates an array expression with one or more other arrays. -```typescript -// Combine the 'items' array with another array field. -field("items").arrayConcat(field("otherItems")); - -``` - | -| [arrayContains(expression)](./firestore_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific element. -```typescript -// Check if the 'sizes' array contains the value from the 'selectedSize' field -field("sizes").arrayContains(field("selectedSize")); - -``` - | -| [arrayContains(value)](./firestore_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific value. -```typescript -// Check if the 'colors' array contains "red" -field("colors").arrayContains("red"); - -``` - | -| [arrayContainsAll(values)](./firestore_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. -```typescript -// Check if the 'tags' array contains both the value in field "tag1" and the literal value "tag2" -field("tags").arrayContainsAll([field("tag1"), "tag2"]); - -``` - | -| [arrayContainsAll(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. -```typescript -// Check if the 'tags' array contains both of the values from field "tag1" and the literal value "tag2" -field("tags").arrayContainsAll(array([field("tag1"), "tag2"])); - -``` - | -| [arrayContainsAny(values)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. -```typescript -// Check if the 'categories' array contains either values from field "cate1" or "cate2" -field("categories").arrayContainsAny([field("cate1"), field("cate2")]); - -``` - | -| [arrayContainsAny(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. -```typescript -// Check if the 'groups' array contains either the value from the 'userGroup' field -// or the value "guest" -field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); - -``` - | -| [arrayGet(offset)](./firestore_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the 'tags' field array at index `1`. -field('tags').arrayGet(1); - -``` - | -| [arrayGet(offsetExpr)](./firestore_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -field('tags').arrayGet(field('favoriteTag')); - -``` - | -| [arrayLength()](./firestore_pipelines.expression.md#expressionarraylength) | | (Public Preview) Creates an expression that calculates the length of an array. -```typescript -// Get the number of items in the 'cart' array -field("cart").arrayLength(); - -``` - A new Expr representing the length of the array. | -| [arrayReverse()](./firestore_pipelines.expression.md#expressionarrayreverse) | | (Public Preview) Creates an expression that reverses an array. -```typescript -// Reverse the value of the 'myArray' field. -field("myArray").arrayReverse(); - -``` - A new representing the reversed array. | -| [arraySum()](./firestore_pipelines.expression.md#expressionarraysum) | | (Public Preview) Creates an expression that computes the sum of the elements in an array. -```typescript -// Compute the sum of the elements in the 'scores' field. -field("scores").arraySum(); - -``` - A new representing the sum of the elements in the array. | -| [as(name)](./firestore_pipelines.expression.md#expressionas) | | (Public Preview) 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. -```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")); - -``` - | -| [asBoolean()](./firestore_pipelines.expression.md#expressionasboolean) | | (Public Preview) Wraps the expression in a \[BooleanExpression\]. A \[BooleanExpression\] representing the same expression. | -| [ascending()](./firestore_pipelines.expression.md#expressionascending) | | (Public Preview) Creates an that sorts documents in ascending order based on this expression. -```typescript -// Sort documents by the 'name' field in ascending order -pipeline().collection("users") - .sort(field("name").ascending()); - -``` - A new Ordering for ascending sorting. | -| [average()](./firestore_pipelines.expression.md#expressionaverage) | | (Public Preview) Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. -```typescript -// Calculate the average age of users -field("age").average().as("averageAge"); - -``` - A new AggregateFunction representing the 'average' aggregation. | -| [byteLength()](./firestore_pipelines.expression.md#expressionbytelength) | | (Public Preview) Creates an expression that calculates the length of this string expression in bytes. -```typescript -// Calculate the length of the 'myString' field in bytes. -field("myString").byteLength(); - -``` - A new representing the length of the string in bytes. | -| [ceil()](./firestore_pipelines.expression.md#expressionceil) | | (Public Preview) Creates an expression that computes the ceiling of a numeric value. -```typescript -// Compute the ceiling of the 'price' field. -field("price").ceil(); - -``` - A new representing the ceiling of the numeric value. | -| [charLength()](./firestore_pipelines.expression.md#expressioncharlength) | | (Public Preview) Creates an expression that calculates the character length of a string in UTF-8. -```typescript -// Get the character length of the 'name' field in its UTF-8 form. -field("name").charLength(); - -``` - A new Expr representing the length of the string. | -| [collectionId()](./firestore_pipelines.expression.md#expressioncollectionid) | | (Public Preview) Creates an expression that returns the collection ID from a path. -```typescript -// Get the collection ID from a path. -field("__path__").collectionId(); - -``` - A new representing the collectionId operation. | -| [concat(second, others)](./firestore_pipelines.expression.md#expressionconcat) | | (Public Preview) Creates an expression that concatenates expression results together. -```typescript -// Combine the 'firstName', ' ', and 'lastName' fields into a single value. -field("firstName").concat(constant(" "), field("lastName")); - -``` - | -| [cosineDistance(vectorExpression)](./firestore_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the cosine distance between two vectors. -```typescript -// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field -field("userVector").cosineDistance(field("itemVector")); - -``` - | -| [cosineDistance(vector)](./firestore_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the Cosine distance between two vectors. -```typescript -// Calculate the Cosine distance between the 'location' field and a target location -field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); - -``` - | -| [count()](./firestore_pipelines.expression.md#expressioncount) | | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. -```typescript -// Count the total number of products -field("productId").count().as("totalProducts"); - -``` - A new AggregateFunction representing the 'count' aggregation. | -| [countDistinct()](./firestore_pipelines.expression.md#expressioncountdistinct) | | (Public Preview) Creates an aggregation that counts the number of distinct values of the expression or field. -```typescript -// Count the distinct number of products -field("productId").countDistinct().as("distinctProducts"); - -``` - A new AggregateFunction representing the 'count\_distinct' aggregation. | -| [descending()](./firestore_pipelines.expression.md#expressiondescending) | | (Public Preview) Creates an that sorts documents in descending order based on this expression. -```typescript -// Sort documents by the 'createdAt' field in descending order -firestore.pipeline().collection("users") - .sort(field("createdAt").descending()); - -``` - A new Ordering for descending sorting. | -| [divide(divisor)](./firestore_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by another expression. -```typescript -// Divide the 'total' field by the 'count' field -field("total").divide(field("count")); - -``` - | -| [divide(divisor)](./firestore_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by a constant value. -```typescript -// Divide the 'value' field by 10 -field("value").divide(10); - -``` - | -| [documentId()](./firestore_pipelines.expression.md#expressiondocumentid) | | (Public Preview) Creates an expression that returns the document ID from a path. -```typescript -// Get the document ID from a path. -field("__path__").documentId(); - -``` - A new representing the documentId operation. | -| [dotProduct(vectorExpression)](./firestore_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. -```typescript -// Calculate the dot product between a feature vector and a target vector -field("features").dotProduct([0.5, 0.8, 0.2]); - -``` - | -| [dotProduct(vector)](./firestore_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. -```typescript -// Calculate the dot product between a feature vector and a target vector -field("features").dotProduct(new VectorValue([0.5, 0.8, 0.2])); - -``` - | -| [endsWith(suffix)](./firestore_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix. -```typescript -// Check if the 'filename' field ends with ".txt" -field("filename").endsWith(".txt"); - -``` - | -| [endsWith(suffix)](./firestore_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix (represented as an expression). -```typescript -// Check if the 'url' field ends with the value of the 'extension' field -field("url").endsWith(field("extension")); - -``` - | -| [equal(expression)](./firestore_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to another expression. -```typescript -// Check if the 'age' field is equal to 21 -field("age").equal(21); - -``` - | -| [equal(value)](./firestore_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to a constant value. -```typescript -// Check if the 'city' field is equal to "London" -field("city").equal("London"); - -``` - | -| [equalAny(values)](./firestore_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. -```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -field("category").equalAny("Electronics", field("primaryType")); - -``` - | -| [equalAny(arrayExpression)](./firestore_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. -```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -field("category").equalAny(array(["Electronics", field("primaryType")])); - -``` - | -| [euclideanDistance(vectorExpression)](./firestore_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. -```typescript -// Calculate the Euclidean distance between the 'location' field and a target location -field("location").euclideanDistance([37.7749, -122.4194]); - -``` - | -| [euclideanDistance(vector)](./firestore_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. -```typescript -// Calculate the Euclidean distance between the 'location' field and a target location -field("location").euclideanDistance(new VectorValue([37.7749, -122.4194])); - -``` - | -| [exists()](./firestore_pipelines.expression.md#expressionexists) | | (Public Preview) Creates an expression that checks if a field exists in the document. -```typescript -// Check if the document has a field named "phoneNumber" -field("phoneNumber").exists(); - -``` - A new Expr representing the 'exists' check. | -| [exp()](./firestore_pipelines.expression.md#expressionexp) | | (Public Preview) Creates an expression that computes e to the power of this expression. -```typescript -// Compute e to the power of the 'value' field. -field("value").exp(); - -``` - A new representing the exp of the numeric value. | -| [floor()](./firestore_pipelines.expression.md#expressionfloor) | | (Public Preview) Creates an expression that computes the floor of a numeric value. -```typescript -// Compute the floor of the 'price' field. -field("price").floor(); - -``` - A new representing the floor of the numeric value. | -| [greaterThan(expression)](./firestore_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than another expression. -```typescript -// Check if the 'age' field is greater than the 'limit' field -field("age").greaterThan(field("limit")); - -``` - | -| [greaterThan(value)](./firestore_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than a constant value. -```typescript -// Check if the 'price' field is greater than 100 -field("price").greaterThan(100); - -``` - | -| [greaterThanOrEqual(expression)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to another expression. -```typescript -// Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1 -field("quantity").greaterThanOrEqual(field('requirement').add(1)); - -``` - | -| [greaterThanOrEqual(value)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to a constant value. -```typescript -// Check if the 'score' field is greater than or equal to 80 -field("score").greaterThanOrEqual(80); - -``` - | -| [ifAbsent(elseValue)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of the this expression evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -field("optional_field").ifAbsent("default_value") - -``` - | -| [ifAbsent(elseExpression)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or if that is -// absent, then returns the value of the field ` -field("optional_field").ifAbsent(field('default_field')) - -``` - | -| [ifError(catchExpr)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. -```typescript -// Returns the first item in the title field arrays, or returns -// the entire title field if the array is empty or the field is another type. -field("title").arrayGet(0).ifError(field("title")); - -``` - | -| [ifError(catchValue)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. -```typescript -// Returns the first item in the title field arrays, or returns -// "Default Title" -field("title").arrayGet(0).ifError("Default Title"); - -``` - | -| [isAbsent()](./firestore_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. -```typescript -// Check if the field `value` is absent. -field("value").isAbsent(); - -``` - A new representing the 'isAbsent' check. | -| [isError()](./firestore_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. -```typescript -// Check if the result of a calculation is an error -field("title").arrayContains(1).isError(); - -``` - A new representing the 'isError' check. | -| [join(delimiterExpression)](./firestore_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array into a string. -```typescript -// Join the elements of the 'tags' field with the delimiter from the 'separator' field. -field("tags").join(field("separator")) - -``` - | -| [join(delimiter)](./firestore_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array field into a string. -```typescript -// Join the elements of the 'tags' field with a comma and space. -field("tags").join(", ") - -``` - | -| [length()](./firestore_pipelines.expression.md#expressionlength) | | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. -```typescript -// Get the length of the 'name' field. -field("name").length(); - -// Get the number of items in the 'cart' array. -field("cart").length(); - -``` - A new Expr representing the length of the string, array, map, vector, or bytes. | -| [lessThan(experession)](./firestore_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than another expression. -```typescript -// Check if the 'age' field is less than 'limit' -field("age").lessThan(field('limit')); - -``` - | -| [lessThan(value)](./firestore_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than a constant value. -```typescript -// Check if the 'price' field is less than 50 -field("price").lessThan(50); - -``` - | -| [lessThanOrEqual(expression)](./firestore_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to another expression. -```typescript -// Check if the 'quantity' field is less than or equal to 20 -field("quantity").lessThan(constant(20)); - -``` - | -| [lessThanOrEqual(value)](./firestore_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to a constant value. -```typescript -// Check if the 'score' field is less than or equal to 70 -field("score").lessThan(70); - -``` - | -| [like(pattern)](./firestore_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. -```typescript -// Check if the 'title' field contains the word "guide" (case-sensitive) -field("title").like("%guide%"); - -``` - | -| [like(pattern)](./firestore_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. -```typescript -// Check if the 'title' field contains the word "guide" (case-sensitive) -field("title").like("%guide%"); - -``` - | -| [ln()](./firestore_pipelines.expression.md#expressionln) | | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. -```typescript -// Compute the natural logarithm of the 'value' field. -field("value").ln(); - -``` - A new representing the natural logarithm of the numeric value. | -| [log10()](./firestore_pipelines.expression.md#expressionlog10) | | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. -```typescript -// Compute the base-10 logarithm of the 'value' field. -field("value").log10(); - -``` - A new representing the base-10 logarithm of the numeric value. | -| [logicalMaximum(second, others)](./firestore_pipelines.expression.md#expressionlogicalmaximum) | | (Public Preview) Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. -```typescript -// Returns the larger value between the 'timestamp' field and the current timestamp. -field("timestamp").logicalMaximum(Function.currentTimestamp()); - -``` - | -| [logicalMinimum(second, others)](./firestore_pipelines.expression.md#expressionlogicalminimum) | | (Public Preview) Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. -```typescript -// Returns the smaller value between the 'timestamp' field and the current timestamp. -field("timestamp").logicalMinimum(Function.currentTimestamp()); - -``` - | -| [mapGet(subfield)](./firestore_pipelines.expression.md#expressionmapget) | | (Public Preview) Accesses a value from a map (object) field using the provided key. -```typescript -// Get the 'city' value from the 'address' map field -field("address").mapGet("city"); - -``` - | -| [mapMerge(secondMap, otherMaps)](./firestore_pipelines.expression.md#expressionmapmerge) | | (Public Preview) Creates an expression that merges multiple map values. -``` -// 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}, {}) - -``` - | -| [mapRemove(key)](./firestore_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. -``` -// Removes the key 'baz' from the input map. -map({foo: 'bar', baz: true}).mapRemove('baz'); - -``` - | -| [mapRemove(keyExpr)](./firestore_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. -``` -// Removes the key 'baz' from the input map. -map({foo: 'bar', baz: true}).mapRemove(constant('baz')); - -``` - | -| [maximum()](./firestore_pipelines.expression.md#expressionmaximum) | | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. -```typescript -// Find the highest score in a leaderboard -field("score").maximum().as("highestScore"); - -``` - A new AggregateFunction representing the 'maximum' aggregation. | -| [minimum()](./firestore_pipelines.expression.md#expressionminimum) | | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. -```typescript -// Find the lowest price of all products -field("price").minimum().as("lowestPrice"); - -``` - A new AggregateFunction representing the 'minimum' aggregation. | -| [mod(expression)](./firestore_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. -```typescript -// Calculate the remainder of dividing the 'value' field by the 'divisor' field -field("value").mod(field("divisor")); - -``` - | -| [mod(value)](./firestore_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. -```typescript -// Calculate the remainder of dividing the 'value' field by 10 -field("value").mod(10); - -``` - | -| [multiply(second)](./firestore_pipelines.expression.md#expressionmultiply) | | (Public Preview) Creates an expression that multiplies this expression by another expression. -```typescript -// Multiply the 'quantity' field by the 'price' field -field("quantity").multiply(field("price")); - -``` - | -| [notEqual(expression)](./firestore_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to another expression. -```typescript -// Check if the 'status' field is not equal to "completed" -field("status").notEqual("completed"); - -``` - | -| [notEqual(value)](./firestore_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to a constant value. -```typescript -// Check if the 'country' field is not equal to "USA" -field("country").notEqual("USA"); - -``` - | -| [notEqualAny(values)](./firestore_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the provided values or expressions. -```typescript -// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' -field("status").notEqualAny(["pending", field("rejectedStatus")]); - -``` - | -| [notEqualAny(arrayExpression)](./firestore_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. -```typescript -// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' -field("status").notEqualAny(field('rejectedStatuses')); - -``` - | -| [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of another expression. -```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -field("base").pow(field("exponent")); - -``` - | -| [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of a constant value. -```typescript -// Raise the value of the 'base' field to the power of 2. -field("base").pow(2); - -``` - | -| [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. -```typescript -// Check if the 'description' field contains "example" (case-insensitive) -field("description").regexContains("(?i)example"); - -``` - | -| [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. -```typescript -// Check if the 'description' field contains the regular expression stored in field 'regex' -field("description").regexContains(field("regex")); - -``` - | -| [regexMatch(pattern)](./firestore_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. -```typescript -// Check if the 'email' field matches a valid email pattern -field("email").regexMatch("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); - -``` - | -| [regexMatch(pattern)](./firestore_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. -```typescript -// Check if the 'email' field matches a regular expression stored in field 'regex' -field("email").regexMatch(field("regex")); - -``` - | -| [reverse()](./firestore_pipelines.expression.md#expressionreverse) | | (Public Preview) Creates an expression that reverses this string expression. -```typescript -// Reverse the value of the 'myString' field. -field("myString").reverse(); - -``` - A new representing the reversed string. | -| [round()](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. -```typescript -// Round the value of the 'price' field. -field("price").round(); - -``` - A new Expr representing the rounded value. | -| [round(decimalPlaces)](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. -```typescript -// Round the value of the 'price' field to two decimal places. -field("price").round(2); - -``` - | -| [round(decimalPlaces)](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. +| [abs()](./firestore_pipelines.expression.md#expressionabs) | | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | +| [add(second)](./firestore_pipelines.expression.md#expressionadd) | | (Public Preview) Creates an expression that adds this expression to another expression. | +| [arrayConcat(secondArray, otherArrays)](./firestore_pipelines.expression.md#expressionarrayconcat) | | (Public Preview) Creates an expression that concatenates an array expression with one or more other arrays. | +| [arrayContains(expression)](./firestore_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific element. | +| [arrayContains(value)](./firestore_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific value. | +| [arrayContainsAll(values)](./firestore_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. | +| [arrayContainsAll(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. | +| [arrayContainsAny(values)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. | +| [arrayContainsAny(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. | +| [arrayGet(offset)](./firestore_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(offsetExpr)](./firestore_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayLength()](./firestore_pipelines.expression.md#expressionarraylength) | | (Public Preview) Creates an expression that calculates the length of an array. | +| [arrayReverse()](./firestore_pipelines.expression.md#expressionarrayreverse) | | (Public Preview) Creates an expression that reverses an array. | +| [arraySum()](./firestore_pipelines.expression.md#expressionarraysum) | | (Public Preview) Creates an expression that computes the sum of the elements in an array. | +| [as(name)](./firestore_pipelines.expression.md#expressionas) | | (Public Preview) 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. | +| [asBoolean()](./firestore_pipelines.expression.md#expressionasboolean) | | (Public Preview) Wraps the expression in a \[BooleanExpression\]. | +| [ascending()](./firestore_pipelines.expression.md#expressionascending) | | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on this expression. | +| [average()](./firestore_pipelines.expression.md#expressionaverage) | | (Public Preview) Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. | +| [byteLength()](./firestore_pipelines.expression.md#expressionbytelength) | | (Public Preview) Creates an expression that calculates the length of this string expression in bytes. | +| [ceil()](./firestore_pipelines.expression.md#expressionceil) | | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | +| [charLength()](./firestore_pipelines.expression.md#expressioncharlength) | | (Public Preview) Creates an expression that calculates the character length of a string in UTF-8. | +| [collectionId()](./firestore_pipelines.expression.md#expressioncollectionid) | | (Public Preview) Creates an expression that returns the collection ID from a path. | +| [concat(second, others)](./firestore_pipelines.expression.md#expressionconcat) | | (Public Preview) Creates an expression that concatenates expression results together. | +| [cosineDistance(vectorExpression)](./firestore_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the cosine distance between two vectors. | +| [cosineDistance(vector)](./firestore_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the Cosine distance between two vectors. | +| [count()](./firestore_pipelines.expression.md#expressioncount) | | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. | +| [countDistinct()](./firestore_pipelines.expression.md#expressioncountdistinct) | | (Public Preview) Creates an aggregation that counts the number of distinct values of the expression or field. | +| [descending()](./firestore_pipelines.expression.md#expressiondescending) | | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on this expression. | +| [divide(divisor)](./firestore_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by another expression. | +| [divide(divisor)](./firestore_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by a constant value. | +| [documentId()](./firestore_pipelines.expression.md#expressiondocumentid) | | (Public Preview) Creates an expression that returns the document ID from a path. | +| [dotProduct(vectorExpression)](./firestore_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. | +| [dotProduct(vector)](./firestore_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. | +| [endsWith(suffix)](./firestore_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix. | +| [endsWith(suffix)](./firestore_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix (represented as an expression). | +| [equal(expression)](./firestore_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to another expression. | +| [equal(value)](./firestore_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to a constant value. | +| [equalAny(values)](./firestore_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. | +| [equalAny(arrayExpression)](./firestore_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. | +| [euclideanDistance(vectorExpression)](./firestore_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. | +| [euclideanDistance(vector)](./firestore_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. | +| [exists()](./firestore_pipelines.expression.md#expressionexists) | | (Public Preview) Creates an expression that checks if a field exists in the document. | +| [exp()](./firestore_pipelines.expression.md#expressionexp) | | (Public Preview) Creates an expression that computes e to the power of this expression. | +| [floor()](./firestore_pipelines.expression.md#expressionfloor) | | (Public Preview) Creates an expression that computes the floor of a numeric value. | +| [greaterThan(expression)](./firestore_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than another expression. | +| [greaterThan(value)](./firestore_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than a constant value. | +| [greaterThanOrEqual(expression)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to another expression. | +| [greaterThanOrEqual(value)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to a constant value. | +| [ifAbsent(elseValue)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of the this expression evaluation. | +| [ifAbsent(elseExpression)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. ```typescript -// Round the value of the 'price' field to two decimal places. -field("price").round(constant(2)); +// Returns the value of the optional field 'optional_field', or if that is +// absent, then returns the value of the field ` +field("optional_field").ifAbsent(field('default_field')) ``` | +| [ifError(catchExpr)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [isAbsent()](./firestore_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. | +| [isError()](./firestore_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. | +| [join(delimiterExpression)](./firestore_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array into a string. | +| [join(delimiter)](./firestore_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array field into a string. | +| [length()](./firestore_pipelines.expression.md#expressionlength) | | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | +| [lessThan(experession)](./firestore_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than another expression. | +| [lessThan(value)](./firestore_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than a constant value. | +| [lessThanOrEqual(expression)](./firestore_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to another expression. | +| [lessThanOrEqual(value)](./firestore_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to a constant value. | +| [like(pattern)](./firestore_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. | +| [like(pattern)](./firestore_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. | +| [ln()](./firestore_pipelines.expression.md#expressionln) | | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. | +| [log10()](./firestore_pipelines.expression.md#expressionlog10) | | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | +| [logicalMaximum(second, others)](./firestore_pipelines.expression.md#expressionlogicalmaximum) | | (Public Preview) Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. | +| [logicalMinimum(second, others)](./firestore_pipelines.expression.md#expressionlogicalminimum) | | (Public Preview) Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. | +| [mapGet(subfield)](./firestore_pipelines.expression.md#expressionmapget) | | (Public Preview) Accesses a value from a map (object) field using the provided key. | +| [mapMerge(secondMap, otherMaps)](./firestore_pipelines.expression.md#expressionmapmerge) | | (Public Preview) Creates an expression that merges multiple map values. | +| [mapRemove(key)](./firestore_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | +| [mapRemove(keyExpr)](./firestore_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | +| [maximum()](./firestore_pipelines.expression.md#expressionmaximum) | | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | +| [minimum()](./firestore_pipelines.expression.md#expressionminimum) | | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | +| [mod(expression)](./firestore_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. | +| [mod(value)](./firestore_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. | +| [multiply(second)](./firestore_pipelines.expression.md#expressionmultiply) | | (Public Preview) Creates an expression that multiplies this expression by another expression. | +| [notEqual(expression)](./firestore_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to another expression. | +| [notEqual(value)](./firestore_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to a constant value. | +| [notEqualAny(values)](./firestore_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the provided values or expressions. | +| [notEqualAny(arrayExpression)](./firestore_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. | +| [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of another expression. | +| [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of a constant value. | +| [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. | +| [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. | +| [regexMatch(pattern)](./firestore_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. | +| [regexMatch(pattern)](./firestore_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. | +| [reverse()](./firestore_pipelines.expression.md#expressionreverse) | | (Public Preview) Creates an expression that reverses this string expression. | +| [round()](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | +| [round(decimalPlaces)](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [round(decimalPlaces)](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | | [split(delimiter)](./firestore_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | | [split(delimiter)](./firestore_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | -| [sqrt()](./firestore_pipelines.expression.md#expressionsqrt) | | (Public Preview) Creates an expression that computes the square root of a numeric value. -```typescript -// Compute the square root of the 'value' field. -field("value").sqrt(); - -``` - A new representing the square root of the numeric value. | -| [startsWith(prefix)](./firestore_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix. -```typescript -// Check if the 'name' field starts with "Mr." -field("name").startsWith("Mr."); - -``` - | -| [startsWith(prefix)](./firestore_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix (represented as an expression). -```typescript -// Check if the 'fullName' field starts with the value of the 'firstName' field -field("fullName").startsWith(field("firstName")); - -``` - | -| [stringConcat(secondString, otherStrings)](./firestore_pipelines.expression.md#expressionstringconcat) | | (Public Preview) Creates an expression that concatenates string expressions together. -```typescript -// Combine the 'firstName', " ", and 'lastName' fields into a single string -field("firstName").stringConcat(constant(" "), field("lastName")); - -``` - | -| [stringContains(substring)](./firestore_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified substring. -```typescript -// Check if the 'description' field contains "example". -field("description").stringContains("example"); - -``` - | -| [stringContains(expr)](./firestore_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains the string represented by another expression. -```typescript -// Check if the 'description' field contains the value of the 'keyword' field. -field("description").stringContains(field("keyword")); - -``` - | -| [stringReverse()](./firestore_pipelines.expression.md#expressionstringreverse) | | (Public Preview) Creates an expression that reverses a string. -```typescript -// Reverse the value of the 'myString' field. -field("myString").stringReverse(); - -``` - A new representing the reversed string. | +| [sqrt()](./firestore_pipelines.expression.md#expressionsqrt) | | (Public Preview) Creates an expression that computes the square root of a numeric value. | +| [startsWith(prefix)](./firestore_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix. | +| [startsWith(prefix)](./firestore_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix (represented as an expression). | +| [stringConcat(secondString, otherStrings)](./firestore_pipelines.expression.md#expressionstringconcat) | | (Public Preview) Creates an expression that concatenates string expressions together. | +| [stringContains(substring)](./firestore_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified substring. | +| [stringContains(expr)](./firestore_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains the string represented by another expression. | +| [stringReverse()](./firestore_pipelines.expression.md#expressionstringreverse) | | (Public Preview) Creates an expression that reverses a string. | | [substring(position, length)](./firestore_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | | [substring(position, length)](./firestore_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | -| [subtract(subtrahend)](./firestore_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts another expression from this expression. -```typescript -// Subtract the 'discount' field from the 'price' field -field("price").subtract(field("discount")); - -``` - | -| [subtract(subtrahend)](./firestore_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts a constant value from this expression. -```typescript -// Subtract 20 from the value of the 'total' field -field("total").subtract(20); - -``` - | -| [sum()](./firestore_pipelines.expression.md#expressionsum) | | (Public Preview) Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. -```typescript -// Calculate the total revenue from a set of orders -field("orderAmount").sum().as("totalRevenue"); - -``` - A new AggregateFunction representing the 'sum' aggregation. | -| [timestampAdd(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. -```typescript -// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. -field("timestamp").timestampAdd(field("unit"), field("amount")); - -``` - | -| [timestampAdd(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. -```typescript -// Add 1 day to the 'timestamp' field. -field("timestamp").timestampAdd("day", 1); - -``` - | -| [timestampSubtract(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. -```typescript -// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. -field("timestamp").timestampSubtract(field("unit"), field("amount")); - -``` - | -| [timestampSubtract(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. -```typescript -// Subtract 1 day from the 'timestamp' field. -field("timestamp").timestampSubtract("day", 1); - -``` - | -| [timestampToUnixMicros()](./firestore_pipelines.expression.md#expressiontimestamptounixmicros) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to microseconds since epoch. -field("timestamp").timestampToUnixMicros(); - -``` - A new representing the number of microseconds since epoch. | -| [timestampToUnixMillis()](./firestore_pipelines.expression.md#expressiontimestamptounixmillis) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -field("timestamp").timestampToUnixMillis(); - -``` - A new representing the number of milliseconds since epoch. | -| [timestampToUnixSeconds()](./firestore_pipelines.expression.md#expressiontimestamptounixseconds) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to seconds since epoch. -field("timestamp").timestampToUnixSeconds(); - -``` - A new representing the number of seconds since epoch. | +| [subtract(subtrahend)](./firestore_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts another expression from this expression. | +| [subtract(subtrahend)](./firestore_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts a constant value from this expression. | +| [sum()](./firestore_pipelines.expression.md#expressionsum) | | (Public Preview) Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. | +| [timestampAdd(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. | +| [timestampAdd(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. | +| [timestampSubtract(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. | +| [timestampSubtract(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. | +| [timestampToUnixMicros()](./firestore_pipelines.expression.md#expressiontimestamptounixmicros) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixMillis()](./firestore_pipelines.expression.md#expressiontimestamptounixmillis) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixSeconds()](./firestore_pipelines.expression.md#expressiontimestamptounixseconds) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | | [timestampTruncate(granularity, timezone)](./firestore_pipelines.expression.md#expressiontimestamptruncate) | | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | | [timestampTruncate(granularity, timezone)](./firestore_pipelines.expression.md#expressiontimestamptruncate) | | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [toLower()](./firestore_pipelines.expression.md#expressiontolower) | | (Public Preview) Creates an expression that converts a string to lowercase. -```typescript -// Convert the 'name' field to lowercase -field("name").toLower(); - -``` - A new Expr representing the lowercase string. | -| [toUpper()](./firestore_pipelines.expression.md#expressiontoupper) | | (Public Preview) Creates an expression that converts a string to uppercase. -```typescript -// Convert the 'title' field to uppercase -field("title").toUpper(); - -``` - A new Expr representing the uppercase string. | -| [trim(valueToTrim)](./firestore_pipelines.expression.md#expressiontrim) | | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array. -```typescript -// Trim whitespace from the 'userInput' field -field("userInput").trim(); - -// Trim quotes from the 'userInput' field -field("userInput").trim('"'); - -``` - | +| [toLower()](./firestore_pipelines.expression.md#expressiontolower) | | (Public Preview) Creates an expression that converts a string to lowercase. | +| [toUpper()](./firestore_pipelines.expression.md#expressiontoupper) | | (Public Preview) Creates an expression that converts a string to uppercase. | +| [trim(valueToTrim)](./firestore_pipelines.expression.md#expressiontrim) | | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array. | | [type()](./firestore_pipelines.expression.md#expressiontype) | | (Public Preview) Creates an expression that returns the data type of this expression's result, as a string. | -| [unixMicrosToTimestamp()](./firestore_pipelines.expression.md#expressionunixmicrostotimestamp) | | (Public Preview) 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. -```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -field("microseconds").unixMicrosToTimestamp(); - -``` - A new representing the timestamp. | -| [unixMillisToTimestamp()](./firestore_pipelines.expression.md#expressionunixmillistotimestamp) | | (Public Preview) 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. -```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -field("milliseconds").unixMillisToTimestamp(); - -``` - A new representing the timestamp. | -| [unixSecondsToTimestamp()](./firestore_pipelines.expression.md#expressionunixsecondstotimestamp) | | (Public Preview) 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. -```typescript -// Interpret the 'seconds' field as seconds since epoch. -field("seconds").unixSecondsToTimestamp(); - -``` - A new representing the timestamp. | -| [vectorLength()](./firestore_pipelines.expression.md#expressionvectorlength) | | (Public Preview) Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. -```typescript -// Get the vector length (dimension) of the field 'embedding'. -field("embedding").vectorLength(); - -``` - A new representing the length of the vector. | +| [unixMicrosToTimestamp()](./firestore_pipelines.expression.md#expressionunixmicrostotimestamp) | | (Public Preview) 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. | +| [unixMillisToTimestamp()](./firestore_pipelines.expression.md#expressionunixmillistotimestamp) | | (Public Preview) 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. | +| [unixSecondsToTimestamp()](./firestore_pipelines.expression.md#expressionunixsecondstotimestamp) | | (Public Preview) 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. | +| [vectorLength()](./firestore_pipelines.expression.md#expressionvectorlength) | | (Public Preview) Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. | ## Expression.expressionType @@ -871,28 +184,53 @@ abstract readonly expressionType: ExpressionType; Creates an expression that computes the absolute value of a numeric value. +Signature: + +```typescript +abs(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. + +### Example + + ```typescript // Compute the absolute value of the 'price' field. field("price").abs(); ``` - A new representing the absolute value of the numeric value. + +## Expression.add() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds this expression to another expression. Signature: ```typescript -abs(): FunctionExpression; +add(second: Expression | unknown): FunctionExpression; ``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The expression or literal to add to this expression. | + Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.add() +A new `Expression` representing the addition operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that adds this expression to another expression. ```typescript // Add the value of the 'quantity' field and the 'reserve' field. @@ -900,28 +238,34 @@ field("quantity").add(field("reserve")); ``` +## Expression.arrayConcat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates an array expression with one or more other arrays. + Signature: ```typescript -add(second: Expression | unknown): FunctionExpression; +arrayConcat(secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The expression or literal to add to this expression. | +| secondArray | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\] | Second array expression or array literal to concatenate. | +| otherArrays | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.arrayConcat() +A new `Expression` representing the concatenated array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that concatenates an array expression with one or more other arrays. ```typescript // Combine the 'items' array with another array field. @@ -929,29 +273,33 @@ field("items").arrayConcat(field("otherItems")); ``` +## Expression.arrayContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains a specific element. + Signature: ```typescript -arrayConcat(secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; +arrayContains(expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| secondArray | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\] | Second array expression or array literal to concatenate. | -| otherArrays | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. A new Expr representing the concatenated array. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The element to search for in the array. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.arrayContains() +A new `Expression` representing the 'array\_contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array contains a specific element. ```typescript // Check if the 'sizes' array contains the value from the 'selectedSize' field @@ -959,28 +307,33 @@ field("sizes").arrayContains(field("selectedSize")); ``` +## Expression.arrayContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains a specific value. + Signature: ```typescript -arrayContains(expression: Expression): BooleanExpression; +arrayContains(value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The element to search for in the array. A new Expr representing the 'array\_contains' comparison. | +| value | unknown | The element to search for in the array. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.arrayContains() +A new `Expression` representing the 'array\_contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array contains a specific value. ```typescript // Check if the 'colors' array contains "red" @@ -988,28 +341,33 @@ field("colors").arrayContains("red"); ``` +## Expression.arrayContainsAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains all the specified elements. + Signature: ```typescript -arrayContains(value: unknown): BooleanExpression; +arrayContainsAll(values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The element to search for in the array. A new Expr representing the 'array\_contains' comparison. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.arrayContainsAll() +A new `Expression` representing the 'array\_contains\_all' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array contains all the specified elements. ```typescript // Check if the 'tags' array contains both the value in field "tag1" and the literal value "tag2" @@ -1017,28 +375,33 @@ field("tags").arrayContainsAll([field("tag1"), "tag2"]); ``` +## Expression.arrayContainsAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains all the specified elements. + Signature: ```typescript -arrayContainsAll(values: Array): BooleanExpression; +arrayContainsAll(arrayExpression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new Expr representing the 'array\_contains\_all' comparison. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.arrayContainsAll() +A new `Expression` representing the 'array\_contains\_all' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array contains all the specified elements. ```typescript // Check if the 'tags' array contains both of the values from field "tag1" and the literal value "tag2" @@ -1046,28 +409,33 @@ field("tags").arrayContainsAll(array([field("tag1"), "tag2"])); ``` +## Expression.arrayContainsAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains any of the specified elements. + Signature: ```typescript -arrayContainsAll(arrayExpression: Expression): BooleanExpression; +arrayContainsAny(values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. A new Expr representing the 'array\_contains\_all' comparison. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.arrayContainsAny() +A new `Expression` representing the 'array\_contains\_any' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array contains any of the specified elements. ```typescript // Check if the 'categories' array contains either values from field "cate1" or "cate2" @@ -1075,28 +443,33 @@ field("categories").arrayContainsAny([field("cate1"), field("cate2")]); ``` +## Expression.arrayContainsAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array contains any of the specified elements. + Signature: ```typescript -arrayContainsAny(values: Array): BooleanExpression; +arrayContainsAny(arrayExpression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. A new Expr representing the 'array\_contains\_any' comparison. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.arrayContainsAny() +A new `Expression` representing the 'array\_contains\_any' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array contains any of the specified elements. ```typescript // Check if the 'groups' array contains either the value from the 'userGroup' field @@ -1105,28 +478,33 @@ field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); ``` +## Expression.arrayGet() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + Signature: ```typescript -arrayContainsAny(arrayExpression: Expression): BooleanExpression; +arrayGet(offset: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. A new Expr representing the 'array\_contains\_any' comparison. | +| offset | number | The index of the element to return. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.arrayGet() +A new `Expression` representing the 'arrayGet' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. ```typescript // Return the value in the 'tags' field array at index `1`. @@ -1134,28 +512,33 @@ field('tags').arrayGet(1); ``` +## Expression.arrayGet() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + Signature: ```typescript -arrayGet(offset: number): FunctionExpression; +arrayGet(offsetExpr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| offset | number | The index of the element to return. A new Expr representing the 'arrayGet' operation. | +| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.arrayGet() +A new `Expression` representing the 'arrayGet' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. ```typescript // Return the value in the tags field array at index specified by field @@ -1164,90 +547,86 @@ field('tags').arrayGet(field('favoriteTag')); ``` -Signature: +## Expression.arrayLength() -```typescript -arrayGet(offsetExpr: Expression): FunctionExpression; -``` +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> -#### Parameters +Creates an expression that calculates the length of an array. -| Parameter | Type | Description | -| --- | --- | --- | -| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expr evaluating to the index of the element to return. A new Expr representing the 'arrayGet' operation. | +Signature: +```typescript +arrayLength(): FunctionExpression; +``` Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.arrayLength() +A new `Expression` representing the length of the array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of an array. ```typescript // Get the number of items in the 'cart' array field("cart").arrayLength(); ``` - A new `Expr` representing the length of the array. + +## Expression.arrayReverse() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses an array. Signature: ```typescript -arrayLength(): FunctionExpression; +arrayReverse(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.arrayReverse() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses an array. ```typescript // Reverse the value of the 'myArray' field. field("myArray").arrayReverse(); ``` - A new representing the reversed array. + +## Expression.arraySum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. Signature: ```typescript -arrayReverse(): FunctionExpression; +arraySum(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.arraySum() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the sum of the elements in the array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the sum of the elements in an array. ```typescript // Compute the sum of the elements in the 'scores' field. field("scores").arraySum(); ``` - A new representing the sum of the elements in the array. - -Signature: - -```typescript -arraySum(): FunctionExpression; -``` -Returns: - -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) ## Expression.as() @@ -1258,13 +637,6 @@ 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. -```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")); - -``` - Signature: ```typescript @@ -1275,12 +647,24 @@ as(name: string): AliasedExpression; | Parameter | Type | Description | | --- | --- | --- | -| name | string | The alias to assign to this expression. A new that wraps this expression and associates it with the provided alias. | +| name | string | The alias to assign to this expression. | Returns: [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class) +A new [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class) that wraps this expression and associates it with the provided alias. + +### 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")); + +``` + ## Expression.asBoolean() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1288,8 +672,6 @@ as(name: string): AliasedExpression; Wraps the expression in a \[BooleanExpression\]. - A \[BooleanExpression\] representing the same expression. - Signature: ```typescript @@ -1299,12 +681,28 @@ asBoolean(): BooleanExpression; [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +A \[BooleanExpression\] representing the same expression. + ## Expression.ascending() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an that sorts documents in ascending order based on this expression. +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on this expression. + +Signature: + +```typescript +ascending(): Ordering; +``` +Returns: + +[Ordering](./firestore_pipelines.ordering.md#ordering_class) + +A new `Ordering` for ascending sorting. + +### Example + ```typescript // Sort documents by the 'name' field in ascending order @@ -1312,131 +710,141 @@ pipeline().collection("users") .sort(field("name").ascending()); ``` - A new `Ordering` for ascending sorting. + +## Expression.average() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. Signature: ```typescript -ascending(): Ordering; +average(): AggregateFunction; ``` Returns: -[Ordering](./firestore_pipelines.ordering.md#ordering_class) +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -## Expression.average() +A new `AggregateFunction` representing the 'average' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. ```typescript // Calculate the average age of users field("age").average().as("averageAge"); ``` - A new `AggregateFunction` representing the 'average' aggregation. + +## Expression.byteLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of this string expression in bytes. Signature: ```typescript -average(): AggregateFunction; +byteLength(): FunctionExpression; ``` Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.byteLength() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string in bytes. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of this string expression in bytes. ```typescript // Calculate the length of the 'myString' field in bytes. field("myString").byteLength(); ``` - A new representing the length of the string in bytes. + +## Expression.ceil() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. Signature: ```typescript -byteLength(): FunctionExpression; +ceil(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.ceil() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ceiling of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the ceiling of a numeric value. ```typescript // Compute the ceiling of the 'price' field. field("price").ceil(); ``` - A new representing the ceiling of the numeric value. + +## Expression.charLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the character length of a string in UTF-8. Signature: ```typescript -ceil(): FunctionExpression; +charLength(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.charLength() +A new `Expression` representing the length of the string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the character length of a string in UTF-8. ```typescript // Get the character length of the 'name' field in its UTF-8 form. field("name").charLength(); ``` - A new `Expr` representing the length of the string. + +## Expression.collectionId() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. Signature: ```typescript -charLength(): FunctionExpression; +collectionId(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.collectionId() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the collectionId operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the collection ID from a path. ```typescript // Get the collection ID from a path. field("__path__").collectionId(); ``` - A new representing the collectionId operation. - -Signature: - -```typescript -collectionId(): FunctionExpression; -``` -Returns: - -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) ## Expression.concat() @@ -1445,12 +853,6 @@ collectionId(): FunctionExpression; Creates an expression that concatenates expression results together. -```typescript -// Combine the 'firstName', ' ', and 'lastName' fields into a single value. -field("firstName").concat(constant(" "), field("lastName")); - -``` - Signature: ```typescript @@ -1462,25 +864,30 @@ concat(second: Expression | unknown, ...others: Array): Fu | Parameter | Type | Description | | --- | --- | --- | | second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The additional expression or literal to concatenate. | -| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals to concatenate. A new Expr representing the concatenated value. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals to concatenate. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.cosineDistance() +A new `Expression` representing the concatenated value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the cosine distance between two vectors. ```typescript -// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field -field("userVector").cosineDistance(field("itemVector")); +// Combine the 'firstName', ' ', and 'lastName' fields into a single value. +field("firstName").concat(constant(" "), field("lastName")); ``` +## Expression.cosineDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the cosine distance between two vectors. + Signature: ```typescript @@ -1491,25 +898,30 @@ cosineDistance(vectorExpression: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new Expr representing the cosine distance between the two vectors. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to compare against. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.cosineDistance() +A new `Expression` representing the cosine distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Cosine distance between two vectors. ```typescript -// Calculate the Cosine distance between the 'location' field and a target location -field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +field("userVector").cosineDistance(field("itemVector")); ``` +## Expression.cosineDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between two vectors. + Signature: ```typescript @@ -1520,25 +932,29 @@ cosineDistance(vector: VectorValue | number[]): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| vector | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as a VectorValue) to compare against. A new Expr representing the Cosine\* distance between the two vectors. | +| vector | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as a VectorValue) to compare against. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.count() +A new `Expression` representing the Cosine\* distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. ```typescript -// Count the total number of products -field("productId").count().as("totalProducts"); +// Calculate the Cosine distance between the 'location' field and a target location +field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); ``` - A new `AggregateFunction` representing the 'count' aggregation. + +## Expression.count() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. Signature: @@ -1549,19 +965,23 @@ count(): AggregateFunction; [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -## Expression.countDistinct() +A new `AggregateFunction` representing the 'count' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that counts the number of distinct values of the expression or field. ```typescript -// Count the distinct number of products -field("productId").countDistinct().as("distinctProducts"); +// Count the total number of products +field("productId").count().as("totalProducts"); ``` - A new `AggregateFunction` representing the 'count\_distinct' aggregation. + +## Expression.countDistinct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of distinct values of the expression or field. Signature: @@ -1572,20 +992,23 @@ countDistinct(): AggregateFunction; [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -## Expression.descending() +A new `AggregateFunction` representing the 'count\_distinct' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an that sorts documents in descending order based on this expression. ```typescript -// Sort documents by the 'createdAt' field in descending order -firestore.pipeline().collection("users") - .sort(field("createdAt").descending()); +// Count the distinct number of products +field("productId").countDistinct().as("distinctProducts"); ``` - A new `Ordering` for descending sorting. + +## Expression.descending() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on this expression. Signature: @@ -1596,19 +1019,25 @@ descending(): Ordering; [Ordering](./firestore_pipelines.ordering.md#ordering_class) -## Expression.divide() +A new `Ordering` for descending sorting. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that divides this expression by another expression. ```typescript -// Divide the 'total' field by the 'count' field -field("total").divide(field("count")); +// Sort documents by the 'createdAt' field in descending order +firestore.pipeline().collection("users") + .sort(field("createdAt").descending()); ``` +## Expression.divide() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides this expression by another expression. + Signature: ```typescript @@ -1619,25 +1048,30 @@ divide(divisor: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| divisor | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to divide by. A new Expr representing the division operation. | +| divisor | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to divide by. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.divide() +A new `Expression` representing the division operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that divides this expression by a constant value. ```typescript -// Divide the 'value' field by 10 -field("value").divide(10); +// Divide the 'total' field by the 'count' field +field("total").divide(field("count")); ``` +## Expression.divide() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides this expression by a constant value. + Signature: ```typescript @@ -1648,12 +1082,23 @@ divide(divisor: number): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| divisor | number | The constant value to divide by. A new Expr representing the division operation. | +| divisor | number | The constant value to divide by. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the division operation. + +### Example + + +```typescript +// Divide the 'value' field by 10 +field("value").divide(10); + +``` + ## Expression.documentId() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1661,28 +1106,53 @@ divide(divisor: number): FunctionExpression; Creates an expression that returns the document ID from a path. +Signature: + +```typescript +documentId(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. + +### Example + + ```typescript // Get the document ID from a path. field("__path__").documentId(); ``` - A new representing the documentId operation. + +## Expression.dotProduct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between two vectors. Signature: ```typescript -documentId(): FunctionExpression; +dotProduct(vectorExpression: Expression): FunctionExpression; ``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (as an array of numbers) to calculate with. | + Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.dotProduct() +A new `Expression` representing the dot product between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the dot product between two vectors. ```typescript // Calculate the dot product between a feature vector and a target vector @@ -1690,28 +1160,33 @@ field("features").dotProduct([0.5, 0.8, 0.2]); ``` +## Expression.dotProduct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between two vectors. + Signature: ```typescript -dotProduct(vectorExpression: Expression): FunctionExpression; +dotProduct(vector: VectorValue | number[]): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (as an array of numbers) to calculate with. A new Expr representing the dot product between the two vectors. | +| vector | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as an array of numbers) to calculate with. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.dotProduct() +A new `Expression` representing the dot product between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the dot product between two vectors. ```typescript // Calculate the dot product between a feature vector and a target vector @@ -1719,28 +1194,33 @@ field("features").dotProduct(new VectorValue([0.5, 0.8, 0.2])); ``` +## Expression.endsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string ends with a given postfix. + Signature: ```typescript -dotProduct(vector: VectorValue | number[]): FunctionExpression; +endsWith(suffix: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| vector | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as an array of numbers) to calculate with. A new Expr representing the dot product between the two vectors. | +| suffix | string | The postfix to check for. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.endsWith() +A new `Expression` representing the 'ends with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string ends with a given postfix. ```typescript // Check if the 'filename' field ends with ".txt" @@ -1748,28 +1228,33 @@ field("filename").endsWith(".txt"); ``` +## Expression.endsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string ends with a given postfix (represented as an expression). + Signature: ```typescript -endsWith(suffix: string): BooleanExpression; +endsWith(suffix: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| suffix | string | The postfix to check for. A new Expr representing the 'ends with' comparison. | +| suffix | [Expression](./firestore_pipelines.expression.md#expression_class) | The postfix expression to check for. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.endsWith() +A new `Expression` representing the 'ends with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string ends with a given postfix (represented as an expression). ```typescript // Check if the 'url' field ends with the value of the 'extension' field @@ -1777,28 +1262,33 @@ field("url").endsWith(field("extension")); ``` +## Expression.equal() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to another expression. + Signature: ```typescript -endsWith(suffix: Expression): BooleanExpression; +equal(expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| suffix | [Expression](./firestore_pipelines.expression.md#expression_class) | The postfix expression to check for. A new Expr representing the 'ends with' comparison. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for equality. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.equal() +A new `Expression` representing the equality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is equal to another expression. ```typescript // Check if the 'age' field is equal to 21 @@ -1806,28 +1296,33 @@ field("age").equal(21); ``` +## Expression.equal() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to a constant value. + Signature: ```typescript -equal(expression: Expression): BooleanExpression; +equal(value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for equality. A new Expr representing the equality comparison. | +| value | unknown | The constant value to compare for equality. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.equal() +A new `Expression` representing the equality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is equal to a constant value. ```typescript // Check if the 'city' field is equal to "London" @@ -1835,28 +1330,33 @@ field("city").equal("London"); ``` +## Expression.equalAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to any of the provided values or expressions. + Signature: ```typescript -equal(value: unknown): BooleanExpression; +equalAny(values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The constant value to compare for equality. A new Expr representing the equality comparison. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values or expressions to check against. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.equalAny() +A new `Expression` representing the 'IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is equal to any of the provided values or expressions. ```typescript // Check if the 'category' field is either "Electronics" or value of field 'primaryType' @@ -1864,28 +1364,33 @@ field("category").equalAny("Electronics", field("primaryType")); ``` +## Expression.equalAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is equal to any of the provided values or expressions. + Signature: ```typescript -equalAny(values: Array): BooleanExpression; +equalAny(arrayExpression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values or expressions to check against. A new Expr representing the 'IN' comparison. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array of values to check against. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.equalAny() +A new `Expression` representing the 'IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is equal to any of the provided values or expressions. ```typescript // Check if the 'category' field is either "Electronics" or value of field 'primaryType' @@ -1893,28 +1398,33 @@ field("category").equalAny(array(["Electronics", field("primaryType")])); ``` +## Expression.euclideanDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between two vectors. + Signature: ```typescript -equalAny(arrayExpression: Expression): BooleanExpression; +euclideanDistance(vectorExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array of values to check against. A new Expr representing the 'IN' comparison. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (as an array of numbers) to calculate with. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.euclideanDistance() +A new `Expression` representing the Euclidean distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Euclidean distance between two vectors. ```typescript // Calculate the Euclidean distance between the 'location' field and a target location @@ -1922,28 +1432,33 @@ field("location").euclideanDistance([37.7749, -122.4194]); ``` +## Expression.euclideanDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between two vectors. + Signature: ```typescript -euclideanDistance(vectorExpression: Expression): FunctionExpression; +euclideanDistance(vector: VectorValue | number[]): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (as an array of numbers) to calculate with. A new Expr representing the Euclidean distance between the two vectors. | +| vector | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as a VectorValue) to compare against. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.euclideanDistance() +A new `Expression` representing the Euclidean distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Euclidean distance between two vectors. ```typescript // Calculate the Euclidean distance between the 'location' field and a target location @@ -1951,90 +1466,86 @@ field("location").euclideanDistance(new VectorValue([37.7749, -122.4194])); ``` -Signature: +## Expression.exists() -```typescript -euclideanDistance(vector: VectorValue | number[]): FunctionExpression; -``` +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> -#### Parameters +Creates an expression that checks if a field exists in the document. -| Parameter | Type | Description | -| --- | --- | --- | -| vector | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) \| number\[\] | The other vector (as a VectorValue) to compare against. A new Expr representing the Euclidean distance between the two vectors. | +Signature: +```typescript +exists(): BooleanExpression; +``` Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.exists() +A new `Expression` representing the 'exists' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field exists in the document. ```typescript // Check if the document has a field named "phoneNumber" field("phoneNumber").exists(); ``` - A new `Expr` representing the 'exists' check. + +## Expression.exp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes e to the power of this expression. Signature: ```typescript -exists(): BooleanExpression; +exp(): FunctionExpression; ``` Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.exp() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the exp of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes e to the power of this expression. ```typescript // Compute e to the power of the 'value' field. field("value").exp(); ``` - A new representing the exp of the numeric value. + +## Expression.floor() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the floor of a numeric value. Signature: ```typescript -exp(): FunctionExpression; +floor(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.floor() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the floor of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the floor of a numeric value. ```typescript // Compute the floor of the 'price' field. field("price").floor(); ``` - A new representing the floor of the numeric value. - -Signature: - -```typescript -floor(): FunctionExpression; -``` -Returns: - -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) ## Expression.greaterThan() @@ -2043,12 +1554,6 @@ floor(): FunctionExpression; Creates an expression that checks if this expression is greater than another expression. -```typescript -// Check if the 'age' field is greater than the 'limit' field -field("age").greaterThan(field("limit")); - -``` - Signature: ```typescript @@ -2059,25 +1564,30 @@ greaterThan(expression: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for greater than. A new Expr representing the greater than comparison. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for greater than. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.greaterThan() +A new `Expression` representing the greater than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is greater than a constant value. ```typescript -// Check if the 'price' field is greater than 100 -field("price").greaterThan(100); +// Check if the 'age' field is greater than the 'limit' field +field("age").greaterThan(field("limit")); ``` +## Expression.greaterThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than a constant value. + Signature: ```typescript @@ -2088,25 +1598,30 @@ greaterThan(value: unknown): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The constant value to compare for greater than. A new Expr representing the greater than comparison. | +| value | unknown | The constant value to compare for greater than. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.greaterThanOrEqual() +A new `Expression` representing the greater than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is greater than or equal to another expression. ```typescript -// Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1 -field("quantity").greaterThanOrEqual(field('requirement').add(1)); +// Check if the 'price' field is greater than 100 +field("price").greaterThan(100); ``` +## Expression.greaterThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than or equal to another expression. + Signature: ```typescript @@ -2117,25 +1632,30 @@ greaterThanOrEqual(expression: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for greater than or equal to. A new Expr representing the greater than or equal to comparison. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for greater than or equal to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.greaterThanOrEqual() +A new `Expression` representing the greater than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is greater than or equal to a constant value. ```typescript -// Check if the 'score' field is greater than or equal to 80 -field("score").greaterThanOrEqual(80); +// Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1 +field("quantity").greaterThanOrEqual(field('requirement').add(1)); ``` +## Expression.greaterThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is greater than or equal to a constant value. + Signature: ```typescript @@ -2146,26 +1666,30 @@ greaterThanOrEqual(value: unknown): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The constant value to compare for greater than or equal to. A new Expr representing the greater than or equal to comparison. | +| value | unknown | The constant value to compare for greater than or equal to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.ifAbsent() +A new `Expression` representing the greater than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of the this expression evaluation. ```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -field("optional_field").ifAbsent("default_value") +// Check if the 'score' field is greater than or equal to 80 +field("score").greaterThanOrEqual(80); ``` +## Expression.ifAbsent() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of the this expression evaluation. + Signature: ```typescript @@ -2176,12 +1700,24 @@ ifAbsent(elseValue: unknown): Expression; | Parameter | Type | Description | | --- | --- | --- | -| elseValue | unknown | The value that will be returned if this Expression evaluates to an absent value. A new \[Expression\] representing the ifAbsent operation. | +| elseValue | unknown | The value that will be returned if this Expression evaluates to an absent value. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new \[Expression\] representing the ifAbsent operation. + +### Example + + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +field("optional_field").ifAbsent("default_value") + +``` + ## Expression.ifAbsent() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2206,12 +1742,14 @@ ifAbsent(elseExpression: unknown): Expression; | Parameter | Type | Description | | --- | --- | --- | -| elseExpression | unknown | The Expression that will be evaluated if this Expression evaluates to an absent value. A new \[Expression\] representing the ifAbsent operation. | +| elseExpression | unknown | The Expression that will be evaluated if this Expression evaluates to an absent value. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new \[Expression\] representing the ifAbsent operation. + ## Expression.ifError() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2219,13 +1757,6 @@ ifAbsent(elseExpression: unknown): Expression; Creates an expression that returns the result of the `catchExpr` argument if there is an error, else return the result of this expression. -```typescript -// Returns the first item in the title field arrays, or returns -// the entire title field if the array is empty or the field is another type. -field("title").arrayGet(0).ifError(field("title")); - -``` - Signature: ```typescript @@ -2236,25 +1767,30 @@ ifError(catchExpr: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| catchExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The catch expression that will be evaluated and returned if this expression produces an error. A new representing the 'ifError' operation. | +| catchExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The catch expression that will be evaluated and returned if this expression produces an error. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.ifError() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. ```typescript // Returns the first item in the title field arrays, or returns -// "Default Title" -field("title").arrayGet(0).ifError("Default Title"); +// the entire title field if the array is empty or the field is another type. +field("title").arrayGet(0).ifError(field("title")); + +``` + +## Expression.ifError() -``` +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. Signature: @@ -2266,25 +1802,30 @@ ifError(catchValue: unknown): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| catchValue | unknown | The value that will be returned if this expression produces an error. A new representing the 'ifError' operation. | +| catchValue | unknown | The value that will be returned if this expression produces an error. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.isAbsent() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns `true` if the result of this expression is absent. Otherwise, returns `false` even if the value is `null`. ```typescript -// Check if the field `value` is absent. -field("value").isAbsent(); +// Returns the first item in the title field arrays, or returns +// "Default Title" +field("title").arrayGet(0).ifError("Default Title"); ``` - A new representing the 'isAbsent' check. + +## Expression.isAbsent() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns `true` if the result of this expression is absent. Otherwise, returns `false` even if the value is `null`. Signature: @@ -2295,19 +1836,24 @@ isAbsent(): BooleanExpression; [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.isError() +A new [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) representing the 'isAbsent' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a given expression produces an error. ```typescript -// Check if the result of a calculation is an error -field("title").arrayContains(1).isError(); +// Check if the field `value` is absent. +field("value").isAbsent(); +@example ``` - A new representing the 'isError' check. + +## Expression.isError() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a given expression produces an error. Signature: @@ -2318,19 +1864,24 @@ isError(): BooleanExpression; [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.join() +A new [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) representing the 'isError' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that joins the elements of an array into a string. ```typescript -// Join the elements of the 'tags' field with the delimiter from the 'separator' field. -field("tags").join(field("separator")) +// Check if the result of a calculation is an error +field("title").arrayContains(1).isError(); ``` +## Expression.join() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + Signature: ```typescript @@ -2341,25 +1892,30 @@ join(delimiterExpression: Expression): Expression; | Parameter | Type | Description | | --- | --- | --- | -| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. A new Expression representing the join operation. | +| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) -## Expression.join() +A new Expression representing the join operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that joins the elements of an array field into a string. ```typescript -// Join the elements of the 'tags' field with a comma and space. -field("tags").join(", ") +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +field("tags").join(field("separator")) ``` +## Expression.join() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array field into a string. + Signature: ```typescript @@ -2370,28 +1926,29 @@ join(delimiter: string): Expression; | Parameter | Type | Description | | --- | --- | --- | -| delimiter | string | The string to use as a delimiter. A new Expression representing the join operation. | +| delimiter | string | The string to use as a delimiter. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) -## Expression.length() +A new Expression representing the join operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of a string, array, map, vector, or bytes. ```typescript -// Get the length of the 'name' field. -field("name").length(); - -// Get the number of items in the 'cart' array. -field("cart").length(); +// Join the elements of the 'tags' field with a comma and space. +field("tags").join(", ") ``` - A new `Expr` representing the length of the string, array, map, vector, or bytes. + +## Expression.length() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string, array, map, vector, or bytes. Signature: @@ -2402,19 +1959,27 @@ length(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.lessThan() +A new `Expression` representing the length of the string, array, map, vector, or bytes. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is less than another expression. ```typescript -// Check if the 'age' field is less than 'limit' -field("age").lessThan(field('limit')); +// Get the length of the 'name' field. +field("name").length(); + +// Get the number of items in the 'cart' array. +field("cart").length(); ``` +## Expression.lessThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than another expression. + Signature: ```typescript @@ -2425,25 +1990,30 @@ lessThan(experession: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| experession | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for less than. A new Expr representing the less than comparison. | +| experession | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for less than. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.lessThan() +A new `Expression` representing the less than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is less than a constant value. ```typescript -// Check if the 'price' field is less than 50 -field("price").lessThan(50); +// Check if the 'age' field is less than 'limit' +field("age").lessThan(field('limit')); ``` +## Expression.lessThan() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than a constant value. + Signature: ```typescript @@ -2454,25 +2024,30 @@ lessThan(value: unknown): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The constant value to compare for less than. A new Expr representing the less than comparison. | +| value | unknown | The constant value to compare for less than. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.lessThanOrEqual() +A new `Expression` representing the less than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is less than or equal to another expression. ```typescript -// Check if the 'quantity' field is less than or equal to 20 -field("quantity").lessThan(constant(20)); +// Check if the 'price' field is less than 50 +field("price").lessThan(50); ``` +## Expression.lessThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than or equal to another expression. + Signature: ```typescript @@ -2483,25 +2058,30 @@ lessThanOrEqual(expression: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for less than or equal to. A new Expr representing the less than or equal to comparison. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for less than or equal to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.lessThanOrEqual() +A new `Expression` representing the less than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is less than or equal to a constant value. ```typescript -// Check if the 'score' field is less than or equal to 70 -field("score").lessThan(70); +// Check if the 'quantity' field is less than or equal to 20 +field("quantity").lessThan(constant(20)); ``` +## Expression.lessThanOrEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is less than or equal to a constant value. + Signature: ```typescript @@ -2512,25 +2092,30 @@ lessThanOrEqual(value: unknown): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The constant value to compare for less than or equal to. A new Expr representing the less than or equal to comparison. | +| value | unknown | The constant value to compare for less than or equal to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.like() +A new `Expression` representing the less than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a case-sensitive string comparison. ```typescript -// Check if the 'title' field contains the word "guide" (case-sensitive) -field("title").like("%guide%"); +// Check if the 'score' field is less than or equal to 70 +field("score").lessThan(70); ``` +## Expression.like() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive string comparison. + Signature: ```typescript @@ -2541,18 +2126,16 @@ like(pattern: string): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| pattern | string | The pattern to search for. You can use "%" as a wildcard character. A new Expr representing the 'like' comparison. | +| pattern | string | The pattern to search for. You can use "%" as a wildcard character. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.like() +A new `Expression` representing the 'like' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a case-sensitive string comparison. ```typescript // Check if the 'title' field contains the word "guide" (case-sensitive) @@ -2560,6 +2143,13 @@ field("title").like("%guide%"); ``` +## Expression.like() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive string comparison. + Signature: ```typescript @@ -2570,25 +2160,29 @@ like(pattern: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. A new Expr representing the 'like' comparison. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.ln() +A new `Expression` representing the 'like' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the natural logarithm of a numeric value. ```typescript -// Compute the natural logarithm of the 'value' field. -field("value").ln(); +// Check if the 'title' field contains the word "guide" (case-sensitive) +field("title").like("%guide%"); ``` - A new representing the natural logarithm of the numeric value. + +## Expression.ln() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the natural logarithm of a numeric value. Signature: @@ -2599,19 +2193,23 @@ ln(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.log10() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the natural logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the base-10 logarithm of a numeric value. ```typescript -// Compute the base-10 logarithm of the 'value' field. -field("value").log10(); +// Compute the natural logarithm of the 'value' field. +field("value").ln(); ``` - A new representing the base-10 logarithm of the numeric value. + +## Expression.log10() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the base-10 logarithm of a numeric value. Signature: @@ -2622,19 +2220,24 @@ log10(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.logicalMaximum() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the base-10 logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. ```typescript -// Returns the larger value between the 'timestamp' field and the current timestamp. -field("timestamp").logicalMaximum(Function.currentTimestamp()); +// Compute the base-10 logarithm of the 'value' field. +field("value").log10(); ``` +## Expression.logicalMaximum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. + Signature: ```typescript @@ -2646,25 +2249,30 @@ logicalMaximum(second: Expression | unknown, ...others: ArrayReturns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.logicalMinimum() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical maximum operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. ```typescript -// Returns the smaller value between the 'timestamp' field and the current timestamp. -field("timestamp").logicalMinimum(Function.currentTimestamp()); +// Returns the larger value between the 'timestamp' field and the current timestamp. +field("timestamp").logicalMaximum(Function.currentTimestamp()); ``` +## Expression.logicalMinimum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. + Signature: ```typescript @@ -2676,11 +2284,22 @@ logicalMinimum(second: Expression | unknown, ...others: ArrayReturns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical minimum operation. + +### Example + + +```typescript +// Returns the smaller value between the 'timestamp' field and the current timestamp. +field("timestamp").logicalMinimum(Function.currentTimestamp()); + +``` ## Expression.mapGet() @@ -2689,12 +2308,6 @@ logicalMinimum(second: Expression | unknown, ...others: ArraySignature: ```typescript @@ -2705,12 +2318,23 @@ mapGet(subfield: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| subfield | string | The key to access in the map. A new Expr representing the value associated with the given key in the map. | +| subfield | string | The key to access in the map. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the value associated with the given key in the map. + +### Example + + +```typescript +// Get the 'city' value from the 'address' map field +field("address").mapGet("city"); + +``` + ## Expression.mapMerge() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2718,13 +2342,6 @@ mapGet(subfield: string): FunctionExpression; Creates an expression that merges multiple map values. -``` -// 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}, {}) - -``` - Signature: ```typescript @@ -2742,7 +2359,17 @@ mapMerge(secondMap: Record | Expression, ...otherMaps: ArraySignature: ```typescript @@ -2773,21 +2394,24 @@ mapRemove(key: string): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new representing the 'mapRemove' operation. - -## Expression.mapRemove() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'mapRemove' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that removes a key from the map produced by evaluating this expression. ``` // Removes the key 'baz' from the input map. -map({foo: 'bar', baz: true}).mapRemove(constant('baz')); +map({foo: 'bar', baz: true}).mapRemove('baz'); ``` +## Expression.mapRemove() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map produced by evaluating this expression. + Signature: ```typescript @@ -2804,7 +2428,17 @@ mapRemove(keyExpr: Expression): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new representing the 'mapRemove' operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'mapRemove' operation. + +### Example + + +``` +// Removes the key 'baz' from the input map. +map({foo: 'bar', baz: true}).mapRemove(constant('baz')); +@example + +``` ## Expression.maximum() @@ -2813,51 +2447,80 @@ A new representing the 'mapRemove' operation. Creates an aggregation that finds the maximum value of a field across multiple stage inputs. +Signature: + +```typescript +maximum(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'maximum' aggregation. + +### Example + + ```typescript // Find the highest score in a leaderboard field("score").maximum().as("highestScore"); ``` - A new `AggregateFunction` representing the 'maximum' aggregation. + +## Expression.minimum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the minimum value of a field across multiple stage inputs. Signature: ```typescript -maximum(): AggregateFunction; +minimum(): AggregateFunction; ``` Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -## Expression.minimum() +A new `AggregateFunction` representing the 'minimum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that finds the minimum value of a field across multiple stage inputs. ```typescript // Find the lowest price of all products field("price").minimum().as("lowestPrice"); ``` - A new `AggregateFunction` representing the 'minimum' aggregation. + +## Expression.mod() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. Signature: ```typescript -minimum(): AggregateFunction; +mod(expression: Expression): FunctionExpression; ``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to divide by. | + Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.mod() +A new `Expression` representing the modulo operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. ```typescript // Calculate the remainder of dividing the 'value' field by the 'divisor' field @@ -2865,28 +2528,33 @@ field("value").mod(field("divisor")); ``` +## Expression.mod() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. + Signature: ```typescript -mod(expression: Expression): FunctionExpression; +mod(value: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to divide by. A new Expr representing the modulo operation. | +| value | number | The constant value to divide by. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.mod() +A new `Expression` representing the modulo operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. ```typescript // Calculate the remainder of dividing the 'value' field by 10 @@ -2894,28 +2562,33 @@ field("value").mod(10); ``` +## Expression.multiply() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that multiplies this expression by another expression. + Signature: ```typescript -mod(value: number): FunctionExpression; +multiply(second: Expression | number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| value | number | The constant value to divide by. A new Expr representing the modulo operation. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| number | The second expression or literal to multiply by. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.multiply() +A new `Expression` representing the multiplication operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that multiplies this expression by another expression. ```typescript // Multiply the 'quantity' field by the 'price' field @@ -2923,28 +2596,33 @@ field("quantity").multiply(field("price")); ``` +## Expression.notEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to another expression. + Signature: ```typescript -multiply(second: Expression | number): FunctionExpression; +notEqual(expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| number | The second expression or literal to multiply by. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for inequality. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.notEqual() +A new `Expression` representing the inequality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is not equal to another expression. ```typescript // Check if the 'status' field is not equal to "completed" @@ -2952,28 +2630,33 @@ field("status").notEqual("completed"); ``` +## Expression.notEqual() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to a constant value. + Signature: ```typescript -notEqual(expression: Expression): BooleanExpression; +notEqual(value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare for inequality. A new Expr representing the inequality comparison. | +| value | unknown | The constant value to compare for inequality. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.notEqual() +A new `Expression` representing the inequality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is not equal to a constant value. ```typescript // Check if the 'country' field is not equal to "USA" @@ -2981,28 +2664,33 @@ field("country").notEqual("USA"); ``` +## Expression.notEqualAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to any of the provided values or expressions. + Signature: ```typescript -notEqual(value: unknown): BooleanExpression; +notEqualAny(values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| value | unknown | The constant value to compare for inequality. A new Expr representing the inequality comparison. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values or expressions to check against. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.notEqualAny() +A new `Expression` representing the 'notEqualAny' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is not equal to any of the provided values or expressions. ```typescript // Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' @@ -3010,28 +2698,33 @@ field("status").notEqualAny(["pending", field("rejectedStatus")]); ``` +## Expression.notEqualAny() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. + Signature: ```typescript -notEqualAny(values: Array): BooleanExpression; +notEqualAny(arrayExpression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values or expressions to check against. A new Expr representing the 'notEqualAny' comparison. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The values or expressions to check against. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.notEqualAny() +A new `Expression` representing the 'notEqualAny' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. ```typescript // Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' @@ -3039,28 +2732,33 @@ field("status").notEqualAny(field('rejectedStatuses')); ``` +## Expression.pow() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of this expression raised to the power of another expression. + Signature: ```typescript -notEqualAny(arrayExpression: Expression): BooleanExpression; +pow(exponent: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The values or expressions to check against. A new Expr representing the 'notEqualAny' comparison. | +| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise this expression to the power of. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.pow() +A new `Expression` representing the power operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the value of this expression raised to the power of another expression. ```typescript // Raise the value of the 'base' field to the power of the 'exponent' field. @@ -3068,28 +2766,33 @@ field("base").pow(field("exponent")); ``` +## Expression.pow() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of this expression raised to the power of a constant value. + Signature: ```typescript -pow(exponent: Expression): FunctionExpression; +pow(exponent: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise this expression to the power of. A new Expr representing the power operation. | +| exponent | number | The constant value to raise this expression to the power of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.pow() +A new `Expression` representing the power operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the value of this expression raised to the power of a constant value. ```typescript // Raise the value of the 'base' field to the power of 2. @@ -3097,57 +2800,67 @@ field("base").pow(2); ``` +## Expression.regexContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains a specified regular expression as a substring. + Signature: ```typescript -pow(exponent: number): FunctionExpression; +regexContains(pattern: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| exponent | number | The constant value to raise this expression to the power of. A new Expr representing the power operation. | +| pattern | string | The regular expression to use for the search. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.regexContains() +A new `Expression` representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string contains a specified regular expression as a substring. ```typescript // Check if the 'description' field contains "example" (case-insensitive) field("description").regexContains("(?i)example"); -``` +``` + +## Expression.regexContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains a specified regular expression as a substring. Signature: ```typescript -regexContains(pattern: string): BooleanExpression; +regexContains(pattern: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| pattern | string | The regular expression to use for the search. A new Expr representing the 'contains' comparison. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the search. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.regexContains() +A new `Expression` representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string contains a specified regular expression as a substring. ```typescript // Check if the 'description' field contains the regular expression stored in field 'regex' @@ -3155,28 +2868,33 @@ field("description").regexContains(field("regex")); ``` +## Expression.regexMatch() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string matches a specified regular expression. + Signature: ```typescript -regexContains(pattern: Expression): BooleanExpression; +regexMatch(pattern: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the search. A new Expr representing the 'contains' comparison. | +| pattern | string | The regular expression to use for the match. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.regexMatch() +A new `Expression` representing the regular expression match. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string matches a specified regular expression. ```typescript // Check if the 'email' field matches a valid email pattern @@ -3184,28 +2902,33 @@ field("email").regexMatch("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); ``` +## Expression.regexMatch() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string matches a specified regular expression. + Signature: ```typescript -regexMatch(pattern: string): BooleanExpression; +regexMatch(pattern: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| pattern | string | The regular expression to use for the match. A new Expr representing the regular expression match. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the match. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.regexMatch() +A new `Expression` representing the regular expression match. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string matches a specified regular expression. ```typescript // Check if the 'email' field matches a regular expression stored in field 'regex' @@ -3213,67 +2936,59 @@ field("email").regexMatch(field("regex")); ``` -Signature: +## Expression.reverse() -```typescript -regexMatch(pattern: Expression): BooleanExpression; -``` +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> -#### Parameters +Creates an expression that reverses this string expression. -| Parameter | Type | Description | -| --- | --- | --- | -| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the match. A new Expr representing the regular expression match. | +Signature: +```typescript +reverse(): FunctionExpression; +``` Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.reverse() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses this string expression. ```typescript // Reverse the value of the 'myString' field. field("myString").reverse(); ``` - A new representing the reversed string. + +## Expression.round() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the nearest whole number. Signature: ```typescript -reverse(): FunctionExpression; +round(): FunctionExpression; ``` Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.round() +A new `Expression` representing the rounded value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that rounds a numeric value to the nearest whole number. ```typescript // Round the value of the 'price' field. field("price").round(); ``` - A new `Expr` representing the rounded value. - -Signature: - -```typescript -round(): FunctionExpression; -``` -Returns: - -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) ## Expression.round() @@ -3282,12 +2997,6 @@ round(): FunctionExpression; Creates an expression that rounds a numeric value to the specified number of decimal places. -```typescript -// Round the value of the 'price' field to two decimal places. -field("price").round(2); - -``` - Signature: ```typescript @@ -3298,25 +3007,30 @@ round(decimalPlaces: number): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| decimalPlaces | number | A constant specifying the rounding precision in decimal places. A new Expr representing the rounded value. | +| decimalPlaces | number | A constant specifying the rounding precision in decimal places. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.round() +A new `Expression` representing the rounded value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that rounds a numeric value to the specified number of decimal places. ```typescript // Round the value of the 'price' field to two decimal places. -field("price").round(constant(2)); +field("price").round(2); ``` +## Expression.round() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + Signature: ```typescript @@ -3327,12 +3041,23 @@ round(decimalPlaces: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| decimalPlaces | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression specifying the rounding precision in decimal places. A new Expr representing the rounded value. | +| decimalPlaces | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression specifying the rounding precision in decimal places. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the rounded value. + +### Example + + +```typescript +// Round the value of the 'price' field to two decimal places. +field("price").round(constant(2)); + +``` + ## Expression.split() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3356,6 +3081,8 @@ split(delimiter: string): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. + ### Example @@ -3364,7 +3091,6 @@ split(delimiter: string): FunctionExpression; field('scoresCsv').split(',') ``` - A new representing the split function. ## Expression.split() @@ -3389,6 +3115,8 @@ split(delimiter: Expression): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. + ### Example @@ -3397,7 +3125,6 @@ split(delimiter: Expression): FunctionExpression; field('scores').split(conditional(field('format').equal('csv'), constant(','), constant(':')) ``` - A new representing the split function. ## Expression.sqrt() @@ -3406,13 +3133,6 @@ field('scores').split(conditional(field('format').equal('csv'), constant(','), c Creates an expression that computes the square root of a numeric value. -```typescript -// Compute the square root of the 'value' field. -field("value").sqrt(); - -``` - A new representing the square root of the numeric value. - Signature: ```typescript @@ -3422,19 +3142,24 @@ sqrt(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.startsWith() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the square root of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string starts with a given prefix. ```typescript -// Check if the 'name' field starts with "Mr." -field("name").startsWith("Mr."); +// Compute the square root of the 'value' field. +field("value").sqrt(); ``` +## Expression.startsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string starts with a given prefix. + Signature: ```typescript @@ -3445,25 +3170,30 @@ startsWith(prefix: string): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| prefix | string | The prefix to check for. A new Expr representing the 'starts with' comparison. | +| prefix | string | The prefix to check for. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.startsWith() +A new `Expression` representing the 'starts with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string starts with a given prefix (represented as an expression). ```typescript -// Check if the 'fullName' field starts with the value of the 'firstName' field -field("fullName").startsWith(field("firstName")); +// Check if the 'name' field starts with "Mr." +field("name").startsWith("Mr."); ``` +## Expression.startsWith() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string starts with a given prefix (represented as an expression). + Signature: ```typescript @@ -3474,25 +3204,30 @@ startsWith(prefix: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| prefix | [Expression](./firestore_pipelines.expression.md#expression_class) | The prefix expression to check for. A new Expr representing the 'starts with' comparison. | +| prefix | [Expression](./firestore_pipelines.expression.md#expression_class) | The prefix expression to check for. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.stringConcat() +A new `Expression` representing the 'starts with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that concatenates string expressions together. ```typescript -// Combine the 'firstName', " ", and 'lastName' fields into a single string -field("firstName").stringConcat(constant(" "), field("lastName")); +// Check if the 'fullName' field starts with the value of the 'firstName' field +field("fullName").startsWith(field("firstName")); ``` +## Expression.stringConcat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates string expressions together. + Signature: ```typescript @@ -3504,25 +3239,30 @@ stringConcat(secondString: Expression | string, ...otherStrings: ArrayExpr representing the concatenated string. | +| otherStrings | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or string literals to concatenate. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.stringContains() +A new `Expression` representing the concatenated string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string contains a specified substring. ```typescript -// Check if the 'description' field contains "example". -field("description").stringContains("example"); +// Combine the 'firstName', " ", and 'lastName' fields into a single string +field("firstName").stringConcat(constant(" "), field("lastName")); ``` +## Expression.stringContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains a specified substring. + Signature: ```typescript @@ -3533,25 +3273,30 @@ stringContains(substring: string): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| substring | string | The substring to search for. A new Expr representing the 'contains' comparison. | +| substring | string | The substring to search for. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.stringContains() +A new `Expression` representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string contains the string represented by another expression. ```typescript -// Check if the 'description' field contains the value of the 'keyword' field. -field("description").stringContains(field("keyword")); +// Check if the 'description' field contains "example". +field("description").stringContains("example"); ``` +## Expression.stringContains() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string contains the string represented by another expression. + Signature: ```typescript @@ -3562,25 +3307,29 @@ stringContains(expr: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the substring to search for. A new Expr representing the 'contains' comparison. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the substring to search for. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -## Expression.stringReverse() +A new `Expression` representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses a string. ```typescript -// Reverse the value of the 'myString' field. -field("myString").stringReverse(); +// Check if the 'description' field contains the value of the 'keyword' field. +field("description").stringContains(field("keyword")); ``` - A new representing the reversed string. + +## Expression.stringReverse() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string. Signature: @@ -3591,6 +3340,17 @@ stringReverse(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. + +### Example + + +```typescript +// Reverse the value of the 'myString' field. +field("myString").stringReverse(); + +``` + ## Expression.substring() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3646,12 +3406,6 @@ substring(position: Expression, length?: Expression): FunctionExpression; Creates an expression that subtracts another expression from this expression. -```typescript -// Subtract the 'discount' field from the 'price' field -field("price").subtract(field("discount")); - -``` - Signature: ```typescript @@ -3662,25 +3416,30 @@ subtract(subtrahend: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| subtrahend | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract from this expression. A new Expr representing the subtraction operation. | +| subtrahend | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract from this expression. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.subtract() +A new `Expression` representing the subtraction operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a constant value from this expression. ```typescript -// Subtract 20 from the value of the 'total' field -field("total").subtract(20); +// Subtract the 'discount' field from the 'price' field +field("price").subtract(field("discount")); ``` +## Expression.subtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a constant value from this expression. + Signature: ```typescript @@ -3691,11 +3450,22 @@ subtract(subtrahend: number): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| subtrahend | number | The constant value to subtract. A new Expr representing the subtraction operation. | +| subtrahend | number | The constant value to subtract. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the subtraction operation. + +### Example -Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +```typescript +// Subtract 20 from the value of the 'total' field +field("total").subtract(20); + +``` ## Expression.sum() @@ -3704,13 +3474,6 @@ subtract(subtrahend: number): FunctionExpression; Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. -```typescript -// Calculate the total revenue from a set of orders -field("orderAmount").sum().as("totalRevenue"); - -``` - A new `AggregateFunction` representing the 'sum' aggregation. - Signature: ```typescript @@ -3720,19 +3483,24 @@ sum(): AggregateFunction; [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -## Expression.timestampAdd() +A new `AggregateFunction` representing the 'sum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that adds a specified amount of time to this timestamp expression. ```typescript -// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. -field("timestamp").timestampAdd(field("unit"), field("amount")); +// Calculate the total revenue from a set of orders +field("orderAmount").sum().as("totalRevenue"); ``` +## Expression.timestampAdd() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to this timestamp expression. + Signature: ```typescript @@ -3744,25 +3512,30 @@ timestampAdd(unit: Expression, amount: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | | unit | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | -| amount | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | +| amount | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.timestampAdd() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that adds a specified amount of time to this timestamp expression. ```typescript -// Add 1 day to the 'timestamp' field. -field("timestamp").timestampAdd("day", 1); +// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. +field("timestamp").timestampAdd(field("unit"), field("amount")); ``` +## Expression.timestampAdd() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to this timestamp expression. + Signature: ```typescript @@ -3774,25 +3547,30 @@ timestampAdd(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | Parameter | Type | Description | | --- | --- | --- | | unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | -| amount | number | The amount of time to add. A new representing the resulting timestamp. | +| amount | number | The amount of time to add. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.timestampSubtract() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a specified amount of time from this timestamp expression. ```typescript -// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. -field("timestamp").timestampSubtract(field("unit"), field("amount")); +// Add 1 day to the 'timestamp' field. +field("timestamp").timestampAdd("day", 1); ``` +## Expression.timestampSubtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from this timestamp expression. + Signature: ```typescript @@ -3804,25 +3582,30 @@ timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | | unit | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | -| amount | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | +| amount | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.timestampSubtract() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a specified amount of time from this timestamp expression. ```typescript -// Subtract 1 day from the 'timestamp' field. -field("timestamp").timestampSubtract("day", 1); +// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. +field("timestamp").timestampSubtract(field("unit"), field("amount")); ``` +## Expression.timestampSubtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from this timestamp expression. + Signature: ```typescript @@ -3834,25 +3617,29 @@ timestampSubtract(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'h | Parameter | Type | Description | | --- | --- | --- | | unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | -| amount | number | The amount of time to subtract. A new representing the resulting timestamp. | +| amount | number | The amount of time to subtract. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.timestampToUnixMicros() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to microseconds since epoch. -field("timestamp").timestampToUnixMicros(); +// Subtract 1 day from the 'timestamp' field. +field("timestamp").timestampSubtract("day", 1); ``` - A new representing the number of microseconds since epoch. + +## Expression.timestampToUnixMicros() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -3863,19 +3650,23 @@ timestampToUnixMicros(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.timestampToUnixMillis() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of microseconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -field("timestamp").timestampToUnixMillis(); +// Convert the 'timestamp' field to microseconds since epoch. +field("timestamp").timestampToUnixMicros(); ``` - A new representing the number of milliseconds since epoch. + +## Expression.timestampToUnixMillis() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -3886,19 +3677,23 @@ timestampToUnixMillis(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.timestampToUnixSeconds() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of milliseconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to seconds since epoch. -field("timestamp").timestampToUnixSeconds(); +// Convert the 'timestamp' field to milliseconds since epoch. +field("timestamp").timestampToUnixMillis(); ``` - A new representing the number of seconds since epoch. + +## Expression.timestampToUnixSeconds() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -3909,6 +3704,17 @@ timestampToUnixSeconds(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of seconds since epoch. + +### Example + + +```typescript +// Convert the 'timestamp' field to seconds since epoch. +field("timestamp").timestampToUnixSeconds(); + +``` + ## Expression.timestampTruncate() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3927,12 +3733,14 @@ timestampTruncate(granularity: TimeGranularity, timezone?: string | Expression): | Parameter | Type | Description | | --- | --- | --- | | granularity | [TimeGranularity](./firestore_pipelines.md#timegranularity) | The granularity to truncate to. | -| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the truncated timestamp. + ### Example @@ -3960,12 +3768,14 @@ timestampTruncate(granularity: Expression, timezone?: string | Expression): Func | Parameter | Type | Description | | --- | --- | --- | | granularity | [Expression](./firestore_pipelines.expression.md#expression_class) | The granularity to truncate to. | -| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the truncated timestamp. + ### Example @@ -3982,13 +3792,6 @@ field('createdAt').timestampTruncate(field('granularity')) Creates an expression that converts a string to lowercase. -```typescript -// Convert the 'name' field to lowercase -field("name").toLower(); - -``` - A new `Expr` representing the lowercase string. - Signature: ```typescript @@ -3998,19 +3801,23 @@ toLower(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.toUpper() +A new `Expression` representing the lowercase string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a string to uppercase. ```typescript -// Convert the 'title' field to uppercase -field("title").toUpper(); +// Convert the 'name' field to lowercase +field("name").toLower(); ``` - A new `Expr` representing the uppercase string. + +## Expression.toUpper() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string to uppercase. Signature: @@ -4021,22 +3828,24 @@ toUpper(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.trim() +A new `Expression` representing the uppercase string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that removes leading and trailing characters from a string or byte array. ```typescript -// Trim whitespace from the 'userInput' field -field("userInput").trim(); - -// Trim quotes from the 'userInput' field -field("userInput").trim('"'); +// Convert the 'title' field to uppercase +field("title").toUpper(); ``` +## Expression.trim() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes leading and trailing characters from a string or byte array. + Signature: ```typescript @@ -4047,12 +3856,26 @@ trim(valueToTrim?: string | Expression | Bytes): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | 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. A new Expr representing the trimmed string or byte array. | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | 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: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the trimmed string or byte array. + +### Example + + +```typescript +// Trim whitespace from the 'userInput' field +field("userInput").trim(); + +// Trim quotes from the 'userInput' field +field("userInput").trim('"'); + +``` + ## Expression.type() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4069,6 +3892,8 @@ type(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the data type. + ### Example @@ -4077,7 +3902,6 @@ type(): FunctionExpression; field('title').type() ``` - A new {Expression} representing the data type. ## Expression.unixMicrosToTimestamp() @@ -4086,13 +3910,6 @@ field('title').type() 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. -```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -field("microseconds").unixMicrosToTimestamp(); - -``` - A new representing the timestamp. - Signature: ```typescript @@ -4102,19 +3919,23 @@ unixMicrosToTimestamp(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.unixMillisToTimestamp() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -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. ```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -field("milliseconds").unixMillisToTimestamp(); +// Interpret the 'microseconds' field as microseconds since epoch. +field("microseconds").unixMicrosToTimestamp(); ``` - A new representing the timestamp. + +## Expression.unixMillisToTimestamp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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. Signature: @@ -4125,19 +3946,23 @@ unixMillisToTimestamp(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.unixSecondsToTimestamp() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -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. ```typescript -// Interpret the 'seconds' field as seconds since epoch. -field("seconds").unixSecondsToTimestamp(); +// Interpret the 'milliseconds' field as milliseconds since epoch. +field("milliseconds").unixMillisToTimestamp(); ``` - A new representing the timestamp. + +## Expression.unixSecondsToTimestamp() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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. Signature: @@ -4148,19 +3973,23 @@ unixSecondsToTimestamp(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -## Expression.vectorLength() +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. ```typescript -// Get the vector length (dimension) of the field 'embedding'. -field("embedding").vectorLength(); +// Interpret the 'seconds' field as seconds since epoch. +field("seconds").unixSecondsToTimestamp(); ``` - A new representing the length of the vector. + +## Expression.vectorLength() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. Signature: @@ -4171,3 +4000,14 @@ vectorLength(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the vector. + +### Example + + +```typescript +// Get the vector length (dimension) of the field 'embedding'. +field("embedding").vectorLength(); + +``` + diff --git a/docs-devsite/firestore_pipelines.field.md b/docs-devsite/firestore_pipelines.field.md index de4e5fb7b2..3a0a4aa75b 100644 --- a/docs-devsite/firestore_pipelines.field.md +++ b/docs-devsite/firestore_pipelines.field.md @@ -13,21 +13,12 @@ https://github.com/firebase/firebase-js-sdk > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Represents a reference to a field in a Firestore document, or outputs of a stage. +Represents a reference to a field in a Firestore document, or outputs of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) stage.

Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines.

You can create a `Field` instance using the static method: -```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"); - -``` - Signature: ```typescript @@ -101,3 +92,16 @@ get fieldName(): string; ```typescript selectable: true; ``` + +### 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"); + +``` + diff --git a/docs-devsite/firestore_pipelines.functionexpression.md b/docs-devsite/firestore_pipelines.functionexpression.md index 6ba0bb3367..2783f8168e 100644 --- a/docs-devsite/firestore_pipelines.functionexpression.md +++ b/docs-devsite/firestore_pipelines.functionexpression.md @@ -13,9 +13,9 @@ https://github.com/firebase/firebase-js-sdk > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -This class defines the base class for Firestore functions, which can be evaluated within pipeline execution. +This class defines the base class for Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) functions, which can be evaluated within pipeline execution. -Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_.md#and_e72c712), , or the methods on (, , etc.) to construct new Function instances. +Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_pipelines.md#and_e0c48bd), [equal()](./firestore_pipelines.md#equal_b3c3382), or the methods on [Expression](./firestore_pipelines.expression.md#expression_class) ([Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), etc.) to construct new Function instances. Signature: diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 2a3ba65e1f..83f2763dd9 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -16,1630 +16,279 @@ https://github.com/firebase/firebase-js-sdk | Function | Description | | --- | --- | | function() | -| [countAll()](./firestore_pipelines.md#countall) | (Public Preview) Creates an aggregation that counts the total number of stage inputs. -```typescript -// Count the total number of input documents -countAll().as("totalDocument"); - -``` - A new representing the 'countAll' aggregation. | -| [currentTimestamp()](./firestore_pipelines.md#currenttimestamp) | (Public Preview) Creates an expression that evaluates to the current server timestamp. -```typescript -// Get the current server timestamp -currentTimestamp() - -``` - A new Expression representing the current server timestamp. | +| [countAll()](./firestore_pipelines.md#countall) | (Public Preview) Creates an aggregation that counts the total number of stage inputs. | +| [currentTimestamp()](./firestore_pipelines.md#currenttimestamp) | (Public Preview) Creates an expression that evaluates to the current server timestamp. | | function(array, ...) | -| [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_a00ea48) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. -```typescript -// Check if the 'colors' array contains the value of field 'selectedColor' -arrayContains(field("colors"), field("selectedColor")); - -``` - | -| [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_7328608) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. -```typescript -// Check if the 'colors' array contains "red" -arrayContains(field("colors"), "red"); - -``` - | -| [arrayContainsAll(array, values)](./firestore_pipelines.md#arraycontainsall_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. -```typescript -// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" -arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); - -``` - | -| [arrayContainsAll(array, arrayExpression)](./firestore_pipelines.md#arraycontainsall_7b535db) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. -```typescript -// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" -arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); - -``` - | -| [arrayContainsAny(array, values)](./firestore_pipelines.md#arraycontainsany_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. -```typescript -// Check if the 'categories' array contains either values from field "cate1" or "Science" -arrayContainsAny(field("categories"), [field("cate1"), "Science"]); - -``` - | -| [arrayContainsAny(array, values)](./firestore_pipelines.md#arraycontainsany_c381a96) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. -```typescript -// Check if the 'categories' array contains either values from field "cate1" or "Science" -arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); - -``` - | -| [arrayLength(array)](./firestore_pipelines.md#arraylength_195e339) | (Public Preview) Creates an expression that calculates the length of an array expression. -```typescript -// Get the number of items in the 'cart' array -arrayLength(field("cart")); - -``` - | +| [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_a00ea48) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. | +| [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_7328608) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. | +| [arrayContainsAll(array, values)](./firestore_pipelines.md#arraycontainsall_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. | +| [arrayContainsAll(array, arrayExpression)](./firestore_pipelines.md#arraycontainsall_7b535db) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. | +| [arrayContainsAny(array, values)](./firestore_pipelines.md#arraycontainsany_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. | +| [arrayContainsAny(array, values)](./firestore_pipelines.md#arraycontainsany_c381a96) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. | +| [arrayLength(array)](./firestore_pipelines.md#arraylength_195e339) | (Public Preview) Creates an expression that calculates the length of an array expression. | | function(arrayExpression, ...) | -| [arrayGet(arrayExpression, offset)](./firestore_pipelines.md#arrayget_f2e27cc) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index 1. -arrayGet(field('tags'), 1); - -``` - | -| [arrayGet(arrayExpression, offsetExpr)](./firestore_pipelines.md#arrayget_484550d) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -arrayGet(field('tags'), field('favoriteTag')); - -``` - | -| [join(arrayExpression, delimiterExpression)](./firestore_pipelines.md#join_313e6aa) | (Public Preview) Creates an expression that joins the elements of an array into a string. -```typescript -// Join an array of string using the delimiter from the 'separator' field. -join(array(['foo', 'bar']), field("separator")) - -``` - | -| [join(arrayExpression, delimiter)](./firestore_pipelines.md#join_d088d29) | (Public Preview) Creates an expression that joins the elements of an array into a string. -```typescript -// Join the elements of the 'tags' field with a comma and space. -join(field("tags"), ", ") - -``` - | +| [arrayGet(arrayExpression, offset)](./firestore_pipelines.md#arrayget_f2e27cc) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(arrayExpression, offsetExpr)](./firestore_pipelines.md#arrayget_484550d) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [join(arrayExpression, delimiterExpression)](./firestore_pipelines.md#join_313e6aa) | (Public Preview) Creates an expression that joins the elements of an array into a string. | +| [join(arrayExpression, delimiter)](./firestore_pipelines.md#join_d088d29) | (Public Preview) Creates an expression that joins the elements of an array into a string. | | function(arrayField, ...) | -| [arrayGet(arrayField, offset)](./firestore_pipelines.md#arrayget_3f58471) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index 1. -arrayGet('tags', 1); - -``` - | -| [arrayGet(arrayField, offsetExpr)](./firestore_pipelines.md#arrayget_1904c9a) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -arrayGet('tags', field('favoriteTag')); - -``` - | +| [arrayGet(arrayField, offset)](./firestore_pipelines.md#arrayget_3f58471) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(arrayField, offsetExpr)](./firestore_pipelines.md#arrayget_1904c9a) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | | function(arrayFieldName, ...) | -| [join(arrayFieldName, delimiter)](./firestore_pipelines.md#join_478ef36) | (Public Preview) Creates an expression that joins the elements of an array into a string. -```typescript -// Join the elements of the 'tags' field with a comma and space. -join("tags", ", ") - -``` - | -| [join(arrayFieldName, delimiterExpression)](./firestore_pipelines.md#join_829294c) | (Public Preview) Creates an expression that joins the elements of an array into a string. -```typescript -// Join the elements of the 'tags' field with the delimiter from the 'separator' field. -join('tags', field("separator")) - -``` - | +| [join(arrayFieldName, delimiter)](./firestore_pipelines.md#join_478ef36) | (Public Preview) Creates an expression that joins the elements of an array into a string. | +| [join(arrayFieldName, delimiterExpression)](./firestore_pipelines.md#join_829294c) | (Public Preview) Creates an expression that joins the elements of an array into a string. | | function(base, ...) | -| [pow(base, exponent)](./firestore_pipelines.md#pow_e4a9e64) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent expression. -```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -pow(field("base"), field("exponent")); - -``` - | -| [pow(base, exponent)](./firestore_pipelines.md#pow_93eae7f) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent. -```typescript -// Raise the value of the 'base' field to the power of 2. -pow(field("base"), 2); - -``` - | -| [pow(base, exponent)](./firestore_pipelines.md#pow_a237721) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent expression. -```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -pow("base", field("exponent")); - -``` - | -| [pow(base, exponent)](./firestore_pipelines.md#pow_f4d7908) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent. -```typescript -// Raise the value of the 'base' field to the power of 2. -pow("base", 2); - -``` - | +| [pow(base, exponent)](./firestore_pipelines.md#pow_e4a9e64) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent expression. | +| [pow(base, exponent)](./firestore_pipelines.md#pow_93eae7f) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent. | +| [pow(base, exponent)](./firestore_pipelines.md#pow_a237721) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent expression. | +| [pow(base, exponent)](./firestore_pipelines.md#pow_f4d7908) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent. | | function(booleanExpr, ...) | -| [countIf(booleanExpr)](./firestore_pipelines.md#countif_c5b8fb1) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. -```typescript -// Count the number of documents where 'is_active' field equals true -countIf(field("is_active").equal(true)).as("numActiveDocuments"); - -``` - | -| [not(booleanExpr)](./firestore_pipelines.md#not_c5b8fb1) | (Public Preview) Creates an expression that negates a filter condition. -```typescript -// Find documents where the 'completed' field is NOT true -not(equal("completed", true)); - -``` - | +| [countIf(booleanExpr)](./firestore_pipelines.md#countif_c5b8fb1) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. | +| [not(booleanExpr)](./firestore_pipelines.md#not_c5b8fb1) | (Public Preview) Creates an expression that negates a filter condition. | | function(condition, ...) | -| [conditional(condition, thenExpr, elseExpr)](./firestore_pipelines.md#conditional_07a206d) | (Public Preview) Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. -```typescript -// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". -conditional( - greaterThan("age", 18), constant("Adult"), constant("Minor")); - -``` - | +| [conditional(condition, thenExpr, elseExpr)](./firestore_pipelines.md#conditional_07a206d) | (Public Preview) Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. | | function(documentPath, ...) | -| [documentId(documentPath)](./firestore_pipelines.md#documentid_cef293c) | (Public Preview) Creates an expression that returns the document ID from a path. -```typescript -// Get the document ID from a path. -documentId(myDocumentReference); - -``` - A new representing the documentId operation. | +| [documentId(documentPath)](./firestore_pipelines.md#documentid_cef293c) | (Public Preview) Creates an expression that returns the document ID from a path. | | function(documentPathExpr, ...) | -| [documentId(documentPathExpr)](./firestore_pipelines.md#documentid_9a69021) | (Public Preview) Creates an expression that returns the document ID from a path. -```typescript -// Get the document ID from a path. -documentId(field("__path__")); - -``` - A new representing the documentId operation. | +| [documentId(documentPathExpr)](./firestore_pipelines.md#documentid_9a69021) | (Public Preview) Creates an expression that returns the document ID from a path. | | function(element, ...) | -| [notEqualAny(element, values)](./firestore_pipelines.md#notequalany_c2c5bcb) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. -```typescript -// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' -notEqualAny(field("status"), ["pending", field("rejectedStatus")]); - -``` - | -| [notEqualAny(element, arrayExpression)](./firestore_pipelines.md#notequalany_16b2851) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. -```typescript -// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' -notEqualAny(field("status"), ["pending", field("rejectedStatus")]); - -``` - | +| [notEqualAny(element, values)](./firestore_pipelines.md#notequalany_c2c5bcb) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | +| [notEqualAny(element, arrayExpression)](./firestore_pipelines.md#notequalany_16b2851) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | | function(elements, ...) | -| [array(elements)](./firestore_pipelines.md#array_7d853aa) | (Public Preview) Creates an expression that creates a Firestore array value from an input array. -```typescript -// Create an array value from the input array and reference the 'baz' field value from the input document. -array(['bar', Field.of('baz')]).as('foo'); - -``` - | -| [map(elements)](./firestore_pipelines.md#map_ce5dee1) | (Public Preview) Creates an expression that creates a Firestore map value from an input object. -```typescript -// Create a map from the input object and reference the 'baz' field value from the input document. -map({foo: 'bar', baz: Field.of('baz')}).as('data'); - -``` - | +| [array(elements)](./firestore_pipelines.md#array_7d853aa) | (Public Preview) Creates an expression that creates a Firestore array value from an input array. | +| [map(elements)](./firestore_pipelines.md#map_ce5dee1) | (Public Preview) Creates an expression that creates a Firestore map value from an input object. | | function(expr, ...) | | [abs(expr)](./firestore_pipelines.md#abs_005f3d4) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | -| [ascending(expr)](./firestore_pipelines.md#ascending_005f3d4) | (Public Preview) Creates an that sorts documents in ascending order based on an expression. -```typescript -// Sort documents by the 'name' field in lowercase in ascending order -firestore.pipeline().collection("users") - .sort(ascending(field("name").toLower())); - -``` - | -| [byteLength(expr)](./firestore_pipelines.md#bytelength_005f3d4) | (Public Preview) Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. -```typescript -// Calculate the length of the 'myString' field in bytes. -byteLength(field("myString")); - -``` - | +| [ascending(expr)](./firestore_pipelines.md#ascending_005f3d4) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. | +| [byteLength(expr)](./firestore_pipelines.md#bytelength_005f3d4) | (Public Preview) Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. | | [countDistinct(expr)](./firestore_pipelines.md#countdistinct_3c28b08) | (Public Preview) Creates an aggregation that counts the number of distinct values of a field. | -| [descending(expr)](./firestore_pipelines.md#descending_005f3d4) | (Public Preview) Creates an that sorts documents in descending order based on an expression. -```typescript -// Sort documents by the 'name' field in lowercase in descending order -firestore.pipeline().collection("users") - .sort(descending(field("name").toLower())); - -``` - | +| [descending(expr)](./firestore_pipelines.md#descending_005f3d4) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. | | [floor(expr)](./firestore_pipelines.md#floor_005f3d4) | (Public Preview) Creates an expression that computes the floor of a numeric value. | -| [timestampToUnixMicros(expr)](./firestore_pipelines.md#timestamptounixmicros_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to microseconds since epoch. -timestampToUnixMicros(field("timestamp")); - -``` - | -| [timestampToUnixMillis(expr)](./firestore_pipelines.md#timestamptounixmillis_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -timestampToUnixMillis(field("timestamp")); - -``` - | -| [timestampToUnixSeconds(expr)](./firestore_pipelines.md#timestamptounixseconds_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to seconds since epoch. -timestampToUnixSeconds(field("timestamp")); - -``` - | -| [unixMicrosToTimestamp(expr)](./firestore_pipelines.md#unixmicrostotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -unixMicrosToTimestamp(field("microseconds")); - -``` - | -| [unixMillisToTimestamp(expr)](./firestore_pipelines.md#unixmillistotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -unixMillisToTimestamp(field("milliseconds")); - -``` - | -| [unixSecondsToTimestamp(expr)](./firestore_pipelines.md#unixsecondstotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'seconds' field as seconds since epoch. -unixSecondsToTimestamp(field("seconds")); - -``` - | +| [timestampToUnixMicros(expr)](./firestore_pipelines.md#timestamptounixmicros_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixMillis(expr)](./firestore_pipelines.md#timestamptounixmillis_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixSeconds(expr)](./firestore_pipelines.md#timestamptounixseconds_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [unixMicrosToTimestamp(expr)](./firestore_pipelines.md#unixmicrostotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixMillisToTimestamp(expr)](./firestore_pipelines.md#unixmillistotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixSecondsToTimestamp(expr)](./firestore_pipelines.md#unixsecondstotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | | function(expression, ...) | -| [arraySum(expression)](./firestore_pipelines.md#arraysum_1138a27) | (Public Preview) Creates an expression that computes the sum of the elements in an array. -```typescript -// Compute the sum of the elements in the 'scores' field. -arraySum(field("scores")); - -``` - | -| [average(expression)](./firestore_pipelines.md#average_1138a27) | (Public Preview) Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. -```typescript -// Calculate the average age of users -average(field("age")).as("averageAge"); - -``` - | -| [ceil(expression)](./firestore_pipelines.md#ceil_1138a27) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. -```typescript -// Compute the ceiling of the 'price' field. -ceil(field("price")); - -``` - | -| [collectionId(expression)](./firestore_pipelines.md#collectionid_1138a27) | (Public Preview) Creates an expression that returns the collection ID from a path. -```typescript -// Get the collection ID from a path. -collectionId(field("__name__")); - -``` - | -| [count(expression)](./firestore_pipelines.md#count_1138a27) | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. -```typescript -// Count the number of items where the price is greater than 10 -count(field("price").greaterThan(10)).as("expensiveItemCount"); - -``` - | -| [divide(expression, value)](./firestore_pipelines.md#divide_01df3cf) | (Public Preview) Creates an expression that divides an expression by a constant value. -```typescript -// Divide the 'value' field by 10 -divide(field("value"), 10); - -``` - | -| [equal(expression, value)](./firestore_pipelines.md#equal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is equal to a constant value. -```typescript -// Check if the 'age' field is equal to 21 -equal(field("age"), 21); - -``` - | -| [equalAny(expression, values)](./firestore_pipelines.md#equalany_7e759b5) | (Public Preview) Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. -```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -equalAny(field("category"), [constant("Electronics"), field("primaryType")]); - -``` - | -| [equalAny(expression, arrayExpression)](./firestore_pipelines.md#equalany_214ce68) | (Public Preview) Creates an expression that checks if an expression is equal to any of the provided values. -```typescript -// Check if the 'category' field is set to a value in the disabledCategories field -equalAny(field("category"), field('disabledCategories')); - -``` - | -| [exp(expression)](./firestore_pipelines.md#exp_1138a27) | (Public Preview) Creates an expression that computes e to the power of the expression's result. -```typescript -// Compute e to the power of 2. -exp(constant(2)); - -``` - A new representing the exp of the numeric value. | -| [greaterThan(expression, value)](./firestore_pipelines.md#greaterthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than a constant value. -```typescript -// Check if the 'age' field is greater than 18 -greaterThan(field("age"), 18); - -``` - | -| [greaterThanOrEqual(expression, value)](./firestore_pipelines.md#greaterthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than or equal to a constant value. -```typescript -// Check if the 'quantity' field is greater than or equal to 10 -greaterThanOrEqual(field("quantity"), 10); - -``` - | -| [length\_2(expression)](./firestore_pipelines.md#length_2_1138a27) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. -```typescript -// Get the length of the 'name' field. -length(field("name")); - -// Get the number of items in the 'cart' array. -length(field("cart")); - -``` - | -| [lessThan(expression, value)](./firestore_pipelines.md#lessthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than a constant value. -```typescript -// Check if the 'age' field is less than 30 -lessThan(field("age"), 30); - -``` - | -| [lessThanOrEqual(expression, value)](./firestore_pipelines.md#lessthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than or equal to a constant value. -```typescript -// Check if the 'quantity' field is less than or equal to 20 -lessThan(field("quantity"), 20); - -``` - | -| [ln(expression)](./firestore_pipelines.md#ln_1138a27) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. -```typescript -// Compute the natural logarithm of the 'value' field. -ln(field("value")); - -``` - | -| [log(expression, base)](./firestore_pipelines.md#log_ac183e2) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. -```typescript -// Compute the logarithm of the 'value' field with base 10. -log(field("value"), 10); - -``` - | -| [log(expression, base)](./firestore_pipelines.md#log_1894737) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. -```typescript -// Compute the logarithm of the 'value' field with the base in the 'base' field. -log(field("value"), field("base")); - -``` - | -| [log10(expression)](./firestore_pipelines.md#log10_1138a27) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. -```typescript -// Compute the base-10 logarithm of the 'value' field. -log10(field("value")); - -``` - | -| [maximum(expression)](./firestore_pipelines.md#maximum_1138a27) | (Public Preview) Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. -```typescript -// Find the highest score in a leaderboard -maximum(field("score")).as("highestScore"); - -``` - | -| [minimum(expression)](./firestore_pipelines.md#minimum_1138a27) | (Public Preview) Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. -```typescript -// Find the lowest price of all products -minimum(field("price")).as("lowestPrice"); - -``` - | -| [mod(expression, value)](./firestore_pipelines.md#mod_01df3cf) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. -```typescript -// Calculate the remainder of dividing 'field1' by 5. -mod(field("field1"), 5); - -``` - | -| [notEqual(expression, value)](./firestore_pipelines.md#notequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is not equal to a constant value. -```typescript -// Check if the 'status' field is not equal to "completed" -notEqual(field("status"), "completed"); - -``` - | -| [round(expression)](./firestore_pipelines.md#round_1138a27) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. -```typescript -// Round the value of the 'price' field. -round(field("price")); - -``` - | -| [round(expression, decimalPlaces)](./firestore_pipelines.md#round_a3a92d0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. -```typescript -// Round the value of the 'price' field to two decimal places. -round(field("price"), constant(2)); - -``` - | +| [arraySum(expression)](./firestore_pipelines.md#arraysum_1138a27) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | +| [average(expression)](./firestore_pipelines.md#average_1138a27) | (Public Preview) Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. | +| [ceil(expression)](./firestore_pipelines.md#ceil_1138a27) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | +| [collectionId(expression)](./firestore_pipelines.md#collectionid_1138a27) | (Public Preview) Creates an expression that returns the collection ID from a path. | +| [count(expression)](./firestore_pipelines.md#count_1138a27) | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. | +| [divide(expression, value)](./firestore_pipelines.md#divide_01df3cf) | (Public Preview) Creates an expression that divides an expression by a constant value. | +| [equal(expression, value)](./firestore_pipelines.md#equal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is equal to a constant value. | +| [equalAny(expression, values)](./firestore_pipelines.md#equalany_7e759b5) | (Public Preview) Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. | +| [equalAny(expression, arrayExpression)](./firestore_pipelines.md#equalany_214ce68) | (Public Preview) Creates an expression that checks if an expression is equal to any of the provided values. | +| [exp(expression)](./firestore_pipelines.md#exp_1138a27) | (Public Preview) Creates an expression that computes e to the power of the expression's result. | +| [greaterThan(expression, value)](./firestore_pipelines.md#greaterthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than a constant value. | +| [greaterThanOrEqual(expression, value)](./firestore_pipelines.md#greaterthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than or equal to a constant value. | +| [length\_2(expression)](./firestore_pipelines.md#length_2_1138a27) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | +| [lessThan(expression, value)](./firestore_pipelines.md#lessthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than a constant value. | +| [lessThanOrEqual(expression, value)](./firestore_pipelines.md#lessthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than or equal to a constant value. | +| [ln(expression)](./firestore_pipelines.md#ln_1138a27) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. | +| [log(expression, base)](./firestore_pipelines.md#log_ac183e2) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. | +| [log(expression, base)](./firestore_pipelines.md#log_1894737) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. | +| [log10(expression)](./firestore_pipelines.md#log10_1138a27) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | +| [maximum(expression)](./firestore_pipelines.md#maximum_1138a27) | (Public Preview) Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. | +| [minimum(expression)](./firestore_pipelines.md#minimum_1138a27) | (Public Preview) Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. | +| [mod(expression, value)](./firestore_pipelines.md#mod_01df3cf) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. | +| [notEqual(expression, value)](./firestore_pipelines.md#notequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is not equal to a constant value. | +| [round(expression)](./firestore_pipelines.md#round_1138a27) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | +| [round(expression, decimalPlaces)](./firestore_pipelines.md#round_a3a92d0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | | [split(expression, delimiter)](./firestore_pipelines.md#split_5b5612b) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | | [split(expression, delimiter)](./firestore_pipelines.md#split_5a171ed) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | -| [sqrt(expression)](./firestore_pipelines.md#sqrt_1138a27) | (Public Preview) Creates an expression that computes the square root of a numeric value. -```typescript -// Compute the square root of the 'value' field. -sqrt(field("value")); - -``` - | -| [subtract(expression, value)](./firestore_pipelines.md#subtract_01df3cf) | (Public Preview) Creates an expression that subtracts a constant value from an expression. -```typescript -// Subtract the constant value 2 from the 'value' field -subtract(field("value"), 2); - -``` - | -| [sum(expression)](./firestore_pipelines.md#sum_1138a27) | (Public Preview) Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. -```typescript -// Calculate the total revenue from a set of orders -sum(field("orderAmount")).as("totalRevenue"); - -``` - | +| [sqrt(expression)](./firestore_pipelines.md#sqrt_1138a27) | (Public Preview) Creates an expression that computes the square root of a numeric value. | +| [subtract(expression, value)](./firestore_pipelines.md#subtract_01df3cf) | (Public Preview) Creates an expression that subtracts a constant value from an expression. | +| [sum(expression)](./firestore_pipelines.md#sum_1138a27) | (Public Preview) Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. | | [type(expression)](./firestore_pipelines.md#type_1138a27) | (Public Preview) Creates an expression that returns the data type of an expression's result. | | function(field, ...) | -| [isAbsent(field)](./firestore_pipelines.md#isabsent_0fb8cd4) | (Public Preview) Creates an expression that returns true if a field is absent. Otherwise, returns false even if the field value is null. -```typescript -// Check if the field `value` is absent. -isAbsent("value"); - -``` - | -| [reverse(field)](./firestore_pipelines.md#reverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. -```typescript -// Reverse the value of the 'myString' field. -reverse("myString"); - -``` - | -| [stringReverse(field)](./firestore_pipelines.md#stringreverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. -```typescript -// Reverse the value of the 'myString' field. -strReverse("myString"); - -``` - | +| [isAbsent(field)](./firestore_pipelines.md#isabsent_0fb8cd4) | (Public Preview) Creates an expression that returns true if a field is absent. Otherwise, returns false even if the field value is null. | +| [reverse(field)](./firestore_pipelines.md#reverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. | +| [stringReverse(field)](./firestore_pipelines.md#stringreverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. | | [substring(field, position, length)](./firestore_pipelines.md#substring_0d9573a) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | | [substring(field, position, length)](./firestore_pipelines.md#substring_05cb14e) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | | function(fieldName, ...) | | [abs(fieldName)](./firestore_pipelines.md#abs_e5b0480) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | -| [add(fieldName, second)](./firestore_pipelines.md#add_b75bb8b) | (Public Preview) Creates an expression that adds a field's value to an expression. -```typescript -// Add the value of the 'quantity' field and the 'reserve' field. -add("quantity", field("reserve")); - -``` - | -| [arrayContains(fieldName, element)](./firestore_pipelines.md#arraycontains_aaace4a) | (Public Preview) Creates an expression that checks if a field's array value contains a specific element. -```typescript -// Check if the 'colors' array contains the value of field 'selectedColor' -arrayContains("colors", field("selectedColor")); - -``` - | -| [arrayContains(fieldName, element)](./firestore_pipelines.md#arraycontains_999590f) | (Public Preview) Creates an expression that checks if a field's array value contains a specific value. -```typescript -// Check if the 'colors' array contains "red" -arrayContains("colors", "red"); - -``` - | -| [arrayContainsAll(fieldName, values)](./firestore_pipelines.md#arraycontainsall_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. -```typescript -// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" -arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); - -``` - | -| [arrayContainsAll(fieldName, arrayExpression)](./firestore_pipelines.md#arraycontainsall_48da8d9) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. -```typescript -// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" -arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); - -``` - | -| [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. -```typescript -// Check if the 'groups' array contains either the value from the 'userGroup' field -// or the value "guest" -arrayContainsAny("categories", [field("cate1"), "Science"]); - -``` - | -| [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_1b4f7cd) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. -```typescript -// Check if the 'groups' array contains either the value from the 'userGroup' field -// or the value "guest" -arrayContainsAny("categories", array([field("cate1"), "Science"])); - -``` - | -| [arrayLength(fieldName)](./firestore_pipelines.md#arraylength_e5b0480) | (Public Preview) Creates an expression that calculates the length of an array in a specified field. -```typescript -// Get the number of items in field 'cart' -arrayLength('cart'); - -``` - | -| [arraySum(fieldName)](./firestore_pipelines.md#arraysum_e5b0480) | (Public Preview) Creates an expression that computes the sum of the elements in an array. -```typescript -// Compute the sum of the elements in the 'scores' field. -arraySum("scores"); - -``` - | -| [ascending(fieldName)](./firestore_pipelines.md#ascending_e5b0480) | (Public Preview) Creates an that sorts documents in ascending order based on a field. -```typescript -// Sort documents by the 'name' field in ascending order -firestore.pipeline().collection("users") - .sort(ascending("name")); - -``` - | -| [average(fieldName)](./firestore_pipelines.md#average_e5b0480) | (Public Preview) Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. -```typescript -// Calculate the average age of users -average("age").as("averageAge"); - -``` - | -| [byteLength(fieldName)](./firestore_pipelines.md#bytelength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. -```typescript -// Calculate the length of the 'myString' field in bytes. -byteLength("myString"); - -``` - | -| [ceil(fieldName)](./firestore_pipelines.md#ceil_e5b0480) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. -```typescript -// Compute the ceiling of the 'price' field. -ceil("price"); - -``` - | -| [charLength(fieldName)](./firestore_pipelines.md#charlength_e5b0480) | (Public Preview) Creates an expression that calculates the character length of a string field in UTF8. -```typescript -// Get the character length of the 'name' field in UTF-8. -strLength("name"); - -``` - | -| [collectionId(fieldName)](./firestore_pipelines.md#collectionid_e5b0480) | (Public Preview) Creates an expression that returns the collection ID from a path. -```typescript -// Get the collection ID from a path. -collectionId("__name__"); - -``` - | -| [concat(fieldName, second, others)](./firestore_pipelines.md#concat_828272e) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. -```typescript -// Concatenate a field with a literal string. -concat(field("firstName"), "Doe") - -``` - | -| [cosineDistance(fieldName, vector)](./firestore_pipelines.md#cosinedistance_463a23e) | (Public Preview) Calculates the Cosine distance between a field's vector value and a literal vector value. -```typescript -// Calculate the Cosine distance between the 'location' field and a target location -cosineDistance("location", [37.7749, -122.4194]); - -``` - | -| [cosineDistance(fieldName, vectorExpression)](./firestore_pipelines.md#cosinedistance_ed766a1) | (Public Preview) Calculates the Cosine distance between a field's vector value and a vector expression. -```typescript -// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field -cosineDistance("userVector", field("itemVector")); - -``` - | -| [count(fieldName)](./firestore_pipelines.md#count_e5b0480) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the input field exists. -```typescript -// Count the total number of products -count("productId").as("totalProducts"); - -``` - | -| [descending(fieldName)](./firestore_pipelines.md#descending_e5b0480) | (Public Preview) Creates an that sorts documents in descending order based on a field. -```typescript -// Sort documents by the 'name' field in descending order -firestore.pipeline().collection("users") - .sort(descending("name")); - -``` - | -| [divide(fieldName, expressions)](./firestore_pipelines.md#divide_cf36e43) | (Public Preview) Creates an expression that divides a field's value by an expression. -```typescript -// Divide the 'total' field by the 'count' field -divide("total", field("count")); - -``` - | -| [divide(fieldName, value)](./firestore_pipelines.md#divide_65e2f32) | (Public Preview) Creates an expression that divides a field's value by a constant value. -```typescript -// Divide the 'value' field by 10 -divide("value", 10); - -``` - | -| [dotProduct(fieldName, vector)](./firestore_pipelines.md#dotproduct_463a23e) | (Public Preview) Calculates the dot product between a field's vector value and a double array. -```typescript -// Calculate the dot product distance between a feature vector and a target vector -dotProduct("features", [0.5, 0.8, 0.2]); - -``` - | -| [dotProduct(fieldName, vectorExpression)](./firestore_pipelines.md#dotproduct_ed766a1) | (Public Preview) Calculates the dot product between a field's vector value and a vector expression. -```typescript -// Calculate the dot product distance between two document vectors: 'docVector1' and 'docVector2' -dotProduct("docVector1", field("docVector2")); - -``` - | -| [endsWith(fieldName, suffix)](./firestore_pipelines.md#endswith_05ca3b0) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. -```typescript -// Check if the 'filename' field ends with ".txt" -endsWith("filename", ".txt"); - -``` - | -| [endsWith(fieldName, suffix)](./firestore_pipelines.md#endswith_8fc0ebc) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. -```typescript -// Check if the 'url' field ends with the value of the 'extension' field -endsWith("url", field("extension")); - -``` - | -| [equal(fieldName, expression)](./firestore_pipelines.md#equal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is equal to an expression. -```typescript -// Check if the 'age' field is equal to the 'limit' field -equal("age", field("limit")); - -``` - | -| [equal(fieldName, value)](./firestore_pipelines.md#equal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is equal to a constant value. -```typescript -// Check if the 'city' field is equal to string constant "London" -equal("city", "London"); - -``` - | -| [equalAny(fieldName, values)](./firestore_pipelines.md#equalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. -```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -equalAny("category", [constant("Electronics"), field("primaryType")]); - -``` - | -| [equalAny(fieldName, arrayExpression)](./firestore_pipelines.md#equalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. -```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -equalAny("category", ["Electronics", field("primaryType")]); - -``` - | -| [euclideanDistance(fieldName, vector)](./firestore_pipelines.md#euclideandistance_463a23e) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a double array. -```typescript -// Calculate the Euclidean distance between the 'location' field and a target location -euclideanDistance("location", [37.7749, -122.4194]); - -``` - | -| [euclideanDistance(fieldName, vectorExpression)](./firestore_pipelines.md#euclideandistance_ed766a1) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a vector expression. -```typescript -// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' -euclideanDistance("pointA", field("pointB")); - -``` - | -| [exists(fieldName)](./firestore_pipelines.md#exists_e5b0480) | (Public Preview) Creates an expression that checks if a field exists. -```typescript -// Check if the document has a field named "phoneNumber" -exists("phoneNumber"); - -``` - | -| [exp(fieldName)](./firestore_pipelines.md#exp_e5b0480) | (Public Preview) Creates an expression that computes e to the power of the expression's result. -```typescript -// Compute e to the power of the 'value' field. -exp('value'); - -``` - A new representing the exp of the numeric value. | +| [add(fieldName, second)](./firestore_pipelines.md#add_b75bb8b) | (Public Preview) Creates an expression that adds a field's value to an expression. | +| [arrayContains(fieldName, element)](./firestore_pipelines.md#arraycontains_aaace4a) | (Public Preview) Creates an expression that checks if a field's array value contains a specific element. | +| [arrayContains(fieldName, element)](./firestore_pipelines.md#arraycontains_999590f) | (Public Preview) Creates an expression that checks if a field's array value contains a specific value. | +| [arrayContainsAll(fieldName, values)](./firestore_pipelines.md#arraycontainsall_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. | +| [arrayContainsAll(fieldName, arrayExpression)](./firestore_pipelines.md#arraycontainsall_48da8d9) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. | +| [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. | +| [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_1b4f7cd) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. | +| [arrayLength(fieldName)](./firestore_pipelines.md#arraylength_e5b0480) | (Public Preview) Creates an expression that calculates the length of an array in a specified field. | +| [arraySum(fieldName)](./firestore_pipelines.md#arraysum_e5b0480) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | +| [ascending(fieldName)](./firestore_pipelines.md#ascending_e5b0480) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. | +| [average(fieldName)](./firestore_pipelines.md#average_e5b0480) | (Public Preview) Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. | +| [byteLength(fieldName)](./firestore_pipelines.md#bytelength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. | +| [ceil(fieldName)](./firestore_pipelines.md#ceil_e5b0480) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | +| [charLength(fieldName)](./firestore_pipelines.md#charlength_e5b0480) | (Public Preview) Creates an expression that calculates the character length of a string field in UTF8. | +| [collectionId(fieldName)](./firestore_pipelines.md#collectionid_e5b0480) | (Public Preview) Creates an expression that returns the collection ID from a path. | +| [concat(fieldName, second, others)](./firestore_pipelines.md#concat_828272e) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | +| [cosineDistance(fieldName, vector)](./firestore_pipelines.md#cosinedistance_463a23e) | (Public Preview) Calculates the Cosine distance between a field's vector value and a literal vector value. | +| [cosineDistance(fieldName, vectorExpression)](./firestore_pipelines.md#cosinedistance_ed766a1) | (Public Preview) Calculates the Cosine distance between a field's vector value and a vector expression. | +| [count(fieldName)](./firestore_pipelines.md#count_e5b0480) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the input field exists. | +| [descending(fieldName)](./firestore_pipelines.md#descending_e5b0480) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on a field. | +| [divide(fieldName, expressions)](./firestore_pipelines.md#divide_cf36e43) | (Public Preview) Creates an expression that divides a field's value by an expression. | +| [divide(fieldName, value)](./firestore_pipelines.md#divide_65e2f32) | (Public Preview) Creates an expression that divides a field's value by a constant value. | +| [dotProduct(fieldName, vector)](./firestore_pipelines.md#dotproduct_463a23e) | (Public Preview) Calculates the dot product between a field's vector value and a double array. | +| [dotProduct(fieldName, vectorExpression)](./firestore_pipelines.md#dotproduct_ed766a1) | (Public Preview) Calculates the dot product between a field's vector value and a vector expression. | +| [endsWith(fieldName, suffix)](./firestore_pipelines.md#endswith_05ca3b0) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. | +| [endsWith(fieldName, suffix)](./firestore_pipelines.md#endswith_8fc0ebc) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. | +| [equal(fieldName, expression)](./firestore_pipelines.md#equal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is equal to an expression. | +| [equal(fieldName, value)](./firestore_pipelines.md#equal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is equal to a constant value. | +| [equalAny(fieldName, values)](./firestore_pipelines.md#equalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. | +| [equalAny(fieldName, arrayExpression)](./firestore_pipelines.md#equalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. | +| [euclideanDistance(fieldName, vector)](./firestore_pipelines.md#euclideandistance_463a23e) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a double array. | +| [euclideanDistance(fieldName, vectorExpression)](./firestore_pipelines.md#euclideandistance_ed766a1) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a vector expression. | +| [exists(fieldName)](./firestore_pipelines.md#exists_e5b0480) | (Public Preview) Creates an expression that checks if a field exists. | +| [exp(fieldName)](./firestore_pipelines.md#exp_e5b0480) | (Public Preview) Creates an expression that computes e to the power of the expression's result. | | [floor(fieldName)](./firestore_pipelines.md#floor_e5b0480) | (Public Preview) Creates an expression that computes the floor of a numeric value. | -| [greaterThan(fieldName, expression)](./firestore_pipelines.md#greaterthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is greater than an expression. -```typescript -// Check if the value of field 'age' is greater than the value of field 'limit' -greaterThan("age", field("limit")); - -``` - | -| [greaterThan(fieldName, value)](./firestore_pipelines.md#greaterthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than a constant value. -```typescript -// Check if the 'price' field is greater than 100 -greaterThan("price", 100); - -``` - | -| [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_2e16acb) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to an expression. -```typescript -// Check if the value of field 'age' is greater than or equal to the value of field 'limit' -greaterThanOrEqual("age", field("limit")); - -``` - | -| [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to a constant value. -```typescript -// Check if the 'score' field is greater than or equal to 80 -greaterThanOrEqual("score", 80); - -``` - | -| [length\_2(fieldName)](./firestore_pipelines.md#length_2_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. -```typescript -// Get the length of the 'name' field. -length("name"); - -// Get the number of items in the 'cart' array. -length("cart"); - -``` - | -| [lessThan(fieldName, expression)](./firestore_pipelines.md#lessthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than an expression. -```typescript -// Check if the 'age' field is less than the 'limit' field -lessThan("age", field("limit")); - -``` - | -| [lessThan(fieldName, value)](./firestore_pipelines.md#lessthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than a constant value. -```typescript -// Check if the 'price' field is less than 50 -lessThan("price", 50); - -``` - | -| [lessThanOrEqual(fieldName, expression)](./firestore_pipelines.md#lessthanorequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to an expression. -```typescript -// Check if the 'quantity' field is less than or equal to the 'limit' field -lessThan("quantity", field("limit")); - -``` - | -| [lessThanOrEqual(fieldName, value)](./firestore_pipelines.md#lessthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to a constant value. -```typescript -// Check if the 'score' field is less than or equal to 70 -lessThan("score", 70); - -``` - | -| [like(fieldName, pattern)](./firestore_pipelines.md#like_67f7432) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. -```typescript -// Check if the 'title' field contains the string "guide" -like("title", "%guide%"); - -``` - | -| [like(fieldName, pattern)](./firestore_pipelines.md#like_cb1318d) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. -```typescript -// Check if the 'title' field contains the string "guide" -like("title", field("pattern")); - -``` - | -| [ln(fieldName)](./firestore_pipelines.md#ln_e5b0480) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. -```typescript -// Compute the natural logarithm of the 'value' field. -ln("value"); - -``` - | -| [log(fieldName, base)](./firestore_pipelines.md#log_a89e21b) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. -```typescript -// Compute the logarithm of the 'value' field with base 10. -log("value", 10); - -``` - | -| [log(fieldName, base)](./firestore_pipelines.md#log_805b11f) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. -```typescript -// Compute the logarithm of the 'value' field with the base in the 'base' field. -log("value", field("base")); - -``` - | -| [log10(fieldName)](./firestore_pipelines.md#log10_e5b0480) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. -```typescript -// Compute the base-10 logarithm of the 'value' field. -log10("value"); - -``` - | -| [logicalMaximum(fieldName, second, others)](./firestore_pipelines.md#logicalmaximum_828272e) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. -```typescript -// Returns the largest value between the 'field1' field, the 'field2' field, -// and 1000. -logicalMaximum("field1", field("field2"), 1000); - -``` - | -| [logicalMinimum(fieldName, second, others)](./firestore_pipelines.md#logicalminimum_828272e) | (Public Preview) Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. -```typescript -// Returns the smallest value between the 'field1' field, the 'field2' field, -// and 1000. -logicalMinimum("field1", field("field2"), 1000); - -``` - | -| [mapGet(fieldName, subField)](./firestore_pipelines.md#mapget_06663cf) | (Public Preview) Accesses a value from a map (object) field using the provided key. -```typescript -// Get the 'city' value from the 'address' map field -mapGet("address", "city"); - -``` - | -| [maximum(fieldName)](./firestore_pipelines.md#maximum_e5b0480) | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. -```typescript -// Find the highest score in a leaderboard -maximum("score").as("highestScore"); - -``` - | -| [minimum(fieldName)](./firestore_pipelines.md#minimum_e5b0480) | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. -```typescript -// Find the lowest price of all products -minimum("price").as("lowestPrice"); - -``` - | -| [mod(fieldName, expression)](./firestore_pipelines.md#mod_1e91657) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. -```typescript -// Calculate the remainder of dividing 'field1' by 'field2'. -mod("field1", field("field2")); - -``` - | -| [mod(fieldName, value)](./firestore_pipelines.md#mod_65e2f32) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. -```typescript -// Calculate the remainder of dividing 'field1' by 5. -mod("field1", 5); - -``` - | -| [multiply(fieldName, second)](./firestore_pipelines.md#multiply_b75bb8b) | (Public Preview) Creates an expression that multiplies a field's value by an expression. -```typescript -// Multiply the 'quantity' field by the 'price' field -multiply("quantity", field("price")); - -``` - | -| [notEqual(fieldName, expression)](./firestore_pipelines.md#notequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is not equal to an expression. -```typescript -// Check if the 'status' field is not equal to the value of 'expectedStatus' -notEqual("status", field("expectedStatus")); - -``` - | -| [notEqual(fieldName, value)](./firestore_pipelines.md#notequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is not equal to a constant value. -```typescript -// Check if the 'country' field is not equal to "USA" -notEqual("country", "USA"); - -``` - | -| [notEqualAny(fieldName, values)](./firestore_pipelines.md#notequalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. -```typescript -// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' -notEqualAny("status", [constant("pending"), field("rejectedStatus")]); - -``` - | -| [notEqualAny(fieldName, arrayExpression)](./firestore_pipelines.md#notequalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. -```typescript -// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' -notEqualAny("status", field("rejectedStatuses")); - -``` - | -| [regexContains(fieldName, pattern)](./firestore_pipelines.md#regexcontains_67f7432) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. -```typescript -// Check if the 'description' field contains "example" (case-insensitive) -regexContains("description", "(?i)example"); - -``` - | -| [regexContains(fieldName, pattern)](./firestore_pipelines.md#regexcontains_cb1318d) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. -```typescript -// Check if the 'description' field contains "example" (case-insensitive) -regexContains("description", field("pattern")); - -``` - | -| [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_67f7432) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. -```typescript -// Check if the 'email' field matches a valid email pattern -regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); - -``` - | -| [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_cb1318d) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. -```typescript -// Check if the 'email' field matches a valid email pattern -regexMatch("email", field("pattern")); - -``` - | -| [round(fieldName)](./firestore_pipelines.md#round_e5b0480) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. -```typescript -// Round the value of the 'price' field. -round("price"); - -``` - | -| [round(fieldName, decimalPlaces)](./firestore_pipelines.md#round_07d0cf0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. -```typescript -// Round the value of the 'price' field to two decimal places. -round("price", 2); - -``` - | +| [greaterThan(fieldName, expression)](./firestore_pipelines.md#greaterthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is greater than an expression. | +| [greaterThan(fieldName, value)](./firestore_pipelines.md#greaterthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than a constant value. | +| [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_2e16acb) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to an expression. | +| [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to a constant value. | +| [length\_2(fieldName)](./firestore_pipelines.md#length_2_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | +| [lessThan(fieldName, expression)](./firestore_pipelines.md#lessthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than an expression. | +| [lessThan(fieldName, value)](./firestore_pipelines.md#lessthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than a constant value. | +| [lessThanOrEqual(fieldName, expression)](./firestore_pipelines.md#lessthanorequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to an expression. | +| [lessThanOrEqual(fieldName, value)](./firestore_pipelines.md#lessthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to a constant value. | +| [like(fieldName, pattern)](./firestore_pipelines.md#like_67f7432) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. | +| [like(fieldName, pattern)](./firestore_pipelines.md#like_cb1318d) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. | +| [ln(fieldName)](./firestore_pipelines.md#ln_e5b0480) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. | +| [log(fieldName, base)](./firestore_pipelines.md#log_a89e21b) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. | +| [log(fieldName, base)](./firestore_pipelines.md#log_805b11f) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. | +| [log10(fieldName)](./firestore_pipelines.md#log10_e5b0480) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | +| [logicalMaximum(fieldName, second, others)](./firestore_pipelines.md#logicalmaximum_828272e) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | +| [logicalMinimum(fieldName, second, others)](./firestore_pipelines.md#logicalminimum_828272e) | (Public Preview) Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. | +| [mapGet(fieldName, subField)](./firestore_pipelines.md#mapget_06663cf) | (Public Preview) Accesses a value from a map (object) field using the provided key. | +| [maximum(fieldName)](./firestore_pipelines.md#maximum_e5b0480) | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | +| [minimum(fieldName)](./firestore_pipelines.md#minimum_e5b0480) | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | +| [mod(fieldName, expression)](./firestore_pipelines.md#mod_1e91657) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. | +| [mod(fieldName, value)](./firestore_pipelines.md#mod_65e2f32) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. | +| [multiply(fieldName, second)](./firestore_pipelines.md#multiply_b75bb8b) | (Public Preview) Creates an expression that multiplies a field's value by an expression. | +| [notEqual(fieldName, expression)](./firestore_pipelines.md#notequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is not equal to an expression. | +| [notEqual(fieldName, value)](./firestore_pipelines.md#notequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is not equal to a constant value. | +| [notEqualAny(fieldName, values)](./firestore_pipelines.md#notequalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. | +| [notEqualAny(fieldName, arrayExpression)](./firestore_pipelines.md#notequalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. | +| [regexContains(fieldName, pattern)](./firestore_pipelines.md#regexcontains_67f7432) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. | +| [regexContains(fieldName, pattern)](./firestore_pipelines.md#regexcontains_cb1318d) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. | +| [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_67f7432) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | +| [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_cb1318d) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | +| [round(fieldName)](./firestore_pipelines.md#round_e5b0480) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | +| [round(fieldName, decimalPlaces)](./firestore_pipelines.md#round_07d0cf0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | | [split(fieldName, delimiter)](./firestore_pipelines.md#split_2cfdd37) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | | [split(fieldName, delimiter)](./firestore_pipelines.md#split_f4fe06a) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | -| [sqrt(fieldName)](./firestore_pipelines.md#sqrt_e5b0480) | (Public Preview) Creates an expression that computes the square root of a numeric value. -```typescript -// Compute the square root of the 'value' field. -sqrt("value"); - -``` - | -| [startsWith(fieldName, prefix)](./firestore_pipelines.md#startswith_89325cc) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. -```typescript -// Check if the 'name' field starts with "Mr." -startsWith("name", "Mr."); - -``` - | -| [startsWith(fieldName, prefix)](./firestore_pipelines.md#startswith_266c338) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. -```typescript -// Check if the 'fullName' field starts with the value of the 'firstName' field -startsWith("fullName", field("firstName")); - -``` - | -| [stringConcat(fieldName, secondString, otherStrings)](./firestore_pipelines.md#stringconcat_d80077e) | (Public Preview) Creates an expression that concatenates string functions, fields or constants together. -```typescript -// Combine the 'firstName', " ", and 'lastName' fields into a single string -stringConcat("firstName", " ", field("lastName")); - -``` - | -| [stringContains(fieldName, substring)](./firestore_pipelines.md#stringcontains_5b94cfe) | (Public Preview) Creates an expression that checks if a string field contains a specified substring. -```typescript -// Check if the 'description' field contains "example". -stringContains("description", "example"); - -``` - | -| [stringContains(fieldName, substring)](./firestore_pipelines.md#stringcontains_ac3ba47) | (Public Preview) Creates an expression that checks if a string field contains a substring specified by an expression. -```typescript -// Check if the 'description' field contains the value of the 'keyword' field. -stringContains("description", field("keyword")); - -``` - | -| [subtract(fieldName, expression)](./firestore_pipelines.md#subtract_1e91657) | (Public Preview) Creates an expression that subtracts an expression from a field's value. -```typescript -// Subtract the 'discount' field from the 'price' field -subtract("price", field("discount")); - -``` - | -| [subtract(fieldName, value)](./firestore_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. -```typescript -// Subtract 20 from the value of the 'total' field -subtract("total", 20); - -``` - | -| [sum(fieldName)](./firestore_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. -```typescript -// Calculate the total revenue from a set of orders -sum("orderAmount").as("totalRevenue"); - -``` - | -| [timestampAdd(fieldName, unit, amount)](./firestore_pipelines.md#timestampadd_341fe7d) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. -```typescript -// Add 1 day to the 'timestamp' field. -timestampAdd("timestamp", "day", 1); - -``` - | -| [timestampSubtract(fieldName, unit, amount)](./firestore_pipelines.md#timestampsubtract_341fe7d) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. -```typescript -// Subtract 1 day from the 'timestamp' field. -timestampSubtract("timestamp", "day", 1); - -``` - | -| [timestampToUnixMicros(fieldName)](./firestore_pipelines.md#timestamptounixmicros_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to microseconds since epoch. -timestampToUnixMicros("timestamp"); - -``` - | -| [timestampToUnixMillis(fieldName)](./firestore_pipelines.md#timestamptounixmillis_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -timestampToUnixMillis("timestamp"); - -``` - | -| [timestampToUnixSeconds(fieldName)](./firestore_pipelines.md#timestamptounixseconds_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to seconds since epoch. -timestampToUnixSeconds("timestamp"); - -``` - | +| [sqrt(fieldName)](./firestore_pipelines.md#sqrt_e5b0480) | (Public Preview) Creates an expression that computes the square root of a numeric value. | +| [startsWith(fieldName, prefix)](./firestore_pipelines.md#startswith_89325cc) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. | +| [startsWith(fieldName, prefix)](./firestore_pipelines.md#startswith_266c338) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. | +| [stringConcat(fieldName, secondString, otherStrings)](./firestore_pipelines.md#stringconcat_d80077e) | (Public Preview) Creates an expression that concatenates string functions, fields or constants together. | +| [stringContains(fieldName, substring)](./firestore_pipelines.md#stringcontains_5b94cfe) | (Public Preview) Creates an expression that checks if a string field contains a specified substring. | +| [stringContains(fieldName, substring)](./firestore_pipelines.md#stringcontains_ac3ba47) | (Public Preview) Creates an expression that checks if a string field contains a substring specified by an expression. | +| [subtract(fieldName, expression)](./firestore_pipelines.md#subtract_1e91657) | (Public Preview) Creates an expression that subtracts an expression from a field's value. | +| [subtract(fieldName, value)](./firestore_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. | +| [sum(fieldName)](./firestore_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. | +| [timestampAdd(fieldName, unit, amount)](./firestore_pipelines.md#timestampadd_341fe7d) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. | +| [timestampSubtract(fieldName, unit, amount)](./firestore_pipelines.md#timestampsubtract_341fe7d) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. | +| [timestampToUnixMicros(fieldName)](./firestore_pipelines.md#timestamptounixmicros_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixMillis(fieldName)](./firestore_pipelines.md#timestamptounixmillis_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixSeconds(fieldName)](./firestore_pipelines.md#timestamptounixseconds_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | | [timestampTruncate(fieldName, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_b6c7512) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | | [timestampTruncate(fieldName, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_ed83d46) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [toLower(fieldName)](./firestore_pipelines.md#tolower_e5b0480) | (Public Preview) Creates an expression that converts a string field to lowercase. -```typescript -// Convert the 'name' field to lowercase -toLower("name"); - -``` - | -| [toUpper(fieldName)](./firestore_pipelines.md#toupper_e5b0480) | (Public Preview) Creates an expression that converts a string field to uppercase. -```typescript -// Convert the 'title' field to uppercase -toUpper("title"); - -``` - | -| [trim(fieldName, valueToTrim)](./firestore_pipelines.md#trim_c9f90ee) | (Public Preview) Creates an expression that removes leading and trailing whitespace from a string or byte array. -```typescript -// Trim whitespace from the 'userInput' field -trim("userInput"); - -// Trim quotes from the 'userInput' field -trim("userInput", '"'); - -``` - | +| [toLower(fieldName)](./firestore_pipelines.md#tolower_e5b0480) | (Public Preview) Creates an expression that converts a string field to lowercase. | +| [toUpper(fieldName)](./firestore_pipelines.md#toupper_e5b0480) | (Public Preview) Creates an expression that converts a string field to uppercase. | +| [trim(fieldName, valueToTrim)](./firestore_pipelines.md#trim_c9f90ee) | (Public Preview) Creates an expression that removes leading and trailing whitespace from a string or byte array. | | [type(fieldName)](./firestore_pipelines.md#type_e5b0480) | (Public Preview) Creates an expression that returns the data type of the data in the specified field. | -| [unixMicrosToTimestamp(fieldName)](./firestore_pipelines.md#unixmicrostotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -unixMicrosToTimestamp("microseconds"); - -``` - | -| [unixMillisToTimestamp(fieldName)](./firestore_pipelines.md#unixmillistotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -unixMillisToTimestamp("milliseconds"); - -``` - | -| [unixSecondsToTimestamp(fieldName)](./firestore_pipelines.md#unixsecondstotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'seconds' field as seconds since epoch. -unixSecondsToTimestamp("seconds"); - -``` - | -| [vectorLength(fieldName)](./firestore_pipelines.md#vectorlength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector represented by a field. -```typescript -// Get the vector length (dimension) of the field 'embedding'. -vectorLength("embedding"); - -``` - | +| [unixMicrosToTimestamp(fieldName)](./firestore_pipelines.md#unixmicrostotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixMillisToTimestamp(fieldName)](./firestore_pipelines.md#unixmillistotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixSecondsToTimestamp(fieldName)](./firestore_pipelines.md#unixsecondstotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [vectorLength(fieldName)](./firestore_pipelines.md#vectorlength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector represented by a field. | | function(first, ...) | -| [add(first, second)](./firestore_pipelines.md#add_846ca1b) | (Public Preview) Creates an expression that adds two expressions together. -```typescript -// Add the value of the 'quantity' field and the 'reserve' field. -add(field("quantity"), field("reserve")); - -``` - | -| [and(first, second, more)](./firestore_pipelines.md#and_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'AND' operation on multiple filter conditions. -```typescript -// Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND -// the 'status' field is "active" -const condition = and(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); - -``` - | -| [concat(first, second, others)](./firestore_pipelines.md#concat_83be015) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. -```typescript -// Concatenate the 'firstName' and 'lastName' fields with a space in between. -concat(field("firstName"), " ", field("lastName")) - -``` - | -| [logicalMaximum(first, second, others)](./firestore_pipelines.md#logicalmaximum_83be015) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. -```typescript -// Returns the largest value between the 'field1' field, the 'field2' field, -// and 1000 -logicalMaximum(field("field1"), field("field2"), 1000); - -``` - | -| [logicalMinimum(first, second, others)](./firestore_pipelines.md#logicalminimum_83be015) | (Public Preview) Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. -```typescript -// Returns the smallest value between the 'field1' field, the 'field2' field, -// and 1000. -logicalMinimum(field("field1"), field("field2"), 1000); - -``` - | -| [multiply(first, second)](./firestore_pipelines.md#multiply_846ca1b) | (Public Preview) Creates an expression that multiplies two expressions together. -```typescript -// Multiply the 'quantity' field by the 'price' field -multiply(field("quantity"), field("price")); - -``` - | -| [or(first, second, more)](./firestore_pipelines.md#or_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'OR' operation on multiple filter conditions. -```typescript -// Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR -// the 'status' field is "active" -const condition = or(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); - -``` - | -| [xor(first, second, additionalConditions)](./firestore_pipelines.md#xor_8197113) | (Public Preview) Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. -```typescript -// Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London", -// or 'status' is "active". -const condition = xor( - greaterThan("age", 18), - equal("city", "London"), - equal("status", "active")); - -``` - | +| [add(first, second)](./firestore_pipelines.md#add_846ca1b) | (Public Preview) Creates an expression that adds two expressions together. | +| [and(first, second, more)](./firestore_pipelines.md#and_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'AND' operation on multiple filter conditions. | +| [concat(first, second, others)](./firestore_pipelines.md#concat_83be015) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | +| [logicalMaximum(first, second, others)](./firestore_pipelines.md#logicalmaximum_83be015) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | +| [logicalMinimum(first, second, others)](./firestore_pipelines.md#logicalminimum_83be015) | (Public Preview) Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. | +| [multiply(first, second)](./firestore_pipelines.md#multiply_846ca1b) | (Public Preview) Creates an expression that multiplies two expressions together. | +| [or(first, second, more)](./firestore_pipelines.md#or_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'OR' operation on multiple filter conditions. | +| [xor(first, second, additionalConditions)](./firestore_pipelines.md#xor_8197113) | (Public Preview) Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. | | function(firstArray, ...) | -| [arrayConcat(firstArray, secondArray, otherArrays)](./firestore_pipelines.md#arrayconcat_c00d5d7) | (Public Preview) Creates an expression that concatenates an array expression with other arrays. -```typescript -// Combine the 'items' array with two new item arrays -arrayConcat(field("items"), [field("newItems"), field("otherItems")]); - -``` - | -| function(firstArrayField, ...) | -| [arrayConcat(firstArrayField, secondArray, otherArrays)](./firestore_pipelines.md#arrayconcat_f92063d) | (Public Preview) Creates an expression that concatenates a field's array value with other arrays. -```typescript -// Combine the 'items' array with two new item arrays -arrayConcat("items", [field("newItems"), field("otherItems")]); - -``` - | +| [arrayConcat(firstArray, secondArray, otherArrays)](./firestore_pipelines.md#arrayconcat_c00d5d7) | (Public Preview) Creates an expression that concatenates an array expression with other arrays. | +| function(firstArrayField, ...) | +| [arrayConcat(firstArrayField, secondArray, otherArrays)](./firestore_pipelines.md#arrayconcat_f92063d) | (Public Preview) Creates an expression that concatenates a field's array value with other arrays. | | function(firstMap, ...) | -| [mapMerge(firstMap, secondMap, otherMaps)](./firestore_pipelines.md#mapmerge_cfe77ce) | (Public Preview) Creates an expression that merges multiple map values. -``` -// Merges the map in the settings field with, a map literal, and a map in -// that is conditionally returned by another expression -mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) - -``` - | +| [mapMerge(firstMap, secondMap, otherMaps)](./firestore_pipelines.md#mapmerge_cfe77ce) | (Public Preview) Creates an expression that merges multiple map values. | | function(firstString, ...) | -| [stringConcat(firstString, secondString, otherStrings)](./firestore_pipelines.md#stringconcat_8a8d1b6) | (Public Preview) Creates an expression that concatenates string expressions together. -```typescript -// Combine the 'firstName', " ", and 'lastName' fields into a single string -stringConcat(field("firstName"), " ", field("lastName")); - -``` - | +| [stringConcat(firstString, secondString, otherStrings)](./firestore_pipelines.md#stringconcat_8a8d1b6) | (Public Preview) Creates an expression that concatenates string expressions together. | | function(ifExpr, ...) | -| [ifAbsent(ifExpr, elseExpr)](./firestore_pipelines.md#ifabsent_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -ifAbsent(field("optional_field"), constant("default_value")) - -``` - | -| [ifAbsent(ifExpr, elseValue)](./firestore_pipelines.md#ifabsent_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -ifAbsent(field("optional_field"), "default_value") - -``` - | +| [ifAbsent(ifExpr, elseExpr)](./firestore_pipelines.md#ifabsent_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | +| [ifAbsent(ifExpr, elseValue)](./firestore_pipelines.md#ifabsent_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | | function(ifFieldName, ...) | -| [ifAbsent(ifFieldName, elseExpr)](./firestore_pipelines.md#ifabsent_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName is absent, else return the value of the field. -```typescript -// Returns the value of the optional field 'optional_field', or returns the value of -// 'default_field' if 'optional_field' is absent. -ifAbsent("optional_field", field("default_field")) - -``` - | -| [ifAbsent(ifFieldName, elseValue)](./firestore_pipelines.md#ifabsent_d8f2823) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName is absent, else return the value of the field. -```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -ifAbsent("optional_field", "default_value") - -``` - | +| [ifAbsent(ifFieldName, elseExpr)](./firestore_pipelines.md#ifabsent_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName is absent, else return the value of the field. | +| [ifAbsent(ifFieldName, elseValue)](./firestore_pipelines.md#ifabsent_d8f2823) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName is absent, else return the value of the field. | | function(input, ...) | | [substring(input, position, length)](./firestore_pipelines.md#substring_e6e0aa3) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | | [substring(input, position, length)](./firestore_pipelines.md#substring_ab56dc6) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | | function(left, ...) | -| [divide(left, right)](./firestore_pipelines.md#divide_b3c3382) | (Public Preview) Creates an expression that divides two expressions. -```typescript -// Divide the 'total' field by the 'count' field -divide(field("total"), field("count")); - -``` - | -| [equal(left, right)](./firestore_pipelines.md#equal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are equal. -```typescript -// Check if the 'age' field is equal to an expression -equal(field("age"), field("minAge").add(10)); - -``` - | -| [greaterThan(left, right)](./firestore_pipelines.md#greaterthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than the second expression. -```typescript -// Check if the 'age' field is greater than 18 -greaterThan(field("age"), Constant(9).add(9)); - -``` - | -| [greaterThanOrEqual(left, right)](./firestore_pipelines.md#greaterthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than or equal to the second expression. -```typescript -// Check if the 'quantity' field is greater than or equal to the field "threshold" -greaterThanOrEqual(field("quantity"), field("threshold")); - -``` - | -| [lessThan(left, right)](./firestore_pipelines.md#lessthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than the second expression. -```typescript -// Check if the 'age' field is less than 30 -lessThan(field("age"), field("limit")); - -``` - | -| [lessThanOrEqual(left, right)](./firestore_pipelines.md#lessthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than or equal to the second expression. -```typescript -// Check if the 'quantity' field is less than or equal to 20 -lessThan(field("quantity"), field("limit")); - -``` - | -| [mod(left, right)](./firestore_pipelines.md#mod_b3c3382) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing two expressions. -```typescript -// Calculate the remainder of dividing 'field1' by 'field2'. -mod(field("field1"), field("field2")); - -``` - | -| [notEqual(left, right)](./firestore_pipelines.md#notequal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are not equal. -```typescript -// Check if the 'status' field is not equal to field 'finalState' -notEqual(field("status"), field("finalState")); - -``` - | +| [divide(left, right)](./firestore_pipelines.md#divide_b3c3382) | (Public Preview) Creates an expression that divides two expressions. | +| [equal(left, right)](./firestore_pipelines.md#equal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are equal. | +| [greaterThan(left, right)](./firestore_pipelines.md#greaterthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than the second expression. | +| [greaterThanOrEqual(left, right)](./firestore_pipelines.md#greaterthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than or equal to the second expression. | +| [lessThan(left, right)](./firestore_pipelines.md#lessthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than the second expression. | +| [lessThanOrEqual(left, right)](./firestore_pipelines.md#lessthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than or equal to the second expression. | +| [mod(left, right)](./firestore_pipelines.md#mod_b3c3382) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing two expressions. | +| [notEqual(left, right)](./firestore_pipelines.md#notequal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are not equal. | | [pipelineResultEqual(left, right)](./firestore_pipelines.md#pipelineresultequal_707a755) | (Public Preview) Test equality of two PipelineResults. | -| [subtract(left, right)](./firestore_pipelines.md#subtract_b3c3382) | (Public Preview) Creates an expression that subtracts two expressions. -```typescript -// Subtract the 'discount' field from the 'price' field -subtract(field("price"), field("discount")); - -``` - | +| [subtract(left, right)](./firestore_pipelines.md#subtract_b3c3382) | (Public Preview) Creates an expression that subtracts two expressions. | | function(mapExpr, ...) | -| [mapRemove(mapExpr, key)](./firestore_pipelines.md#mapremove_23c7d51) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. -``` -// Removes the key 'baz' from the input map. -mapRemove(map({foo: 'bar', baz: true}), 'baz'); - -``` - | -| [mapRemove(mapExpr, keyExpr)](./firestore_pipelines.md#mapremove_9fbcaa3) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. -``` -// Removes the key 'baz' from the input map. -mapRemove(map({foo: 'bar', baz: true}), constant('baz')); - -``` - | +| [mapRemove(mapExpr, key)](./firestore_pipelines.md#mapremove_23c7d51) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. | +| [mapRemove(mapExpr, keyExpr)](./firestore_pipelines.md#mapremove_9fbcaa3) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. | | function(mapExpression, ...) | -| [mapGet(mapExpression, subField)](./firestore_pipelines.md#mapget_688c050) | (Public Preview) Accesses a value from a map (object) expression using the provided key. -```typescript -// Get the 'city' value from the 'address' map field -mapGet(field("address"), "city"); - -``` - | -| function(mapField, ...) | -| [mapMerge(mapField, secondMap, otherMaps)](./firestore_pipelines.md#mapmerge_70a564b) | (Public Preview) Creates an expression that merges multiple map values. -``` -// Merges the map in the settings field with, a map literal, and a map in -// that is conditionally returned by another expression -mapMerge('settings', { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) - -``` - | -| [mapRemove(mapField, key)](./firestore_pipelines.md#mapremove_bd5726e) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. -``` -// Removes the key 'city' field from the map in the address field of the input document. -mapRemove('address', 'city'); - -``` - | -| [mapRemove(mapField, keyExpr)](./firestore_pipelines.md#mapremove_8406d13) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. -``` -// Removes the key 'city' field from the map in the address field of the input document. -mapRemove('address', constant('city')); - -``` - | -| function(name, ...) | -| [field(name)](./firestore_pipelines.md#field_1eaaff4) | (Public Preview) Creates a instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). -```typescript -// Create a Field instance for the 'title' field -const titleField = field("title"); - -// Create a Field instance for a nested field 'author.firstName' -const authorFirstNameField = field("author.firstName"); - -``` - | -| function(options, ...) | -| [execute(options)](./firestore_pipelines.md#execute_9e87e31) | (Public Preview) Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a that contains a list of objects. Each typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:

  • If there are no stages or only transformation stages, each represents a single document.
  • If there is an aggregation, only a single is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each represents a distinct group and its associated aggregated values.

Example: -```typescript -const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") - .where(gt(field("rating"), 4.5)) - .select("title", "author", "rating")); - -const results: PipelineResults = snapshot.results; - -``` - | -| function(path, ...) | -| [field(path)](./firestore_pipelines.md#field_34ee07d) | (Public Preview) Creates a instance representing the field at the given path. | -| function(pipeline, ...) | -| [execute(pipeline)](./firestore_pipelines.md#execute_01df620) | (Public Preview) Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a that contains a list of objects. Each typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:

  • If there are no stages or only transformation stages, each represents a single document.
  • If there is an aggregation, only a single is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each represents a distinct group and its associated aggregated values.

Example: -```typescript -const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") - .where(gt(field("rating"), 4.5)) - .select("title", "author", "rating")); - -const results: PipelineResults = snapshot.results; - -``` - | -| function(stringExpression, ...) | -| [charLength(stringExpression)](./firestore_pipelines.md#charlength_c25a54a) | (Public Preview) Creates an expression that calculates the character length of a string expression in UTF-8. -```typescript -// Get the character length of the 'name' field in UTF-8. -strLength(field("name")); - -``` - | -| [endsWith(stringExpression, suffix)](./firestore_pipelines.md#endswith_0a0b889) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. -```typescript -// Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." -endsWith(field("fullName"), "Jr."); - -``` - | -| [endsWith(stringExpression, suffix)](./firestore_pipelines.md#endswith_13aee0d) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. -```typescript -// Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." -endsWith(field("fullName"), constant("Jr.")); - -``` - | -| [like(stringExpression, pattern)](./firestore_pipelines.md#like_a84c581) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. -```typescript -// Check if the 'title' field contains the string "guide" -like(field("title"), "%guide%"); - -``` - | -| [like(stringExpression, pattern)](./firestore_pipelines.md#like_b534848) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. -```typescript -// Check if the 'title' field contains the string "guide" -like(field("title"), field("pattern")); - -``` - | -| [regexContains(stringExpression, pattern)](./firestore_pipelines.md#regexcontains_a84c581) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. -```typescript -// Check if the 'description' field contains "example" (case-insensitive) -regexContains(field("description"), "(?i)example"); - -``` - | -| [regexContains(stringExpression, pattern)](./firestore_pipelines.md#regexcontains_b534848) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. -```typescript -// Check if the 'description' field contains "example" (case-insensitive) -regexContains(field("description"), field("pattern")); - -``` - | -| [regexMatch(stringExpression, pattern)](./firestore_pipelines.md#regexmatch_a84c581) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. -```typescript -// Check if the 'email' field matches a valid email pattern -regexMatch(field("email"), "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); - -``` - | -| [regexMatch(stringExpression, pattern)](./firestore_pipelines.md#regexmatch_b534848) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. -```typescript -// Check if the 'email' field matches a valid email pattern -regexMatch(field("email"), field("pattern")); - -``` - | -| [reverse(stringExpression)](./firestore_pipelines.md#reverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. -```typescript -// Reverse the value of the 'myString' field. -reverse(field("myString")); - -``` - | -| [startsWith(stringExpression, prefix)](./firestore_pipelines.md#startswith_75c3dbb) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. -```typescript -// Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." -startsWith(field("fullName"), "Mr."); - -``` - | -| [startsWith(stringExpression, prefix)](./firestore_pipelines.md#startswith_52f218a) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. -```typescript -// Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." -startsWith(field("fullName"), field("prefix")); - -``` - | -| [stringContains(stringExpression, substring)](./firestore_pipelines.md#stringcontains_3e9ff32) | (Public Preview) Creates an expression that checks if a string expression contains a specified substring. -```typescript -// Check if the 'description' field contains "example". -stringContains(field("description"), "example"); - -``` - | -| [stringContains(stringExpression, substring)](./firestore_pipelines.md#stringcontains_cc6ee02) | (Public Preview) Creates an expression that checks if a string expression contains a substring specified by another expression. -```typescript -// Check if the 'description' field contains the value of the 'keyword' field. -stringContains(field("description"), field("keyword")); - -``` - | -| [stringReverse(stringExpression)](./firestore_pipelines.md#stringreverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. -```typescript -// Reverse the value of the 'myString' field. -strReverse(field("myString")); - -``` - | -| [toLower(stringExpression)](./firestore_pipelines.md#tolower_c25a54a) | (Public Preview) Creates an expression that converts a string expression to lowercase. -```typescript -// Convert the 'name' field to lowercase -toLower(field("name")); - -``` - | -| [toUpper(stringExpression)](./firestore_pipelines.md#toupper_c25a54a) | (Public Preview) Creates an expression that converts a string expression to uppercase. -```typescript -// Convert the 'title' field to uppercase -toUppercase(field("title")); - -``` - | -| [trim(stringExpression, valueToTrim)](./firestore_pipelines.md#trim_dd54322) | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array expression. -```typescript -// Trim whitespace from the 'userInput' field -trim(field("userInput")); - -// Trim quotes from the 'userInput' field -trim(field("userInput"), '"'); - -``` - | -| function(timestamp, ...) | -| [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_98418f9) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. -```typescript -// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. -timestampAdd(field("timestamp"), field("unit"), field("amount")); - -``` - | -| [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_ffe8e57) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. -```typescript -// Add 1 day to the 'timestamp' field. -timestampAdd(field("timestamp"), "day", 1); - -``` - | -| [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_98418f9) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. -```typescript -// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. -timestampSubtract(field("timestamp"), field("unit"), field("amount")); - -``` - | -| [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_ffe8e57) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. -```typescript -// Subtract 1 day from the 'timestamp' field. -timestampSubtract(field("timestamp"), "day", 1); - -``` - | +| [mapGet(mapExpression, subField)](./firestore_pipelines.md#mapget_688c050) | (Public Preview) Accesses a value from a map (object) expression using the provided key. | +| function(mapField, ...) | +| [mapMerge(mapField, secondMap, otherMaps)](./firestore_pipelines.md#mapmerge_70a564b) | (Public Preview) Creates an expression that merges multiple map values. | +| [mapRemove(mapField, key)](./firestore_pipelines.md#mapremove_bd5726e) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. | +| [mapRemove(mapField, keyExpr)](./firestore_pipelines.md#mapremove_8406d13) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. | +| function(name, ...) | +| [field(name)](./firestore_pipelines.md#field_1eaaff4) | (Public Preview) Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). | +| function(options, ...) | +| [execute(options)](./firestore_pipelines.md#execute_9e87e31) | (Public Preview) Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:

  • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
  • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
| +| function(path, ...) | +| [field(path)](./firestore_pipelines.md#field_34ee07d) | (Public Preview) Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. | +| function(pipeline, ...) | +| [execute(pipeline)](./firestore_pipelines.md#execute_01df620) | (Public Preview) Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:
  • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
  • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
| +| function(stringExpression, ...) | +| [charLength(stringExpression)](./firestore_pipelines.md#charlength_c25a54a) | (Public Preview) Creates an expression that calculates the character length of a string expression in UTF-8. | +| [endsWith(stringExpression, suffix)](./firestore_pipelines.md#endswith_0a0b889) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. | +| [endsWith(stringExpression, suffix)](./firestore_pipelines.md#endswith_13aee0d) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. | +| [like(stringExpression, pattern)](./firestore_pipelines.md#like_a84c581) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. | +| [like(stringExpression, pattern)](./firestore_pipelines.md#like_b534848) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. | +| [regexContains(stringExpression, pattern)](./firestore_pipelines.md#regexcontains_a84c581) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. | +| [regexContains(stringExpression, pattern)](./firestore_pipelines.md#regexcontains_b534848) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. | +| [regexMatch(stringExpression, pattern)](./firestore_pipelines.md#regexmatch_a84c581) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. | +| [regexMatch(stringExpression, pattern)](./firestore_pipelines.md#regexmatch_b534848) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. | +| [reverse(stringExpression)](./firestore_pipelines.md#reverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. | +| [startsWith(stringExpression, prefix)](./firestore_pipelines.md#startswith_75c3dbb) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. | +| [startsWith(stringExpression, prefix)](./firestore_pipelines.md#startswith_52f218a) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. | +| [stringContains(stringExpression, substring)](./firestore_pipelines.md#stringcontains_3e9ff32) | (Public Preview) Creates an expression that checks if a string expression contains a specified substring. | +| [stringContains(stringExpression, substring)](./firestore_pipelines.md#stringcontains_cc6ee02) | (Public Preview) Creates an expression that checks if a string expression contains a substring specified by another expression. | +| [stringReverse(stringExpression)](./firestore_pipelines.md#stringreverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. | +| [toLower(stringExpression)](./firestore_pipelines.md#tolower_c25a54a) | (Public Preview) Creates an expression that converts a string expression to lowercase. | +| [toUpper(stringExpression)](./firestore_pipelines.md#toupper_c25a54a) | (Public Preview) Creates an expression that converts a string expression to uppercase. | +| [trim(stringExpression, valueToTrim)](./firestore_pipelines.md#trim_dd54322) | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array expression. | +| function(timestamp, ...) | +| [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_98418f9) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | +| [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_ffe8e57) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | +| [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_98418f9) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | +| [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_ffe8e57) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | | function(timestampExpression, ...) | | [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_ad5d843) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | | [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_d6ab2a4) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | | function(tryExpr, ...) | -| [ifError(tryExpr, catchExpr)](./firestore_pipelines.md#iferror_a99a327) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation.This overload is useful when a BooleanExpression is required. -```typescript -// Create an expression that protects against a divide by zero error -// but always returns a boolean expression. -ifError(constant(50).divide('length').gt(1), constant(false)); - -``` - | -| [ifError(tryExpr, catchExpr)](./firestore_pipelines.md#iferror_756c12e) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. -```typescript -// Returns the first item in the title field arrays, or returns -// the entire title field if the array is empty or the field is another type. -ifError(field("title").arrayGet(0), field("title")); - -``` - | -| [ifError(tryExpr, catchValue)](./firestore_pipelines.md#iferror_dc532f9) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. -```typescript -// Returns the first item in the title field arrays, or returns -// "Default Title" -ifError(field("title").arrayGet(0), "Default Title"); - -``` - | +| [ifError(tryExpr, catchExpr)](./firestore_pipelines.md#iferror_a99a327) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation.This overload is useful when a BooleanExpression is required. | +| [ifError(tryExpr, catchExpr)](./firestore_pipelines.md#iferror_756c12e) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. | +| [ifError(tryExpr, catchValue)](./firestore_pipelines.md#iferror_dc532f9) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. | | function(value, ...) | | [constant(value)](./firestore_pipelines.md#constant_0c00f91) | (Public Preview) Creates a Constant instance for a number value. | | [constant(value)](./firestore_pipelines.md#constant_6dac335) | (Public Preview) Creates a Constant instance for a VectorValue value. | @@ -1651,78 +300,17 @@ ifError(field("title").arrayGet(0), "Default Title"); | [constant(value)](./firestore_pipelines.md#constant_5131bf7) | (Public Preview) Creates a Constant instance for a Date value. | | [constant(value)](./firestore_pipelines.md#constant_fdf565d) | (Public Preview) Creates a Constant instance for a Bytes value. | | [constant(value)](./firestore_pipelines.md#constant_bcd2b0b) | (Public Preview) Creates a Constant instance for a DocumentReference value. | -| [exists(value)](./firestore_pipelines.md#exists_f3daf14) | (Public Preview) Creates an expression that checks if a field exists. -```typescript -// Check if the document has a field named "phoneNumber" -exists(field("phoneNumber")); - -``` - | -| [isAbsent(value)](./firestore_pipelines.md#isabsent_f3daf14) | (Public Preview) Creates an expression that returns true if a value is absent. Otherwise, returns false even if the value is null. -```typescript -// Check if the field `value` is absent. -isAbsent(field("value")); - -``` - | -| [isError(value)](./firestore_pipelines.md#iserror_f3daf14) | (Public Preview) Creates an expression that checks if a given expression produces an error. -```typescript -// Check if the result of a calculation is an error -isError(field("title").arrayContains(1)); - -``` - | +| [exists(value)](./firestore_pipelines.md#exists_f3daf14) | (Public Preview) Creates an expression that checks if a field exists. | +| [isAbsent(value)](./firestore_pipelines.md#isabsent_f3daf14) | (Public Preview) Creates an expression that returns true if a value is absent. Otherwise, returns false even if the value is null. | +| [isError(value)](./firestore_pipelines.md#iserror_f3daf14) | (Public Preview) Creates an expression that checks if a given expression produces an error. | | function(vectorExpression, ...) | -| [cosineDistance(vectorExpression, vector)](./firestore_pipelines.md#cosinedistance_3a80317) | (Public Preview) Calculates the Cosine distance between a vector expression and a vector literal. -```typescript -// Calculate the cosine distance between the 'location' field and a target location -cosineDistance(field("location"), [37.7749, -122.4194]); - -``` - | -| [cosineDistance(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#cosinedistance_17b5bcc) | (Public Preview) Calculates the Cosine distance between two vector expressions. -```typescript -// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field -cosineDistance(field("userVector"), field("itemVector")); - -``` - | -| [dotProduct(vectorExpression, vector)](./firestore_pipelines.md#dotproduct_3a80317) | (Public Preview) Calculates the dot product between a vector expression and a double array. -```typescript -// Calculate the dot product between a feature vector and a target vector -dotProduct(field("features"), [0.5, 0.8, 0.2]); - -``` - | -| [dotProduct(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#dotproduct_17b5bcc) | (Public Preview) Calculates the dot product between two vector expressions. -```typescript -// Calculate the dot product between two document vectors: 'docVector1' and 'docVector2' -dotProduct(field("docVector1"), field("docVector2")); - -``` - | -| [euclideanDistance(vectorExpression, vector)](./firestore_pipelines.md#euclideandistance_3a80317) | (Public Preview) Calculates the Euclidean distance between a vector expression and a double array. -```typescript -// Calculate the Euclidean distance between the 'location' field and a target location - -euclideanDistance(field("location"), [37.7749, -122.4194]); - -``` - | -| [euclideanDistance(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#euclideandistance_17b5bcc) | (Public Preview) Calculates the Euclidean distance between two vector expressions. -```typescript -// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' -euclideanDistance(field("pointA"), field("pointB")); - -``` - | -| [vectorLength(vectorExpression)](./firestore_pipelines.md#vectorlength_58a039b) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector. -```typescript -// Get the vector length (dimension) of the field 'embedding'. -vectorLength(field("embedding")); - -``` - | +| [cosineDistance(vectorExpression, vector)](./firestore_pipelines.md#cosinedistance_3a80317) | (Public Preview) Calculates the Cosine distance between a vector expression and a vector literal. | +| [cosineDistance(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#cosinedistance_17b5bcc) | (Public Preview) Calculates the Cosine distance between two vector expressions. | +| [dotProduct(vectorExpression, vector)](./firestore_pipelines.md#dotproduct_3a80317) | (Public Preview) Calculates the dot product between a vector expression and a double array. | +| [dotProduct(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#dotproduct_17b5bcc) | (Public Preview) Calculates the dot product between two vector expressions. | +| [euclideanDistance(vectorExpression, vector)](./firestore_pipelines.md#euclideandistance_3a80317) | (Public Preview) Calculates the Euclidean distance between a vector expression and a double array. | +| [euclideanDistance(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#euclideandistance_17b5bcc) | (Public Preview) Calculates the Euclidean distance between two vector expressions. | +| [vectorLength(vectorExpression)](./firestore_pipelines.md#vectorlength_58a039b) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector. | ## Classes @@ -1736,32 +324,23 @@ vectorLength(field("embedding")); | [CollectionReference](./firestore_pipelines.collectionreference.md#collectionreference_class) | A CollectionReference object can be used for adding documents, getting document references, and querying for documents (using [query()](./firestore_.md#query_9f7b0f4)). | | [DocumentReference](./firestore_pipelines.documentreference.md#documentreference_class) | A DocumentReference refers to a document location in a Firestore database and can be used to write, read, or listen to the location. The document at the referenced location may or may not exist. | | [DocumentSnapshot](./firestore_pipelines.documentsnapshot.md#documentsnapshot_class) | A DocumentSnapshot contains data read from a document in your Firestore database. The data can be extracted with .data() or .get(<field>) to get a specific field.For a DocumentSnapshot that points to a non-existing document, any data access will return 'undefined'. You can use the exists() method to explicitly verify a document's existence. | -| [Expression](./firestore_pipelines.expression.md#expression_class) | (Public Preview) Represents an expression that can be evaluated to a value within the execution of a .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 Expr class provides a fluent API for building expressions. You can chain together method calls to create complex expressions. | -| [Field](./firestore_pipelines.field.md#field_class) | (Public Preview) Represents a reference to a field in a Firestore document, or outputs of a stage.

Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines.

You can create a Field instance using the static method: -```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"); - -``` - | +| [Expression](./firestore_pipelines.expression.md#expression_class) | (Public Preview) Represents an expression that can be evaluated to a value within the execution of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class).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. | +| [Field](./firestore_pipelines.field.md#field_class) | (Public Preview) Represents a reference to a field in a Firestore document, or outputs of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) stage.

Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines.

You can create a Field instance using the static method: | | [FieldPath](./firestore_pipelines.fieldpath.md#fieldpath_class) | A FieldPath refers to a field in a document. The path may consist of a single field name (referring to a top-level field in the document), or a list of field names (referring to a nested field in the document).Create a FieldPath by providing field names. If more than one field name is provided, the path will point to a nested field in a document. | | [FieldValue](./firestore_pipelines.fieldvalue.md#fieldvalue_class) | Sentinel values that can be used when writing document fields with set() or update(). | | [Firestore](./firestore_pipelines.firestore.md#firestore_class) | The Cloud Firestore service interface.Do not call this constructor directly. Instead, use [getFirestore()](./firestore_.md#getfirestore). | -| [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) | (Public Preview) This class defines the base class for Firestore functions, which can be evaluated within pipeline execution.Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_.md#and_e72c712), , or the methods on (, , etc.) to construct new Function instances. | +| [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) | (Public Preview) This class defines the base class for Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) functions, which can be evaluated within pipeline execution.Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_pipelines.md#and_e0c48bd), [equal()](./firestore_pipelines.md#equal_b3c3382), or the methods on [Expression](./firestore_pipelines.expression.md#expression_class) ([Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), etc.) to construct new Function instances. | | [GeoPoint](./firestore_pipelines.geopoint.md#geopoint_class) | An immutable object representing a geographic location in Firestore. The location is represented as latitude/longitude pair.Latitude values are in the range of \[-90, 90\]. Longitude values are in the range of \[-180, 180\]. | | [Ordering](./firestore_pipelines.ordering.md#ordering_class) | (Public Preview) Represents an ordering criterion for sorting documents in a Firestore pipeline.You create Ordering instances using the ascending and descending helper functions. | | [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | (Public Preview) | -| [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) | (Public Preview) A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the or methods.

If the PipelineResult represents a non-document result, ref will return a undefined value. | -| [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) | (Public Preview) Represents the results of a Firestore pipeline execution.A PipelineSnapshot contains zero or more objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. | -| [PipelineSource](./firestore_pipelines.pipelinesource.md#pipelinesource_class) | (Public Preview) Provides the entry point for defining the data source of a Firestore .Use the methods of this class (e.g., , , , or ) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. | +| [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) | (Public Preview) A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the [PipelineResult.data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) or [PipelineResult.get()](./firestore_pipelines.pipelineresult.md#pipelineresultget) methods.

If the PipelineResult represents a non-document result, ref will return a undefined value. | +| [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) | (Public Preview) Represents the results of a Firestore pipeline execution.A PipelineSnapshot contains zero or more [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. | +| [PipelineSource](./firestore_pipelines.pipelinesource.md#pipelinesource_class) | (Public Preview) Provides the entry point for defining the data source of a Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class).Use the methods of this class (e.g., [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection), [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup), [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase), or [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments)) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. | | [Query](./firestore_pipelines.query.md#query_class) | A Query refers to a query which you can read or listen to. You can also construct refined Query objects by adding filters and ordering. | | [QueryDocumentSnapshot](./firestore_pipelines.querydocumentsnapshot.md#querydocumentsnapshot_class) | A QueryDocumentSnapshot contains data read from a document in your Firestore database as part of a query. The document is guaranteed to exist and its data can be extracted with .data() or .get(<field>) to get a specific field.A QueryDocumentSnapshot offers the same API surface as a DocumentSnapshot. Since query results contain only existing documents, the exists property will always be true and data() will never return 'undefined'. | | [SnapshotMetadata](./firestore_pipelines.snapshotmetadata.md#snapshotmetadata_class) | Metadata about a snapshot, describing the state of the snapshot. | | [Timestamp](./firestore_pipelines.timestamp.md#timestamp_class) | A Timestamp represents a point in time independent of any time zone or calendar, represented as seconds and fractions of seconds at nanosecond resolution in UTC Epoch time.It is encoded using the Proleptic Gregorian Calendar which extends the Gregorian calendar backwards to year one. It is encoded assuming all minutes are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.For examples and further specifications, refer to the [Timestamp definition](https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto). | -| [VectorValue](./firestore_pipelines.vectorvalue.md#vectorvalue_class) | Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). VectorValue | +| [VectorValue](./firestore_pipelines.vectorvalue.md#vectorvalue_class) | Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). | ## Interfaces @@ -1778,30 +357,30 @@ const cityField = field("address.city"); | Type Alias | Description | | --- | --- | -| [AddFieldsStageOptions](./firestore_pipelines.md#addfieldsstageoptions) | (Public Preview) Options defining how an AddFieldsStage is evaluated. See . | -| [AggregateStageOptions](./firestore_pipelines.md#aggregatestageoptions) | (Public Preview) Options defining how an AggregateStage is evaluated. See . | -| [CollectionGroupStageOptions](./firestore_pipelines.md#collectiongroupstageoptions) | (Public Preview) Defines the configuration options for a within a pipeline. This type extends and provides specific settings for how a collection group is identified and processed during pipeline execution. | -| [CollectionStageOptions](./firestore_pipelines.md#collectionstageoptions) | (Public Preview) Options defining how a CollectionStage is evaluated. See . | -| [DatabaseStageOptions](./firestore_pipelines.md#databasestageoptions) | (Public Preview) Options defining how a DatabaseStage is evaluated. See . | -| [DistinctStageOptions](./firestore_pipelines.md#distinctstageoptions) | (Public Preview) Options defining how a DistinctStage is evaluated. See . | -| [DocumentsStageOptions](./firestore_pipelines.md#documentsstageoptions) | (Public Preview) Options defining how a DocumentsStage is evaluated. See . | +| [AddFieldsStageOptions](./firestore_pipelines.md#addfieldsstageoptions) | (Public Preview) Options defining how an AddFieldsStage is evaluated. See [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields). | +| [AggregateStageOptions](./firestore_pipelines.md#aggregatestageoptions) | (Public Preview) Options defining how an AggregateStage is evaluated. See [Pipeline.aggregate()](./firestore_pipelines.pipeline.md#pipelineaggregate). | +| [CollectionGroupStageOptions](./firestore_pipelines.md#collectiongroupstageoptions) | (Public Preview) Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution.See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. | +| [CollectionStageOptions](./firestore_pipelines.md#collectionstageoptions) | (Public Preview) Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). | +| [DatabaseStageOptions](./firestore_pipelines.md#databasestageoptions) | (Public Preview) Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). | +| [DistinctStageOptions](./firestore_pipelines.md#distinctstageoptions) | (Public Preview) Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). | +| [DocumentsStageOptions](./firestore_pipelines.md#documentsstageoptions) | (Public Preview) Options defining how a DocumentsStage is evaluated. See [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments). | | [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) An enumeration of the different types of expressions. | -| [FindNearestStageOptions](./firestore_pipelines.md#findneareststageoptions) | (Public Preview) Options defining how a FindNearestStage is evaluated. See . | -| [LimitStageOptions](./firestore_pipelines.md#limitstageoptions) | (Public Preview) Options defining how a LimitStage is evaluated. See . | -| [OffsetStageOptions](./firestore_pipelines.md#offsetstageoptions) | (Public Preview) Options defining how an OffsetStage is evaluated. See . | -| [OneOf](./firestore_pipelines.md#oneof) | (Public Preview) Utility type to create an type that only allows one property of the Type param T to be set.type XorY = OneOf<{ x: unknown, y: unknown}> let a = { x: "foo" } // OK let b = { y: "foo" } // OK let c = { a: "foo", y: "foo" } // Not OK | +| [FindNearestStageOptions](./firestore_pipelines.md#findneareststageoptions) | (Public Preview) Options defining how a FindNearestStage is evaluated. See [Pipeline.findNearest()](./firestore_pipelines.pipeline.md#pipelinefindnearest). | +| [LimitStageOptions](./firestore_pipelines.md#limitstageoptions) | (Public Preview) Options defining how a LimitStage is evaluated. See [Pipeline.limit()](./firestore_pipelines.pipeline.md#pipelinelimit). | +| [OffsetStageOptions](./firestore_pipelines.md#offsetstageoptions) | (Public Preview) Options defining how an OffsetStage is evaluated. See [Pipeline.offset()](./firestore_pipelines.pipeline.md#pipelineoffset). | +| [OneOf](./firestore_pipelines.md#oneof) | (Public Preview) Utility type to create an type that only allows one property of the Type param T to be set. | | [PartialWithFieldValue](./firestore_pipelines.md#partialwithfieldvalue) | Similar to TypeScript's Partial<T>, but allows nested fields to be omitted and FieldValues to be passed in as property values. | | [Primitive](./firestore_pipelines.md#primitive) | Primitive types. | -| [RemoveFieldsStageOptions](./firestore_pipelines.md#removefieldsstageoptions) | (Public Preview) Options defining how a RemoveFieldsStage is evaluated. See . | -| [ReplaceWithStageOptions](./firestore_pipelines.md#replacewithstageoptions) | (Public Preview) Options defining how a ReplaceWithStage is evaluated. See . | -| [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) | (Public Preview) Defines the options for evaluating a sample stage within a pipeline. This type combines common with a specific configuration where only one of the defined sampling methods can be applied.See to create a sample stage.. | -| [SelectStageOptions](./firestore_pipelines.md#selectstageoptions) | (Public Preview) Options defining how a SelectStage is evaluated. See . | +| [RemoveFieldsStageOptions](./firestore_pipelines.md#removefieldsstageoptions) | (Public Preview) Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). | +| [ReplaceWithStageOptions](./firestore_pipelines.md#replacewithstageoptions) | (Public Preview) Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). | +| [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) | (Public Preview) Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied.See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. | +| [SelectStageOptions](./firestore_pipelines.md#selectstageoptions) | (Public Preview) Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). | | [SetOptions](./firestore_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | -| [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See . | +| [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | | [TimeGranularity](./firestore_pipelines.md#timegranularity) | (Public Preview) Specify time granularity for expressions. | -| [UnionStageOptions](./firestore_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See . | +| [UnionStageOptions](./firestore_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | | [UnnestStageOptions](./firestore_pipelines.md#unneststageoptions) | (Public Preview) Represents the specific options available for configuring an UnnestStage within a pipeline. | -| [WhereStageOptions](./firestore_pipelines.md#wherestageoptions) | (Public Preview) Options defining how a WhereStage is evaluated. See . | +| [WhereStageOptions](./firestore_pipelines.md#wherestageoptions) | (Public Preview) Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). | | [WithFieldValue](./firestore_pipelines.md#withfieldvalue) | Allows FieldValues to be passed in as a property value while maintaining type safety. | ## function() @@ -1813,13 +392,6 @@ const cityField = field("address.city"); Creates an aggregation that counts the total number of stage inputs. -```typescript -// Count the total number of input documents -countAll().as("totalDocument"); - -``` - A new representing the 'countAll' aggregation. - Signature: ```typescript @@ -1829,19 +401,23 @@ export declare function countAll(): AggregateFunction; [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -### currentTimestamp() {:#currenttimestamp} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'countAll' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that evaluates to the current server timestamp. ```typescript -// Get the current server timestamp -currentTimestamp() +// Count the total number of input documents +countAll().as("totalDocument"); ``` - A new Expression representing the current server timestamp. + +### currentTimestamp() {:#currenttimestamp} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to the current server timestamp. Signature: @@ -1852,6 +428,17 @@ export declare function currentTimestamp(): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new Expression representing the current server timestamp. + +### Example + + +```typescript +// Get the current server timestamp +currentTimestamp() + +``` + ## function(array, ...) ### arrayContains(array, element) {:#arraycontains_a00ea48} @@ -1861,12 +448,6 @@ export declare function currentTimestamp(): FunctionExpression; Creates an expression that checks if an array expression contains a specific element. -```typescript -// Check if the 'colors' array contains the value of field 'selectedColor' -arrayContains(field("colors"), field("selectedColor")); - -``` - Signature: ```typescript @@ -1878,25 +459,30 @@ export declare function arrayContains(array: Expression, element: Expression): B | Parameter | Type | Description | | --- | --- | --- | | array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to check. | -| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The element to search for in the array. A new representing the 'array\_contains' comparison. | +| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The element to search for in the array. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContains(array, element) {:#arraycontains_7328608} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array expression contains a specific element. ```typescript -// Check if the 'colors' array contains "red" -arrayContains(field("colors"), "red"); +// Check if the 'colors' array contains the value of field 'selectedColor' +arrayContains(field("colors"), field("selectedColor")); ``` +### arrayContains(array, element) {:#arraycontains_7328608} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains a specific element. + Signature: ```typescript @@ -1908,25 +494,30 @@ export declare function arrayContains(array: Expression, element: unknown): Bool | Parameter | Type | Description | | --- | --- | --- | | array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to check. | -| element | unknown | The element to search for in the array. A new representing the 'array\_contains' comparison. | +| element | unknown | The element to search for in the array. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAll(array, values) {:#arraycontainsall_c658ad5} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array expression contains all the specified elements. ```typescript -// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" -arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); +// Check if the 'colors' array contains "red" +arrayContains(field("colors"), "red"); ``` +### arrayContainsAll(array, values) {:#arraycontainsall_c658ad5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains all the specified elements. + Signature: ```typescript @@ -1938,18 +529,16 @@ export declare function arrayContainsAll(array: Expression, values: ArrayReturns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAll(array, arrayExpression) {:#arraycontainsall_7b535db} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array expression contains all the specified elements. ```typescript // Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" @@ -1957,6 +546,13 @@ arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]) ``` +### arrayContainsAll(array, arrayExpression) {:#arraycontainsall_7b535db} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains all the specified elements. + Signature: ```typescript @@ -1968,25 +564,30 @@ export declare function arrayContainsAll(array: Expression, arrayExpression: Exp | Parameter | Type | Description | | --- | --- | --- | | array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to check. | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. A new representing the 'array\_contains\_all' comparison. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAny(array, values) {:#arraycontainsany_c658ad5} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array expression contains any of the specified elements. ```typescript -// Check if the 'categories' array contains either values from field "cate1" or "Science" -arrayContainsAny(field("categories"), [field("cate1"), "Science"]); +// Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" +arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); ``` +### arrayContainsAny(array, values) {:#arraycontainsany_c658ad5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains any of the specified elements. + Signature: ```typescript @@ -1998,25 +599,30 @@ export declare function arrayContainsAny(array: Expression, values: ArrayReturns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAny(array, values) {:#arraycontainsany_c381a96} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an array expression contains any of the specified elements. ```typescript // Check if the 'categories' array contains either values from field "cate1" or "Science" -arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); +arrayContainsAny(field("categories"), [field("cate1"), "Science"]); ``` +### arrayContainsAny(array, values) {:#arraycontainsany_c381a96} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an array expression contains any of the specified elements. + Signature: ```typescript @@ -2028,25 +634,30 @@ export declare function arrayContainsAny(array: Expression, values: Expression): | Parameter | Type | Description | | --- | --- | --- | | array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to check. | -| values | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array. A new representing the 'array\_contains\_any' comparison. | +| values | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### arrayLength(array) {:#arraylength_195e339} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of an array expression. ```typescript -// Get the number of items in the 'cart' array -arrayLength(field("cart")); +// Check if the 'categories' array contains either values from field "cate1" or "Science" +arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); ``` +### arrayLength(array) {:#arraylength_195e339} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of an array expression. + Signature: ```typescript @@ -2057,12 +668,23 @@ export declare function arrayLength(array: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to calculate the length of. A new representing the length of the array. | +| array | [Expression](./firestore_pipelines.expression.md#expression_class) | The array expression to calculate the length of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the array. + +### Example + + +```typescript +// Get the number of items in the 'cart' array +arrayLength(field("cart")); + +``` + ## function(arrayExpression, ...) ### arrayGet(arrayExpression, offset) {:#arrayget_f2e27cc} @@ -2072,12 +694,6 @@ export declare function arrayLength(array: Expression): FunctionExpression; Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index 1. -arrayGet(field('tags'), 1); - -``` - Signature: ```typescript @@ -2088,27 +704,31 @@ export declare function arrayGet(arrayExpression: Expression, offset: number): F | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expr evaluating to an array. | -| offset | number | The index of the element to return. A new Expr representing the 'arrayGet' operation. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to an array. | +| offset | number | The index of the element to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### arrayGet(arrayExpression, offsetExpr) {:#arrayget_484550d} +A new `Expression` representing the 'arrayGet' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. ```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -arrayGet(field('tags'), field('favoriteTag')); +// Return the value in the tags field array at index 1. +arrayGet(field('tags'), 1); ``` +### arrayGet(arrayExpression, offsetExpr) {:#arrayget_484550d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + Signature: ```typescript @@ -2119,25 +739,31 @@ export declare function arrayGet(arrayExpression: Expression, offsetExpr: Expres | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expr evaluating to an array. | -| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expr evaluating to the index of the element to return. A new Expr representing the 'arrayGet' operation. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to an array. | +| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### join(arrayExpression, delimiterExpression) {:#join_313e6aa} +A new `Expression` representing the 'arrayGet' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that joins the elements of an array into a string. ```typescript -// Join an array of string using the delimiter from the 'separator' field. -join(array(['foo', 'bar']), field("separator")) +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet(field('tags'), field('favoriteTag')); + +``` + +### join(arrayExpression, delimiterExpression) {:#join_313e6aa} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> -``` +Creates an expression that joins the elements of an array into a string. Signature: @@ -2150,25 +776,30 @@ export declare function join(arrayExpression: Expression, delimiterExpression: E | Parameter | Type | Description | | --- | --- | --- | | arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | -| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. A new Expression representing the join operation. | +| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) -### join(arrayExpression, delimiter) {:#join_d088d29} +A new Expression representing the join operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that joins the elements of an array into a string. ```typescript -// Join the elements of the 'tags' field with a comma and space. -join(field("tags"), ", ") +// Join an array of string using the delimiter from the 'separator' field. +join(array(['foo', 'bar']), field("separator")) ``` +### join(arrayExpression, delimiter) {:#join_d088d29} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + Signature: ```typescript @@ -2180,12 +811,23 @@ export declare function join(arrayExpression: Expression, delimiter: string): Ex | Parameter | Type | Description | | --- | --- | --- | | arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | -| delimiter | string | The string to use as a delimiter. A new Expression representing the join operation. | +| delimiter | string | The string to use as a delimiter. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new Expression representing the join operation. + +### Example + + +```typescript +// Join the elements of the 'tags' field with a comma and space. +join(field("tags"), ", ") + +``` + ## function(arrayField, ...) ### arrayGet(arrayField, offset) {:#arrayget_3f58471} @@ -2195,12 +837,6 @@ export declare function join(arrayExpression: Expression, delimiter: string): Ex Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. -```typescript -// Return the value in the tags field array at index 1. -arrayGet('tags', 1); - -``` - Signature: ```typescript @@ -2212,26 +848,30 @@ export declare function arrayGet(arrayField: string, offset: number): FunctionEx | Parameter | Type | Description | | --- | --- | --- | | arrayField | string | The name of the array field. | -| offset | number | The index of the element to return. A new Expr representing the 'arrayGet' operation. | +| offset | number | The index of the element to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### arrayGet(arrayField, offsetExpr) {:#arrayget_1904c9a} +A new `Expression` representing the 'arrayGet' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. ```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -arrayGet('tags', field('favoriteTag')); +// Return the value in the tags field array at index 1. +arrayGet('tags', 1); ``` +### arrayGet(arrayField, offsetExpr) {:#arrayget_1904c9a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. + Signature: ```typescript @@ -2243,12 +883,24 @@ export declare function arrayGet(arrayField: string, offsetExpr: Expression): Fu | Parameter | Type | Description | | --- | --- | --- | | arrayField | string | The name of the array field. | -| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expr evaluating to the index of the element to return. A new Expr representing the 'arrayGet' operation. | +| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the 'arrayGet' operation. + +### Example + + +```typescript +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet('tags', field('favoriteTag')); + +``` + ## function(arrayFieldName, ...) ### join(arrayFieldName, delimiter) {:#join_478ef36} @@ -2258,12 +910,6 @@ export declare function arrayGet(arrayField: string, offsetExpr: Expression): Fu Creates an expression that joins the elements of an array into a string. -```typescript -// Join the elements of the 'tags' field with a comma and space. -join("tags", ", ") - -``` - Signature: ```typescript @@ -2275,25 +921,30 @@ export declare function join(arrayFieldName: string, delimiter: string): Express | Parameter | Type | Description | | --- | --- | --- | | arrayFieldName | string | The name of the field containing the array. | -| delimiter | string | The string to use as a delimiter. A new Expression representing the join operation. | +| delimiter | string | The string to use as a delimiter. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) -### join(arrayFieldName, delimiterExpression) {:#join_829294c} +A new Expression representing the join operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that joins the elements of an array into a string. ```typescript -// Join the elements of the 'tags' field with the delimiter from the 'separator' field. -join('tags', field("separator")) +// Join the elements of the 'tags' field with a comma and space. +join("tags", ", ") ``` +### join(arrayFieldName, delimiterExpression) {:#join_829294c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + Signature: ```typescript @@ -2305,12 +956,23 @@ export declare function join(arrayFieldName: string, delimiterExpression: Expres | Parameter | Type | Description | | --- | --- | --- | | arrayFieldName | string | The name of the field containing the array. | -| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. A new Expression representing the join operation. | +| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new Expression representing the join operation. + +### Example + + +```typescript +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +join('tags', field("separator")) + +``` + ## function(base, ...) ### pow(base, exponent) {:#pow_e4a9e64} @@ -2320,12 +982,6 @@ export declare function join(arrayFieldName: string, delimiterExpression: Expres Creates an expression that returns the value of the base expression raised to the power of the exponent expression. -```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -pow(field("base"), field("exponent")); - -``` - Signature: ```typescript @@ -2337,25 +993,30 @@ export declare function pow(base: Expression, exponent: Expression): FunctionExp | Parameter | Type | Description | | --- | --- | --- | | base | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | -| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. A new Expr representing the power operation. | +| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### pow(base, exponent) {:#pow_93eae7f} +A new `Expression` representing the power operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the value of the base expression raised to the power of the exponent. ```typescript -// Raise the value of the 'base' field to the power of 2. -pow(field("base"), 2); +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow(field("base"), field("exponent")); ``` +### pow(base, exponent) {:#pow_93eae7f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base expression raised to the power of the exponent. + Signature: ```typescript @@ -2367,25 +1028,30 @@ export declare function pow(base: Expression, exponent: number): FunctionExpress | Parameter | Type | Description | | --- | --- | --- | | base | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | -| exponent | number | The constant value to raise the base to the power of. A new Expr representing the power operation. | +| exponent | number | The constant value to raise the base to the power of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### pow(base, exponent) {:#pow_a237721} +A new `Expression` representing the power operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the value of the base field raised to the power of the exponent expression. ```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -pow("base", field("exponent")); +// Raise the value of the 'base' field to the power of 2. +pow(field("base"), 2); ``` +### pow(base, exponent) {:#pow_a237721} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base field raised to the power of the exponent expression. + Signature: ```typescript @@ -2397,25 +1063,30 @@ export declare function pow(base: string, exponent: Expression): FunctionExpress | Parameter | Type | Description | | --- | --- | --- | | base | string | The name of the field to raise to the power of the exponent. | -| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. A new Expr representing the power operation. | +| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### pow(base, exponent) {:#pow_f4d7908} +A new `Expression` representing the power operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the value of the base field raised to the power of the exponent. ```typescript -// Raise the value of the 'base' field to the power of 2. -pow("base", 2); +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow("base", field("exponent")); ``` +### pow(base, exponent) {:#pow_f4d7908} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base field raised to the power of the exponent. + Signature: ```typescript @@ -2427,12 +1098,23 @@ export declare function pow(base: string, exponent: number): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | | base | string | The name of the field to raise to the power of the exponent. | -| exponent | number | The constant value to raise the base to the power of. A new Expr representing the power operation. | +| exponent | number | The constant value to raise the base to the power of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the power operation. + +### Example + + +```typescript +// Raise the value of the 'base' field to the power of 2. +pow("base", 2); + +``` + ## function(booleanExpr, ...) ### countIf(booleanExpr) {:#countif_c5b8fb1} @@ -2442,12 +1124,6 @@ export declare function pow(base: string, exponent: number): FunctionExpression; Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. -```typescript -// Count the number of documents where 'is_active' field equals true -countIf(field("is_active").equal(true)).as("numActiveDocuments"); - -``` - Signature: ```typescript @@ -2466,6 +1142,15 @@ export declare function countIf(booleanExpr: BooleanExpression): AggregateFuncti A new `AggregateFunction` representing the 'countIf' aggregation. +### Example + + +```typescript +// Count the number of documents where 'is_active' field equals true +countIf(field("is_active").equal(true)).as("numActiveDocuments"); + +``` + ### not(booleanExpr) {:#not_c5b8fb1} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2473,12 +1158,6 @@ A new `AggregateFunction` representing the 'countIf' aggregation. Creates an expression that negates a filter condition. -```typescript -// Find documents where the 'completed' field is NOT true -not(equal("completed", true)); - -``` - Signature: ```typescript @@ -2489,12 +1168,23 @@ export declare function not(booleanExpr: BooleanExpression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| booleanExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The filter condition to negate. A new representing the negated filter condition. | +| booleanExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The filter condition to negate. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the negated filter condition. + +### Example + + +```typescript +// Find documents where the 'completed' field is NOT true +not(equal("completed", true)); + +``` + ## function(condition, ...) ### conditional(condition, thenExpr, elseExpr) {:#conditional_07a206d} @@ -2504,13 +1194,6 @@ export declare function not(booleanExpr: BooleanExpression): BooleanExpression; Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. -```typescript -// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". -conditional( - greaterThan("age", 18), constant("Adult"), constant("Minor")); - -``` - Signature: ```typescript @@ -2523,12 +1206,24 @@ export declare function conditional(condition: BooleanExpression, thenExpr: Expr | --- | --- | --- | | condition | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The condition to evaluate. | | thenExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is true. | -| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. A new representing the conditional expression. | +| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the conditional expression. + +### Example + + +```typescript +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +conditional( + greaterThan("age", 18), constant("Adult"), constant("Minor")); + +``` + ## function(documentPath, ...) ### documentId(documentPath) {:#documentid_cef293c} @@ -2538,13 +1233,6 @@ export declare function conditional(condition: BooleanExpression, thenExpr: Expr Creates an expression that returns the document ID from a path. -```typescript -// Get the document ID from a path. -documentId(myDocumentReference); - -``` - A new representing the documentId operation. - Signature: ```typescript @@ -2561,6 +1249,17 @@ export declare function documentId(documentPath: string | DocumentReference): Fu [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. + +### Example + + +```typescript +// Get the document ID from a path. +documentId(myDocumentReference); + +``` + ## function(documentPathExpr, ...) ### documentId(documentPathExpr) {:#documentid_9a69021} @@ -2570,13 +1269,6 @@ export declare function documentId(documentPath: string | DocumentReference): Fu Creates an expression that returns the document ID from a path. -```typescript -// Get the document ID from a path. -documentId(field("__path__")); - -``` - A new representing the documentId operation. - Signature: ```typescript @@ -2593,6 +1285,17 @@ export declare function documentId(documentPathExpr: Expression): FunctionExpres [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. + +### Example + + +```typescript +// Get the document ID from a path. +documentId(field("__path__")); + +``` + ## function(element, ...) ### notEqualAny(element, values) {:#notequalany_c2c5bcb} @@ -2602,12 +1305,6 @@ export declare function documentId(documentPathExpr: Expression): FunctionExpres Creates an expression that checks if an expression is not equal to any of the provided values or expressions. -```typescript -// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' -notEqualAny(field("status"), ["pending", field("rejectedStatus")]); - -``` - Signature: ```typescript @@ -2619,11 +1316,22 @@ export declare function notEqualAny(element: Expression, values: ArrayReturns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. + +### Example + + +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` ### notEqualAny(element, arrayExpression) {:#notequalany_16b2851} @@ -2632,12 +1340,6 @@ export declare function notEqualAny(element: Expression, values: ArraySignature: ```typescript @@ -2649,12 +1351,23 @@ export declare function notEqualAny(element: Expression, arrayExpression: Expres | Parameter | Type | Description | | --- | --- | --- | | element | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The values to check against. A new representing the 'NOT IN' comparison. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The values to check against. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. + +### Example + + +```typescript +// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + ## function(elements, ...) ### array(elements) {:#array_7d853aa} @@ -2664,12 +1377,6 @@ export declare function notEqualAny(element: Expression, arrayExpression: Expres Creates an expression that creates a Firestore array value from an input array. -```typescript -// Create an array value from the input array and reference the 'baz' field value from the input document. -array(['bar', Field.of('baz')]).as('foo'); - -``` - Signature: ```typescript @@ -2680,25 +1387,30 @@ export declare function array(elements: unknown[]): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| elements | unknown\[\] | The input array to evaluate in the expression. A new representing the array function. | +| elements | unknown\[\] | The input array to evaluate in the expression. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### map(elements) {:#map_ce5dee1} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the array function. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that creates a Firestore map value from an input object. ```typescript -// Create a map from the input object and reference the 'baz' field value from the input document. -map({foo: 'bar', baz: Field.of('baz')}).as('data'); +// Create an array value from the input array and reference the 'baz' field value from the input document. +array(['bar', Field.of('baz')]).as('foo'); ``` +### map(elements) {:#map_ce5dee1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that creates a Firestore map value from an input object. + Signature: ```typescript @@ -2709,12 +1421,23 @@ export declare function map(elements: Record): FunctionExpressi | Parameter | Type | Description | | --- | --- | --- | -| elements | Record<string, unknown> | The input map to evaluate in the expression. A new representing the map function. | +| elements | Record<string, unknown> | The input map to evaluate in the expression. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the map function. + +### Example + + +```typescript +// Create a map from the input object and reference the 'baz' field value from the input document. +map({foo: 'bar', baz: Field.of('baz')}).as('data'); + +``` + ## function(expr, ...) ### abs(expr) {:#abs_005f3d4} @@ -2734,25 +1457,20 @@ export declare function abs(expr: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compute the absolute value of. A new representing the absolute value of the numeric value. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compute the absolute value of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. + ### ascending(expr) {:#ascending_005f3d4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an that sorts documents in ascending order based on an expression. - -```typescript -// Sort documents by the 'name' field in lowercase in ascending order -firestore.pipeline().collection("users") - .sort(ascending(field("name").toLower())); - -``` +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. Signature: @@ -2764,25 +1482,31 @@ export declare function ascending(expr: Expression): Ordering; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to create an ascending ordering for. A new Ordering for ascending sorting. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to create an ascending ordering for. | Returns: [Ordering](./firestore_pipelines.ordering.md#ordering_class) -### byteLength(expr) {:#bytelength_005f3d4} +A new `Ordering` for ascending sorting. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. ```typescript -// Calculate the length of the 'myString' field in bytes. -byteLength(field("myString")); +// Sort documents by the 'name' field in lowercase in ascending order +firestore.pipeline().collection("users") + .sort(ascending(field("name").toLower())); ``` +### byteLength(expr) {:#bytelength_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. + Signature: ```typescript @@ -2793,12 +1517,23 @@ export declare function byteLength(expr: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string. A new representing the length of the string in bytes. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string in bytes. + +### Example + + +```typescript +// Calculate the length of the 'myString' field in bytes. +byteLength(field("myString")); + +``` + ### countDistinct(expr) {:#countdistinct_3c28b08} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2816,25 +1551,20 @@ export declare function countDistinct(expr: Expression | string): AggregateFunct | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) \| string | The expression or field to count distinct values of. A new AggregateFunction representing the 'count\_distinct' aggregation. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) \| string | The expression or field to count distinct values of. | Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +A new `AggregateFunction` representing the 'count\_distinct' aggregation. + ### descending(expr) {:#descending_005f3d4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an that sorts documents in descending order based on an expression. - -```typescript -// Sort documents by the 'name' field in lowercase in descending order -firestore.pipeline().collection("users") - .sort(descending(field("name").toLower())); - -``` +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. Signature: @@ -2846,12 +1576,24 @@ export declare function descending(expr: Expression): Ordering; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to create a descending ordering for. A new Ordering for descending sorting. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to create a descending ordering for. | Returns: [Ordering](./firestore_pipelines.ordering.md#ordering_class) +A new `Ordering` for descending sorting. + +### Example + + +```typescript +// Sort documents by the 'name' field in lowercase in descending order +firestore.pipeline().collection("users") + .sort(descending(field("name").toLower())); + +``` + ### floor(expr) {:#floor_005f3d4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2869,12 +1611,14 @@ export declare function floor(expr: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compute the floor of. A new representing the floor of the numeric value. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compute the floor of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the floor of the numeric value. + ### timestampToUnixMicros(expr) {:#timestamptounixmicros_005f3d4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2882,12 +1626,6 @@ export declare function floor(expr: Expression): FunctionExpression; Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). -```typescript -// Convert the 'timestamp' field to microseconds since epoch. -timestampToUnixMicros(field("timestamp")); - -``` - Signature: ```typescript @@ -2898,25 +1636,30 @@ export declare function timestampToUnixMicros(expr: Expression): FunctionExpress | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. A new representing the number of microseconds since epoch. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### timestampToUnixMillis(expr) {:#timestamptounixmillis_005f3d4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of microseconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -timestampToUnixMillis(field("timestamp")); +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros(field("timestamp")); ``` +### timestampToUnixMillis(expr) {:#timestamptounixmillis_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + Signature: ```typescript @@ -2927,25 +1670,30 @@ export declare function timestampToUnixMillis(expr: Expression): FunctionExpress | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. A new representing the number of milliseconds since epoch. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### timestampToUnixSeconds(expr) {:#timestamptounixseconds_005f3d4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of milliseconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to seconds since epoch. -timestampToUnixSeconds(field("timestamp")); +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis(field("timestamp")); ``` +### timestampToUnixSeconds(expr) {:#timestamptounixseconds_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + Signature: ```typescript @@ -2956,25 +1704,30 @@ export declare function timestampToUnixSeconds(expr: Expression): FunctionExpres | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. A new representing the number of seconds since epoch. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### unixMicrosToTimestamp(expr) {:#unixmicrostotimestamp_005f3d4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of seconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. ```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -unixMicrosToTimestamp(field("microseconds")); +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds(field("timestamp")); ``` +### unixMicrosToTimestamp(expr) {:#unixmicrostotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + Signature: ```typescript @@ -2985,25 +1738,30 @@ export declare function unixMicrosToTimestamp(expr: Expression): FunctionExpress | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of microseconds since epoch. A new representing the timestamp. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of microseconds since epoch. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### unixMillisToTimestamp(expr) {:#unixmillistotimestamp_005f3d4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. ```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -unixMillisToTimestamp(field("milliseconds")); +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp(field("microseconds")); ``` +### unixMillisToTimestamp(expr) {:#unixmillistotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + Signature: ```typescript @@ -3014,25 +1772,30 @@ export declare function unixMillisToTimestamp(expr: Expression): FunctionExpress | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of milliseconds since epoch. A new representing the timestamp. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of milliseconds since epoch. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### unixSecondsToTimestamp(expr) {:#unixsecondstotimestamp_005f3d4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. ```typescript -// Interpret the 'seconds' field as seconds since epoch. -unixSecondsToTimestamp(field("seconds")); +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp(field("milliseconds")); ``` +### unixSecondsToTimestamp(expr) {:#unixsecondstotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + Signature: ```typescript @@ -3043,12 +1806,23 @@ export declare function unixSecondsToTimestamp(expr: Expression): FunctionExpres | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of seconds since epoch. A new representing the timestamp. | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of seconds since epoch. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. + +### Example + + +```typescript +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp(field("seconds")); + +``` + ## function(expression, ...) ### arraySum(expression) {:#arraysum_1138a27} @@ -3058,12 +1832,6 @@ export declare function unixSecondsToTimestamp(expr: Expression): FunctionExpres Creates an expression that computes the sum of the elements in an array. -```typescript -// Compute the sum of the elements in the 'scores' field. -arraySum(field("scores")); - -``` - Signature: ```typescript @@ -3074,25 +1842,30 @@ export declare function arraySum(expression: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric array, which the sum will be computed for. A new Expr representing the sum of the elements in the array. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric array, which the sum will be computed for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### average(expression) {:#average_1138a27} +A new `Expression` representing the sum of the elements in the array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. ```typescript -// Calculate the average age of users -average(field("age")).as("averageAge"); +// Compute the sum of the elements in the 'scores' field. +arraySum(field("scores")); ``` +### average(expression) {:#average_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. + Signature: ```typescript @@ -3103,25 +1876,30 @@ export declare function average(expression: Expression): AggregateFunction; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the values to average. A new representing the 'average' aggregation. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the values to average. | Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -### ceil(expression) {:#ceil_1138a27} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'average' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the ceiling of a numeric value. ```typescript -// Compute the ceiling of the 'price' field. -ceil(field("price")); +// Calculate the average age of users +average(field("age")).as("averageAge"); ``` +### ceil(expression) {:#ceil_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. + Signature: ```typescript @@ -3132,24 +1910,29 @@ export declare function ceil(expression: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the ceiling will be computed for. A new representing the ceiling of the numeric value. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the ceiling will be computed for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### collectionId(expression) {:#collectionid_1138a27} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ceiling of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the collection ID from a path. ```typescript -// Get the collection ID from a path. -collectionId(field("__name__")); +// Compute the ceiling of the 'price' field. +ceil(field("price")); + +``` + +### collectionId(expression) {:#collectionid_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> -``` +Creates an expression that returns the collection ID from a path. Signature: @@ -3161,25 +1944,30 @@ export declare function collectionId(expression: Expression): FunctionExpression | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a path, which the collection ID will be extracted from. A new representing the collectionId operation. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a path, which the collection ID will be extracted from. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### count(expression) {:#count_1138a27} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the collectionId operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. ```typescript -// Count the number of items where the price is greater than 10 -count(field("price").greaterThan(10)).as("expensiveItemCount"); +// Get the collection ID from a path. +collectionId(field("__name__")); ``` +### count(expression) {:#count_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. + Signature: ```typescript @@ -3190,25 +1978,30 @@ export declare function count(expression: Expression): AggregateFunction; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to count. A new representing the 'count' aggregation. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to count. | Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -### divide(expression, value) {:#divide_01df3cf} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'count' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that divides an expression by a constant value. ```typescript -// Divide the 'value' field by 10 -divide(field("value"), 10); +// Count the number of items where the price is greater than 10 +count(field("price").greaterThan(10)).as("expensiveItemCount"); ``` +### divide(expression, value) {:#divide_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides an expression by a constant value. + Signature: ```typescript @@ -3220,25 +2013,30 @@ export declare function divide(expression: Expression, value: unknown): Function | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to be divided. | -| value | unknown | The constant value to divide by. A new representing the division operation. | +| value | unknown | The constant value to divide by. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### equal(expression, value) {:#equal_01df3cf} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the division operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is equal to a constant value. ```typescript -// Check if the 'age' field is equal to 21 -equal(field("age"), 21); +// Divide the 'value' field by 10 +divide(field("value"), 10); ``` +### equal(expression, value) {:#equal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is equal to a constant value. + Signature: ```typescript @@ -3250,25 +2048,30 @@ export declare function equal(expression: Expression, value: unknown): BooleanEx | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the equality comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### equalAny(expression, values) {:#equalany_7e759b5} +A new `Expression` representing the equality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. ```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -equalAny(field("category"), [constant("Electronics"), field("primaryType")]); +// Check if the 'age' field is equal to 21 +equal(field("age"), 21); ``` +### equalAny(expression, values) {:#equalany_7e759b5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. + Signature: ```typescript @@ -3280,25 +2083,30 @@ export declare function equalAny(expression: Expression, values: ArrayReturns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### equalAny(expression, arrayExpression) {:#equalany_214ce68} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is equal to any of the provided values. ```typescript -// Check if the 'category' field is set to a value in the disabledCategories field -equalAny(field("category"), field('disabledCategories')); +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny(field("category"), [constant("Electronics"), field("primaryType")]); ``` +### equalAny(expression, arrayExpression) {:#equalany_214ce68} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is equal to any of the provided values. + Signature: ```typescript @@ -3310,25 +2118,29 @@ export declare function equalAny(expression: Expression, arrayExpression: Expres | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression whose results to compare. | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input. A new representing the 'IN' comparison. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### exp(expression) {:#exp_1138a27} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes e to the power of the expression's result. ```typescript -// Compute e to the power of 2. -exp(constant(2)); +// Check if the 'category' field is set to a value in the disabledCategories field +equalAny(field("category"), field('disabledCategories')); ``` - A new representing the exp of the numeric value. + +### exp(expression) {:#exp_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes e to the power of the expression's result. Signature: @@ -3346,19 +2158,24 @@ export declare function exp(expression: Expression): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### greaterThan(expression, value) {:#greaterthan_01df3cf} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the exp of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is greater than a constant value. ```typescript -// Check if the 'age' field is greater than 18 -greaterThan(field("age"), 18); +// Compute e to the power of 2. +exp(constant(2)); ``` +### greaterThan(expression, value) {:#greaterthan_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is greater than a constant value. + Signature: ```typescript @@ -3370,25 +2187,30 @@ export declare function greaterThan(expression: Expression, value: unknown): Boo | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the greater than comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThanOrEqual(expression, value) {:#greaterthanorequal_01df3cf} +A new `Expression` representing the greater than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is greater than or equal to a constant value. ```typescript -// Check if the 'quantity' field is greater than or equal to 10 -greaterThanOrEqual(field("quantity"), 10); +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), 18); ``` +### greaterThanOrEqual(expression, value) {:#greaterthanorequal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is greater than or equal to a constant value. + Signature: ```typescript @@ -3400,28 +2222,30 @@ export declare function greaterThanOrEqual(expression: Expression, value: unknow | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the greater than or equal to comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### length\_2(expression) {:#length_2_1138a27} +A new `Expression` representing the greater than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of a string, array, map, vector, or bytes. ```typescript -// Get the length of the 'name' field. -length(field("name")); - -// Get the number of items in the 'cart' array. -length(field("cart")); +// Check if the 'quantity' field is greater than or equal to 10 +greaterThanOrEqual(field("quantity"), 10); ``` +### length\_2(expression) {:#length_2_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string, array, map, vector, or bytes. + Signature: ```typescript @@ -3432,25 +2256,33 @@ declare function length_2(expression: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. A new Expr representing the length of the string, array, map, vector, or bytes. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### lessThan(expression, value) {:#lessthan_01df3cf} +A new `Expression` representing the length of the string, array, map, vector, or bytes. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is less than a constant value. ```typescript -// Check if the 'age' field is less than 30 -lessThan(field("age"), 30); +// Get the length of the 'name' field. +length(field("name")); + +// Get the number of items in the 'cart' array. +length(field("cart")); ``` +### lessThan(expression, value) {:#lessthan_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is less than a constant value. + Signature: ```typescript @@ -3462,25 +2294,30 @@ export declare function lessThan(expression: Expression, value: unknown): Boolea | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the less than comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### lessThanOrEqual(expression, value) {:#lessthanorequal_01df3cf} +A new `Expression` representing the less than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is less than or equal to a constant value. ```typescript -// Check if the 'quantity' field is less than or equal to 20 -lessThan(field("quantity"), 20); +// Check if the 'age' field is less than 30 +lessThan(field("age"), 30); ``` +### lessThanOrEqual(expression, value) {:#lessthanorequal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is less than or equal to a constant value. + Signature: ```typescript @@ -3492,25 +2329,30 @@ export declare function lessThanOrEqual(expression: Expression, value: unknown): | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the less than or equal to comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### ln(expression) {:#ln_1138a27} +A new `Expression` representing the less than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the natural logarithm of a numeric value. ```typescript -// Compute the natural logarithm of the 'value' field. -ln(field("value")); +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), 20); ``` +### ln(expression) {:#ln_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the natural logarithm of a numeric value. + Signature: ```typescript @@ -3521,25 +2363,30 @@ export declare function ln(expression: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the natural logarithm will be computed for. A new Expr representing the natural logarithm of the numeric value. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the natural logarithm will be computed for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### log(expression, base) {:#log_ac183e2} +A new `Expression` representing the natural logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the logarithm of an expression to a given base. ```typescript -// Compute the logarithm of the 'value' field with base 10. -log(field("value"), 10); +// Compute the natural logarithm of the 'value' field. +ln(field("value")); ``` +### log(expression, base) {:#log_ac183e2} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of an expression to a given base. + Signature: ```typescript @@ -3551,25 +2398,30 @@ export declare function log(expression: Expression, base: number): FunctionExpre | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | -| base | number | The base of the logarithm. A new representing the logarithm of the numeric value. | +| base | number | The base of the logarithm. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### log(expression, base) {:#log_1894737} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the logarithm of an expression to a given base. ```typescript -// Compute the logarithm of the 'value' field with the base in the 'base' field. -log(field("value"), field("base")); +// Compute the logarithm of the 'value' field with base 10. +log(field("value"), 10); ``` +### log(expression, base) {:#log_1894737} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of an expression to a given base. + Signature: ```typescript @@ -3581,25 +2433,30 @@ export declare function log(expression: Expression, base: Expression): FunctionE | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | -| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The base of the logarithm. A new representing the logarithm of the numeric value. | +| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The base of the logarithm. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### log10(expression) {:#log10_1138a27} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the base-10 logarithm of a numeric value. ```typescript -// Compute the base-10 logarithm of the 'value' field. -log10(field("value")); +// Compute the logarithm of the 'value' field with the base in the 'base' field. +log(field("value"), field("base")); ``` +### log10(expression) {:#log10_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the base-10 logarithm of a numeric value. + Signature: ```typescript @@ -3610,11 +2467,22 @@ export declare function log10(expression: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. A new Expr representing the base-10 logarithm of the numeric value. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the base-10 logarithm of the numeric value. + +### Example + + +```typescript +// Compute the base-10 logarithm of the 'value' field. +log10(field("value")); + +``` ### maximum(expression) {:#maximum_1138a27} @@ -3623,12 +2491,6 @@ export declare function log10(expression: Expression): FunctionExpression; Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. -```typescript -// Find the highest score in a leaderboard -maximum(field("score")).as("highestScore"); - -``` - Signature: ```typescript @@ -3639,25 +2501,30 @@ export declare function maximum(expression: Expression): AggregateFunction; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the maximum value of. A new representing the 'maximum' aggregation. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the maximum value of. | Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -### minimum(expression) {:#minimum_1138a27} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'maximum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. ```typescript -// Find the lowest price of all products -minimum(field("price")).as("lowestPrice"); +// Find the highest score in a leaderboard +maximum(field("score")).as("highestScore"); ``` +### minimum(expression) {:#minimum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. + Signature: ```typescript @@ -3668,25 +2535,30 @@ export declare function minimum(expression: Expression): AggregateFunction; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the minimum value of. A new representing the 'minimum' aggregation. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the minimum value of. | Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -### mod(expression, value) {:#mod_01df3cf} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'minimum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. ```typescript -// Calculate the remainder of dividing 'field1' by 5. -mod(field("field1"), 5); +// Find the lowest price of all products +minimum(field("price")).as("lowestPrice"); ``` +### mod(expression, value) {:#mod_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. + Signature: ```typescript @@ -3698,25 +2570,30 @@ export declare function mod(expression: Expression, value: unknown): FunctionExp | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The dividend expression. | -| value | unknown | The divisor constant. A new representing the modulo operation. | +| value | unknown | The divisor constant. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### notEqual(expression, value) {:#notequal_01df3cf} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the modulo operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if an expression is not equal to a constant value. ```typescript -// Check if the 'status' field is not equal to "completed" -notEqual(field("status"), "completed"); +// Calculate the remainder of dividing 'field1' by 5. +mod(field("field1"), 5); ``` +### notEqual(expression, value) {:#notequal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to a constant value. + Signature: ```typescript @@ -3728,25 +2605,30 @@ export declare function notEqual(expression: Expression, value: unknown): Boolea | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the inequality comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### round(expression) {:#round_1138a27} +A new `Expression` representing the inequality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that rounds a numeric value to the nearest whole number. ```typescript -// Round the value of the 'price' field. -round(field("price")); +// Check if the 'status' field is not equal to "completed" +notEqual(field("status"), "completed"); ``` +### round(expression) {:#round_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the nearest whole number. + Signature: ```typescript @@ -3757,25 +2639,30 @@ export declare function round(expression: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. A new Expr representing the rounded value. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### round(expression, decimalPlaces) {:#round_a3a92d0} +A new `Expression` representing the rounded value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that rounds a numeric value to the specified number of decimal places. ```typescript -// Round the value of the 'price' field to two decimal places. -round(field("price"), constant(2)); +// Round the value of the 'price' field. +round(field("price")); ``` +### round(expression, decimalPlaces) {:#round_a3a92d0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + Signature: ```typescript @@ -3787,12 +2674,23 @@ export declare function round(expression: Expression, decimalPlaces: number | Ex | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | -| decimalPlaces | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. A new Expr representing the rounded value. | +| decimalPlaces | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the rounded value. + +### Example + + +```typescript +// Round the value of the 'price' field to two decimal places. +round(field("price"), constant(2)); + +``` + ### split(expression, delimiter) {:#split_5b5612b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3811,12 +2709,14 @@ export declare function split(expression: Expression, delimiter: string): Functi | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | Split the result of this expression. | -| delimiter | string | Split on this delimiter. A new representing the split function. | +| delimiter | string | Split on this delimiter. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. + ### Example @@ -3844,12 +2744,14 @@ export declare function split(expression: Expression, delimiter: Expression): Fu | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | Split the result of this expression. | -| delimiter | [Expression](./firestore_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. A new representing the split function. | +| delimiter | [Expression](./firestore_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. + ### Example @@ -3866,12 +2768,6 @@ split(field('scores'), conditional(field('format').equal('csv'), constant(','), Creates an expression that computes the square root of a numeric value. -```typescript -// Compute the square root of the 'value' field. -sqrt(field("value")); - -``` - Signature: ```typescript @@ -3882,25 +2778,30 @@ export declare function sqrt(expression: Expression): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the square root will be computed for. A new representing the square root of the numeric value. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the square root will be computed for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### subtract(expression, value) {:#subtract_01df3cf} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the square root of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a constant value from an expression. ```typescript -// Subtract the constant value 2 from the 'value' field -subtract(field("value"), 2); +// Compute the square root of the 'value' field. +sqrt(field("value")); ``` +### subtract(expression, value) {:#subtract_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a constant value from an expression. + Signature: ```typescript @@ -3912,25 +2813,30 @@ export declare function subtract(expression: Expression, value: unknown): Functi | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract from. | -| value | unknown | The constant value to subtract. A new representing the subtraction operation. | +| value | unknown | The constant value to subtract. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### sum(expression) {:#sum_1138a27} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the subtraction operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. ```typescript -// Calculate the total revenue from a set of orders -sum(field("orderAmount")).as("totalRevenue"); +// Subtract the constant value 2 from the 'value' field +subtract(field("value"), 2); ``` +### sum(expression) {:#sum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. + Signature: ```typescript @@ -3941,12 +2847,23 @@ export declare function sum(expression: Expression): AggregateFunction; | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to sum up. A new representing the 'sum' aggregation. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to sum up. | Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'sum' aggregation. + +### Example + + +```typescript +// Calculate the total revenue from a set of orders +sum(field("orderAmount")).as("totalRevenue"); + +``` + ### type(expression) {:#type_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3970,6 +2887,8 @@ export declare function type(expression: Expression): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the data type. + ### Example @@ -3978,7 +2897,6 @@ export declare function type(expression: Expression): FunctionExpression; type(conditional(exists('foo'), constant(1), constant(true))) ``` - A new {Expression} representing the data type. ## function(field, ...) @@ -3989,12 +2907,6 @@ type(conditional(exists('foo'), constant(1), constant(true))) Creates an expression that returns `true` if a field is absent. Otherwise, returns `false` even if the field value is `null`. -```typescript -// Check if the field `value` is absent. -isAbsent("value"); - -``` - Signature: ```typescript @@ -4005,25 +2917,30 @@ export declare function isAbsent(field: string): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| field | string | The field to check. A new representing the 'isAbsent' check. | +| field | string | The field to check. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### reverse(field) {:#reverse_0fb8cd4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'isAbsent' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses a string value in the specified field. ```typescript -// Reverse the value of the 'myString' field. -reverse("myString"); +// Check if the field `value` is absent. +isAbsent("value"); ``` +### reverse(field) {:#reverse_0fb8cd4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string value in the specified field. + Signature: ```typescript @@ -4034,25 +2951,30 @@ export declare function reverse(field: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| field | string | The name of the field representing the string to reverse. A new representing the reversed string. | +| field | string | The name of the field representing the string to reverse. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### stringReverse(field) {:#stringreverse_0fb8cd4} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses a string value in the specified field. ```typescript // Reverse the value of the 'myString' field. -strReverse("myString"); +reverse("myString"); ``` +### stringReverse(field) {:#stringreverse_0fb8cd4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string value in the specified field. + Signature: ```typescript @@ -4063,12 +2985,23 @@ export declare function stringReverse(field: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| field | string | The name of the field representing the string to reverse. A new representing the reversed string. | +| field | string | The name of the field representing the string to reverse. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. + +### Example + + +```typescript +// Reverse the value of the 'myString' field. +strReverse("myString"); + +``` + ### substring(field, position, length) {:#substring_0d9573a} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4138,12 +3071,14 @@ export declare function abs(fieldName: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field to compute the absolute value of. A new representing the absolute value of the numeric value. | +| fieldName | string | The field to compute the absolute value of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. + ### add(fieldName, second) {:#add_b75bb8b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4151,12 +3086,6 @@ export declare function abs(fieldName: string): FunctionExpression; Creates an expression that adds a field's value to an expression. -```typescript -// Add the value of the 'quantity' field and the 'reserve' field. -add("quantity", field("reserve")); - -``` - Signature: ```typescript @@ -4174,6 +3103,17 @@ export declare function add(fieldName: string, second: Expression | unknown): Fu [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the addition operation. + +### Example + + +```typescript +// Add the value of the 'quantity' field and the 'reserve' field. +add("quantity", field("reserve")); + +``` + ### arrayContains(fieldName, element) {:#arraycontains_aaace4a} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4181,16 +3121,45 @@ export declare function add(fieldName: string, second: Expression | unknown): Fu Creates an expression that checks if a field's array value contains a specific element. +Signature: + +```typescript +export declare function arrayContains(fieldName: string, element: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The field name to check. | +| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The element to search for in the array. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. + +### Example + + ```typescript // Check if the 'colors' array contains the value of field 'selectedColor' arrayContains("colors", field("selectedColor")); ``` +### arrayContains(fieldName, element) {:#arraycontains_999590f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains a specific value. + Signature: ```typescript -export declare function arrayContains(fieldName: string, element: Expression): BooleanExpression; +export declare function arrayContains(fieldName: string, element: unknown): BooleanExpression; ``` #### Parameters @@ -4198,29 +3167,34 @@ export declare function arrayContains(fieldName: string, element: Expression): B | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to check. | -| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The element to search for in the array. A new representing the 'array\_contains' comparison. | +| element | unknown | The element to search for in the array. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContains(fieldName, element) {:#arraycontains_999590f} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's array value contains a specific value. ```typescript // Check if the 'colors' array contains "red" arrayContains("colors", "red"); -``` +``` + +### arrayContainsAll(fieldName, values) {:#arraycontainsall_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains all the specified values or expressions. Signature: ```typescript -export declare function arrayContains(fieldName: string, element: unknown): BooleanExpression; +export declare function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; ``` #### Parameters @@ -4228,18 +3202,16 @@ export declare function arrayContains(fieldName: string, element: unknown): Bool | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to check. | -| element | unknown | The element to search for in the array. A new representing the 'array\_contains' comparison. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAll(fieldName, values) {:#arraycontainsall_8060b23} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's array value contains all the specified values or expressions. ```typescript // Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" @@ -4247,10 +3219,17 @@ arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); ``` +### arrayContainsAll(fieldName, arrayExpression) {:#arraycontainsall_48da8d9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains all the specified values or expressions. + Signature: ```typescript -export declare function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; +export declare function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; ``` #### Parameters @@ -4258,18 +3237,16 @@ export declare function arrayContainsAll(fieldName: string, values: ArrayReturns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAll(fieldName, arrayExpression) {:#arraycontainsall_48da8d9} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's array value contains all the specified values or expressions. ```typescript // Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" @@ -4277,10 +3254,17 @@ arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); ``` +### arrayContainsAny(fieldName, values) {:#arraycontainsany_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains any of the specified elements. + Signature: ```typescript -export declare function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; +export declare function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; ``` #### Parameters @@ -4288,18 +3272,16 @@ export declare function arrayContainsAll(fieldName: string, arrayExpression: Exp | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to check. | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. A new representing the 'array\_contains\_all' comparison. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAny(fieldName, values) {:#arraycontainsany_8060b23} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's array value contains any of the specified elements. ```typescript // Check if the 'groups' array contains either the value from the 'userGroup' field @@ -4308,10 +3290,17 @@ arrayContainsAny("categories", [field("cate1"), "Science"]); ``` +### arrayContainsAny(fieldName, values) {:#arraycontainsany_1b4f7cd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's array value contains any of the specified elements. + Signature: ```typescript -export declare function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; +export declare function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; ``` #### Parameters @@ -4319,18 +3308,16 @@ export declare function arrayContainsAny(fieldName: string, values: ArrayReturns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### arrayContainsAny(fieldName, values) {:#arraycontainsany_1b4f7cd} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's array value contains any of the specified elements. ```typescript // Check if the 'groups' array contains either the value from the 'userGroup' field @@ -4339,29 +3326,33 @@ arrayContainsAny("categories", array([field("cate1"), "Science"])); ``` +### arrayLength(fieldName) {:#arraylength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of an array in a specified field. + Signature: ```typescript -export declare function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; +export declare function arrayLength(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| values | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array field. A new representing the 'array\_contains\_any' comparison. | +| fieldName | string | The name of the field containing an array to calculate the length of. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### arrayLength(fieldName) {:#arraylength_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of an array in a specified field. ```typescript // Get the number of items in field 'cart' @@ -4369,28 +3360,33 @@ arrayLength('cart'); ``` +### arraySum(fieldName) {:#arraysum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. + Signature: ```typescript -export declare function arrayLength(fieldName: string): FunctionExpression; +export declare function arraySum(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing an array to calculate the length of. A new representing the length of the array. | +| fieldName | string | The name of the field to compute the sum of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### arraySum(fieldName) {:#arraysum_e5b0480} +A new `Expression` representing the sum of the elements in the array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the sum of the elements in an array. ```typescript // Compute the sum of the elements in the 'scores' field. @@ -4398,28 +3394,33 @@ arraySum("scores"); ``` +### ascending(fieldName) {:#ascending_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. + Signature: ```typescript -export declare function arraySum(fieldName: string): FunctionExpression; +export declare function ascending(fieldName: string): Ordering; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the sum of. A new Expr representing the sum of the elements in the array. | +| fieldName | string | The field to create an ascending ordering for. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[Ordering](./firestore_pipelines.ordering.md#ordering_class) -### ascending(fieldName) {:#ascending_e5b0480} +A new `Ordering` for ascending sorting. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an that sorts documents in ascending order based on a field. ```typescript // Sort documents by the 'name' field in ascending order @@ -4428,28 +3429,33 @@ firestore.pipeline().collection("users") ``` +### average(fieldName) {:#average_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. + Signature: ```typescript -export declare function ascending(fieldName: string): Ordering; +export declare function average(fieldName: string): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field to create an ascending ordering for. A new Ordering for ascending sorting. | +| fieldName | string | The name of the field containing numeric values to average. | Returns: -[Ordering](./firestore_pipelines.ordering.md#ordering_class) +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -### average(fieldName) {:#average_e5b0480} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'average' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. ```typescript // Calculate the average age of users @@ -4457,28 +3463,33 @@ average("age").as("averageAge"); ``` +### byteLength(fieldName) {:#bytelength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. + Signature: ```typescript -export declare function average(fieldName: string): AggregateFunction; +export declare function byteLength(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing numeric values to average. A new representing the 'average' aggregation. | +| fieldName | string | The name of the field containing the string. | Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### byteLength(fieldName) {:#bytelength_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string in bytes. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. ```typescript // Calculate the length of the 'myString' field in bytes. @@ -4486,28 +3497,33 @@ byteLength("myString"); ``` +### ceil(fieldName) {:#ceil_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. + Signature: ```typescript -export declare function byteLength(fieldName: string): FunctionExpression; +export declare function ceil(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the string. A new representing the length of the string in bytes. | +| fieldName | string | The name of the field to compute the ceiling of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### ceil(fieldName) {:#ceil_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ceiling of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the ceiling of a numeric value. ```typescript // Compute the ceiling of the 'price' field. @@ -4515,28 +3531,33 @@ ceil("price"); ``` +### charLength(fieldName) {:#charlength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the character length of a string field in UTF8. + Signature: ```typescript -export declare function ceil(fieldName: string): FunctionExpression; +export declare function charLength(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the ceiling of. A new representing the ceiling of the numeric value. | +| fieldName | string | The name of the field containing the string. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### charLength(fieldName) {:#charlength_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the character length of a string field in UTF8. ```typescript // Get the character length of the 'name' field in UTF-8. @@ -4544,28 +3565,33 @@ strLength("name"); ``` +### collectionId(fieldName) {:#collectionid_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. + Signature: ```typescript -export declare function charLength(fieldName: string): FunctionExpression; +export declare function collectionId(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the string. A new representing the length of the string. | +| fieldName | string | The name of the field to get the collection ID from. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### collectionId(fieldName) {:#collectionid_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the collectionId operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the collection ID from a path. ```typescript // Get the collection ID from a path. @@ -4573,28 +3599,35 @@ collectionId("__name__"); ``` +### concat(fieldName, second, others) {:#concat_828272e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. + Signature: ```typescript -export declare function collectionId(fieldName: string): FunctionExpression; +export declare function concat(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to get the collection ID from. A new representing the collectionId operation. | +| fieldName | string | The name of a field to concatenate. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second literal or expression to concatenate. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Additional literal or expressions to concatenate. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### concat(fieldName, second, others) {:#concat_828272e} +A new `Expression` representing the concatenation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. ```typescript // Concatenate a field with a literal string. @@ -4602,30 +3635,34 @@ concat(field("firstName"), "Doe") ``` +### cosineDistance(fieldName, vector) {:#cosinedistance_463a23e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between a field's vector value and a literal vector value. + Signature: ```typescript -export declare function concat(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +export declare function cosineDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of a field to concatenate. | -| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second literal or expression to concatenate. | -| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Additional literal or expressions to concatenate. A new Expression representing the concatenation. | +| fieldName | string | The name of the field containing the first vector. | +| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles) or [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) to compare against. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### cosineDistance(fieldName, vector) {:#cosinedistance_463a23e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the Cosine distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Cosine distance between a field's vector value and a literal vector value. ```typescript // Calculate the Cosine distance between the 'location' field and a target location @@ -4633,10 +3670,17 @@ cosineDistance("location", [37.7749, -122.4194]); ``` +### cosineDistance(fieldName, vectorExpression) {:#cosinedistance_ed766a1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between a field's vector value and a vector expression. + Signature: ```typescript -export declare function cosineDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; +export declare function cosineDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; ``` #### Parameters @@ -4644,18 +3688,16 @@ export declare function cosineDistance(fieldName: string, vector: number[] | Vec | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the first vector. | -| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles) or [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) to compare against. A new representing the Cosine distance between the two vectors. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to compare against. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### cosineDistance(fieldName, vectorExpression) {:#cosinedistance_ed766a1} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the cosine distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Cosine distance between a field's vector value and a vector expression. ```typescript // Calculate the cosine distance between the 'userVector' field and the 'itemVector' field @@ -4663,29 +3705,33 @@ cosineDistance("userVector", field("itemVector")); ``` +### count(fieldName) {:#count_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs where the input field exists. + Signature: ```typescript -export declare function cosineDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; +export declare function count(fieldName: string): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the first vector. | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the cosine distance between the two vectors. | +| fieldName | string | The name of the field to count. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -### count(fieldName) {:#count_e5b0480} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'count' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that counts the number of stage inputs where the input field exists. ```typescript // Count the total number of products @@ -4693,28 +3739,33 @@ count("productId").as("totalProducts"); ``` +### descending(fieldName) {:#descending_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on a field. + Signature: ```typescript -export declare function count(fieldName: string): AggregateFunction; +export declare function descending(fieldName: string): Ordering; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to count. A new representing the 'count' aggregation. | +| fieldName | string | The field to create a descending ordering for. | Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[Ordering](./firestore_pipelines.ordering.md#ordering_class) -### descending(fieldName) {:#descending_e5b0480} +A new `Ordering` for descending sorting. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an that sorts documents in descending order based on a field. ```typescript // Sort documents by the 'name' field in descending order @@ -4723,28 +3774,34 @@ firestore.pipeline().collection("users") ``` +### divide(fieldName, expressions) {:#divide_cf36e43} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides a field's value by an expression. + Signature: ```typescript -export declare function descending(fieldName: string): Ordering; +export declare function divide(fieldName: string, expressions: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field to create a descending ordering for. A new Ordering for descending sorting. | +| fieldName | string | The field name to be divided. | +| expressions | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to divide by. | Returns: -[Ordering](./firestore_pipelines.ordering.md#ordering_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### divide(fieldName, expressions) {:#divide_cf36e43} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the division operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that divides a field's value by an expression. ```typescript // Divide the 'total' field by the 'count' field @@ -4752,10 +3809,17 @@ divide("total", field("count")); ``` +### divide(fieldName, value) {:#divide_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides a field's value by a constant value. + Signature: ```typescript -export declare function divide(fieldName: string, expressions: Expression): FunctionExpression; +export declare function divide(fieldName: string, value: unknown): FunctionExpression; ``` #### Parameters @@ -4763,18 +3827,16 @@ export declare function divide(fieldName: string, expressions: Expression): Func | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to be divided. | -| expressions | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to divide by. A new representing the division operation. | +| value | unknown | The constant value to divide by. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### divide(fieldName, value) {:#divide_65e2f32} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the division operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that divides a field's value by a constant value. ```typescript // Divide the 'value' field by 10 @@ -4782,29 +3844,34 @@ divide("value", 10); ``` +### dotProduct(fieldName, vector) {:#dotproduct_463a23e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between a field's vector value and a double array. + Signature: ```typescript -export declare function divide(fieldName: string, value: unknown): FunctionExpression; +export declare function dotProduct(fieldName: string, vector: number[] | VectorValue): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to be divided. | -| value | unknown | The constant value to divide by. A new representing the division operation. | +| fieldName | string | The name of the field containing the first vector. | +| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to calculate with. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### dotProduct(fieldName, vector) {:#dotproduct_463a23e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the dot product between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the dot product between a field's vector value and a double array. ```typescript // Calculate the dot product distance between a feature vector and a target vector @@ -4812,10 +3879,17 @@ dotProduct("features", [0.5, 0.8, 0.2]); ``` +### dotProduct(fieldName, vectorExpression) {:#dotproduct_ed766a1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between a field's vector value and a vector expression. + Signature: ```typescript -export declare function dotProduct(fieldName: string, vector: number[] | VectorValue): FunctionExpression; +export declare function dotProduct(fieldName: string, vectorExpression: Expression): FunctionExpression; ``` #### Parameters @@ -4823,18 +3897,16 @@ export declare function dotProduct(fieldName: string, vector: number[] | VectorV | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the first vector. | -| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to calculate with. A new representing the dot product between the two vectors. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to calculate with. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### dotProduct(fieldName, vectorExpression) {:#dotproduct_ed766a1} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the dot product between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the dot product between a field's vector value and a vector expression. ```typescript // Calculate the dot product distance between two document vectors: 'docVector1' and 'docVector2' @@ -4842,29 +3914,34 @@ dotProduct("docVector1", field("docVector2")); ``` +### endsWith(fieldName, suffix) {:#endswith_05ca3b0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value ends with a given postfix. + Signature: ```typescript -export declare function dotProduct(fieldName: string, vectorExpression: Expression): FunctionExpression; +export declare function endsWith(fieldName: string, suffix: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the first vector. | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to calculate with. A new representing the dot product between the two vectors. | +| fieldName | string | The field name to check. | +| suffix | string | The postfix to check for. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### endsWith(fieldName, suffix) {:#endswith_05ca3b0} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ends with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value ends with a given postfix. ```typescript // Check if the 'filename' field ends with ".txt" @@ -4872,10 +3949,17 @@ endsWith("filename", ".txt"); ``` +### endsWith(fieldName, suffix) {:#endswith_8fc0ebc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value ends with a given postfix. + Signature: ```typescript -export declare function endsWith(fieldName: string, suffix: string): BooleanExpression; +export declare function endsWith(fieldName: string, suffix: Expression): BooleanExpression; ``` #### Parameters @@ -4883,18 +3967,16 @@ export declare function endsWith(fieldName: string, suffix: string): BooleanExpr | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to check. | -| suffix | string | The postfix to check for. A new representing the 'ends with' comparison. | +| suffix | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the postfix. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### endsWith(fieldName, suffix) {:#endswith_8fc0ebc} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ends with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value ends with a given postfix. ```typescript // Check if the 'url' field ends with the value of the 'extension' field @@ -4902,29 +3984,34 @@ endsWith("url", field("extension")); ``` +### equal(fieldName, expression) {:#equal_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to an expression. + Signature: ```typescript -export declare function endsWith(fieldName: string, suffix: Expression): BooleanExpression; +export declare function equal(fieldName: string, expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| suffix | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the postfix. A new representing the 'ends with' comparison. | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### equal(fieldName, expression) {:#equal_1e91657} +A new `Expression` representing the equality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is equal to an expression. ```typescript // Check if the 'age' field is equal to the 'limit' field @@ -4932,10 +4019,17 @@ equal("age", field("limit")); ``` +### equal(fieldName, value) {:#equal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to a constant value. + Signature: ```typescript -export declare function equal(fieldName: string, expression: Expression): BooleanExpression; +export declare function equal(fieldName: string, value: unknown): BooleanExpression; ``` #### Parameters @@ -4943,18 +4037,16 @@ export declare function equal(fieldName: string, expression: Expression): Boolea | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the equality comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### equal(fieldName, value) {:#equal_65e2f32} +A new `Expression` representing the equality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is equal to a constant value. ```typescript // Check if the 'city' field is equal to string constant "London" @@ -4962,29 +4054,34 @@ equal("city", "London"); ``` +### equalAny(fieldName, values) {:#equalany_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to any of the provided values or expressions. + Signature: ```typescript -export declare function equal(fieldName: string, value: unknown): BooleanExpression; +export declare function equalAny(fieldName: string, values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the equality comparison. | +| fieldName | string | The field to compare. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values to check against. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### equalAny(fieldName, values) {:#equalany_8060b23} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is equal to any of the provided values or expressions. ```typescript // Check if the 'category' field is either "Electronics" or value of field 'primaryType' @@ -4992,10 +4089,17 @@ equalAny("category", [constant("Electronics"), field("primaryType")]); ``` +### equalAny(fieldName, arrayExpression) {:#equalany_48da8d9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is equal to any of the provided values or expressions. + Signature: ```typescript -export declare function equalAny(fieldName: string, values: Array): BooleanExpression; +export declare function equalAny(fieldName: string, arrayExpression: Expression): BooleanExpression; ``` #### Parameters @@ -5003,18 +4107,16 @@ export declare function equalAny(fieldName: string, values: ArrayReturns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### equalAny(fieldName, arrayExpression) {:#equalany_48da8d9} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is equal to any of the provided values or expressions. ```typescript // Check if the 'category' field is either "Electronics" or value of field 'primaryType' @@ -5022,29 +4124,34 @@ equalAny("category", ["Electronics", field("primaryType")]); ``` +### euclideanDistance(fieldName, vector) {:#euclideandistance_463a23e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between a field's vector value and a double array. + Signature: ```typescript -export declare function equalAny(fieldName: string, arrayExpression: Expression): BooleanExpression; +export declare function euclideanDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field to compare. | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input field. A new representing the 'IN' comparison. | +| fieldName | string | The name of the field containing the first vector. | +| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### euclideanDistance(fieldName, vector) {:#euclideandistance_463a23e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the Euclidean distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Euclidean distance between a field's vector value and a double array. ```typescript // Calculate the Euclidean distance between the 'location' field and a target location @@ -5052,10 +4159,17 @@ euclideanDistance("location", [37.7749, -122.4194]); ``` +### euclideanDistance(fieldName, vectorExpression) {:#euclideandistance_ed766a1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between a field's vector value and a vector expression. + Signature: ```typescript -export declare function euclideanDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; +export declare function euclideanDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; ``` #### Parameters @@ -5063,18 +4177,16 @@ export declare function euclideanDistance(fieldName: string, vector: number[] | | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the first vector. | -| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. A new representing the Euclidean distance between the two vectors. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to compare against. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### euclideanDistance(fieldName, vectorExpression) {:#euclideandistance_ed766a1} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the Euclidean distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Euclidean distance between a field's vector value and a vector expression. ```typescript // Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' @@ -5082,29 +4194,33 @@ euclideanDistance("pointA", field("pointB")); ``` +### exists(fieldName) {:#exists_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field exists. + Signature: ```typescript -export declare function euclideanDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; +export declare function exists(fieldName: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the first vector. | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the Euclidean distance between the two vectors. | +| fieldName | string | The field name to check. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### exists(fieldName) {:#exists_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'exists' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field exists. ```typescript // Check if the document has a field named "phoneNumber" @@ -5112,81 +4228,93 @@ exists("phoneNumber"); ``` +### exp(fieldName) {:#exp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes e to the power of the expression's result. + Signature: ```typescript -export declare function exists(fieldName: string): BooleanExpression; +export declare function exp(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. A new representing the 'exists' check. | +| fieldName | string | | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### exp(fieldName) {:#exp_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the exp of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes e to the power of the expression's result. ```typescript // Compute e to the power of the 'value' field. exp('value'); ``` - A new representing the exp of the numeric value. + +### floor(fieldName) {:#floor_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the floor of a numeric value. Signature: ```typescript -export declare function exp(fieldName: string): FunctionExpression; +export declare function floor(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | | +| fieldName | string | The name of the field to compute the floor of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### floor(fieldName) {:#floor_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the floor of the numeric value. + +### greaterThan(fieldName, expression) {:#greaterthan_1e91657} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the floor of a numeric value. +Creates an expression that checks if a field's value is greater than an expression. Signature: ```typescript -export declare function floor(fieldName: string): FunctionExpression; +export declare function greaterThan(fieldName: string, expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the floor of. A new representing the floor of the numeric value. | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThan(fieldName, expression) {:#greaterthan_1e91657} +A new `Expression` representing the greater than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is greater than an expression. ```typescript // Check if the value of field 'age' is greater than the value of field 'limit' @@ -5194,10 +4322,17 @@ greaterThan("age", field("limit")); ``` +### greaterThan(fieldName, value) {:#greaterthan_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than a constant value. + Signature: ```typescript -export declare function greaterThan(fieldName: string, expression: Expression): BooleanExpression; +export declare function greaterThan(fieldName: string, value: unknown): BooleanExpression; ``` #### Parameters @@ -5205,29 +4340,34 @@ export declare function greaterThan(fieldName: string, expression: Expression): | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the greater than comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThan(fieldName, value) {:#greaterthan_65e2f32} +A new `Expression` representing the greater than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is greater than a constant value. ```typescript // Check if the 'price' field is greater than 100 greaterThan("price", 100); -``` +``` + +### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_2e16acb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than or equal to an expression. Signature: ```typescript -export declare function greaterThan(fieldName: string, value: unknown): BooleanExpression; +export declare function greaterThanOrEqual(fieldName: string, value: Expression): BooleanExpression; ``` #### Parameters @@ -5235,18 +4375,16 @@ export declare function greaterThan(fieldName: string, value: unknown): BooleanE | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the greater than comparison. | +| value | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_2e16acb} +A new `Expression` representing the greater than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is greater than or equal to an expression. ```typescript // Check if the value of field 'age' is greater than or equal to the value of field 'limit' @@ -5254,10 +4392,17 @@ greaterThanOrEqual("age", field("limit")); ``` +### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is greater than or equal to a constant value. + Signature: ```typescript -export declare function greaterThanOrEqual(fieldName: string, value: Expression): BooleanExpression; +export declare function greaterThanOrEqual(fieldName: string, value: unknown): BooleanExpression; ``` #### Parameters @@ -5265,18 +4410,16 @@ export declare function greaterThanOrEqual(fieldName: string, value: Expression) | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| value | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the greater than or equal to comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_65e2f32} +A new `Expression` representing the greater than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is greater than or equal to a constant value. ```typescript // Check if the 'score' field is greater than or equal to 80 @@ -5284,29 +4427,33 @@ greaterThanOrEqual("score", 80); ``` +### length\_2(fieldName) {:#length_2_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a string, array, map, vector, or bytes. + Signature: ```typescript -export declare function greaterThanOrEqual(fieldName: string, value: unknown): BooleanExpression; +declare function length_2(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the greater than or equal to comparison. | +| fieldName | string | The name of the field to calculate the length of. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### length\_2(fieldName) {:#length_2_e5b0480} +A new `Expression` representing the length of the string, array, map, vector, or bytes. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of a string, array, map, vector, or bytes. ```typescript // Get the length of the 'name' field. @@ -5317,28 +4464,34 @@ length("cart"); ``` +### lessThan(fieldName, expression) {:#lessthan_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than an expression. + Signature: ```typescript -declare function length_2(fieldName: string): FunctionExpression; +export declare function lessThan(fieldName: string, expression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to calculate the length of. A new Expr representing the length of the string, array, map, vector, or bytes. | +| fieldName | string | The field name to compare. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### lessThan(fieldName, expression) {:#lessthan_1e91657} +A new `Expression` representing the less than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is less than an expression. ```typescript // Check if the 'age' field is less than the 'limit' field @@ -5346,10 +4499,17 @@ lessThan("age", field("limit")); ``` +### lessThan(fieldName, value) {:#lessthan_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than a constant value. + Signature: ```typescript -export declare function lessThan(fieldName: string, expression: Expression): BooleanExpression; +export declare function lessThan(fieldName: string, value: unknown): BooleanExpression; ``` #### Parameters @@ -5357,18 +4517,16 @@ export declare function lessThan(fieldName: string, expression: Expression): Boo | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the less than comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### lessThan(fieldName, value) {:#lessthan_65e2f32} +A new `Expression` representing the less than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is less than a constant value. ```typescript // Check if the 'price' field is less than 50 @@ -5376,10 +4534,17 @@ lessThan("price", 50); ``` +### lessThanOrEqual(fieldName, expression) {:#lessthanorequal_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than or equal to an expression. + Signature: ```typescript -export declare function lessThan(fieldName: string, value: unknown): BooleanExpression; +export declare function lessThanOrEqual(fieldName: string, expression: Expression): BooleanExpression; ``` #### Parameters @@ -5387,18 +4552,16 @@ export declare function lessThan(fieldName: string, value: unknown): BooleanExpr | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the less than comparison. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### lessThanOrEqual(fieldName, expression) {:#lessthanorequal_1e91657} +A new `Expression` representing the less than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is less than or equal to an expression. ```typescript // Check if the 'quantity' field is less than or equal to the 'limit' field @@ -5406,10 +4569,17 @@ lessThan("quantity", field("limit")); ``` +### lessThanOrEqual(fieldName, value) {:#lessthanorequal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is less than or equal to a constant value. + Signature: ```typescript -export declare function lessThanOrEqual(fieldName: string, expression: Expression): BooleanExpression; +export declare function lessThanOrEqual(fieldName: string, value: unknown): BooleanExpression; ``` #### Parameters @@ -5417,18 +4587,16 @@ export declare function lessThanOrEqual(fieldName: string, expression: Expressio | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the less than or equal to comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### lessThanOrEqual(fieldName, value) {:#lessthanorequal_65e2f32} +A new `Expression` representing the less than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is less than or equal to a constant value. ```typescript // Check if the 'score' field is less than or equal to 70 @@ -5436,29 +4604,34 @@ lessThan("score", 70); ``` +### like(fieldName, pattern) {:#like_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison against a field. + Signature: ```typescript -export declare function lessThanOrEqual(fieldName: string, value: unknown): BooleanExpression; +export declare function like(fieldName: string, pattern: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the less than or equal to comparison. | +| fieldName | string | The name of the field containing the string. | +| pattern | string | The pattern to search for. You can use "%" as a wildcard character. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### like(fieldName, pattern) {:#like_67f7432} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'like' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a case-sensitive wildcard string comparison against a field. ```typescript // Check if the 'title' field contains the string "guide" @@ -5466,10 +4639,17 @@ like("title", "%guide%"); ``` +### like(fieldName, pattern) {:#like_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison against a field. + Signature: ```typescript -export declare function like(fieldName: string, pattern: string): BooleanExpression; +export declare function like(fieldName: string, pattern: Expression): BooleanExpression; ``` #### Parameters @@ -5477,18 +4657,16 @@ export declare function like(fieldName: string, pattern: string): BooleanExpress | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| pattern | string | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### like(fieldName, pattern) {:#like_cb1318d} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'like' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a case-sensitive wildcard string comparison against a field. ```typescript // Check if the 'title' field contains the string "guide" @@ -5496,29 +4674,33 @@ like("title", field("pattern")); ``` +### ln(fieldName) {:#ln_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the natural logarithm of a numeric value. + Signature: ```typescript -export declare function like(fieldName: string, pattern: Expression): BooleanExpression; +export declare function ln(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the string. | -| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | +| fieldName | string | The name of the field to compute the natural logarithm of. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### ln(fieldName) {:#ln_e5b0480} +A new `Expression` representing the natural logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the natural logarithm of a numeric value. ```typescript // Compute the natural logarithm of the 'value' field. @@ -5526,28 +4708,34 @@ ln("value"); ``` +### log(fieldName, base) {:#log_a89e21b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of a field to a given base. + Signature: ```typescript -export declare function ln(fieldName: string): FunctionExpression; +export declare function log(fieldName: string, base: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the natural logarithm of. A new Expr representing the natural logarithm of the numeric value. | +| fieldName | string | The name of the field to compute the logarithm of. | +| base | number | The base of the logarithm. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### log(fieldName, base) {:#log_a89e21b} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the logarithm of a field to a given base. ```typescript // Compute the logarithm of the 'value' field with base 10. @@ -5555,10 +4743,17 @@ log("value", 10); ``` +### log(fieldName, base) {:#log_805b11f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the logarithm of a field to a given base. + Signature: ```typescript -export declare function log(fieldName: string, base: number): FunctionExpression; +export declare function log(fieldName: string, base: Expression): FunctionExpression; ``` #### Parameters @@ -5566,18 +4761,16 @@ export declare function log(fieldName: string, base: number): FunctionExpression | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field to compute the logarithm of. | -| base | number | The base of the logarithm. A new representing the logarithm of the numeric value. | +| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The base of the logarithm. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### log(fieldName, base) {:#log_805b11f} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the logarithm of a field to a given base. ```typescript // Compute the logarithm of the 'value' field with the base in the 'base' field. @@ -5585,29 +4778,33 @@ log("value", field("base")); ``` +### log10(fieldName) {:#log10_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the base-10 logarithm of a numeric value. + Signature: ```typescript -export declare function log(fieldName: string, base: Expression): FunctionExpression; +export declare function log10(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the logarithm of. | -| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The base of the logarithm. A new representing the logarithm of the numeric value. | +| fieldName | string | The name of the field to compute the base-10 logarithm of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### log10(fieldName) {:#log10_e5b0480} +A new `Expression` representing the base-10 logarithm of the numeric value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that computes the base-10 logarithm of a numeric value. ```typescript // Compute the base-10 logarithm of the 'value' field. @@ -5615,28 +4812,35 @@ log10("value"); ``` +### logicalMaximum(fieldName, second, others) {:#logicalmaximum_828272e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. + Signature: ```typescript -export declare function log10(fieldName: string): FunctionExpression; +export declare function logicalMaximum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to compute the base-10 logarithm of. A new Expr representing the base-10 logarithm of the numeric value. | +| fieldName | string | The first operand field name. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### logicalMaximum(fieldName, second, others) {:#logicalmaximum_828272e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical maximum operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. ```typescript // Returns the largest value between the 'field1' field, the 'field2' field, @@ -5645,10 +4849,17 @@ logicalMaximum("field1", field("field2"), 1000); ``` +### logicalMinimum(fieldName, second, others) {:#logicalminimum_828272e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. + Signature: ```typescript -export declare function logicalMaximum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +export declare function logicalMinimum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; ``` #### Parameters @@ -5657,18 +4868,16 @@ export declare function logicalMaximum(fieldName: string, second: Expression | u | --- | --- | --- | | fieldName | string | The first operand field name. | | second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | -| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical maximum operation. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### logicalMinimum(fieldName, second, others) {:#logicalminimum_828272e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical minimum operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. ```typescript // Returns the smallest value between the 'field1' field, the 'field2' field, @@ -5677,24 +4886,6 @@ logicalMinimum("field1", field("field2"), 1000); ``` -Signature: - -```typescript -export declare function logicalMinimum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| fieldName | string | The first operand field name. | -| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | -| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical minimum operation. | - -Returns: - -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) - ### mapGet(fieldName, subField) {:#mapget_06663cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -5702,12 +4893,6 @@ export declare function logicalMinimum(fieldName: string, second: Expression | u Accesses a value from a map (object) field using the provided key. -```typescript -// Get the 'city' value from the 'address' map field -mapGet("address", "city"); - -``` - Signature: ```typescript @@ -5719,12 +4904,23 @@ export declare function mapGet(fieldName: string, subField: string): FunctionExp | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name of the map field. | -| subField | string | The key to access in the map. A new representing the value associated with the given key in the map. | +| subField | string | The key to access in the map. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the value associated with the given key in the map. + +### Example + + +```typescript +// Get the 'city' value from the 'address' map field +mapGet("address", "city"); + +``` + ### maximum(fieldName) {:#maximum_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -5732,12 +4928,6 @@ export declare function mapGet(fieldName: string, subField: string): FunctionExp Creates an aggregation that finds the maximum value of a field across multiple stage inputs. -```typescript -// Find the highest score in a leaderboard -maximum("score").as("highestScore"); - -``` - Signature: ```typescript @@ -5748,25 +4938,30 @@ export declare function maximum(fieldName: string): AggregateFunction; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to find the maximum value of. A new representing the 'maximum' aggregation. | +| fieldName | string | The name of the field to find the maximum value of. | Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -### minimum(fieldName) {:#minimum_e5b0480} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'maximum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that finds the minimum value of a field across multiple stage inputs. ```typescript -// Find the lowest price of all products -minimum("price").as("lowestPrice"); +// Find the highest score in a leaderboard +maximum("score").as("highestScore"); ``` +### minimum(fieldName) {:#minimum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the minimum value of a field across multiple stage inputs. + Signature: ```typescript @@ -5777,25 +4972,30 @@ export declare function minimum(fieldName: string): AggregateFunction; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to find the minimum value of. A new representing the 'minimum' aggregation. | +| fieldName | string | The name of the field to find the minimum value of. | Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -### mod(fieldName, expression) {:#mod_1e91657} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'minimum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. ```typescript -// Calculate the remainder of dividing 'field1' by 'field2'. -mod("field1", field("field2")); +// Find the lowest price of all products +minimum("price").as("lowestPrice"); ``` +### mod(fieldName, expression) {:#mod_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. + Signature: ```typescript @@ -5807,25 +5007,30 @@ export declare function mod(fieldName: string, expression: Expression): Function | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The dividend field name. | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The divisor expression. A new representing the modulo operation. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The divisor expression. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### mod(fieldName, value) {:#mod_65e2f32} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the modulo operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. ```typescript -// Calculate the remainder of dividing 'field1' by 5. -mod("field1", 5); +// Calculate the remainder of dividing 'field1' by 'field2'. +mod("field1", field("field2")); ``` +### mod(fieldName, value) {:#mod_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. + Signature: ```typescript @@ -5837,25 +5042,30 @@ export declare function mod(fieldName: string, value: unknown): FunctionExpressi | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The dividend field name. | -| value | unknown | The divisor constant. A new representing the modulo operation. | +| value | unknown | The divisor constant. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### multiply(fieldName, second) {:#multiply_b75bb8b} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the modulo operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that multiplies a field's value by an expression. ```typescript -// Multiply the 'quantity' field by the 'price' field -multiply("quantity", field("price")); +// Calculate the remainder of dividing 'field1' by 5. +mod("field1", 5); ``` +### multiply(fieldName, second) {:#multiply_b75bb8b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that multiplies a field's value by an expression. + Signature: ```typescript @@ -5873,19 +5083,24 @@ export declare function multiply(fieldName: string, second: Expression | unknown [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### notEqual(fieldName, expression) {:#notequal_1e91657} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the multiplication operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is not equal to an expression. ```typescript -// Check if the 'status' field is not equal to the value of 'expectedStatus' -notEqual("status", field("expectedStatus")); +// Multiply the 'quantity' field by the 'price' field +multiply("quantity", field("price")); ``` +### notEqual(fieldName, expression) {:#notequal_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to an expression. + Signature: ```typescript @@ -5897,25 +5112,30 @@ export declare function notEqual(fieldName: string, expression: Expression): Boo | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. A new Expr representing the inequality comparison. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### notEqual(fieldName, value) {:#notequal_65e2f32} +A new `Expression` representing the inequality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is not equal to a constant value. ```typescript -// Check if the 'country' field is not equal to "USA" -notEqual("country", "USA"); +// Check if the 'status' field is not equal to the value of 'expectedStatus' +notEqual("status", field("expectedStatus")); ``` +### notEqual(fieldName, value) {:#notequal_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to a constant value. + Signature: ```typescript @@ -5927,25 +5147,30 @@ export declare function notEqual(fieldName: string, value: unknown): BooleanExpr | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| value | unknown | The constant value to compare to. A new Expr representing the inequality comparison. | +| value | unknown | The constant value to compare to. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### notEqualAny(fieldName, values) {:#notequalany_8060b23} +A new `Expression` representing the inequality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. ```typescript -// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' -notEqualAny("status", [constant("pending"), field("rejectedStatus")]); +// Check if the 'country' field is not equal to "USA" +notEqual("country", "USA"); ``` +### notEqualAny(fieldName, values) {:#notequalany_8060b23} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. + Signature: ```typescript @@ -5957,25 +5182,30 @@ export declare function notEqualAny(fieldName: string, values: ArrayReturns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### notEqualAny(fieldName, arrayExpression) {:#notequalany_48da8d9} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. ```typescript -// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' -notEqualAny("status", field("rejectedStatuses")); +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +notEqualAny("status", [constant("pending"), field("rejectedStatus")]); ``` +### notEqualAny(fieldName, arrayExpression) {:#notequalany_48da8d9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. + Signature: ```typescript @@ -5987,25 +5217,30 @@ export declare function notEqualAny(fieldName: string, arrayExpression: Expressi | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to compare. | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The values to check against. A new representing the 'NOT IN' comparison. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The values to check against. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### regexContains(fieldName, pattern) {:#regexcontains_67f7432} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string field contains a specified regular expression as a substring. ```typescript -// Check if the 'description' field contains "example" (case-insensitive) -regexContains("description", "(?i)example"); +// Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' +notEqualAny("status", field("rejectedStatuses")); ``` +### regexContains(fieldName, pattern) {:#regexcontains_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a specified regular expression as a substring. + Signature: ```typescript @@ -6017,25 +5252,30 @@ export declare function regexContains(fieldName: string, pattern: string): Boole | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| pattern | string | The regular expression to use for the search. A new representing the 'contains' comparison. | +| pattern | string | The regular expression to use for the search. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### regexContains(fieldName, pattern) {:#regexcontains_cb1318d} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string field contains a specified regular expression as a substring. ```typescript // Check if the 'description' field contains "example" (case-insensitive) -regexContains("description", field("pattern")); +regexContains("description", "(?i)example"); ``` +### regexContains(fieldName, pattern) {:#regexcontains_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a specified regular expression as a substring. + Signature: ```typescript @@ -6047,25 +5287,30 @@ export declare function regexContains(fieldName: string, pattern: Expression): B | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the search. A new representing the 'contains' comparison. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the search. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### regexMatch(fieldName, pattern) {:#regexmatch_67f7432} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string field matches a specified regular expression. ```typescript -// Check if the 'email' field matches a valid email pattern -regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); +// Check if the 'description' field contains "example" (case-insensitive) +regexContains("description", field("pattern")); ``` +### regexMatch(fieldName, pattern) {:#regexmatch_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field matches a specified regular expression. + Signature: ```typescript @@ -6077,25 +5322,30 @@ export declare function regexMatch(fieldName: string, pattern: string): BooleanE | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| pattern | string | The regular expression to use for the match. A new representing the regular expression match. | +| pattern | string | The regular expression to use for the match. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### regexMatch(fieldName, pattern) {:#regexmatch_cb1318d} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression match. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string field matches a specified regular expression. ```typescript // Check if the 'email' field matches a valid email pattern -regexMatch("email", field("pattern")); +regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); ``` +### regexMatch(fieldName, pattern) {:#regexmatch_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field matches a specified regular expression. + Signature: ```typescript @@ -6107,25 +5357,30 @@ export declare function regexMatch(fieldName: string, pattern: Expression): Bool | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the match. A new representing the regular expression match. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the match. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### round(fieldName) {:#round_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression match. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that rounds a numeric value to the nearest whole number. ```typescript -// Round the value of the 'price' field. -round("price"); +// Check if the 'email' field matches a valid email pattern +regexMatch("email", field("pattern")); ``` +### round(fieldName) {:#round_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the nearest whole number. + Signature: ```typescript @@ -6136,25 +5391,30 @@ export declare function round(fieldName: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to round. A new Expr representing the rounded value. | +| fieldName | string | The name of the field to round. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### round(fieldName, decimalPlaces) {:#round_07d0cf0} +A new `Expression` representing the rounded value. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that rounds a numeric value to the specified number of decimal places. ```typescript -// Round the value of the 'price' field to two decimal places. -round("price", 2); +// Round the value of the 'price' field. +round("price"); ``` +### round(fieldName, decimalPlaces) {:#round_07d0cf0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that rounds a numeric value to the specified number of decimal places. + Signature: ```typescript @@ -6166,12 +5426,23 @@ export declare function round(fieldName: string, decimalPlaces: number | Express | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field to round. | -| decimalPlaces | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. A new Expr representing the rounded value. | +| decimalPlaces | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the rounded value. + +### Example + + +```typescript +// Round the value of the 'price' field to two decimal places. +round("price", 2); + +``` + ### split(fieldName, delimiter) {:#split_2cfdd37} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -6190,12 +5461,14 @@ export declare function split(fieldName: string, delimiter: string): FunctionExp | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | Split the value in this field. | -| delimiter | string | Split on this delimiter. A new representing the split function. | +| delimiter | string | Split on this delimiter. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. + ### Example @@ -6223,12 +5496,14 @@ export declare function split(fieldName: string, delimiter: Expression): Functio | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | Split the value in this field. | -| delimiter | [Expression](./firestore_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. A new representing the split function. | +| delimiter | [Expression](./firestore_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. + ### Example @@ -6245,12 +5520,6 @@ split('scores', conditional(field('format').equal('csv'), constant(','), constan Creates an expression that computes the square root of a numeric value. -```typescript -// Compute the square root of the 'value' field. -sqrt("value"); - -``` - Signature: ```typescript @@ -6259,13 +5528,24 @@ export declare function sqrt(fieldName: string): FunctionExpression; #### Parameters -| Parameter | Type | Description | -| --- | --- | --- | -| fieldName | string | The name of the field to compute the square root of. A new representing the square root of the numeric value. | +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to compute the square root of. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the square root of the numeric value. + +### Example + -Returns: +```typescript +// Compute the square root of the 'value' field. +sqrt("value"); -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +``` ### startsWith(fieldName, prefix) {:#startswith_89325cc} @@ -6274,12 +5554,6 @@ export declare function sqrt(fieldName: string): FunctionExpression; Creates an expression that checks if a field's value starts with a given prefix. -```typescript -// Check if the 'name' field starts with "Mr." -startsWith("name", "Mr."); - -``` - Signature: ```typescript @@ -6291,25 +5565,30 @@ export declare function startsWith(fieldName: string, prefix: string): BooleanEx | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to check. | -| prefix | string | The prefix to check for. A new representing the 'starts with' comparison. | +| prefix | string | The prefix to check for. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### startsWith(fieldName, prefix) {:#startswith_266c338} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'starts with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a field's value starts with a given prefix. ```typescript -// Check if the 'fullName' field starts with the value of the 'firstName' field -startsWith("fullName", field("firstName")); +// Check if the 'name' field starts with "Mr." +startsWith("name", "Mr."); ``` +### startsWith(fieldName, prefix) {:#startswith_266c338} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a field's value starts with a given prefix. + Signature: ```typescript @@ -6321,25 +5600,30 @@ export declare function startsWith(fieldName: string, prefix: Expression): Boole | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to check. | -| prefix | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the prefix. A new representing the 'starts with' comparison. | +| prefix | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the prefix. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### stringConcat(fieldName, secondString, otherStrings) {:#stringconcat_d80077e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'starts with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that concatenates string functions, fields or constants together. ```typescript -// Combine the 'firstName', " ", and 'lastName' fields into a single string -stringConcat("firstName", " ", field("lastName")); +// Check if the 'fullName' field starts with the value of the 'firstName' field +startsWith("fullName", field("firstName")); ``` +### stringConcat(fieldName, secondString, otherStrings) {:#stringconcat_d80077e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates string functions, fields or constants together. + Signature: ```typescript @@ -6352,25 +5636,30 @@ export declare function stringConcat(fieldName: string, secondString: Expression | --- | --- | --- | | fieldName | string | The field name containing the initial string value. | | secondString | [Expression](./firestore_pipelines.expression.md#expression_class) \| string | An expression or string literal to concatenate. | -| otherStrings | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or literals (typically strings) to concatenate. A new representing the concatenated string. | +| otherStrings | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or literals (typically strings) to concatenate. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### stringContains(fieldName, substring) {:#stringcontains_5b94cfe} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the concatenated string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string field contains a specified substring. ```typescript -// Check if the 'description' field contains "example". -stringContains("description", "example"); +// Combine the 'firstName', " ", and 'lastName' fields into a single string +stringConcat("firstName", " ", field("lastName")); ``` +### stringContains(fieldName, substring) {:#stringcontains_5b94cfe} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a specified substring. + Signature: ```typescript @@ -6382,25 +5671,30 @@ export declare function stringContains(fieldName: string, substring: string): Bo | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| substring | string | The substring to search for. A new representing the 'contains' comparison. | +| substring | string | The substring to search for. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### stringContains(fieldName, substring) {:#stringcontains_ac3ba47} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string field contains a substring specified by an expression. ```typescript -// Check if the 'description' field contains the value of the 'keyword' field. -stringContains("description", field("keyword")); +// Check if the 'description' field contains "example". +stringContains("description", "example"); ``` +### stringContains(fieldName, substring) {:#stringcontains_ac3ba47} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string field contains a substring specified by an expression. + Signature: ```typescript @@ -6412,25 +5706,30 @@ export declare function stringContains(fieldName: string, substring: Expression) | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field containing the string. | -| substring | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the substring to search for. A new representing the 'contains' comparison. | +| substring | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the substring to search for. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### subtract(fieldName, expression) {:#subtract_1e91657} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts an expression from a field's value. ```typescript -// Subtract the 'discount' field from the 'price' field -subtract("price", field("discount")); +// Check if the 'description' field contains the value of the 'keyword' field. +stringContains("description", field("keyword")); ``` +### subtract(fieldName, expression) {:#subtract_1e91657} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts an expression from a field's value. + Signature: ```typescript @@ -6442,25 +5741,30 @@ export declare function subtract(fieldName: string, expression: Expression): Fun | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to subtract from. | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract. A new representing the subtraction operation. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### subtract(fieldName, value) {:#subtract_65e2f32} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the subtraction operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a constant value from a field's value. ```typescript -// Subtract 20 from the value of the 'total' field -subtract("total", 20); +// Subtract the 'discount' field from the 'price' field +subtract("price", field("discount")); ``` +### subtract(fieldName, value) {:#subtract_65e2f32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a constant value from a field's value. + Signature: ```typescript @@ -6472,25 +5776,30 @@ export declare function subtract(fieldName: string, value: unknown): FunctionExp | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The field name to subtract from. | -| value | unknown | The constant value to subtract. A new representing the subtraction operation. | +| value | unknown | The constant value to subtract. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### sum(fieldName) {:#sum_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the subtraction operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. ```typescript -// Calculate the total revenue from a set of orders -sum("orderAmount").as("totalRevenue"); +// Subtract 20 from the value of the 'total' field +subtract("total", 20); ``` +### sum(fieldName) {:#sum_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. + Signature: ```typescript @@ -6501,25 +5810,30 @@ export declare function sum(fieldName: string): AggregateFunction; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing numeric values to sum up. A new representing the 'sum' aggregation. | +| fieldName | string | The name of the field containing numeric values to sum up. | Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -### timestampAdd(fieldName, unit, amount) {:#timestampadd_341fe7d} +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'sum' aggregation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that adds a specified amount of time to a timestamp represented by a field. ```typescript -// Add 1 day to the 'timestamp' field. -timestampAdd("timestamp", "day", 1); +// Calculate the total revenue from a set of orders +sum("orderAmount").as("totalRevenue"); ``` +### timestampAdd(fieldName, unit, amount) {:#timestampadd_341fe7d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to a timestamp represented by a field. + Signature: ```typescript @@ -6532,25 +5846,30 @@ export declare function timestampAdd(fieldName: string, unit: 'microsecond' | 'm | --- | --- | --- | | fieldName | string | The name of the field representing the timestamp. | | unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | -| amount | number | The amount of time to add. A new representing the resulting timestamp. | +| amount | number | The amount of time to add. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_341fe7d} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. ```typescript -// Subtract 1 day from the 'timestamp' field. -timestampSubtract("timestamp", "day", 1); +// Add 1 day to the 'timestamp' field. +timestampAdd("timestamp", "day", 1); ``` +### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_341fe7d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. + Signature: ```typescript @@ -6563,25 +5882,30 @@ export declare function timestampSubtract(fieldName: string, unit: 'microsecond' | --- | --- | --- | | fieldName | string | The name of the field representing the timestamp. | | unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | -| amount | number | The amount of time to subtract. A new representing the resulting timestamp. | +| amount | number | The amount of time to subtract. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### timestampToUnixMicros(fieldName) {:#timestamptounixmicros_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to microseconds since epoch. -timestampToUnixMicros("timestamp"); +// Subtract 1 day from the 'timestamp' field. +timestampSubtract("timestamp", "day", 1); ``` +### timestampToUnixMicros(fieldName) {:#timestamptounixmicros_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + Signature: ```typescript @@ -6592,25 +5916,30 @@ export declare function timestampToUnixMicros(fieldName: string): FunctionExpres | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the timestamp. A new representing the number of microseconds since epoch. | +| fieldName | string | The name of the field representing the timestamp. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### timestampToUnixMillis(fieldName) {:#timestamptounixmillis_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of microseconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -timestampToUnixMillis("timestamp"); +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros("timestamp"); ``` +### timestampToUnixMillis(fieldName) {:#timestamptounixmillis_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + Signature: ```typescript @@ -6621,25 +5950,30 @@ export declare function timestampToUnixMillis(fieldName: string): FunctionExpres | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the timestamp. A new representing the number of milliseconds since epoch. | +| fieldName | string | The name of the field representing the timestamp. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### timestampToUnixSeconds(fieldName) {:#timestamptounixseconds_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of milliseconds since epoch. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). ```typescript -// Convert the 'timestamp' field to seconds since epoch. -timestampToUnixSeconds("timestamp"); +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis("timestamp"); ``` +### timestampToUnixSeconds(fieldName) {:#timestamptounixseconds_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + Signature: ```typescript @@ -6650,12 +5984,23 @@ export declare function timestampToUnixSeconds(fieldName: string): FunctionExpre | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the timestamp. A new representing the number of seconds since epoch. | +| fieldName | string | The name of the field representing the timestamp. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of seconds since epoch. + +### Example + + +```typescript +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds("timestamp"); + +``` + ### timestampTruncate(fieldName, granularity, timezone) {:#timestamptruncate_b6c7512} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -6675,12 +6020,14 @@ export declare function timestampTruncate(fieldName: string, granularity: TimeGr | --- | --- | --- | | fieldName | string | Truncate the timestamp value contained in this field. | | granularity | [TimeGranularity](./firestore_pipelines.md#timegranularity) | The granularity to truncate to. | -| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the truncated timestamp. + ### Example @@ -6709,12 +6056,14 @@ export declare function timestampTruncate(fieldName: string, granularity: Expres | --- | --- | --- | | fieldName | string | Truncate the timestamp value contained in this field. | | granularity | [Expression](./firestore_pipelines.expression.md#expression_class) | The granularity to truncate to. | -| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the truncated timestamp. + ### Example @@ -6731,34 +6080,60 @@ field('createdAt').timestampTruncate(field('granularity')) Creates an expression that converts a string field to lowercase. +Signature: + +```typescript +export declare function toLower(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the lowercase string. + +### Example + + ```typescript // Convert the 'name' field to lowercase toLower("name"); ``` +### toUpper(fieldName) {:#toupper_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string field to uppercase. + Signature: ```typescript -export declare function toLower(fieldName: string): FunctionExpression; +export declare function toUpper(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the string. A new representing the lowercase string. | +| fieldName | string | The name of the field containing the string. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### toUpper(fieldName) {:#toupper_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the uppercase string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a string field to uppercase. ```typescript // Convert the 'title' field to uppercase @@ -6766,28 +6141,34 @@ toUpper("title"); ``` +### trim(fieldName, valueToTrim) {:#trim_c9f90ee} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes leading and trailing whitespace from a string or byte array. + Signature: ```typescript -export declare function toUpper(fieldName: string): FunctionExpression; +export declare function trim(fieldName: string, valueToTrim?: string | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the string. A new representing the uppercase string. | +| fieldName | string | The name of the field containing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | 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: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### trim(fieldName, valueToTrim) {:#trim_c9f90ee} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that removes leading and trailing whitespace from a string or byte array. ```typescript // Trim whitespace from the 'userInput' field @@ -6798,23 +6179,6 @@ trim("userInput", '"'); ``` -Signature: - -```typescript -export declare function trim(fieldName: string, valueToTrim?: string | Expression): FunctionExpression; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| fieldName | string | The name of the field containing the string or byte array. | -| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | 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. A new representing the trimmed string. | - -Returns: - -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) - ### type(fieldName) {:#type_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -6838,6 +6202,8 @@ export declare function type(fieldName: string): FunctionExpression; [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the data type. + ### Example @@ -6846,7 +6212,6 @@ export declare function type(fieldName: string): FunctionExpression; type('title') ``` - A new {Expression} representing the data type. ### unixMicrosToTimestamp(fieldName) {:#unixmicrostotimestamp_e5b0480} @@ -6855,12 +6220,6 @@ type('title') Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. -```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -unixMicrosToTimestamp("microseconds"); - -``` - Signature: ```typescript @@ -6871,25 +6230,30 @@ export declare function unixMicrosToTimestamp(fieldName: string): FunctionExpres | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the number of microseconds since epoch. A new representing the timestamp. | +| fieldName | string | The name of the field representing the number of microseconds since epoch. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### unixMillisToTimestamp(fieldName) {:#unixmillistotimestamp_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. ```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -unixMillisToTimestamp("milliseconds"); +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp("microseconds"); ``` +### unixMillisToTimestamp(fieldName) {:#unixmillistotimestamp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + Signature: ```typescript @@ -6900,25 +6264,30 @@ export declare function unixMillisToTimestamp(fieldName: string): FunctionExpres | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the number of milliseconds since epoch. A new representing the timestamp. | +| fieldName | string | The name of the field representing the number of milliseconds since epoch. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### unixSecondsToTimestamp(fieldName) {:#unixsecondstotimestamp_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. ```typescript -// Interpret the 'seconds' field as seconds since epoch. -unixSecondsToTimestamp("seconds"); +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp("milliseconds"); ``` +### unixSecondsToTimestamp(fieldName) {:#unixsecondstotimestamp_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + Signature: ```typescript @@ -6929,25 +6298,30 @@ export declare function unixSecondsToTimestamp(fieldName: string): FunctionExpre | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the number of seconds since epoch. A new representing the timestamp. | +| fieldName | string | The name of the field representing the number of seconds since epoch. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### vectorLength(fieldName) {:#vectorlength_e5b0480} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of a Firestore Vector represented by a field. ```typescript -// Get the vector length (dimension) of the field 'embedding'. -vectorLength("embedding"); +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp("seconds"); ``` +### vectorLength(fieldName) {:#vectorlength_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a Firestore Vector represented by a field. + Signature: ```typescript @@ -6958,12 +6332,23 @@ export declare function vectorLength(fieldName: string): FunctionExpression; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field representing the Firestore Vector. A new representing the length of the array. | +| fieldName | string | The name of the field representing the Firestore Vector. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the array. + +### Example + + +```typescript +// Get the vector length (dimension) of the field 'embedding'. +vectorLength("embedding"); + +``` + ## function(first, ...) ### add(first, second) {:#add_846ca1b} @@ -6973,12 +6358,6 @@ export declare function vectorLength(fieldName: string): FunctionExpression; Creates an expression that adds two expressions together. -```typescript -// Add the value of the 'quantity' field and the 'reserve' field. -add(field("quantity"), field("reserve")); - -``` - Signature: ```typescript @@ -6996,20 +6375,24 @@ export declare function add(first: Expression, second: Expression | unknown): Fu [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### and(first, second, more) {:#and_e0c48bd} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the addition operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a logical 'AND' operation on multiple filter conditions. ```typescript -// Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND -// the 'status' field is "active" -const condition = and(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); +// Add the value of the 'quantity' field and the 'reserve' field. +add(field("quantity"), field("reserve")); ``` +### and(first, second, more) {:#and_e0c48bd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'AND' operation on multiple filter conditions. + Signature: ```typescript @@ -7022,25 +6405,31 @@ export declare function and(first: BooleanExpression, second: BooleanExpression, | --- | --- | --- | | first | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The first filter condition. | | second | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The second filter condition. | -| more | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'AND' together. A new representing the logical 'AND' operation. | +| more | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'AND' together. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### concat(first, second, others) {:#concat_83be015} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical 'AND' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. ```typescript -// Concatenate the 'firstName' and 'lastName' fields with a space in between. -concat(field("firstName"), " ", field("lastName")) +// Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND +// the 'status' field is "active" +const condition = and(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); ``` +### concat(first, second, others) {:#concat_83be015} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. + Signature: ```typescript @@ -7053,26 +6442,30 @@ export declare function concat(first: Expression, second: Expression | unknown, | --- | --- | --- | | first | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expressions to concatenate. | | second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second literal or expression to concatenate. | -| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Additional literals or expressions to concatenate. A new Expression representing the concatenation. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Additional literals or expressions to concatenate. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### logicalMaximum(first, second, others) {:#logicalmaximum_83be015} +A new `Expression` representing the concatenation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. ```typescript -// Returns the largest value between the 'field1' field, the 'field2' field, -// and 1000 -logicalMaximum(field("field1"), field("field2"), 1000); +// Concatenate the 'firstName' and 'lastName' fields with a space in between. +concat(field("firstName"), " ", field("lastName")) ``` +### logicalMaximum(first, second, others) {:#logicalmaximum_83be015} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. + Signature: ```typescript @@ -7085,26 +6478,31 @@ export declare function logicalMaximum(first: Expression, second: Expression | u | --- | --- | --- | | first | [Expression](./firestore_pipelines.expression.md#expression_class) | The first operand expression. | | second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | -| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical maximum operation. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### logicalMinimum(first, second, others) {:#logicalminimum_83be015} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical maximum operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. ```typescript -// Returns the smallest value between the 'field1' field, the 'field2' field, -// and 1000. -logicalMinimum(field("field1"), field("field2"), 1000); +// Returns the largest value between the 'field1' field, the 'field2' field, +// and 1000 +logicalMaximum(field("field1"), field("field2"), 1000); ``` +### logicalMinimum(first, second, others) {:#logicalminimum_83be015} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. + Signature: ```typescript @@ -7117,25 +6515,31 @@ export declare function logicalMinimum(first: Expression, second: Expression | u | --- | --- | --- | | first | [Expression](./firestore_pipelines.expression.md#expression_class) | The first operand expression. | | second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal. | -| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. A new representing the logical minimum operation. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions or literals. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### multiply(first, second) {:#multiply_846ca1b} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical minimum operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that multiplies two expressions together. ```typescript -// Multiply the 'quantity' field by the 'price' field -multiply(field("quantity"), field("price")); +// Returns the smallest value between the 'field1' field, the 'field2' field, +// and 1000. +logicalMinimum(field("field1"), field("field2"), 1000); ``` +### multiply(first, second) {:#multiply_846ca1b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that multiplies two expressions together. + Signature: ```typescript @@ -7153,20 +6557,24 @@ export declare function multiply(first: Expression, second: Expression | unknown [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### or(first, second, more) {:#or_e0c48bd} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the multiplication operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a logical 'OR' operation on multiple filter conditions. ```typescript -// Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR -// the 'status' field is "active" -const condition = or(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); +// Multiply the 'quantity' field by the 'price' field +multiply(field("quantity"), field("price")); ``` +### or(first, second, more) {:#or_e0c48bd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'OR' operation on multiple filter conditions. + Signature: ```typescript @@ -7179,29 +6587,31 @@ export declare function or(first: BooleanExpression, second: BooleanExpression, | --- | --- | --- | | first | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The first filter condition. | | second | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The second filter condition. | -| more | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'OR' together. A new representing the logical 'OR' operation. | +| more | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'OR' together. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### xor(first, second, additionalConditions) {:#xor_8197113} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical 'OR' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. ```typescript -// Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London", -// or 'status' is "active". -const condition = xor( - greaterThan("age", 18), - equal("city", "London"), - equal("status", "active")); +// Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR +// the 'status' field is "active" +const condition = or(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); ``` +### xor(first, second, additionalConditions) {:#xor_8197113} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. + Signature: ```typescript @@ -7214,12 +6624,27 @@ export declare function xor(first: BooleanExpression, second: BooleanExpression, | --- | --- | --- | | first | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The first condition. | | second | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The second condition. | -| additionalConditions | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional conditions to 'XOR' together. A new representing the logical 'XOR' operation. | +| additionalConditions | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional conditions to 'XOR' together. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logical 'XOR' operation. + +### Example + + +```typescript +// Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London", +// or 'status' is "active". +const condition = xor( + greaterThan("age", 18), + equal("city", "London"), + equal("status", "active")); + +``` + ## function(firstArray, ...) ### arrayConcat(firstArray, secondArray, otherArrays) {:#arrayconcat_c00d5d7} @@ -7229,12 +6654,6 @@ export declare function xor(first: BooleanExpression, second: BooleanExpression, Creates an expression that concatenates an array expression with other arrays. -```typescript -// Combine the 'items' array with two new item arrays -arrayConcat(field("items"), [field("newItems"), field("otherItems")]); - -``` - Signature: ```typescript @@ -7247,11 +6666,22 @@ export declare function arrayConcat(firstArray: Expression, secondArray: Express | --- | --- | --- | | firstArray | [Expression](./firestore_pipelines.expression.md#expression_class) | The first array expression to concatenate to. | | secondArray | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\] | The second array expression or array literal to concatenate to. | -| otherArrays | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. A new representing the concatenated array. | +| otherArrays | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the concatenated array. + +### Example + + +```typescript +// Combine the 'items' array with two new item arrays +arrayConcat(field("items"), [field("newItems"), field("otherItems")]); + +``` ## function(firstArrayField, ...) @@ -7262,12 +6692,6 @@ export declare function arrayConcat(firstArray: Expression, secondArray: Express Creates an expression that concatenates a field's array value with other arrays. -```typescript -// Combine the 'items' array with two new item arrays -arrayConcat("items", [field("newItems"), field("otherItems")]); - -``` - Signature: ```typescript @@ -7280,12 +6704,23 @@ export declare function arrayConcat(firstArrayField: string, secondArray: Expres | --- | --- | --- | | firstArrayField | string | The first array to concatenate to. | | secondArray | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\] | The second array expression or array literal to concatenate to. | -| otherArrays | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. A new representing the concatenated array. | +| otherArrays | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown\[\]> | Optional additional array expressions or array literals to concatenate. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the concatenated array. + +### Example + + +```typescript +// Combine the 'items' array with two new item arrays +arrayConcat("items", [field("newItems"), field("otherItems")]); + +``` + ## function(firstMap, ...) ### mapMerge(firstMap, secondMap, otherMaps) {:#mapmerge_cfe77ce} @@ -7295,13 +6730,6 @@ export declare function arrayConcat(firstArrayField: string, secondArray: Expres Creates an expression that merges multiple map values. -``` -// Merges the map in the settings field with, a map literal, and a map in -// that is conditionally returned by another expression -mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) - -``` - Signature: ```typescript @@ -7320,6 +6748,16 @@ export declare function mapMerge(firstMap: Record | Expression, [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +### Example + + +``` +// Merges the map in the settings field with, a map literal, and a map in +// that is conditionally returned by another expression +mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) + +``` + ## function(firstString, ...) ### stringConcat(firstString, secondString, otherStrings) {:#stringconcat_8a8d1b6} @@ -7329,12 +6767,6 @@ export declare function mapMerge(firstMap: Record | Expression, Creates an expression that concatenates string expressions together. -```typescript -// Combine the 'firstName', " ", and 'lastName' fields into a single string -stringConcat(field("firstName"), " ", field("lastName")); - -``` - Signature: ```typescript @@ -7347,12 +6779,23 @@ export declare function stringConcat(firstString: Expression, secondString: Expr | --- | --- | --- | | firstString | [Expression](./firestore_pipelines.expression.md#expression_class) | The initial string expression to concatenate to. | | secondString | [Expression](./firestore_pipelines.expression.md#expression_class) \| string | An expression or string literal to concatenate. | -| otherStrings | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or literals (typically strings) to concatenate. A new representing the concatenated string. | +| otherStrings | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| string> | Optional additional expressions or literals (typically strings) to concatenate. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the concatenated string. + +### Example + + +```typescript +// Combine the 'firstName', " ", and 'lastName' fields into a single string +stringConcat(field("firstName"), " ", field("lastName")); + +``` + ## function(ifExpr, ...) ### ifAbsent(ifExpr, elseExpr) {:#ifabsent_0e6d161} @@ -7362,13 +6805,6 @@ export declare function stringConcat(firstString: Expression, secondString: Expr Creates an expression that returns the `elseExpr` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -ifAbsent(field("optional_field"), constant("default_value")) - -``` - Signature: ```typescript @@ -7380,26 +6816,31 @@ export declare function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expr | Parameter | Type | Description | | --- | --- | --- | | ifExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check for absence. | -| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if \[ifExpr\] is absent. A new Expression representing the ifAbsent operation. | +| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if \[ifExpr\] is absent. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) -### ifAbsent(ifExpr, elseValue) {:#ifabsent_c34e5ed} +A new Expression representing the ifAbsent operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `elseValue` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. ```typescript // Returns the value of the optional field 'optional_field', or returns 'default_value' // if the field is absent. -ifAbsent(field("optional_field"), "default_value") +ifAbsent(field("optional_field"), constant("default_value")) ``` +### ifAbsent(ifExpr, elseValue) {:#ifabsent_c34e5ed} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. + Signature: ```typescript @@ -7411,12 +6852,24 @@ export declare function ifAbsent(ifExpr: Expression, elseValue: unknown): Expres | Parameter | Type | Description | | --- | --- | --- | | ifExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check for absence. | -| elseValue | unknown | The value that will be returned if ifExpr evaluates to an absent value. A new \[Expression\] representing the ifAbsent operation. | +| elseValue | unknown | The value that will be returned if ifExpr evaluates to an absent value. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new \[Expression\] representing the ifAbsent operation. + +### Example + + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent(field("optional_field"), "default_value") + +``` + ## function(ifFieldName, ...) ### ifAbsent(ifFieldName, elseExpr) {:#ifabsent_e6dabea} @@ -7426,13 +6879,6 @@ export declare function ifAbsent(ifExpr: Expression, elseValue: unknown): Expres Creates an expression that returns the `elseExpr` argument if `ifFieldName` is absent, else return the value of the field. -```typescript -// Returns the value of the optional field 'optional_field', or returns the value of -// 'default_field' if 'optional_field' is absent. -ifAbsent("optional_field", field("default_field")) - -``` - Signature: ```typescript @@ -7444,26 +6890,31 @@ export declare function ifAbsent(ifFieldName: string, elseExpr: Expression): Exp | Parameter | Type | Description | | --- | --- | --- | | ifFieldName | string | The field to check for absence. | -| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if ifFieldName is absent. A new Expression representing the ifAbsent operation. | +| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if ifFieldName is absent. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) -### ifAbsent(ifFieldName, elseValue) {:#ifabsent_d8f2823} +A new Expression representing the ifAbsent operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `elseValue` argument if `ifFieldName` is absent, else return the value of the field. ```typescript -// Returns the value of the optional field 'optional_field', or returns 'default_value' -// if the field is absent. -ifAbsent("optional_field", "default_value") +// Returns the value of the optional field 'optional_field', or returns the value of +// 'default_field' if 'optional_field' is absent. +ifAbsent("optional_field", field("default_field")) ``` +### ifAbsent(ifFieldName, elseValue) {:#ifabsent_d8f2823} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if `ifFieldName` is absent, else return the value of the field. + Signature: ```typescript @@ -7475,12 +6926,24 @@ export declare function ifAbsent(ifFieldName: string | Expression, elseValue: Ex | Parameter | Type | Description | | --- | --- | --- | | ifFieldName | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The field to check for absence. | -| elseValue | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The value that will be returned if \[ifFieldName\] is absent. A new Expression representing the ifAbsent operation. | +| elseValue | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The value that will be returned if \[ifFieldName\] is absent. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new Expression representing the ifAbsent operation. + +### Example + + +```typescript +// Returns the value of the optional field 'optional_field', or returns 'default_value' +// if the field is absent. +ifAbsent("optional_field", "default_value") + +``` + ## function(input, ...) ### substring(input, position, length) {:#substring_e6e0aa3} @@ -7542,12 +7005,6 @@ export declare function substring(input: Expression, position: Expression, lengt Creates an expression that divides two expressions. -```typescript -// Divide the 'total' field by the 'count' field -divide(field("total"), field("count")); - -``` - Signature: ```typescript @@ -7559,25 +7016,30 @@ export declare function divide(left: Expression, right: Expression): FunctionExp | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to be divided. | -| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to divide by. A new representing the division operation. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to divide by. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### equal(left, right) {:#equal_b3c3382} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the division operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if two expressions are equal. ```typescript -// Check if the 'age' field is equal to an expression -equal(field("age"), field("minAge").add(10)); +// Divide the 'total' field by the 'count' field +divide(field("total"), field("count")); ``` +### equal(left, right) {:#equal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if two expressions are equal. + Signature: ```typescript @@ -7589,25 +7051,30 @@ export declare function equal(left: Expression, right: Expression): BooleanExpre | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to compare. | -| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the equality comparison. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThan(left, right) {:#greaterthan_b3c3382} +A new `Expression` representing the equality comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if the first expression is greater than the second expression. ```typescript -// Check if the 'age' field is greater than 18 -greaterThan(field("age"), Constant(9).add(9)); +// Check if the 'age' field is equal to an expression +equal(field("age"), field("minAge").add(10)); ``` +### greaterThan(left, right) {:#greaterthan_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is greater than the second expression. + Signature: ```typescript @@ -7619,25 +7086,30 @@ export declare function greaterThan(left: Expression, right: Expression): Boolea | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to compare. | -| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the greater than comparison. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### greaterThanOrEqual(left, right) {:#greaterthanorequal_b3c3382} +A new `Expression` representing the greater than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if the first expression is greater than or equal to the second expression. ```typescript -// Check if the 'quantity' field is greater than or equal to the field "threshold" -greaterThanOrEqual(field("quantity"), field("threshold")); +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), Constant(9).add(9)); ``` +### greaterThanOrEqual(left, right) {:#greaterthanorequal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is greater than or equal to the second expression. + Signature: ```typescript @@ -7649,25 +7121,30 @@ export declare function greaterThanOrEqual(left: Expression, right: Expression): | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to compare. | -| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the greater than or equal to comparison. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### lessThan(left, right) {:#lessthan_b3c3382} +A new `Expression` representing the greater than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if the first expression is less than the second expression. ```typescript -// Check if the 'age' field is less than 30 -lessThan(field("age"), field("limit")); +// Check if the 'quantity' field is greater than or equal to the field "threshold" +greaterThanOrEqual(field("quantity"), field("threshold")); ``` +### lessThan(left, right) {:#lessthan_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is less than the second expression. + Signature: ```typescript @@ -7679,25 +7156,30 @@ export declare function lessThan(left: Expression, right: Expression): BooleanEx | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to compare. | -| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the less than comparison. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### lessThanOrEqual(left, right) {:#lessthanorequal_b3c3382} +A new `Expression` representing the less than comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if the first expression is less than or equal to the second expression. ```typescript -// Check if the 'quantity' field is less than or equal to 20 -lessThan(field("quantity"), field("limit")); +// Check if the 'age' field is less than 30 +lessThan(field("age"), field("limit")); ``` +### lessThanOrEqual(left, right) {:#lessthanorequal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the first expression is less than or equal to the second expression. + Signature: ```typescript @@ -7709,25 +7191,30 @@ export declare function lessThanOrEqual(left: Expression, right: Expression): Bo | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to compare. | -| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the less than or equal to comparison. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### mod(left, right) {:#mod_b3c3382} +A new `Expression` representing the less than or equal to comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the modulo (remainder) of dividing two expressions. ```typescript -// Calculate the remainder of dividing 'field1' by 'field2'. -mod(field("field1"), field("field2")); +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), field("limit")); ``` +### mod(left, right) {:#mod_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the modulo (remainder) of dividing two expressions. + Signature: ```typescript @@ -7739,25 +7226,30 @@ export declare function mod(left: Expression, right: Expression): FunctionExpres | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_pipelines.expression.md#expression_class) | The dividend expression. | -| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The divisor expression. A new representing the modulo operation. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The divisor expression. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### notEqual(left, right) {:#notequal_b3c3382} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the modulo operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if two expressions are not equal. ```typescript -// Check if the 'status' field is not equal to field 'finalState' -notEqual(field("status"), field("finalState")); +// Calculate the remainder of dividing 'field1' by 'field2'. +mod(field("field1"), field("field2")); ``` +### notEqual(left, right) {:#notequal_b3c3382} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if two expressions are not equal. + Signature: ```typescript @@ -7769,12 +7261,23 @@ export declare function notEqual(left: Expression, right: Expression): BooleanEx | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to compare. | -| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. A new Expr representing the inequality comparison. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The second expression to compare. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +A new `Expression` representing the inequality comparison. + +### Example + + +```typescript +// Check if the 'status' field is not equal to field 'finalState' +notEqual(field("status"), field("finalState")); + +``` + ### pipelineResultEqual(left, right) {:#pipelineresultequal_707a755} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -7792,8 +7295,8 @@ export declare function pipelineResultEqual(left: PipelineResult, right: Pipelin | Parameter | Type | Description | | --- | --- | --- | -| left | [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) | | -| right | [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) | | +| left | [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) | First PipelineResult to compare. | +| right | [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) | Second PipelineResult to compare. | Returns: @@ -7801,16 +7304,10 @@ boolean ### subtract(left, right) {:#subtract_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Creates an expression that subtracts two expressions. - -```typescript -// Subtract the 'discount' field from the 'price' field -subtract(field("price"), field("discount")); - -``` +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts two expressions. Signature: @@ -7823,12 +7320,23 @@ export declare function subtract(left: Expression, right: Expression): FunctionE | Parameter | Type | Description | | --- | --- | --- | | left | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract from. | -| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract. A new representing the subtraction operation. | +| right | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the subtraction operation. + +### Example + + +```typescript +// Subtract the 'discount' field from the 'price' field +subtract(field("price"), field("discount")); + +``` + ## function(mapExpr, ...) ### mapRemove(mapExpr, key) {:#mapremove_23c7d51} @@ -7838,12 +7346,6 @@ export declare function subtract(left: Expression, right: Expression): FunctionE Creates an expression that removes a key from the map produced by evaluating an expression. -``` -// Removes the key 'baz' from the input map. -mapRemove(map({foo: 'bar', baz: true}), 'baz'); - -``` - Signature: ```typescript @@ -7861,19 +7363,23 @@ export declare function mapRemove(mapExpr: Expression, key: string): FunctionExp [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### mapRemove(mapExpr, keyExpr) {:#mapremove_9fbcaa3} - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that removes a key from the map produced by evaluating an expression. ``` // Removes the key 'baz' from the input map. -mapRemove(map({foo: 'bar', baz: true}), constant('baz')); +mapRemove(map({foo: 'bar', baz: true}), 'baz'); +@example ``` +### mapRemove(mapExpr, keyExpr) {:#mapremove_9fbcaa3} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map produced by evaluating an expression. + Signature: ```typescript @@ -7891,6 +7397,16 @@ export declare function mapRemove(mapExpr: Expression, keyExpr: Expression): Fun [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +### Example + + +``` +// Removes the key 'baz' from the input map. +mapRemove(map({foo: 'bar', baz: true}), constant('baz')); +@example + +``` + ## function(mapExpression, ...) ### mapGet(mapExpression, subField) {:#mapget_688c050} @@ -7900,12 +7416,6 @@ export declare function mapRemove(mapExpr: Expression, keyExpr: Expression): Fun Accesses a value from a map (object) expression using the provided key. -```typescript -// Get the 'city' value from the 'address' map field -mapGet(field("address"), "city"); - -``` - Signature: ```typescript @@ -7917,12 +7427,23 @@ export declare function mapGet(mapExpression: Expression, subField: string): Fun | Parameter | Type | Description | | --- | --- | --- | | mapExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the map. | -| subField | string | The key to access in the map. A new representing the value associated with the given key in the map. | +| subField | string | The key to access in the map. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the value associated with the given key in the map. + +### Example + + +```typescript +// Get the 'city' value from the 'address' map field +mapGet(field("address"), "city"); + +``` + ## function(mapField, ...) ### mapMerge(mapField, secondMap, otherMaps) {:#mapmerge_70a564b} @@ -7932,13 +7453,6 @@ export declare function mapGet(mapExpression: Expression, subField: string): Fun Creates an expression that merges multiple map values. -``` -// Merges the map in the settings field with, a map literal, and a map in -// that is conditionally returned by another expression -mapMerge('settings', { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) - -``` - Signature: ```typescript @@ -7957,6 +7471,16 @@ export declare function mapMerge(mapField: string, secondMap: Record This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -7964,12 +7488,6 @@ export declare function mapMerge(mapField: string, secondMap: RecordSignature: ```typescript @@ -7987,19 +7505,22 @@ export declare function mapRemove(mapField: string, key: string): FunctionExpres [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### mapRemove(mapField, keyExpr) {:#mapremove_8406d13} - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that removes a key from the map at the specified field name. ``` // Removes the key 'city' field from the map in the address field of the input document. -mapRemove('address', constant('city')); +mapRemove('address', 'city'); ``` +### mapRemove(mapField, keyExpr) {:#mapremove_8406d13} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes a key from the map at the specified field name. + Signature: ```typescript @@ -8017,6 +7538,15 @@ export declare function mapRemove(mapField: string, keyExpr: Expression): Functi [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +### Example + + +``` +// Removes the key 'city' field from the map in the address field of the input document. +mapRemove('address', constant('city')); + +``` + ## function(name, ...) ### field(name) {:#field_1eaaff4} @@ -8024,19 +7554,10 @@ export declare function mapRemove(mapField: string, keyExpr: Expression): Functi > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates a instance representing the field at the given path. +Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). -```typescript -// Create a Field instance for the 'title' field -const titleField = field("title"); - -// Create a Field instance for a nested field 'author.firstName' -const authorFirstNameField = field("author.firstName"); - -``` - Signature: ```typescript @@ -8047,12 +7568,26 @@ export declare function field(name: string): Field; | Parameter | Type | Description | | --- | --- | --- | -| name | string | The path to the field. A new instance representing the specified field. | +| name | string | The path to the field. | Returns: [Field](./firestore_pipelines.field.md#field_class) +A new [Field](./firestore_pipelines.field.md#field_class) instance representing the specified field. + +### Example + + +```typescript +// Create a Field instance for the 'title' field +const titleField = field("title"); + +// Create a Field instance for a nested field 'author.firstName' +const authorFirstNameField = field("author.firstName"); + +``` + ## function(options, ...) ### execute(options) {:#execute_9e87e31} @@ -8064,20 +7599,9 @@ Executes a pipeline and returns a Promise to represent the asynchronous operatio The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously. -The pipeline results are returned as a that contains a list of objects. Each typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example: - -

  • If there are no stages or only transformation stages, each represents a single document.
  • If there is an aggregation, only a single is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each represents a distinct group and its associated aggregated values.
- -

Example: - -```typescript -const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") - .where(gt(field("rating"), 4.5)) - .select("title", "author", "rating")); - -const results: PipelineResults = snapshot.results; +The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example: -``` +

  • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
  • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
Signature: @@ -8089,12 +7613,26 @@ export declare function execute(options: PipelineExecuteOptions): PromiseReturns: Promise<[PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class)> +A Promise representing the asynchronous pipeline execution. + +### Example + + +```typescript +const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") + .where(gt(field("rating"), 4.5)) + .select("title", "author", "rating")); + +const results: PipelineResults = snapshot.results; + +``` + ## function(path, ...) ### field(path) {:#field_34ee07d} @@ -8102,7 +7640,7 @@ Promise<[PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipeline > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates a instance representing the field at the given path. +Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. Signature: @@ -8114,12 +7652,14 @@ export declare function field(path: FieldPath): Field; | Parameter | Type | Description | | --- | --- | --- | -| path | [FieldPath](./firestore_.fieldpath.md#fieldpath_class) | A FieldPath specifying the field. A new instance representing the specified field. | +| path | [FieldPath](./firestore_.fieldpath.md#fieldpath_class) | A FieldPath specifying the field. | Returns: [Field](./firestore_pipelines.field.md#field_class) +A new [Field](./firestore_pipelines.field.md#field_class) instance representing the specified field. + ## function(pipeline, ...) ### execute(pipeline) {:#execute_01df620} @@ -8131,11 +7671,30 @@ Executes a pipeline and returns a Promise to represent the asynchronous operatio The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously. -The pipeline results are returned as a that contains a list of objects. Each typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example: +The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example: + +
  • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
  • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
+ +Signature: + +```typescript +export declare function execute(pipeline: Pipeline): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pipeline | [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | The pipeline to execute. | + +Returns: + +Promise<[PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class)> + +A Promise representing the asynchronous pipeline execution. -
  • If there are no stages or only transformation stages, each represents a single document.
  • If there is an aggregation, only a single is returned, representing the aggregated results over the entire dataset .
  • If there is an aggregation stage with grouping, each represents a distinct group and its associated aggregated values.
+### Example -

Example: ```typescript const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") @@ -8146,30 +7705,35 @@ const results: PipelineResults = snapshot.results; ``` +## function(stringExpression, ...) + +### charLength(stringExpression) {:#charlength_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the character length of a string expression in UTF-8. + Signature: ```typescript -export declare function execute(pipeline: Pipeline): Promise; +export declare function charLength(stringExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| pipeline | [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | The pipeline to execute. A Promise representing the asynchronous pipeline execution. | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to calculate the length of. | Returns: -Promise<[PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class)> - -## function(stringExpression, ...) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### charLength(stringExpression) {:#charlength_c25a54a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the character length of a string expression in UTF-8. ```typescript // Get the character length of the 'name' field in UTF-8. @@ -8177,28 +7741,34 @@ strLength(field("name")); ``` +### endsWith(stringExpression, suffix) {:#endswith_0a0b889} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression ends with a given postfix. + Signature: ```typescript -export declare function charLength(stringExpression: Expression): FunctionExpression; +export declare function endsWith(stringExpression: Expression, suffix: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to calculate the length of. A new representing the length of the string. | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | +| suffix | string | The postfix to check for. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### endsWith(stringExpression, suffix) {:#endswith_0a0b889} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ends with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression ends with a given postfix. ```typescript // Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." @@ -8206,10 +7776,17 @@ endsWith(field("fullName"), "Jr."); ``` +### endsWith(stringExpression, suffix) {:#endswith_13aee0d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression ends with a given postfix. + Signature: ```typescript -export declare function endsWith(stringExpression: Expression, suffix: string): BooleanExpression; +export declare function endsWith(stringExpression: Expression, suffix: Expression): BooleanExpression; ``` #### Parameters @@ -8217,18 +7794,16 @@ export declare function endsWith(stringExpression: Expression, suffix: string): | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | -| suffix | string | The postfix to check for. A new representing the 'ends with' comparison. | +| suffix | [Expression](./firestore_pipelines.expression.md#expression_class) | The postfix to check for. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### endsWith(stringExpression, suffix) {:#endswith_13aee0d} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ends with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression ends with a given postfix. ```typescript // Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." @@ -8236,29 +7811,34 @@ endsWith(field("fullName"), constant("Jr.")); ``` +### like(stringExpression, pattern) {:#like_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison. + Signature: ```typescript -export declare function endsWith(stringExpression: Expression, suffix: Expression): BooleanExpression; +export declare function like(stringExpression: Expression, pattern: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | -| suffix | [Expression](./firestore_pipelines.expression.md#expression_class) | The postfix to check for. A new representing the 'ends with' comparison. | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| pattern | string | The pattern to search for. You can use "%" as a wildcard character. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### like(stringExpression, pattern) {:#like_a84c581} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'like' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a case-sensitive wildcard string comparison. ```typescript // Check if the 'title' field contains the string "guide" @@ -8266,10 +7846,17 @@ like(field("title"), "%guide%"); ``` +### like(stringExpression, pattern) {:#like_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a case-sensitive wildcard string comparison. + Signature: ```typescript -export declare function like(stringExpression: Expression, pattern: string): BooleanExpression; +export declare function like(stringExpression: Expression, pattern: Expression): BooleanExpression; ``` #### Parameters @@ -8277,29 +7864,34 @@ export declare function like(stringExpression: Expression, pattern: string): Boo | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | -| pattern | string | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### like(stringExpression, pattern) {:#like_b534848} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'like' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that performs a case-sensitive wildcard string comparison. ```typescript // Check if the 'title' field contains the string "guide" like(field("title"), field("pattern")); -``` +``` + +### regexContains(stringExpression, pattern) {:#regexcontains_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a specified regular expression as a substring. Signature: ```typescript -export declare function like(stringExpression: Expression, pattern: Expression): BooleanExpression; +export declare function regexContains(stringExpression: Expression, pattern: string): BooleanExpression; ``` #### Parameters @@ -8307,18 +7899,16 @@ export declare function like(stringExpression: Expression, pattern: Expression): | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | -| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The pattern to search for. You can use "%" as a wildcard character. A new representing the 'like' comparison. | +| pattern | string | The regular expression to use for the search. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### regexContains(stringExpression, pattern) {:#regexcontains_a84c581} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression contains a specified regular expression as a substring. ```typescript // Check if the 'description' field contains "example" (case-insensitive) @@ -8326,10 +7916,17 @@ regexContains(field("description"), "(?i)example"); ``` +### regexContains(stringExpression, pattern) {:#regexcontains_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a specified regular expression as a substring. + Signature: ```typescript -export declare function regexContains(stringExpression: Expression, pattern: string): BooleanExpression; +export declare function regexContains(stringExpression: Expression, pattern: Expression): BooleanExpression; ``` #### Parameters @@ -8337,18 +7934,16 @@ export declare function regexContains(stringExpression: Expression, pattern: str | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | -| pattern | string | The regular expression to use for the search. A new representing the 'contains' comparison. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the search. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### regexContains(stringExpression, pattern) {:#regexcontains_b534848} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression contains a specified regular expression as a substring. ```typescript // Check if the 'description' field contains "example" (case-insensitive) @@ -8356,29 +7951,34 @@ regexContains(field("description"), field("pattern")); ``` +### regexMatch(stringExpression, pattern) {:#regexmatch_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression matches a specified regular expression. + Signature: ```typescript -export declare function regexContains(stringExpression: Expression, pattern: Expression): BooleanExpression; +export declare function regexMatch(stringExpression: Expression, pattern: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | -| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the search. A new representing the 'contains' comparison. | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to match against. | +| pattern | string | The regular expression to use for the match. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### regexMatch(stringExpression, pattern) {:#regexmatch_a84c581} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression match. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression matches a specified regular expression. ```typescript // Check if the 'email' field matches a valid email pattern @@ -8386,10 +7986,17 @@ regexMatch(field("email"), "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); ``` +### regexMatch(stringExpression, pattern) {:#regexmatch_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression matches a specified regular expression. + Signature: ```typescript -export declare function regexMatch(stringExpression: Expression, pattern: string): BooleanExpression; +export declare function regexMatch(stringExpression: Expression, pattern: Expression): BooleanExpression; ``` #### Parameters @@ -8397,18 +8004,16 @@ export declare function regexMatch(stringExpression: Expression, pattern: string | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to match against. | -| pattern | string | The regular expression to use for the match. A new representing the regular expression match. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the match. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### regexMatch(stringExpression, pattern) {:#regexmatch_b534848} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression match. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression matches a specified regular expression. ```typescript // Check if the 'email' field matches a valid email pattern @@ -8416,29 +8021,33 @@ regexMatch(field("email"), field("pattern")); ``` +### reverse(stringExpression) {:#reverse_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string. + Signature: ```typescript -export declare function regexMatch(stringExpression: Expression, pattern: Expression): BooleanExpression; +export declare function reverse(stringExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to match against. | -| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to use for the match. A new representing the regular expression match. | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a string value, which will be reversed. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### reverse(stringExpression) {:#reverse_c25a54a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses a string. ```typescript // Reverse the value of the 'myString' field. @@ -8446,28 +8055,34 @@ reverse(field("myString")); ``` +### startsWith(stringExpression, prefix) {:#startswith_75c3dbb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression starts with a given prefix. + Signature: ```typescript -export declare function reverse(stringExpression: Expression): FunctionExpression; +export declare function startsWith(stringExpression: Expression, prefix: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a string value, which will be reversed. A new representing the reversed string. | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | +| prefix | string | The prefix to check for. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### startsWith(stringExpression, prefix) {:#startswith_75c3dbb} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'starts with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression starts with a given prefix. ```typescript // Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." @@ -8475,10 +8090,17 @@ startsWith(field("fullName"), "Mr."); ``` +### startsWith(stringExpression, prefix) {:#startswith_52f218a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression starts with a given prefix. + Signature: ```typescript -export declare function startsWith(stringExpression: Expression, prefix: string): BooleanExpression; +export declare function startsWith(stringExpression: Expression, prefix: Expression): BooleanExpression; ``` #### Parameters @@ -8486,18 +8108,16 @@ export declare function startsWith(stringExpression: Expression, prefix: string) | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | -| prefix | string | The prefix to check for. A new representing the 'starts with' comparison. | +| prefix | [Expression](./firestore_pipelines.expression.md#expression_class) | The prefix to check for. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### startsWith(stringExpression, prefix) {:#startswith_52f218a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'starts with' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression starts with a given prefix. ```typescript // Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." @@ -8505,29 +8125,34 @@ startsWith(field("fullName"), field("prefix")); ``` +### stringContains(stringExpression, substring) {:#stringcontains_3e9ff32} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a specified substring. + Signature: ```typescript -export declare function startsWith(stringExpression: Expression, prefix: Expression): BooleanExpression; +export declare function stringContains(stringExpression: Expression, substring: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | -| prefix | [Expression](./firestore_pipelines.expression.md#expression_class) | The prefix to check for. A new representing the 'starts with' comparison. | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | +| substring | string | The substring to search for. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### stringContains(stringExpression, substring) {:#stringcontains_3e9ff32} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression contains a specified substring. ```typescript // Check if the 'description' field contains "example". @@ -8535,10 +8160,17 @@ stringContains(field("description"), "example"); ``` +### stringContains(stringExpression, substring) {:#stringcontains_cc6ee02} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a string expression contains a substring specified by another expression. + Signature: ```typescript -export declare function stringContains(stringExpression: Expression, substring: string): BooleanExpression; +export declare function stringContains(stringExpression: Expression, substring: Expression): BooleanExpression; ``` #### Parameters @@ -8546,18 +8178,16 @@ export declare function stringContains(stringExpression: Expression, substring: | Parameter | Type | Description | | --- | --- | --- | | stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | -| substring | string | The substring to search for. A new representing the 'contains' comparison. | +| substring | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the substring to search for. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### stringContains(stringExpression, substring) {:#stringcontains_cc6ee02} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'contains' comparison. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a string expression contains a substring specified by another expression. ```typescript // Check if the 'description' field contains the value of the 'keyword' field. @@ -8565,29 +8195,33 @@ stringContains(field("description"), field("keyword")); ``` +### stringReverse(stringExpression) {:#stringreverse_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that reverses a string. + Signature: ```typescript -export declare function stringContains(stringExpression: Expression, substring: Expression): BooleanExpression; +export declare function stringReverse(stringExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to perform the comparison on. | -| substring | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the substring to search for. A new representing the 'contains' comparison. | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a string value, which will be reversed. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### stringReverse(stringExpression) {:#stringreverse_c25a54a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that reverses a string. ```typescript // Reverse the value of the 'myString' field. @@ -8595,28 +8229,33 @@ strReverse(field("myString")); ``` +### toLower(stringExpression) {:#tolower_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string expression to lowercase. + Signature: ```typescript -export declare function stringReverse(stringExpression: Expression): FunctionExpression; +export declare function toLower(stringExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a string value, which will be reversed. A new representing the reversed string. | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to convert to lowercase. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### toLower(stringExpression) {:#tolower_c25a54a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the lowercase string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a string expression to lowercase. ```typescript // Convert the 'name' field to lowercase @@ -8624,28 +8263,33 @@ toLower(field("name")); ``` +### toUpper(stringExpression) {:#toupper_c25a54a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a string expression to uppercase. + Signature: ```typescript -export declare function toLower(stringExpression: Expression): FunctionExpression; +export declare function toUpper(stringExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to convert to lowercase. A new representing the lowercase string. | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to convert to uppercase. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### toUpper(stringExpression) {:#toupper_c25a54a} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the uppercase string. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that converts a string expression to uppercase. ```typescript // Convert the 'title' field to uppercase @@ -8653,28 +8297,34 @@ toUppercase(field("title")); ``` +### trim(stringExpression, valueToTrim) {:#trim_dd54322} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that removes leading and trailing characters from a string or byte array expression. + Signature: ```typescript -export declare function toUpper(stringExpression: Expression): FunctionExpression; +export declare function trim(stringExpression: Expression, valueToTrim?: string | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to convert to uppercase. A new representing the uppercase string. | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array to trim. | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | 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: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### trim(stringExpression, valueToTrim) {:#trim_dd54322} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that removes leading and trailing characters from a string or byte array expression. ```typescript // Trim whitespace from the 'userInput' field @@ -8685,23 +8335,6 @@ trim(field("userInput"), '"'); ``` -Signature: - -```typescript -export declare function trim(stringExpression: Expression, valueToTrim?: string | Expression): FunctionExpression; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array to trim. | -| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | 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. A new representing the trimmed string or byte array. | - -Returns: - -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) - ## function(timestamp, ...) ### timestampAdd(timestamp, unit, amount) {:#timestampadd_98418f9} @@ -8711,12 +8344,6 @@ export declare function trim(stringExpression: Expression, valueToTrim?: string Creates an expression that adds a specified amount of time to a timestamp. -```typescript -// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. -timestampAdd(field("timestamp"), field("unit"), field("amount")); - -``` - Signature: ```typescript @@ -8729,25 +8356,30 @@ export declare function timestampAdd(timestamp: Expression, unit: Expression, am | --- | --- | --- | | timestamp | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | | unit | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | -| amount | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | +| amount | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### timestampAdd(timestamp, unit, amount) {:#timestampadd_ffe8e57} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that adds a specified amount of time to a timestamp. ```typescript -// Add 1 day to the 'timestamp' field. -timestampAdd(field("timestamp"), "day", 1); +// Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. +timestampAdd(field("timestamp"), field("unit"), field("amount")); ``` +### timestampAdd(timestamp, unit, amount) {:#timestampadd_ffe8e57} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that adds a specified amount of time to a timestamp. + Signature: ```typescript @@ -8760,25 +8392,30 @@ export declare function timestampAdd(timestamp: Expression, unit: 'microsecond' | --- | --- | --- | | timestamp | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | | unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | -| amount | number | The amount of time to add. A new representing the resulting timestamp. | +| amount | number | The amount of time to add. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_98418f9} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that subtracts a specified amount of time from a timestamp. ```typescript -// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. -timestampSubtract(field("timestamp"), field("unit"), field("amount")); +// Add 1 day to the 'timestamp' field. +timestampAdd(field("timestamp"), "day", 1); ``` +### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_98418f9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that subtracts a specified amount of time from a timestamp. + Signature: ```typescript @@ -8791,11 +8428,22 @@ export declare function timestampSubtract(timestamp: Expression, unit: Expressio | --- | --- | --- | | timestamp | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | | unit | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | -| amount | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. A new representing the resulting timestamp. | +| amount | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to amount of the unit. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. + +### Example + + +```typescript +// Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. +timestampSubtract(field("timestamp"), field("unit"), field("amount")); + +``` ### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_ffe8e57} @@ -8804,12 +8452,6 @@ export declare function timestampSubtract(timestamp: Expression, unit: Expressio Creates an expression that subtracts a specified amount of time from a timestamp. -```typescript -// Subtract 1 day from the 'timestamp' field. -timestampSubtract(field("timestamp"), "day", 1); - -``` - Signature: ```typescript @@ -8822,12 +8464,23 @@ export declare function timestampSubtract(timestamp: Expression, unit: 'microsec | --- | --- | --- | | timestamp | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | | unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | -| amount | number | The amount of time to subtract. A new representing the resulting timestamp. | +| amount | number | The amount of time to subtract. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the resulting timestamp. + +### Example + + +```typescript +// Subtract 1 day from the 'timestamp' field. +timestampSubtract(field("timestamp"), "day", 1); + +``` + ## function(timestampExpression, ...) ### timestampTruncate(timestampExpression, granularity, timezone) {:#timestamptruncate_ad5d843} @@ -8849,12 +8502,14 @@ export declare function timestampTruncate(timestampExpression: Expression, granu | --- | --- | --- | | timestampExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | Truncate the timestamp value that is returned by this expression. | | granularity | [TimeGranularity](./firestore_pipelines.md#timegranularity) | The granularity to truncate to. | -| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the truncated timestamp. + ### Example @@ -8883,12 +8538,14 @@ export declare function timestampTruncate(timestampExpression: Expression, granu | --- | --- | --- | | timestampExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | Truncate the timestamp value that is returned by this expression. | | granularity | [Expression](./firestore_pipelines.expression.md#expression_class) | The granularity to truncate to. | -| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". A new {Expression} representing the truncated timestamp. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for truncation. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1". | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new `Expression` representing the truncated timestamp. + ### Example @@ -8909,13 +8566,6 @@ Creates an expression that returns the `catch` argument if there is an error, el This overload is useful when a BooleanExpression is required. -```typescript -// Create an expression that protects against a divide by zero error -// but always returns a boolean expression. -ifError(constant(50).divide('length').gt(1), constant(false)); - -``` - Signature: ```typescript @@ -8927,26 +8577,31 @@ export declare function ifError(tryExpr: BooleanExpression, catchExpr: BooleanEx | Parameter | Type | Description | | --- | --- | --- | | tryExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The try expression. | -| catchExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The catch expression that will be evaluated and returned if the tryExpr produces an error. A new representing the 'ifError' operation. | +| catchExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The catch expression that will be evaluated and returned if the tryExpr produces an error. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### ifError(tryExpr, catchExpr) {:#iferror_756c12e} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. ```typescript -// Returns the first item in the title field arrays, or returns -// the entire title field if the array is empty or the field is another type. -ifError(field("title").arrayGet(0), field("title")); +// Create an expression that protects against a divide by zero error +// but always returns a boolean expression. +ifError(constant(50).divide('length').gt(1), constant(false)); ``` +### ifError(tryExpr, catchExpr) {:#iferror_756c12e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. + Signature: ```typescript @@ -8958,26 +8613,31 @@ export declare function ifError(tryExpr: Expression, catchExpr: Expression): Fun | Parameter | Type | Description | | --- | --- | --- | | tryExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The try expression. | -| catchExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The catch expression that will be evaluated and returned if the tryExpr produces an error. A new representing the 'ifError' operation. | +| catchExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The catch expression that will be evaluated and returned if the tryExpr produces an error. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### ifError(tryExpr, catchValue) {:#iferror_dc532f9} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. ```typescript // Returns the first item in the title field arrays, or returns -// "Default Title" -ifError(field("title").arrayGet(0), "Default Title"); +// the entire title field if the array is empty or the field is another type. +ifError(field("title").arrayGet(0), field("title")); ``` +### ifError(tryExpr, catchValue) {:#iferror_dc532f9} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. + Signature: ```typescript @@ -8989,12 +8649,24 @@ export declare function ifError(tryExpr: Expression, catchValue: unknown): Funct | Parameter | Type | Description | | --- | --- | --- | | tryExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The try expression. | -| catchValue | unknown | The value that will be returned if the tryExpr produces an error. A new representing the 'ifError' operation. | +| catchValue | unknown | The value that will be returned if the tryExpr produces an error. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'ifError' operation. + +### Example + + +```typescript +// Returns the first item in the title field arrays, or returns +// "Default Title" +ifError(field("title").arrayGet(0), "Default Title"); + +``` + ## function(value, ...) ### constant(value) {:#constant_0c00f91} @@ -9014,12 +8686,14 @@ export declare function constant(value: number): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | number | The number value. A new Constant instance. | +| value | number | The number value. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_6dac335} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9037,12 +8711,14 @@ export declare function constant(value: VectorValue): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The VectorValue value. A new Constant instance. | +| value | [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The VectorValue value. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_7c807cd} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9060,12 +8736,14 @@ export declare function constant(value: string): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | string | The string value. A new Constant instance. | +| value | string | The string value. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_b2e4f8d} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9083,12 +8761,14 @@ export declare function constant(value: boolean): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | boolean | The boolean value. A new Constant instance. | +| value | boolean | The boolean value. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +A new `Constant` instance. + ### constant(value) {:#constant_73ebd84} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9106,12 +8786,14 @@ export declare function constant(value: null): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | null | The null value. A new Constant instance. | +| value | null | The null value. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_72a76cb} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9129,12 +8811,14 @@ export declare function constant(value: GeoPoint): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | [GeoPoint](./firestore_.geopoint.md#geopoint_class) | The GeoPoint value. A new Constant instance. | +| value | [GeoPoint](./firestore_.geopoint.md#geopoint_class) | The GeoPoint value. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_000477d} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9152,12 +8836,14 @@ export declare function constant(value: Timestamp): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | [Timestamp](./firestore_.timestamp.md#timestamp_class) | The Timestamp value. A new Constant instance. | +| value | [Timestamp](./firestore_.timestamp.md#timestamp_class) | The Timestamp value. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_5131bf7} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9175,12 +8861,14 @@ export declare function constant(value: Date): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | Date | The Date value. A new Constant instance. | +| value | Date | The Date value. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_fdf565d} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9198,12 +8886,14 @@ export declare function constant(value: Bytes): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | [Bytes](./firestore_.bytes.md#bytes_class) | The Bytes value. A new Constant instance. | +| value | [Bytes](./firestore_.bytes.md#bytes_class) | The Bytes value. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### constant(value) {:#constant_bcd2b0b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9221,12 +8911,14 @@ export declare function constant(value: DocumentReference): Expression; | Parameter | Type | Description | | --- | --- | --- | -| value | [DocumentReference](./firestore_.documentreference.md#documentreference_class) | The DocumentReference value. A new Constant instance. | +| value | [DocumentReference](./firestore_.documentreference.md#documentreference_class) | The DocumentReference value. | Returns: [Expression](./firestore_pipelines.expression.md#expression_class) +A new `Constant` instance. + ### exists(value) {:#exists_f3daf14} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9234,12 +8926,6 @@ export declare function constant(value: DocumentReference): Expression; Creates an expression that checks if a field exists. -```typescript -// Check if the document has a field named "phoneNumber" -exists(field("phoneNumber")); - -``` - Signature: ```typescript @@ -9250,25 +8936,30 @@ export declare function exists(value: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluates to the name of the field to check. A new representing the 'exists' check. | +| value | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluates to the name of the field to check. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### isAbsent(value) {:#isabsent_f3daf14} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'exists' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that returns `true` if a value is absent. Otherwise, returns `false` even if the value is `null`. ```typescript -// Check if the field `value` is absent. -isAbsent(field("value")); +// Check if the document has a field named "phoneNumber" +exists(field("phoneNumber")); ``` +### isAbsent(value) {:#isabsent_f3daf14} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns `true` if a value is absent. Otherwise, returns `false` even if the value is `null`. + Signature: ```typescript @@ -9279,25 +8970,30 @@ export declare function isAbsent(value: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. A new representing the 'isAbsent' check. | +| value | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -### isError(value) {:#iserror_f3daf14} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'isAbsent' check. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that checks if a given expression produces an error. ```typescript -// Check if the result of a calculation is an error -isError(field("title").arrayContains(1)); +// Check if the field `value` is absent. +isAbsent(field("value")); ``` +### isError(value) {:#iserror_f3daf14} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if a given expression produces an error. + Signature: ```typescript @@ -9308,12 +9004,23 @@ export declare function isError(value: Expression): BooleanExpression; | Parameter | Type | Description | | --- | --- | --- | -| value | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. A new representing the 'isError' check. | +| value | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | Returns: [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'isError' check. + +### Example + + +```typescript +// Check if the result of a calculation is an error +isError(field("title").arrayContains(1)); + +``` + ## function(vectorExpression, ...) ### cosineDistance(vectorExpression, vector) {:#cosinedistance_3a80317} @@ -9323,12 +9030,6 @@ export declare function isError(value: Expression): BooleanExpression; Calculates the Cosine distance between a vector expression and a vector literal. -```typescript -// Calculate the cosine distance between the 'location' field and a target location -cosineDistance(field("location"), [37.7749, -122.4194]); - -``` - Signature: ```typescript @@ -9339,26 +9040,31 @@ export declare function cosineDistance(vectorExpression: Expression, vector: num | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | -| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. A new representing the cosine distance between the two vectors. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expression) to compare against. | +| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### cosineDistance(vectorExpression, otherVectorExpression) {:#cosinedistance_17b5bcc} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the cosine distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Cosine distance between two vector expressions. ```typescript -// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field -cosineDistance(field("userVector"), field("itemVector")); +// Calculate the cosine distance between the 'location' field and a target location +cosineDistance(field("location"), [37.7749, -122.4194]); ``` +### cosineDistance(vectorExpression, otherVectorExpression) {:#cosinedistance_17b5bcc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Cosine distance between two vector expressions. + Signature: ```typescript @@ -9369,26 +9075,31 @@ export declare function cosineDistance(vectorExpression: Expression, otherVector | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | -| otherVectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the cosine distance between the two vectors. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expression) to compare against. | +| otherVectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to compare against. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### dotProduct(vectorExpression, vector) {:#dotproduct_3a80317} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the cosine distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the dot product between a vector expression and a double array. ```typescript -// Calculate the dot product between a feature vector and a target vector -dotProduct(field("features"), [0.5, 0.8, 0.2]); +// Calculate the cosine distance between the 'userVector' field and the 'itemVector' field +cosineDistance(field("userVector"), field("itemVector")); ``` +### dotProduct(vectorExpression, vector) {:#dotproduct_3a80317} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between a vector expression and a double array. + Signature: ```typescript @@ -9399,26 +9110,31 @@ export declare function dotProduct(vectorExpression: Expression, vector: number[ | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to calculate with. | -| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to calculate with. A new representing the dot product between the two vectors. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expression) to calculate with. | +| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to calculate with. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### dotProduct(vectorExpression, otherVectorExpression) {:#dotproduct_17b5bcc} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the dot product between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the dot product between two vector expressions. ```typescript -// Calculate the dot product between two document vectors: 'docVector1' and 'docVector2' -dotProduct(field("docVector1"), field("docVector2")); +// Calculate the dot product between a feature vector and a target vector +dotProduct(field("features"), [0.5, 0.8, 0.2]); ``` +### dotProduct(vectorExpression, otherVectorExpression) {:#dotproduct_17b5bcc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the dot product between two vector expressions. + Signature: ```typescript @@ -9429,27 +9145,31 @@ export declare function dotProduct(vectorExpression: Expression, otherVectorExpr | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to calculate with. | -| otherVectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to calculate with. A new representing the dot product between the two vectors. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expression) to calculate with. | +| otherVectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to calculate with. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### euclideanDistance(vectorExpression, vector) {:#euclideandistance_3a80317} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the dot product between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Euclidean distance between a vector expression and a double array. ```typescript -// Calculate the Euclidean distance between the 'location' field and a target location - -euclideanDistance(field("location"), [37.7749, -122.4194]); +// Calculate the dot product between two document vectors: 'docVector1' and 'docVector2' +dotProduct(field("docVector1"), field("docVector2")); ``` +### euclideanDistance(vectorExpression, vector) {:#euclideandistance_3a80317} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between a vector expression and a double array. + Signature: ```typescript @@ -9460,26 +9180,32 @@ export declare function euclideanDistance(vectorExpression: Expression, vector: | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | -| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. A new representing the Euclidean distance between the two vectors. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expression) to compare against. | +| vector | number\[\] \| [VectorValue](./firestore_.vectorvalue.md#vectorvalue_class) | The other vector (as an array of doubles or VectorValue) to compare against. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### euclideanDistance(vectorExpression, otherVectorExpression) {:#euclideandistance_17b5bcc} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the Euclidean distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Calculates the Euclidean distance between two vector expressions. ```typescript -// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' -euclideanDistance(field("pointA"), field("pointB")); +// Calculate the Euclidean distance between the 'location' field and a target location + +euclideanDistance(field("location"), [37.7749, -122.4194]); ``` +### euclideanDistance(vectorExpression, otherVectorExpression) {:#euclideandistance_17b5bcc} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Calculates the Euclidean distance between two vector expressions. + Signature: ```typescript @@ -9490,26 +9216,31 @@ export declare function euclideanDistance(vectorExpression: Expression, otherVec | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expr) to compare against. | -| otherVectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expr) to compare against. A new representing the Euclidean distance between the two vectors. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first vector (represented as an Expression) to compare against. | +| otherVectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The other vector (represented as an Expression) to compare against. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### vectorLength(vectorExpression) {:#vectorlength_58a039b} +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the Euclidean distance between the two vectors. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example -Creates an expression that calculates the length of a Firestore Vector. ```typescript -// Get the vector length (dimension) of the field 'embedding'. -vectorLength(field("embedding")); +// Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' +euclideanDistance(field("pointA"), field("pointB")); ``` +### vectorLength(vectorExpression) {:#vectorlength_58a039b} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the length of a Firestore Vector. + Signature: ```typescript @@ -9520,18 +9251,29 @@ export declare function vectorLength(vectorExpression: Expression): FunctionExpr | Parameter | Type | Description | | --- | --- | --- | -| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the Firestore Vector. A new representing the length of the array. | +| vectorExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the Firestore Vector. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the array. + +### Example + + +```typescript +// Get the vector length (dimension) of the field 'embedding'. +vectorLength(field("embedding")); + +``` + ## AddFieldsStageOptions > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how an AddFieldsStage is evaluated. See . +Options defining how an AddFieldsStage is evaluated. See [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields). Signature: @@ -9546,7 +9288,7 @@ export declare type AddFieldsStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how an AggregateStage is evaluated. See . +Options defining how an AggregateStage is evaluated. See [Pipeline.aggregate()](./firestore_pipelines.pipeline.md#pipelineaggregate). Signature: @@ -9562,7 +9304,9 @@ export declare type AggregateStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Defines the configuration options for a within a pipeline. This type extends and provides specific settings for how a collection group is identified and processed during pipeline execution. +Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution. + +See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. Signature: @@ -9578,7 +9322,7 @@ export declare type CollectionGroupStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a CollectionStage is evaluated. See . +Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). Signature: @@ -9594,7 +9338,7 @@ export declare type CollectionStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a DatabaseStage is evaluated. See . +Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). Signature: @@ -9607,7 +9351,7 @@ export declare type DatabaseStageOptions = StageOptions & {}; > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a DistinctStage is evaluated. See . +Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). Signature: @@ -9622,7 +9366,7 @@ export declare type DistinctStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a DocumentsStage is evaluated. See . +Options defining how a DocumentsStage is evaluated. See [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments). Signature: @@ -9650,7 +9394,7 @@ export declare type ExpressionType = 'Field' | 'Constant' | 'Function' | 'Aggreg > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a FindNearestStage is evaluated. See . +Options defining how a FindNearestStage is evaluated. See [Pipeline.findNearest()](./firestore_pipelines.pipeline.md#pipelinefindnearest). Signature: @@ -9669,7 +9413,7 @@ export declare type FindNearestStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a LimitStage is evaluated. See . +Options defining how a LimitStage is evaluated. See [Pipeline.limit()](./firestore_pipelines.pipeline.md#pipelinelimit). Signature: @@ -9684,7 +9428,7 @@ export declare type LimitStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how an OffsetStage is evaluated. See . +Options defining how an OffsetStage is evaluated. See [Pipeline.offset()](./firestore_pipelines.pipeline.md#pipelineoffset). Signature: @@ -9701,8 +9445,6 @@ export declare type OffsetStageOptions = StageOptions & { Utility type to create an type that only allows one property of the Type param T to be set. -type XorY = OneOf<{ x: unknown, y: unknown}> let a = { x: "foo" } // OK let b = { y: "foo" } // OK let c = { a: "foo", y: "foo" } // Not OK - Signature: ```typescript @@ -9713,6 +9455,17 @@ export declare type OneOf = { }[keyof T]; ``` +### Example + + +``` +type XorY = OneOf<{ x: unknown, y: unknown }> +let a = { x: "foo" } // OK +let b = { y: "foo" } // OK +let c = { a: "foo", y: "foo" } // Not OK + +``` + ## PartialWithFieldValue Similar to TypeScript's `Partial`, but allows nested fields to be omitted and FieldValues to be passed in as property values. @@ -9740,7 +9493,7 @@ export declare type Primitive = string | number | boolean | undefined | null; > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a RemoveFieldsStage is evaluated. See . +Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). Signature: @@ -9755,7 +9508,7 @@ export declare type RemoveFieldsStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a ReplaceWithStage is evaluated. See . +Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). Signature: @@ -9770,9 +9523,9 @@ export declare type ReplaceWithStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Defines the options for evaluating a sample stage within a pipeline. This type combines common with a specific configuration where only one of the defined sampling methods can be applied. +Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied. -See to create a sample stage.. +See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. Signature: @@ -9788,7 +9541,7 @@ export declare type SampleStageOptions = StageOptions & OneOf<{ > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a SelectStage is evaluated. See . +Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). Signature: @@ -9817,7 +9570,7 @@ export declare type SetOptions = { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a SortStage is evaluated. See . +Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). Signature: @@ -9845,7 +9598,7 @@ export declare type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a UnionStage is evaluated. See . +Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). Signature: @@ -9876,7 +9629,7 @@ export declare type UnnestStageOptions = StageOptions & { > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a WhereStage is evaluated. See . +Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). Signature: diff --git a/docs-devsite/firestore_pipelines.pipelineexecuteoptions.md b/docs-devsite/firestore_pipelines.pipelineexecuteoptions.md index fc0ed90769..68110fa74f 100644 --- a/docs-devsite/firestore_pipelines.pipelineexecuteoptions.md +++ b/docs-devsite/firestore_pipelines.pipelineexecuteoptions.md @@ -27,33 +27,7 @@ export declare interface PipelineExecuteOptions | --- | --- | --- | | [indexMode](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionsindexmode) | 'recommended' | (Public Preview) Specify the index mode. | | [pipeline](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionspipeline) | [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | (Public Preview) Pipeline to be evaluated. | -| [rawOptions](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionsrawoptions) | { \[name: string\]: unknown; } | (Public Preview) An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Custom option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK.Override the example_option: -``` - execute({ - pipeline: myPipeline, - rawOptions: { - // Override `example_option`. This will not - // merge with the existing `example_option` object. - "example_option": { - foo: "bar" - } - } - } - -``` -rawOptions supports dot notation, if you want to override a nested option. -``` - execute({ - pipeline: myPipeline, - rawOptions: { - // Override `example_option.foo` and do not override - // any other properties of `example_option`. - "example_option.foo": "bar" - } - } - -``` - | +| [rawOptions](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionsrawoptions) | { \[name: string\]: unknown; } | (Public Preview) An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Custom option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK. | ## PipelineExecuteOptions.indexMode @@ -94,6 +68,16 @@ Custom option values can be any type supported by Firestore (for example: string Values specified in rawOptions will take precedence over any options with the same name set by the SDK. +Signature: + +```typescript +rawOptions?: { + [name: string]: unknown; + }; +``` + +### Example + Override the `example_option`: ``` @@ -123,10 +107,3 @@ Override the `example_option`: ``` -Signature: - -```typescript -rawOptions?: { - [name: string]: unknown; - }; -``` diff --git a/docs-devsite/firestore_pipelines.pipelineresult.md b/docs-devsite/firestore_pipelines.pipelineresult.md index b5dfb1a41d..6a04334e14 100644 --- a/docs-devsite/firestore_pipelines.pipelineresult.md +++ b/docs-devsite/firestore_pipelines.pipelineresult.md @@ -13,7 +13,7 @@ https://github.com/firebase/firebase-js-sdk > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the or methods. +A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the [PipelineResult.data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) or [PipelineResult.get()](./firestore_pipelines.pipelineresult.md#pipelineresultget) methods.

If the PipelineResult represents a non-document result, `ref` will return a undefined value. @@ -27,10 +27,10 @@ export declare class PipelineResult | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [createTime](./firestore_pipelines.pipelineresult.md#pipelineresultcreatetime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was created. Undefined if this result is not a document. {Timestamp\|undefined} | -| [id](./firestore_pipelines.pipelineresult.md#pipelineresultid) | | string \| undefined | (Public Preview) The ID of the document for which this PipelineResult contains data, if it is a document; otherwise undefined. {string} | +| [createTime](./firestore_pipelines.pipelineresult.md#pipelineresultcreatetime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was created. Undefined if this result is not a document. | +| [id](./firestore_pipelines.pipelineresult.md#pipelineresultid) | | string \| undefined | (Public Preview) The ID of the document for which this PipelineResult contains data, if it is a document; otherwise undefined. | | [ref](./firestore_pipelines.pipelineresult.md#pipelineresultref) | | [DocumentReference](./firestore_.documentreference.md#documentreference_class) \| undefined | (Public Preview) The reference of the document, if it is a document; otherwise undefined. | -| [updateTime](./firestore_pipelines.pipelineresult.md#pipelineresultupdatetime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. {Timestamp\|undefined} | +| [updateTime](./firestore_pipelines.pipelineresult.md#pipelineresultupdatetime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. | ## Methods @@ -46,8 +46,6 @@ export declare class PipelineResult The time the document was created. Undefined if this result is not a document. - {Timestamp\|undefined} - Signature: ```typescript @@ -61,8 +59,6 @@ get createTime(): Timestamp | undefined; The ID of the document for which this PipelineResult contains data, if it is a document; otherwise `undefined`. - {string} - Signature: ```typescript @@ -89,8 +85,6 @@ get ref(): DocumentReference | undefined; The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. - {Timestamp\|undefined} - Signature: ```typescript @@ -113,7 +107,7 @@ data(): AppModelType; AppModelType -{T} An object containing all fields in the document or 'undefined' if the document doesn't exist. +An object containing all fields in the document or 'undefined' if the document doesn't exist. ### Example @@ -151,7 +145,7 @@ get(fieldPath: string | FieldPath | Field): any; any -{\*} The data at the specified field location or undefined if no such field exists. +The data at the specified field location or `undefined` if no such field exists. ### Example diff --git a/docs-devsite/firestore_pipelines.pipelinesnapshot.md b/docs-devsite/firestore_pipelines.pipelinesnapshot.md index 7f6d4744f4..6aced9e047 100644 --- a/docs-devsite/firestore_pipelines.pipelinesnapshot.md +++ b/docs-devsite/firestore_pipelines.pipelinesnapshot.md @@ -15,7 +15,7 @@ https://github.com/firebase/firebase-js-sdk Represents the results of a Firestore pipeline execution. -A `PipelineSnapshot` contains zero or more objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. +A `PipelineSnapshot` contains zero or more [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. Signature: @@ -33,7 +33,7 @@ export declare class PipelineSnapshot | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [executionTime](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshotexecutiontime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) | (Public Preview) The time at which the pipeline producing this result is executed. {Timestamp} | +| [executionTime](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshotexecutiontime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) | (Public Preview) The time at which the pipeline producing this result is executed. | | [results](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshotresults) | | [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class)\[\] | (Public Preview) An array of all the results in the PipelineSnapshot. | ## PipelineSnapshot.(constructor) @@ -64,8 +64,6 @@ constructor(pipeline: Pipeline, results: PipelineResult[], executionTime?: Times The time at which the pipeline producing this result is executed. - {Timestamp} - Signature: ```typescript diff --git a/docs-devsite/firestore_pipelines.pipelinesource.md b/docs-devsite/firestore_pipelines.pipelinesource.md index 383f31f7fd..31c5192dfd 100644 --- a/docs-devsite/firestore_pipelines.pipelinesource.md +++ b/docs-devsite/firestore_pipelines.pipelinesource.md @@ -13,9 +13,9 @@ https://github.com/firebase/firebase-js-sdk > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Provides the entry point for defining the data source of a Firestore . +Provides the entry point for defining the data source of a Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class). -Use the methods of this class (e.g., , , , or ) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. +Use the methods of this class (e.g., [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection), [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup), [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase), or [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments)) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. Signature: @@ -154,7 +154,7 @@ createFrom(query: Query): Pipeline; #### Exceptions - Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. +`FirestoreError` Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. ## PipelineSource.database() @@ -220,7 +220,7 @@ PipelineType #### Exceptions - Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. +`FirestoreError` Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. ## PipelineSource.documents() @@ -247,5 +247,5 @@ PipelineType #### Exceptions - Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. +`FirestoreError` Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. diff --git a/docs-devsite/firestore_pipelines.vectorvalue.md b/docs-devsite/firestore_pipelines.vectorvalue.md index 8185645466..2b02bcea9f 100644 --- a/docs-devsite/firestore_pipelines.vectorvalue.md +++ b/docs-devsite/firestore_pipelines.vectorvalue.md @@ -12,8 +12,6 @@ https://github.com/firebase/firebase-js-sdk # VectorValue class Represents a vector type in Firestore documents. Create an instance with [vector()](./firestore_.md#vector_0dbdaf2). - VectorValue - Signature: ```typescript diff --git a/packages/firestore/src/api/aggregate.ts b/packages/firestore/src/api/aggregate.ts index 453f9e0a84..d747905106 100644 --- a/packages/firestore/src/api/aggregate.ts +++ b/packages/firestore/src/api/aggregate.ts @@ -55,7 +55,7 @@ export { * used. Every invocation of this function necessarily involves a round trip to * the server. * - * @param query The query whose result set size is calculated. + * @param query - The query whose result set size is calculated. * @returns A Promise that will be resolved with the count; the count can be * retrieved from `snapshot.data().count`, where `snapshot` is the * `AggregateQuerySnapshot` to which the returned Promise resolves. @@ -95,8 +95,8 @@ export function getCountFromServer< * used. Every invocation of this function necessarily involves a round trip to * the server. * - * @param query The query whose result set is aggregated over. - * @param aggregateSpec An `AggregateSpec` object that specifies the aggregates + * @param query - The query whose result set is aggregated over. + * @param aggregateSpec - An `AggregateSpec` object that specifies the aggregates * to perform over the result set. The AggregateSpec specifies aliases for each * aggregate, which can be used to retrieve the aggregate result. * @example @@ -147,7 +147,7 @@ export function getAggregateFromServer< * Converts the core aggregation result to an `AggregateQuerySnapshot` * that can be returned to the consumer. * @param query - * @param aggregateResult Core aggregation result + * @param aggregateResult - Core aggregation result * @internal */ function convertToAggregateQuerySnapshot< diff --git a/packages/firestore/src/api/cache_config.ts b/packages/firestore/src/api/cache_config.ts index 072c67ec7a..205888d36a 100644 --- a/packages/firestore/src/api/cache_config.ts +++ b/packages/firestore/src/api/cache_config.ts @@ -419,7 +419,7 @@ export type PersistentSingleTabManagerSettings = { /** * Creates an instance of `PersistentSingleTabManager`. * - * @param settings Configures the created tab manager. + * @param settings - Configures the created tab manager. */ export function persistentSingleTabManager( settings: PersistentSingleTabManagerSettings | undefined diff --git a/packages/firestore/src/api/persistent_cache_index_manager.ts b/packages/firestore/src/api/persistent_cache_index_manager.ts index 6568ebde1d..edd86aad32 100644 --- a/packages/firestore/src/api/persistent_cache_index_manager.ts +++ b/packages/firestore/src/api/persistent_cache_index_manager.ts @@ -42,7 +42,7 @@ export class PersistentCacheIndexManager { * Returns the PersistentCache Index Manager used by the given `Firestore` * object. * - * @return The `PersistentCacheIndexManager` instance, or `null` if local + * @returns The `PersistentCacheIndexManager` instance, or `null` if local * persistent storage is not in use. */ export function getPersistentCacheIndexManager( diff --git a/packages/firestore/src/api/pipeline_impl.ts b/packages/firestore/src/api/pipeline_impl.ts index e5d650847d..ba4544f407 100644 --- a/packages/firestore/src/api/pipeline_impl.ts +++ b/packages/firestore/src/api/pipeline_impl.ts @@ -40,7 +40,7 @@ import { ExpUserDataWriter } from './user_data_writer'; declare module './database' { /** * @beta - * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link Pipeline}. + * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link @firebase/firestore/pipelines#Pipeline}. * * @example * ``` @@ -59,23 +59,22 @@ declare module './database' { * The returned Promise can be used to track the progress of the pipeline execution * and retrieve the results (or handle any errors) asynchronously. * - * The pipeline results are returned as a {@link PipelineSnapshot} that contains - * a list of {@link PipelineResult} objects. Each {@link PipelineResult} typically + * The pipeline results are returned as a {@link @firebase/firestore/pipelines#PipelineSnapshot} that contains + * a list of {@link @firebase/firestore/pipelines#PipelineResult} objects. Each {@link @firebase/firestore/pipelines#PipelineResult} typically * represents a single key/value map that has passed through all the * stages of the pipeline, however this might differ depending on the stages involved in the * pipeline. For example: * *

    - *
  • If there are no stages or only transformation stages, each {@link PipelineResult} + *
  • If there are no stages or only transformation stages, each {@link @firebase/firestore/pipelines#PipelineResult} * represents a single document.
  • - *
  • If there is an aggregation, only a single {@link PipelineResult} is returned, + *
  • If there is an aggregation, only a single {@link @firebase/firestore/pipelines#PipelineResult} is returned, * representing the aggregated results over the entire dataset .
  • - *
  • If there is an aggregation stage with grouping, each {@link PipelineResult} represents a + *
  • If there is an aggregation stage with grouping, each {@link @firebase/firestore/pipelines#PipelineResult} represents a * distinct group and its associated aggregated values.
  • *
* - *

Example: - * + * @example * ```typescript * const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") * .where(gt(field("rating"), 4.5)) @@ -84,8 +83,8 @@ declare module './database' { * const results: PipelineResults = snapshot.results; * ``` * - * @param pipeline The pipeline to execute. - * @return A Promise representing the asynchronous pipeline execution. + * @param pipeline - The pipeline to execute. + * @returns A Promise representing the asynchronous pipeline execution. */ export function execute(pipeline: LitePipeline): Promise; /** @@ -95,23 +94,22 @@ export function execute(pipeline: LitePipeline): Promise; * The returned Promise can be used to track the progress of the pipeline execution * and retrieve the results (or handle any errors) asynchronously. * - * The pipeline results are returned as a {@link PipelineSnapshot} that contains - * a list of {@link PipelineResult} objects. Each {@link PipelineResult} typically + * The pipeline results are returned as a {@link @firebase/firestore/pipelines#PipelineSnapshot} that contains + * a list of {@link @firebase/firestore/pipelines#PipelineResult} objects. Each {@link @firebase/firestore/pipelines#PipelineResult} typically * represents a single key/value map that has passed through all the * stages of the pipeline, however this might differ depending on the stages involved in the * pipeline. For example: * *

    - *
  • If there are no stages or only transformation stages, each {@link PipelineResult} + *
  • If there are no stages or only transformation stages, each {@link @firebase/firestore/pipelines#PipelineResult} * represents a single document.
  • - *
  • If there is an aggregation, only a single {@link PipelineResult} is returned, + *
  • If there is an aggregation, only a single {@link @firebase/firestore/pipelines#PipelineResult} is returned, * representing the aggregated results over the entire dataset .
  • - *
  • If there is an aggregation stage with grouping, each {@link PipelineResult} represents a + *
  • If there is an aggregation stage with grouping, each {@link @firebase/firestore/pipelines#PipelineResult} represents a * distinct group and its associated aggregated values.
  • *
* - *

Example: - * + * @example * ```typescript * const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") * .where(gt(field("rating"), 4.5)) @@ -120,8 +118,8 @@ export function execute(pipeline: LitePipeline): Promise; * const results: PipelineResults = snapshot.results; * ``` * - * @param options Specifies the pipeline to execute and other options for execute. - * @return A Promise representing the asynchronous pipeline execution. + * @param options - Specifies the pipeline to execute and other options for execute. + * @returns A Promise representing the asynchronous pipeline execution. */ export function execute( options: PipelineExecuteOptions @@ -191,7 +189,7 @@ export function execute( /** * @beta - * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link Pipeline}. + * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link @firebase/firestore/pipelines#Pipeline}. * * @example * ``` diff --git a/packages/firestore/src/core/database_info.ts b/packages/firestore/src/core/database_info.ts index ec75ba2486..ae3082493c 100644 --- a/packages/firestore/src/core/database_info.ts +++ b/packages/firestore/src/core/database_info.ts @@ -35,8 +35,8 @@ export class DatabaseInfo { * when using WebChannel as the network transport. * @param autoDetectLongPolling - Whether to use the detectBufferingProxy * option when using WebChannel as the network transport. - * @param longPollingOptions Options that configure long-polling. - * @param useFetchStreams Whether to use the Fetch API instead of + * @param longPollingOptions - Options that configure long-polling. + * @param useFetchStreams - Whether to use the Fetch API instead of * XMLHTTPRequest */ constructor( diff --git a/packages/firestore/src/lite-api/aggregate.ts b/packages/firestore/src/lite-api/aggregate.ts index 0ffc42bebe..c1cc173f61 100644 --- a/packages/firestore/src/lite-api/aggregate.ts +++ b/packages/firestore/src/lite-api/aggregate.ts @@ -44,7 +44,7 @@ import { fieldPathFromArgument } from './user_data_reader'; * count the documents in cases where the result set is prohibitively large to * download entirely (thousands of documents). * - * @param query The query whose result set size is calculated. + * @param query - The query whose result set size is calculated. * @returns A Promise that will be resolved with the count; the count can be * retrieved from `snapshot.data().count`, where `snapshot` is the * `AggregateQuerySnapshot` to which the returned Promise resolves. @@ -74,8 +74,8 @@ export function getCount( * function can perform aggregations of the documents in cases where the result * set is prohibitively large to download entirely (thousands of documents). * - * @param query The query whose result set is aggregated over. - * @param aggregateSpec An `AggregateSpec` object that specifies the aggregates + * @param query - The query whose result set is aggregated over. + * @param aggregateSpec - An `AggregateSpec` object that specifies the aggregates * to perform over the result set. The AggregateSpec specifies aliases for each * aggregate, which can be used to retrieve the aggregate result. * @example @@ -143,7 +143,7 @@ function convertToAggregateQuerySnapshot< /** * Create an AggregateField object that can be used to compute the sum of * a specified field over a range of documents in the result set of a query. - * @param field Specifies the field to sum across the result set. + * @param field - Specifies the field to sum across the result set. */ export function sum(field: string | FieldPath): AggregateField { return new AggregateField('sum', fieldPathFromArgument('sum', field)); @@ -152,7 +152,7 @@ export function sum(field: string | FieldPath): AggregateField { /** * Create an AggregateField object that can be used to compute the average of * a specified field over a range of documents in the result set of a query. - * @param field Specifies the field to average across the result set. + * @param field - Specifies the field to average across the result set. */ export function average( field: string | FieldPath @@ -171,8 +171,8 @@ export function count(): AggregateField { /** * Compares two 'AggregateField` instances for equality. * - * @param left Compare this AggregateField to the `right`. - * @param right Compare this AggregateField to the `left`. + * @param left - Compare this AggregateField to the `right`. + * @param right - Compare this AggregateField to the `left`. */ export function aggregateFieldEqual( left: AggregateField, diff --git a/packages/firestore/src/lite-api/aggregate_types.ts b/packages/firestore/src/lite-api/aggregate_types.ts index 292a2edd4f..ae090f8f9a 100644 --- a/packages/firestore/src/lite-api/aggregate_types.ts +++ b/packages/firestore/src/lite-api/aggregate_types.ts @@ -43,8 +43,8 @@ export class AggregateField { /** * Create a new AggregateField - * @param aggregateType Specifies the type of aggregation operation to perform. - * @param _internalFieldPath Optionally specifies the field that is aggregated. + * @param aggregateType - Specifies the type of aggregation operation to perform. + * @param _internalFieldPath - Optionally specifies the field that is aggregated. * @internal */ constructor( diff --git a/packages/firestore/src/lite-api/bytes.ts b/packages/firestore/src/lite-api/bytes.ts index 225ad7918a..76ba3181ae 100644 --- a/packages/firestore/src/lite-api/bytes.ts +++ b/packages/firestore/src/lite-api/bytes.ts @@ -116,7 +116,7 @@ export class Bytes { /** * Builds a `Bytes` instance from a JSON object created by {@link Bytes.toJSON}. * - * @param json a JSON object represention of a `Bytes` instance + * @param json - a JSON object represention of a `Bytes` instance * @returns an instance of {@link Bytes} if the JSON object could be parsed. Throws a * {@link FirestoreError} if an error occurs. */ diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index 7b236ea5c6..0bae99b45f 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -56,7 +56,7 @@ export type ExpressionType = | 'AliasedExpression'; /** - * Converts a value to an Expr, Returning either a Constant, MapFunction, + * Converts a value to an Expression, Returning either a Constant, MapFunction, * ArrayFunction, or the input itself (if it's already an expression). * * @private @@ -79,7 +79,7 @@ function valueToDefaultExpr(value: unknown): Expression { } /** - * Converts a value to an Expr, Returning either a Constant, MapFunction, + * Converts a value to an Expression, Returning either a Constant, MapFunction, * ArrayFunction, or the input itself (if it's already an expression). * * @private @@ -99,7 +99,7 @@ function vectorToExpr(value: VectorValue | number[] | Expression): Expression { } /** - * Converts a value to an Expr, Returning either a Constant, MapFunction, + * 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. @@ -121,7 +121,7 @@ function fieldOrExpression(value: unknown): Expression { * @beta * * Represents an expression that can be evaluated to a value within the execution of a {@link - * Pipeline}. + * @firebase/firestore/pipelines#Pipeline}. * * Expressions are the building blocks for creating complex queries and transformations in * Firestore pipelines. They can represent: @@ -130,7 +130,7 @@ function fieldOrExpression(value: unknown): Expression { * - **Literals:** Represent constant values (strings, numbers, booleans). * - **Function calls:** Apply functions to one or more expressions. * - * The `Expr` class provides a fluent API for building expressions. You can chain together + * The `Expression` class provides a fluent API for building expressions. You can chain together * method calls to create complex expressions. */ export abstract class Expression implements ProtoValueSerializable, UserData { @@ -154,14 +154,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { /** * 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. - * @return A new `Expr` representing the addition operation. + * @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: Expression | unknown): FunctionExpression { return new FunctionExpression( @@ -175,7 +176,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Wraps the expression in a [BooleanExpression]. * - * @return A [BooleanExpression] representing the same expression. + * @returns A [BooleanExpression] representing the same expression. */ asBoolean(): BooleanExpression { if (this instanceof BooleanExpression) { @@ -198,13 +199,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that subtracts another expression from this expression. * + * @example * ```typescript * // Subtract the 'discount' field from the 'price' field * field("price").subtract(field("discount")); * ``` * - * @param subtrahend The expression to subtract from this expression. - * @return A new `Expr` representing the subtraction operation. + * @param subtrahend - The expression to subtract from this expression. + * @returns A new `Expression` representing the subtraction operation. */ subtract(subtrahend: Expression): FunctionExpression; @@ -212,13 +214,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that subtracts a constant value from this expression. * + * @example * ```typescript * // Subtract 20 from the value of the 'total' field * field("total").subtract(20); * ``` * - * @param subtrahend The constant value to subtract. - * @return A new `Expr` representing the subtraction operation. + * @param subtrahend - The constant value to subtract. + * @returns A new `Expression` representing the subtraction operation. */ subtract(subtrahend: number): FunctionExpression; subtract(subtrahend: number | Expression): FunctionExpression { @@ -233,14 +236,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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. - * @return A new `Expr` representing the multiplication operation. + * @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: Expression | number): FunctionExpression { return new FunctionExpression( @@ -254,13 +258,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that divides this expression by another expression. * + * @example * ```typescript * // Divide the 'total' field by the 'count' field * field("total").divide(field("count")); * ``` * - * @param divisor The expression to divide by. - * @return A new `Expr` representing the division operation. + * @param divisor - The expression to divide by. + * @returns A new `Expression` representing the division operation. */ divide(divisor: Expression): FunctionExpression; @@ -268,13 +273,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that divides this expression by a constant value. * + * @example * ```typescript * // Divide the 'value' field by 10 * field("value").divide(10); * ``` * - * @param divisor The constant value to divide by. - * @return A new `Expr` representing the division operation. + * @param divisor - The constant value to divide by. + * @returns A new `Expression` representing the division operation. */ divide(divisor: number): FunctionExpression; divide(divisor: number | Expression): FunctionExpression { @@ -289,13 +295,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. * + * @example * ```typescript * // Calculate the remainder of dividing the 'value' field by the 'divisor' field * field("value").mod(field("divisor")); * ``` * - * @param expression The expression to divide by. - * @return A new `Expr` representing the modulo operation. + * @param expression - The expression to divide by. + * @returns A new `Expression` representing the modulo operation. */ mod(expression: Expression): FunctionExpression; @@ -303,13 +310,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. * + * @example * ```typescript * // Calculate the remainder of dividing the 'value' field by 10 * field("value").mod(10); * ``` * - * @param value The constant value to divide by. - * @return A new `Expr` representing the modulo operation. + * @param value - The constant value to divide by. + * @returns A new `Expression` representing the modulo operation. */ mod(value: number): FunctionExpression; mod(other: number | Expression): FunctionExpression { @@ -324,13 +332,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if this expression is equal to another expression. * + * @example * ```typescript * // Check if the 'age' field is equal to 21 * field("age").equal(21); * ``` * - * @param expression The expression to compare for equality. - * @return A new `Expr` representing the equality comparison. + * @param expression - The expression to compare for equality. + * @returns A new `Expression` representing the equality comparison. */ equal(expression: Expression): BooleanExpression; @@ -338,13 +347,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if this expression is equal to a constant value. * + * @example * ```typescript * // Check if the 'city' field is equal to "London" * field("city").equal("London"); * ``` * - * @param value The constant value to compare for equality. - * @return A new `Expr` representing the equality comparison. + * @param value - The constant value to compare for equality. + * @returns A new `Expression` representing the equality comparison. */ equal(value: unknown): BooleanExpression; equal(other: unknown): BooleanExpression { @@ -359,13 +369,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if this expression is not equal to another expression. * + * @example * ```typescript * // Check if the 'status' field is not equal to "completed" * field("status").notEqual("completed"); * ``` * - * @param expression The expression to compare for inequality. - * @return A new `Expr` representing the inequality comparison. + * @param expression - The expression to compare for inequality. + * @returns A new `Expression` representing the inequality comparison. */ notEqual(expression: Expression): BooleanExpression; @@ -373,13 +384,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if this expression is not equal to a constant value. * + * @example * ```typescript * // Check if the 'country' field is not equal to "USA" * field("country").notEqual("USA"); * ``` * - * @param value The constant value to compare for inequality. - * @return A new `Expr` representing the inequality comparison. + * @param value - The constant value to compare for inequality. + * @returns A new `Expression` representing the inequality comparison. */ notEqual(value: unknown): BooleanExpression; notEqual(other: unknown): BooleanExpression { @@ -394,13 +406,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if this expression is less than another expression. * + * @example * ```typescript * // Check if the 'age' field is less than 'limit' * field("age").lessThan(field('limit')); * ``` * - * @param experession The expression to compare for less than. - * @return A new `Expr` representing the less than comparison. + * @param experession - The expression to compare for less than. + * @returns A new `Expression` representing the less than comparison. */ lessThan(experession: Expression): BooleanExpression; @@ -408,13 +421,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if this expression is less than a constant value. * + * @example * ```typescript * // Check if the 'price' field is less than 50 * field("price").lessThan(50); * ``` * - * @param value The constant value to compare for less than. - * @return A new `Expr` representing the less than comparison. + * @param value - The constant value to compare for less than. + * @returns A new `Expression` representing the less than comparison. */ lessThan(value: unknown): BooleanExpression; lessThan(other: unknown): BooleanExpression { @@ -430,13 +444,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that checks if this expression is less than or equal to another * expression. * + * @example * ```typescript * // Check if the 'quantity' field is less than or equal to 20 * field("quantity").lessThan(constant(20)); * ``` * - * @param expression The expression to compare for less than or equal to. - * @return A new `Expr` representing the less than or equal to comparison. + * @param expression - The expression to compare for less than or equal to. + * @returns A new `Expression` representing the less than or equal to comparison. */ lessThanOrEqual(expression: Expression): BooleanExpression; @@ -444,13 +459,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if this expression is less than or equal to a constant value. * + * @example * ```typescript * // Check if the 'score' field is less than or equal to 70 * field("score").lessThan(70); * ``` * - * @param value The constant value to compare for less than or equal to. - * @return A new `Expr` representing the less than or equal to comparison. + * @param value - The constant value to compare for less than or equal to. + * @returns A new `Expression` representing the less than or equal to comparison. */ lessThanOrEqual(value: unknown): BooleanExpression; lessThanOrEqual(other: unknown): BooleanExpression { @@ -465,13 +481,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if this expression is greater than another expression. * + * @example * ```typescript * // Check if the 'age' field is greater than the 'limit' field * field("age").greaterThan(field("limit")); * ``` * - * @param expression The expression to compare for greater than. - * @return A new `Expr` representing the greater than comparison. + * @param expression - The expression to compare for greater than. + * @returns A new `Expression` representing the greater than comparison. */ greaterThan(expression: Expression): BooleanExpression; @@ -479,13 +496,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if this expression is greater than a constant value. * + * @example * ```typescript * // Check if the 'price' field is greater than 100 * field("price").greaterThan(100); * ``` * - * @param value The constant value to compare for greater than. - * @return A new `Expr` representing the greater than comparison. + * @param value - The constant value to compare for greater than. + * @returns A new `Expression` representing the greater than comparison. */ greaterThan(value: unknown): BooleanExpression; greaterThan(other: unknown): BooleanExpression { @@ -501,13 +519,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that checks if this expression is greater than or equal to another * expression. * + * @example * ```typescript * // Check if the 'quantity' field is greater than or equal to field 'requirement' plus 1 * field("quantity").greaterThanOrEqual(field('requirement').add(1)); * ``` * - * @param expression The expression to compare for greater than or equal to. - * @return A new `Expr` representing the greater than or equal to comparison. + * @param expression - The expression to compare for greater than or equal to. + * @returns A new `Expression` representing the greater than or equal to comparison. */ greaterThanOrEqual(expression: Expression): BooleanExpression; @@ -516,13 +535,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that checks if this expression is greater than or equal to a constant * value. * + * @example * ```typescript * // Check if the 'score' field is greater than or equal to 80 * field("score").greaterThanOrEqual(80); * ``` * - * @param value The constant value to compare for greater than or equal to. - * @return A new `Expr` representing the greater than or equal to comparison. + * @param value - The constant value to compare for greater than or equal to. + * @returns A new `Expression` representing the greater than or equal to comparison. */ greaterThanOrEqual(value: unknown): BooleanExpression; greaterThanOrEqual(other: unknown): BooleanExpression { @@ -537,13 +557,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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. - * @return A new `Expr` representing the concatenated array. + * @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: Expression | unknown[], @@ -562,13 +583,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if an array contains a specific element. * + * @example * ```typescript * // Check if the 'sizes' array contains the value from the 'selectedSize' field * field("sizes").arrayContains(field("selectedSize")); * ``` * - * @param expression The element to search for in the array. - * @return A new `Expr` representing the 'array_contains' comparison. + * @param expression - The element to search for in the array. + * @returns A new `Expression` representing the 'array_contains' comparison. */ arrayContains(expression: Expression): BooleanExpression; @@ -576,13 +598,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if an array contains a specific value. * + * @example * ```typescript * // Check if the 'colors' array contains "red" * field("colors").arrayContains("red"); * ``` * - * @param value The element to search for in the array. - * @return A new `Expr` representing the 'array_contains' comparison. + * @param value - The element to search for in the array. + * @returns A new `Expression` representing the 'array_contains' comparison. */ arrayContains(value: unknown): BooleanExpression; arrayContains(element: unknown): BooleanExpression { @@ -597,13 +620,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if an array contains all the specified elements. * + * @example * ```typescript * // Check if the 'tags' array contains both the value in field "tag1" and the literal value "tag2" * field("tags").arrayContainsAll([field("tag1"), "tag2"]); * ``` * - * @param values The elements to check for in the array. - * @return A new `Expr` representing the 'array_contains_all' comparison. + * @param values - The elements to check for in the array. + * @returns A new `Expression` representing the 'array_contains_all' comparison. */ arrayContainsAll(values: Array): BooleanExpression; @@ -611,13 +635,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if an array contains all the specified elements. * + * @example * ```typescript * // Check if the 'tags' array contains both of the values from field "tag1" and the literal value "tag2" * field("tags").arrayContainsAll(array([field("tag1"), "tag2"])); * ``` * - * @param arrayExpression The elements to check for in the array. - * @return A new `Expr` representing the 'array_contains_all' comparison. + * @param arrayExpression - The elements to check for in the array. + * @returns A new `Expression` representing the 'array_contains_all' comparison. */ arrayContainsAll(arrayExpression: Expression): BooleanExpression; arrayContainsAll(values: unknown[] | Expression): BooleanExpression { @@ -635,13 +660,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if an array contains any of the specified elements. * + * @example * ```typescript * // Check if the 'categories' array contains either values from field "cate1" or "cate2" * field("categories").arrayContainsAny([field("cate1"), field("cate2")]); * ``` * - * @param values The elements to check for in the array. - * @return A new `Expr` representing the 'array_contains_any' comparison. + * @param values - The elements to check for in the array. + * @returns A new `Expression` representing the 'array_contains_any' comparison. */ arrayContainsAny(values: Array): BooleanExpression; @@ -649,14 +675,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if an array contains any of the specified elements. * + * @example * ```typescript * // Check if the 'groups' array contains either the value from the 'userGroup' field * // or the value "guest" * field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); * ``` * - * @param arrayExpression The elements to check for in the array. - * @return A new `Expr` representing the 'array_contains_any' comparison. + * @param arrayExpression - The elements to check for in the array. + * @returns A new `Expression` representing the 'array_contains_any' comparison. */ arrayContainsAny(arrayExpression: Expression): BooleanExpression; arrayContainsAny( @@ -676,12 +703,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that reverses an array. * + * @example * ```typescript * // Reverse the value of the 'myArray' field. * field("myArray").arrayReverse(); * ``` * - * @return A new {@code Expr} representing the reversed array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the reversed array. */ arrayReverse(): FunctionExpression { return new FunctionExpression('array_reverse', [this]); @@ -691,12 +719,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new `Expr` representing the length of the array. + * @returns A new `Expression` representing the length of the array. */ arrayLength(): FunctionExpression { return new FunctionExpression('array_length', [this], 'arrayLength'); @@ -707,13 +736,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that checks if this expression is equal to any of the provided values or * expressions. * + * @example * ```typescript * // Check if the 'category' field is either "Electronics" or value of field 'primaryType' * field("category").equalAny("Electronics", field("primaryType")); * ``` * - * @param values The values or expressions to check against. - * @return A new `Expr` representing the 'IN' comparison. + * @param values - The values or expressions to check against. + * @returns A new `Expression` representing the 'IN' comparison. */ equalAny(values: Array): BooleanExpression; @@ -722,13 +752,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that checks if this expression is equal to any of the provided values or * expressions. * + * @example * ```typescript * // Check if the 'category' field is either "Electronics" or value of field 'primaryType' * field("category").equalAny(array(["Electronics", field("primaryType")])); * ``` * - * @param arrayExpression An expression that evaluates to an array of values to check against. - * @return A new `Expr` representing the 'IN' comparison. + * @param arrayExpression - An expression that evaluates to an array of values to check against. + * @returns A new `Expression` representing the 'IN' comparison. */ equalAny(arrayExpression: Expression): BooleanExpression; equalAny(others: unknown[] | Expression): BooleanExpression { @@ -747,13 +778,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that checks if this expression is not equal to any of the provided values or * expressions. * + * @example * ```typescript * // Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' * field("status").notEqualAny(["pending", field("rejectedStatus")]); * ``` * - * @param values The values or expressions to check against. - * @return A new `Expr` representing the 'notEqualAny' comparison. + * @param values - The values or expressions to check against. + * @returns A new `Expression` representing the 'notEqualAny' comparison. */ notEqualAny(values: Array): BooleanExpression; @@ -761,13 +793,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. * + * @example * ```typescript * // Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' * field("status").notEqualAny(field('rejectedStatuses')); * ``` * - * @param arrayExpression The values or expressions to check against. - * @return A new `Expr` representing the 'notEqualAny' comparison. + * @param arrayExpression - The values or expressions to check against. + * @returns A new `Expression` representing the 'notEqualAny' comparison. */ notEqualAny(arrayExpression: Expression): BooleanExpression; notEqualAny(others: unknown[] | Expression): BooleanExpression { @@ -785,12 +818,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new `Expr` representing the 'exists' check. + * @returns A new `Expression` representing the 'exists' check. */ exists(): BooleanExpression { return new FunctionExpression('exists', [this], 'exists').asBoolean(); @@ -800,12 +834,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new `Expr` representing the length of the string. + * @returns A new `Expression` representing the length of the string. */ charLength(): FunctionExpression { return new FunctionExpression('char_length', [this], 'charLength'); @@ -815,13 +850,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that performs a case-sensitive string comparison. * + * @example * ```typescript * // Check if the 'title' field contains the word "guide" (case-sensitive) * field("title").like("%guide%"); * ``` * - * @param pattern The pattern to search for. You can use "%" as a wildcard character. - * @return A new `Expr` representing the 'like' comparison. + * @param pattern - The pattern to search for. You can use "%" as a wildcard character. + * @returns A new `Expression` representing the 'like' comparison. */ like(pattern: string): BooleanExpression; @@ -829,13 +865,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that performs a case-sensitive string comparison. * + * @example * ```typescript * // Check if the 'title' field contains the word "guide" (case-sensitive) * field("title").like("%guide%"); * ``` * - * @param pattern The pattern to search for. You can use "%" as a wildcard character. - * @return A new `Expr` representing the 'like' comparison. + * @param pattern - The pattern to search for. You can use "%" as a wildcard character. + * @returns A new `Expression` representing the 'like' comparison. */ like(pattern: Expression): BooleanExpression; like(stringOrExpr: string | Expression): BooleanExpression { @@ -851,13 +888,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that checks if a string contains a specified regular expression as a * substring. * + * @example * ```typescript * // Check if the 'description' field contains "example" (case-insensitive) * field("description").regexContains("(?i)example"); * ``` * - * @param pattern The regular expression to use for the search. - * @return A new `Expr` representing the 'contains' comparison. + * @param pattern - The regular expression to use for the search. + * @returns A new `Expression` representing the 'contains' comparison. */ regexContains(pattern: string): BooleanExpression; @@ -866,13 +904,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that checks if a string contains a specified regular expression as a * substring. * + * @example * ```typescript * // Check if the 'description' field contains the regular expression stored in field 'regex' * field("description").regexContains(field("regex")); * ``` * - * @param pattern The regular expression to use for the search. - * @return A new `Expr` representing the 'contains' comparison. + * @param pattern - The regular expression to use for the search. + * @returns A new `Expression` representing the 'contains' comparison. */ regexContains(pattern: Expression): BooleanExpression; regexContains(stringOrExpr: string | Expression): BooleanExpression { @@ -887,13 +926,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if a string matches a specified regular expression. * + * @example * ```typescript * // Check if the 'email' field matches a valid email pattern * field("email").regexMatch("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); * ``` * - * @param pattern The regular expression to use for the match. - * @return A new `Expr` representing the regular expression match. + * @param pattern - The regular expression to use for the match. + * @returns A new `Expression` representing the regular expression match. */ regexMatch(pattern: string): BooleanExpression; @@ -901,13 +941,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if a string matches a specified regular expression. * + * @example * ```typescript * // Check if the 'email' field matches a regular expression stored in field 'regex' * field("email").regexMatch(field("regex")); * ``` * - * @param pattern The regular expression to use for the match. - * @return A new `Expr` representing the regular expression match. + * @param pattern - The regular expression to use for the match. + * @returns A new `Expression` representing the regular expression match. */ regexMatch(pattern: Expression): BooleanExpression; regexMatch(stringOrExpr: string | Expression): BooleanExpression { @@ -922,13 +963,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if a string contains a specified substring. * + * @example * ```typescript * // Check if the 'description' field contains "example". * field("description").stringContains("example"); * ``` * - * @param substring The substring to search for. - * @return A new `Expr` representing the 'contains' comparison. + * @param substring - The substring to search for. + * @returns A new `Expression` representing the 'contains' comparison. */ stringContains(substring: string): BooleanExpression; @@ -936,13 +978,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if a string contains the string represented by another expression. * + * @example * ```typescript * // Check if the 'description' field contains the value of the 'keyword' field. * field("description").stringContains(field("keyword")); * ``` * - * @param expr The expression representing the substring to search for. - * @return A new `Expr` representing the 'contains' comparison. + * @param expr - The expression representing the substring to search for. + * @returns A new `Expression` representing the 'contains' comparison. */ stringContains(expr: Expression): BooleanExpression; stringContains(stringOrExpr: string | Expression): BooleanExpression { @@ -957,13 +1000,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if a string starts with a given prefix. * + * @example * ```typescript * // Check if the 'name' field starts with "Mr." * field("name").startsWith("Mr."); * ``` * - * @param prefix The prefix to check for. - * @return A new `Expr` representing the 'starts with' comparison. + * @param prefix - The prefix to check for. + * @returns A new `Expression` representing the 'starts with' comparison. */ startsWith(prefix: string): BooleanExpression; @@ -972,13 +1016,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that checks if a string starts with a given prefix (represented as an * expression). * + * @example * ```typescript * // Check if the 'fullName' field starts with the value of the 'firstName' field * field("fullName").startsWith(field("firstName")); * ``` * - * @param prefix The prefix expression to check for. - * @return A new `Expr` representing the 'starts with' comparison. + * @param prefix - The prefix expression to check for. + * @returns A new `Expression` representing the 'starts with' comparison. */ startsWith(prefix: Expression): BooleanExpression; startsWith(stringOrExpr: string | Expression): BooleanExpression { @@ -993,13 +1038,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that checks if a string ends with a given postfix. * + * @example * ```typescript * // Check if the 'filename' field ends with ".txt" * field("filename").endsWith(".txt"); * ``` * - * @param suffix The postfix to check for. - * @return A new `Expr` representing the 'ends with' comparison. + * @param suffix - The postfix to check for. + * @returns A new `Expression` representing the 'ends with' comparison. */ endsWith(suffix: string): BooleanExpression; @@ -1008,13 +1054,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that checks if a string ends with a given postfix (represented as an * expression). * + * @example * ```typescript * // Check if the 'url' field ends with the value of the 'extension' field * field("url").endsWith(field("extension")); * ``` * - * @param suffix The postfix expression to check for. - * @return A new `Expr` representing the 'ends with' comparison. + * @param suffix - The postfix expression to check for. + * @returns A new `Expression` representing the 'ends with' comparison. */ endsWith(suffix: Expression): BooleanExpression; endsWith(stringOrExpr: string | Expression): BooleanExpression { @@ -1029,12 +1076,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that converts a string to lowercase. * + * @example * ```typescript * // Convert the 'name' field to lowercase * field("name").toLower(); * ``` * - * @return A new `Expr` representing the lowercase string. + * @returns A new `Expression` representing the lowercase string. */ toLower(): FunctionExpression { return new FunctionExpression('to_lower', [this], 'toLower'); @@ -1044,12 +1092,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that converts a string to uppercase. * + * @example * ```typescript * // Convert the 'title' field to uppercase * field("title").toUpper(); * ``` * - * @return A new `Expr` representing the uppercase string. + * @returns A new `Expression` representing the uppercase string. */ toUpper(): FunctionExpression { return new FunctionExpression('to_upper', [this], 'toUpper'); @@ -1059,6 +1108,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); @@ -1066,9 +1116,9 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * // 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 + * @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. - * @return A new `Expr` representing the trimmed string or byte array. + * @returns A new `Expression` representing the trimmed string or byte array. */ trim(valueToTrim?: string | Expression | Bytes): FunctionExpression { const args: Expression[] = [this]; @@ -1082,14 +1132,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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. - * @return A new `Expr` representing the concatenated string. + * @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: Expression | string, @@ -1108,14 +1159,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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. - * @return A new `Expr` representing the concatenated value. + * @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: Expression | unknown, @@ -1130,12 +1182,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that reverses this string expression. * + * @example * ```typescript * // Reverse the value of the 'myString' field. * field("myString").reverse(); * ``` * - * @return A new {@code Expr} representing the reversed string. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the reversed string. */ reverse(): FunctionExpression { return new FunctionExpression('reverse', [this], 'reverse'); @@ -1145,12 +1198,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new {@code Expr} representing the length of the string in bytes. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the length of the string in bytes. */ byteLength(): FunctionExpression { return new FunctionExpression('byte_length', [this], 'byteLength'); @@ -1160,12 +1214,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that computes the ceiling of a numeric value. * + * @example * ```typescript * // Compute the ceiling of the 'price' field. * field("price").ceil(); * ``` * - * @return A new {@code Expr} representing the ceiling of the numeric value. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the ceiling of the numeric value. */ ceil(): FunctionExpression { return new FunctionExpression('ceil', [this]); @@ -1175,12 +1230,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that computes the floor of a numeric value. * + * @example * ```typescript * // Compute the floor of the 'price' field. * field("price").floor(); * ``` * - * @return A new {@code Expr} representing the floor of the numeric value. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the floor of the numeric value. */ floor(): FunctionExpression { return new FunctionExpression('floor', [this]); @@ -1190,12 +1246,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new {@code Expr} representing the absolute value of the numeric value. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the absolute value of the numeric value. */ abs(): FunctionExpression { return new FunctionExpression('abs', [this]); @@ -1205,12 +1262,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new {@code Expr} representing the exp of the numeric value. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the exp of the numeric value. */ exp(): FunctionExpression { return new FunctionExpression('exp', [this]); @@ -1220,13 +1278,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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. - * @return A new `Expr` representing the value associated with the given key in the map. + * @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: string): FunctionExpression { return new FunctionExpression( @@ -1241,12 +1300,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * 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"); * ``` * - * @return A new `AggregateFunction` representing the 'count' aggregation. + * @returns A new `AggregateFunction` representing the 'count' aggregation. */ count(): AggregateFunction { return AggregateFunction._create('count', [this], 'count'); @@ -1256,12 +1316,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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"); * ``` * - * @return A new `AggregateFunction` representing the 'sum' aggregation. + * @returns A new `AggregateFunction` representing the 'sum' aggregation. */ sum(): AggregateFunction { return AggregateFunction._create('sum', [this], 'sum'); @@ -1272,12 +1333,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * 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"); * ``` * - * @return A new `AggregateFunction` representing the 'average' aggregation. + * @returns A new `AggregateFunction` representing the 'average' aggregation. */ average(): AggregateFunction { return AggregateFunction._create('average', [this], 'average'); @@ -1287,12 +1349,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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"); * ``` * - * @return A new `AggregateFunction` representing the 'minimum' aggregation. + * @returns A new `AggregateFunction` representing the 'minimum' aggregation. */ minimum(): AggregateFunction { return AggregateFunction._create('minimum', [this], 'minimum'); @@ -1302,12 +1365,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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"); * ``` * - * @return A new `AggregateFunction` representing the 'maximum' aggregation. + * @returns A new `AggregateFunction` representing the 'maximum' aggregation. */ maximum(): AggregateFunction { return AggregateFunction._create('maximum', [this], 'maximum'); @@ -1317,12 +1381,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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"); * ``` * - * @return A new `AggregateFunction` representing the 'count_distinct' aggregation. + * @returns A new `AggregateFunction` representing the 'count_distinct' aggregation. */ countDistinct(): AggregateFunction { return AggregateFunction._create('count_distinct', [this], 'countDistinct'); @@ -1332,14 +1397,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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. - * @return A new {@code Expr} representing the logical maximum operation. + * @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: Expression | unknown, @@ -1357,14 +1423,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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. - * @return A new {@code Expr} representing the logical minimum operation. + * @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: Expression | unknown, @@ -1382,12 +1449,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new {@code Expr} representing the length of the vector. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the length of the vector. */ vectorLength(): FunctionExpression { return new FunctionExpression('vector_length', [this], 'vectorLength'); @@ -1397,26 +1465,28 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Calculates the cosine distance between two vectors. * + * @example * ```typescript * // Calculate the cosine distance between the 'userVector' field and the 'itemVector' field * field("userVector").cosineDistance(field("itemVector")); * ``` * - * @param vectorExpression The other vector (represented as an Expr) to compare against. - * @return A new `Expr` representing the cosine distance between the two vectors. + * @param vectorExpression - The other vector (represented as an Expression) to compare against. + * @returns A new `Expression` representing the cosine distance between the two vectors. */ cosineDistance(vectorExpression: Expression): FunctionExpression; /** * @beta * Calculates the Cosine distance between two vectors. * + * @example * ```typescript * // Calculate the Cosine distance between the 'location' field and a target location * field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); * ``` * - * @param vector The other vector (as a VectorValue) to compare against. - * @return A new `Expr` representing the Cosine* distance between the two vectors. + * @param vector - The other vector (as a VectorValue) to compare against. + * @returns A new `Expression` representing the Cosine* distance between the two vectors. */ cosineDistance(vector: VectorValue | number[]): FunctionExpression; cosineDistance( @@ -1433,13 +1503,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Calculates the dot product between two vectors. * + * @example * ```typescript * // Calculate the dot product between a feature vector and a target vector * field("features").dotProduct([0.5, 0.8, 0.2]); * ``` * - * @param vectorExpression The other vector (as an array of numbers) to calculate with. - * @return A new `Expr` representing the dot product between the two vectors. + * @param vectorExpression - The other vector (as an array of numbers) to calculate with. + * @returns A new `Expression` representing the dot product between the two vectors. */ dotProduct(vectorExpression: Expression): FunctionExpression; @@ -1447,13 +1518,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Calculates the dot product between two vectors. * + * @example * ```typescript * // Calculate the dot product between a feature vector and a target vector * field("features").dotProduct(new VectorValue([0.5, 0.8, 0.2])); * ``` * - * @param vector The other vector (as an array of numbers) to calculate with. - * @return A new `Expr` representing the dot product between the two vectors. + * @param vector - The other vector (as an array of numbers) to calculate with. + * @returns A new `Expression` representing the dot product between the two vectors. */ dotProduct(vector: VectorValue | number[]): FunctionExpression; dotProduct(other: Expression | VectorValue | number[]): FunctionExpression { @@ -1468,13 +1540,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Calculates the Euclidean distance between two vectors. * + * @example * ```typescript * // Calculate the Euclidean distance between the 'location' field and a target location * field("location").euclideanDistance([37.7749, -122.4194]); * ``` * - * @param vectorExpression The other vector (as an array of numbers) to calculate with. - * @return A new `Expr` representing the Euclidean distance between the two vectors. + * @param vectorExpression - The other vector (as an array of numbers) to calculate with. + * @returns A new `Expression` representing the Euclidean distance between the two vectors. */ euclideanDistance(vectorExpression: Expression): FunctionExpression; @@ -1482,13 +1555,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Calculates the Euclidean distance between two vectors. * + * @example * ```typescript * // Calculate the Euclidean distance between the 'location' field and a target location * field("location").euclideanDistance(new VectorValue([37.7749, -122.4194])); * ``` * - * @param vector The other vector (as a VectorValue) to compare against. - * @return A new `Expr` representing the Euclidean distance between the two vectors. + * @param vector - The other vector (as a VectorValue) to compare against. + * @returns A new `Expression` representing the Euclidean distance between the two vectors. */ euclideanDistance(vector: VectorValue | number[]): FunctionExpression; euclideanDistance( @@ -1506,12 +1580,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * 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(); * ``` * - * @return A new {@code Expr} representing the timestamp. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the timestamp. */ unixMicrosToTimestamp(): FunctionExpression { return new FunctionExpression( @@ -1525,12 +1600,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new {@code Expr} representing the number of microseconds since epoch. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the number of microseconds since epoch. */ timestampToUnixMicros(): FunctionExpression { return new FunctionExpression( @@ -1545,12 +1621,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * 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(); * ``` * - * @return A new {@code Expr} representing the timestamp. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the timestamp. */ unixMillisToTimestamp(): FunctionExpression { return new FunctionExpression( @@ -1564,12 +1641,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new {@code Expr} representing the number of milliseconds since epoch. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the number of milliseconds since epoch. */ timestampToUnixMillis(): FunctionExpression { return new FunctionExpression( @@ -1584,12 +1662,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * 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(); * ``` * - * @return A new {@code Expr} representing the timestamp. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the timestamp. */ unixSecondsToTimestamp(): FunctionExpression { return new FunctionExpression( @@ -1603,12 +1682,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new {@code Expr} representing the number of seconds since epoch. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the number of seconds since epoch. */ timestampToUnixSeconds(): FunctionExpression { return new FunctionExpression( @@ -1622,14 +1702,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that adds a specified amount of time to this timestamp expression. * + * @example * ```typescript * // Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. * field("timestamp").timestampAdd(field("unit"), field("amount")); * ``` * - * @param unit The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. - * @param amount The expression evaluates to amount of the unit. - * @return A new {@code Expr} representing the resulting timestamp. + * @param unit - The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. + * @param amount - The expression evaluates to amount of the unit. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the resulting timestamp. */ timestampAdd(unit: Expression, amount: Expression): FunctionExpression; @@ -1637,14 +1718,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that adds a specified amount of time to this timestamp expression. * + * @example * ```typescript * // Add 1 day to the 'timestamp' field. * field("timestamp").timestampAdd("day", 1); * ``` * - * @param unit The unit of time to add (e.g., "day", "hour"). - * @param amount The amount of time to add. - * @return A new {@code Expr} representing the resulting timestamp. + * @param unit - The unit of time to add (e.g., "day", "hour"). + * @param amount - The amount of time to add. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the resulting timestamp. */ timestampAdd( unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', @@ -1672,14 +1754,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that subtracts a specified amount of time from this timestamp expression. * + * @example * ```typescript * // Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. * field("timestamp").timestampSubtract(field("unit"), field("amount")); * ``` * - * @param unit The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. - * @param amount The expression evaluates to amount of the unit. - * @return A new {@code Expr} representing the resulting timestamp. + * @param unit - The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. + * @param amount - The expression evaluates to amount of the unit. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the resulting timestamp. */ timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; @@ -1687,14 +1770,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that subtracts a specified amount of time from this timestamp expression. * + * @example * ```typescript * // Subtract 1 day from the 'timestamp' field. * field("timestamp").timestampSubtract("day", 1); * ``` * - * @param unit The unit of time to subtract (e.g., "day", "hour"). - * @param amount The amount of time to subtract. - * @return A new {@code Expr} representing the resulting timestamp. + * @param unit - The unit of time to subtract (e.g., "day", "hour"). + * @param amount - The amount of time to subtract. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the resulting timestamp. */ timestampSubtract( unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', @@ -1723,12 +1807,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * * Creates an expression that returns the document ID from a path. * + * @example * ```typescript * // Get the document ID from a path. * field("__path__").documentId(); * ``` * - * @return A new {@code Expr} representing the documentId operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the documentId operation. */ documentId(): FunctionExpression { return new FunctionExpression('document_id', [this], 'documentId'); @@ -1739,8 +1824,8 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * * Creates an expression that returns a substring of the results of this expression. * - * @param position Index of the first character of the substring. - * @param length Length of the substring. If not provided, the substring will + * @param position - Index of the first character of the substring. + * @param length - Length of the substring. If not provided, the substring will * end at the end of the input. */ substring(position: number, length?: number): FunctionExpression; @@ -1750,8 +1835,8 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * * Creates an expression that returns a substring of the results of this expression. * - * @param position An expression returning the index of the first character of the substring. - * @param length An expression returning the length of the substring. If not provided the + * @param position - An expression returning the index of the first character of the substring. + * @param length - An expression returning the length of the substring. If not provided the * substring will end at the end of the input. */ substring(position: Expression, length?: Expression): FunctionExpression; @@ -1781,13 +1866,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * and returns the element. If the offset exceeds the array length, an error is * returned. A negative offset, starts from the end. * + * @example * ```typescript * // Return the value in the 'tags' field array at index `1`. * field('tags').arrayGet(1); * ``` * - * @param offset The index of the element to return. - * @return A new Expr representing the 'arrayGet' operation. + * @param offset - The index of the element to return. + * @returns A new `Expression` representing the 'arrayGet' operation. */ arrayGet(offset: number): FunctionExpression; @@ -1797,14 +1883,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * and returns the element. If the offset exceeds the array length, an error is * returned. A negative offset, starts from the end. * + * @example * ```typescript * // Return the value in the tags field array at index specified by field * // 'favoriteTag'. * field('tags').arrayGet(field('favoriteTag')); * ``` * - * @param offsetExpr An Expr evaluating to the index of the element to return. - * @return A new Expr representing the 'arrayGet' operation. + * @param offsetExpr - An `Expression` evaluating to the index of the element to return. + * @returns A new `Expression` representing the 'arrayGet' operation. */ arrayGet(offsetExpr: Expression): FunctionExpression; arrayGet(offset: Expression | number): FunctionExpression { @@ -1820,12 +1907,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * * 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(); * ``` * - * @return A new {@code BooleanExpr} representing the 'isError' check. + * @returns A new {@link @firebase/firestore/pipelines#BooleanExpression} representing the 'isError' check. */ isError(): BooleanExpression { return new FunctionExpression('is_error', [this], 'isError').asBoolean(); @@ -1837,15 +1925,16 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that returns the result of the `catchExpr` argument * if there is an error, else return the result of this expression. * + * @example * ```typescript * // Returns the first item in the title field arrays, or returns * // the entire title field if the array is empty or the field is another type. * field("title").arrayGet(0).ifError(field("title")); * ``` * - * @param catchExpr The catch expression that will be evaluated and + * @param catchExpr - The catch expression that will be evaluated and * returned if this expression produces an error. - * @return A new {@code Expr} representing the 'ifError' operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ifError' operation. */ ifError(catchExpr: Expression): FunctionExpression; @@ -1855,15 +1944,16 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that returns the `catch` argument if there is an * error, else return the result of this expression. * + * @example * ```typescript * // Returns the first item in the title field arrays, or returns * // "Default Title" * field("title").arrayGet(0).ifError("Default Title"); * ``` * - * @param catchValue The value that will be returned if this expression + * @param catchValue - The value that will be returned if this expression * produces an error. - * @return A new {@code Expr} representing the 'ifError' operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ifError' operation. */ ifError(catchValue: unknown): FunctionExpression; ifError(catchValue: unknown): FunctionExpression | BooleanExpression { @@ -1884,12 +1974,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * 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 * ``` * - * @return A new {@code BooleanExpr} representing the 'isAbsent' check. + * @returns A new {@link @firebase/firestore/pipelines#BooleanExpression} representing the 'isAbsent' check. */ isAbsent(): BooleanExpression { return new FunctionExpression('is_absent', [this], 'isAbsent').asBoolean(); @@ -1900,13 +1992,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * * Creates an expression that removes a key from the map produced by evaluating this expression. * + * @example * ``` * // Removes the key 'baz' from the input map. * map({foo: 'bar', baz: true}).mapRemove('baz'); * ``` * - * @param key The name of the key to remove from the input map. - * @returns A new {@code FirestoreFunction} representing the 'mapRemove' operation. + * @param key - The name of the key to remove from the input map. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'mapRemove' operation. */ mapRemove(key: string): FunctionExpression; /** @@ -1914,13 +2007,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * * Creates an expression that removes a key from the map produced by evaluating this expression. * + * @example * ``` * // Removes the key 'baz' from the input map. * map({foo: 'bar', baz: true}).mapRemove(constant('baz')); + * @example * ``` * - * @param keyExpr An expression that produces the name of the key to remove from the input map. - * @returns A new {@code FirestoreFunction} representing the 'mapRemove' operation. + * @param keyExpr - An expression that produces the name of the key to remove from the input map. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'mapRemove' operation. */ mapRemove(keyExpr: Expression): FunctionExpression; mapRemove(stringExpr: Expression | string): FunctionExpression { @@ -1936,18 +2031,19 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * * 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 + * @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 + * @param otherMaps - Optional additional maps to merge. Each map is represented * as a literal or an expression that returns a map. * - * @returns A new {@code FirestoreFunction} representing the 'mapMerge' operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'mapMerge' operation. */ mapMerge( secondMap: Record | Expression, @@ -1966,13 +2062,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that returns the value of this expression raised to the power of another expression. * + * @example * ```typescript * // Raise the value of the 'base' field to the power of the 'exponent' field. * field("base").pow(field("exponent")); * ``` * - * @param exponent The expression to raise this expression to the power of. - * @return A new `Expr` representing the power operation. + * @param exponent - The expression to raise this expression to the power of. + * @returns A new `Expression` representing the power operation. */ pow(exponent: Expression): FunctionExpression; @@ -1980,13 +2077,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that returns the value of this expression raised to the power of a constant value. * + * @example * ```typescript * // Raise the value of the 'base' field to the power of 2. * field("base").pow(2); * ``` * - * @param exponent The constant value to raise this expression to the power of. - * @return A new `Expr` representing the power operation. + * @param exponent - The constant value to raise this expression to the power of. + * @returns A new `Expression` representing the power operation. */ pow(exponent: number): FunctionExpression; pow(exponent: number | Expression): FunctionExpression { @@ -1997,40 +2095,43 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that rounds a numeric value to the nearest whole number. * + * @example * ```typescript * // Round the value of the 'price' field. * field("price").round(); * ``` * - * @return A new `Expr` representing the rounded value. + * @returns A new `Expression` representing the rounded value. */ round(): FunctionExpression; /** * @beta * Creates an expression that rounds a numeric value to the specified number of decimal places. * + * @example * ```typescript * // Round the value of the 'price' field to two decimal places. * field("price").round(2); * ``` * - * @param decimalPlaces A constant specifying the rounding precision in decimal places. + * @param decimalPlaces - A constant specifying the rounding precision in decimal places. * - * @return A new `Expr` representing the rounded value. + * @returns A new `Expression` representing the rounded value. */ round(decimalPlaces: number): FunctionExpression; /** * @beta * Creates an expression that rounds a numeric value to the specified number of decimal places. * + * @example * ```typescript * // Round the value of the 'price' field to two decimal places. * field("price").round(constant(2)); * ``` * - * @param decimalPlaces An expression specifying the rounding precision in decimal places. + * @param decimalPlaces - An expression specifying the rounding precision in decimal places. * - * @return A new `Expr` representing the rounded value. + * @returns A new `Expression` representing the rounded value. */ round(decimalPlaces: Expression): FunctionExpression; round(decimalPlaces?: number | Expression): FunctionExpression { @@ -2049,12 +2150,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that returns the collection ID from a path. * + * @example * ```typescript * // Get the collection ID from a path. * field("__path__").collectionId(); * ``` * - * @return A new {@code Expr} representing the collectionId operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the collectionId operation. */ collectionId(): FunctionExpression { return new FunctionExpression('collection_id', [this]); @@ -2064,6 +2166,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); @@ -2072,7 +2175,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * field("cart").length(); * ``` * - * @return A new `Expr` representing the length of the string, array, map, vector, or bytes. + * @returns A new `Expression` representing the length of the string, array, map, vector, or bytes. */ length(): FunctionExpression { return new FunctionExpression('length', [this]); @@ -2082,12 +2185,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new {@code Expr} representing the natural logarithm of the numeric value. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the natural logarithm of the numeric value. */ ln(): FunctionExpression { return new FunctionExpression('ln', [this]); @@ -2097,12 +2201,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new {@code Expr} representing the square root of the numeric value. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the square root of the numeric value. */ sqrt(): FunctionExpression { return new FunctionExpression('sqrt', [this]); @@ -2112,12 +2217,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that reverses a string. * + * @example * ```typescript * // Reverse the value of the 'myString' field. * field("myString").stringReverse(); * ``` * - * @return A new {@code Expr} representing the reversed string. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the reversed string. */ stringReverse(): FunctionExpression { return new FunctionExpression('string_reverse', [this]); @@ -2128,14 +2234,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else * return the result of the this expression evaluation. * + * @example * ```typescript * // Returns the value of the optional field 'optional_field', or returns 'default_value' * // if the field is absent. * field("optional_field").ifAbsent("default_value") * ``` * - * @param elseValue The value that will be returned if this Expression evaluates to an absent value. - * @return A new [Expression] representing the ifAbsent operation. + * @param elseValue - The value that will be returned if this Expression evaluates to an absent value. + * @returns A new [Expression] representing the ifAbsent operation. */ ifAbsent(elseValue: unknown): Expression; @@ -2150,8 +2257,8 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * field("optional_field").ifAbsent(field('default_field')) * ``` * - * @param elseExpression The Expression that will be evaluated if this Expression evaluates to an absent value. - * @return A new [Expression] representing the ifAbsent operation. + * @param elseExpression - The Expression that will be evaluated if this Expression evaluates to an absent value. + * @returns A new [Expression] representing the ifAbsent operation. */ ifAbsent(elseExpression: unknown): Expression; @@ -2167,13 +2274,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that joins the elements of an array into a string. * + * @example * ```typescript * // Join the elements of the 'tags' field with the delimiter from the 'separator' field. * field("tags").join(field("separator")) * ``` * - * @param delimiterExpression The expression that evaluates to the delimiter string. - * @return A new Expression representing the join operation. + * @param delimiterExpression - The expression that evaluates to the delimiter string. + * @returns A new Expression representing the join operation. */ join(delimiterExpression: Expression): Expression; @@ -2181,13 +2289,14 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @beta * Creates an expression that joins the elements of an array field into a string. * + * @example * ```typescript * // Join the elements of the 'tags' field with a comma and space. * field("tags").join(", ") * ``` * - * @param delimiter The string to use as a delimiter. - * @return A new Expression representing the join operation. + * @param delimiter - The string to use as a delimiter. + * @returns A new Expression representing the join operation. */ join(delimiter: string): Expression; @@ -2203,12 +2312,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new {@code Expr} representing the base-10 logarithm of the numeric value. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the base-10 logarithm of the numeric value. */ log10(): FunctionExpression { return new FunctionExpression('log10', [this]); @@ -2218,12 +2328,13 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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(); * ``` * - * @return A new {@code Expr} representing the sum of the elements in the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the sum of the elements in the array. */ arraySum(): FunctionExpression { return new FunctionExpression('sum', [this]); @@ -2240,7 +2351,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * field('scoresCsv').split(',') * ``` * - * @return A new {@code Expression} representing the split function. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the split function. */ split(delimiter: string): FunctionExpression; @@ -2255,7 +2366,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * field('scores').split(conditional(field('format').equal('csv'), constant(','), constant(':')) * ``` * - * @return A new {@code Expression} representing the split function. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the split function. */ split(delimiter: Expression): FunctionExpression; split(delimiter: string | Expression): FunctionExpression { @@ -2274,10 +2385,10 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * field('createdAt').timestampTruncate('day') * ``` * - * @param granularity The granularity to truncate to. - * @param timezone The timezone to use for truncation. Valid values are from + * @param granularity - The granularity to truncate to. + * @param timezone - The timezone to use for truncation. Valid values are from * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". - * @return A new {Expression} representing the truncated timestamp. + * @returns A new `Expression` representing the truncated timestamp. */ timestampTruncate( granularity: TimeGranularity, @@ -2293,10 +2404,10 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * field('createdAt').timestampTruncate(field('granularity')) * ``` * - * @param granularity The granularity to truncate to. - * @param timezone The timezone to use for truncation. Valid values are from + * @param granularity - The granularity to truncate to. + * @param timezone - The timezone to use for truncation. Valid values are from * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". - * @return A new {Expression} representing the truncated timestamp. + * @returns A new `Expression` representing the truncated timestamp. */ timestampTruncate( granularity: Expression, @@ -2327,7 +2438,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * field('title').type() * ``` * - * @return A new {Expression} representing the data type. + * @returns A new `Expression` representing the data type. */ type(): FunctionExpression { return new FunctionExpression('type', [this]); @@ -2337,15 +2448,16 @@ export abstract class Expression implements ProtoValueSerializable, UserData { /** * @beta - * Creates an {@link Ordering} that sorts documents in ascending order based on this expression. + * 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()); * ``` * - * @return A new `Ordering` for ascending sorting. + * @returns A new `Ordering` for ascending sorting. */ ascending(): Ordering { return ascending(this); @@ -2353,15 +2465,16 @@ export abstract class Expression implements ProtoValueSerializable, UserData { /** * @beta - * Creates an {@link Ordering} that sorts documents in descending order based on this expression. + * 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()); * ``` * - * @return A new `Ordering` for descending sorting. + * @returns A new `Ordering` for descending sorting. */ descending(): Ordering { return descending(this); @@ -2374,14 +2487,15 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * 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. - * @return A new {@link AliasedExpression} that wraps this + * @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: string): AliasedExpression { @@ -2468,14 +2582,15 @@ export class AggregateFunction implements ProtoValueSerializable, UserData { * 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. - * @return A new {@link AliasedAggregate} that wraps this + * @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: string): AliasedAggregate { @@ -2591,13 +2706,14 @@ class ListOfExprs extends Expression implements UserData { /** * @beta * - * Represents a reference to a field in a Firestore document, or outputs of a {@link Pipeline} stage. + * Represents a reference to a field in a Firestore document, or outputs of a {@link @firebase/firestore/pipelines#Pipeline} stage. * *

Field references are used to access document field values in expressions and to specify fields * for sorting, filtering, and projecting data in Firestore pipelines. * - *

You can create a `Field` instance using the static {@link #of} method: + *

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"); @@ -2654,11 +2770,12 @@ export class Field extends Expression implements Selectable { /** * @beta - * Creates a {@code Field} instance representing the field at the given path. + * Creates a {@link @firebase/firestore/pipelines#Field} instance representing the field at the given path. * * The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field * (e.g., "address.city"). * + * @example * ```typescript * // Create a Field instance for the 'title' field * const titleField = field("title"); @@ -2667,17 +2784,17 @@ export class Field extends Expression implements Selectable { * const authorFirstNameField = field("author.firstName"); * ``` * - * @param name The path to the field. - * @return A new {@code Field} instance representing the specified field. + * @param name - The path to the field. + * @returns A new {@link @firebase/firestore/pipelines#Field} instance representing the specified field. */ export function field(name: string): Field; /** * @beta - * Creates a {@code Field} instance representing the field at the given path. + * Creates a {@link @firebase/firestore/pipelines#Field} instance representing the field at the given path. * - * @param path A FieldPath specifying the field. - * @return A new {@code Field} instance representing the specified field. + * @param path - A FieldPath specifying the field. + * @returns A new {@link @firebase/firestore/pipelines#Field} instance representing the specified field. */ export function field(path: FieldPath): Field; export function field(nameOrPath: string | FieldPath): Field { @@ -2703,8 +2820,9 @@ export function _field( * * Represents a constant value that can be used in a Firestore pipeline expression. * - * You can create a `Constant` instance using the static {@link #of} method: + * 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); @@ -2722,7 +2840,7 @@ export class Constant extends Expression { * @private * @internal * @hideconstructor - * @param value The value of the constant. + * @param value - The value of the constant. */ constructor( private value: unknown, @@ -2774,8 +2892,8 @@ export class Constant extends Expression { * @beta * Creates a `Constant` instance for a number value. * - * @param value The number value. - * @return A new `Constant` instance. + * @param value - The number value. + * @returns A new `Constant` instance. */ export function constant(value: number): Expression; @@ -2783,8 +2901,8 @@ export function constant(value: number): Expression; * @beta * Creates a `Constant` instance for a string value. * - * @param value The string value. - * @return A new `Constant` instance. + * @param value - The string value. + * @returns A new `Constant` instance. */ export function constant(value: string): Expression; @@ -2792,8 +2910,8 @@ export function constant(value: string): Expression; * @beta * Creates a `BooleanExpression` instance for a boolean value. * - * @param value The boolean value. - * @return A new `Constant` instance. + * @param value - The boolean value. + * @returns A new `Constant` instance. */ export function constant(value: boolean): BooleanExpression; @@ -2801,8 +2919,8 @@ export function constant(value: boolean): BooleanExpression; * @beta * Creates a `Constant` instance for a null value. * - * @param value The null value. - * @return A new `Constant` instance. + * @param value - The null value. + * @returns A new `Constant` instance. */ export function constant(value: null): Expression; @@ -2810,8 +2928,8 @@ export function constant(value: null): Expression; * @beta * Creates a `Constant` instance for a GeoPoint value. * - * @param value The GeoPoint value. - * @return A new `Constant` instance. + * @param value - The GeoPoint value. + * @returns A new `Constant` instance. */ export function constant(value: GeoPoint): Expression; @@ -2819,8 +2937,8 @@ export function constant(value: GeoPoint): Expression; * @beta * Creates a `Constant` instance for a Timestamp value. * - * @param value The Timestamp value. - * @return A new `Constant` instance. + * @param value - The Timestamp value. + * @returns A new `Constant` instance. */ export function constant(value: Timestamp): Expression; @@ -2828,8 +2946,8 @@ export function constant(value: Timestamp): Expression; * @beta * Creates a `Constant` instance for a Date value. * - * @param value The Date value. - * @return A new `Constant` instance. + * @param value - The Date value. + * @returns A new `Constant` instance. */ export function constant(value: Date): Expression; @@ -2837,8 +2955,8 @@ export function constant(value: Date): Expression; * @beta * Creates a `Constant` instance for a Bytes value. * - * @param value The Bytes value. - * @return A new `Constant` instance. + * @param value - The Bytes value. + * @returns A new `Constant` instance. */ export function constant(value: Bytes): Expression; @@ -2846,8 +2964,8 @@ export function constant(value: Bytes): Expression; * @beta * Creates a `Constant` instance for a DocumentReference value. * - * @param value The DocumentReference value. - * @return A new `Constant` instance. + * @param value - The DocumentReference value. + * @returns A new `Constant` instance. */ export function constant(value: DocumentReference): Expression; @@ -2856,8 +2974,8 @@ export function constant(value: DocumentReference): Expression; * For internal use only. * @private * @internal - * @param value The Firestore proto value. - * @return A new `Constant` instance. + * @param value - The Firestore proto value. + * @returns A new `Constant` instance. */ export function constant(value: ProtoValue): Expression; @@ -2865,8 +2983,8 @@ export function constant(value: ProtoValue): Expression; * @beta * Creates a `Constant` instance for a VectorValue value. * - * @param value The VectorValue value. - * @return A new `Constant` instance. + * @param value - The VectorValue value. + * @returns A new `Constant` instance. */ export function constant(value: VectorValue): Expression; @@ -2924,11 +3042,11 @@ export class MapValue extends Expression { /** * @beta * - * This class defines the base class for Firestore {@link Pipeline} functions, which can be evaluated within pipeline + * This class defines the base class for Firestore {@link @firebase/firestore/pipelines#Pipeline} functions, which can be evaluated within pipeline * execution. * - * Typically, you would not use this class or its children directly. Use either the functions like {@link and}, {@link equal}, - * or the methods on {@link Expression} ({@link Expression#equal}, {@link Expression#lessThan}, etc.) to construct new Function instances. + * Typically, you would not use this class or its children directly. Use either the functions like {@link @firebase/firestore/pipelines#and}, {@link @firebase/firestore/pipelines#(equal:1)}, + * or the methods on {@link @firebase/firestore/pipelines#Expression} ({@link @firebase/firestore/pipelines#Expression.(equal:1)}, {@link @firebase/firestore/pipelines#Expression.(lessThan:1)}, etc.) to construct new Function instances. */ export class FunctionExpression extends Expression { readonly expressionType: ExpressionType = 'Function'; @@ -2991,12 +3109,13 @@ export abstract class BooleanExpression extends Expression { * Creates an aggregation that finds the count of input documents satisfying * this boolean expression. * + * @example * ```typescript * // Find the count of documents with a score greater than 90 * field("score").greaterThan(90).countIf().as("highestScore"); * ``` * - * @return A new `AggregateFunction` representing the 'countIf' aggregation. + * @returns A new `AggregateFunction` representing the 'countIf' aggregation. */ countIf(): AggregateFunction { return AggregateFunction._create('count_if', [this], 'countIf'); @@ -3006,12 +3125,13 @@ export abstract class BooleanExpression extends Expression { * @beta * Creates an expression that negates this boolean expression. * + * @example * ```typescript * // Find documents where the 'tags' field does not contain 'completed' * field("tags").arrayContains("completed").not(); * ``` * - * @return A new {@code Expr} representing the negated filter condition. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the negated filter condition. */ not(): BooleanExpression { return new FunctionExpression('not', [this], 'not').asBoolean(); @@ -3023,14 +3143,15 @@ export abstract class BooleanExpression extends Expression { * if `this` expression evaluates to `true`, * or evaluates to the 'else' expression if `this` expressions evaluates `false`. * + * @example * ```typescript * // If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". * field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Minor")); * ``` * - * @param thenExpr The expression to evaluate if the condition is true. - * @param elseExpr The expression to evaluate if the condition is false. - * @return A new {@code Expr} representing the conditional expression. + * @param thenExpr - The expression to evaluate if the condition is true. + * @param elseExpr - The expression to evaluate if the condition is false. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the conditional expression. */ conditional(thenExpr: Expression, elseExpr: Expression): FunctionExpression { return new FunctionExpression( @@ -3046,15 +3167,16 @@ export abstract class BooleanExpression extends Expression { * Creates an expression that returns the `catch` argument if there is an * error, else return the result of this expression. * + * @example * ```typescript * // Create an expression that protects against a divide by zero error * // but always returns a boolean expression. * constant(50).divide('length').gt(1).ifError(constant(false)); * ``` * - * @param catchValue The value that will be returned if this expression + * @param catchValue - The value that will be returned if this expression * produces an error. - * @return A new {@code Expr} representing the 'ifError' operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ifError' operation. */ ifError(catchValue: BooleanExpression): BooleanExpression; @@ -3064,15 +3186,16 @@ export abstract class BooleanExpression extends Expression { * Creates an expression that returns the `catch` argument if there is an * error, else return the result of this expression. * + * @example * ```typescript * // Create an expression that protects against a divide by zero error * // but always returns a boolean expression. * constant(50).divide('length').gt(1).ifError(false); * ``` * - * @param catchValue The value that will be returned if this expression + * @param catchValue - The value that will be returned if this expression * produces an error. - * @return A new {@code Expr} representing the 'ifError' operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ifError' operation. */ ifError(catchValue: boolean): BooleanExpression; @@ -3082,14 +3205,15 @@ export abstract class BooleanExpression extends Expression { * Creates an expression that returns the `catch` argument if there is an * error, else return the result of this expression. * + * @example * ```typescript * // Create an expression that protects against a divide by zero error. * constant(50).divide('length').gt(1).ifError(constant(0)); * ``` * - * @param catchValue The value that will be returned if this expression + * @param catchValue - The value that will be returned if this expression * produces an error. - * @return A new {@code Expr} representing the 'ifError' operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ifError' operation. */ ifError(catchValue: Expression): FunctionExpression; @@ -3099,14 +3223,15 @@ export abstract class BooleanExpression extends Expression { * Creates an expression that returns the `catch` argument if there is an * error, else return the result of this expression. * + * @example * ```typescript * // Create an expression that protects against a divide by zero error. * constant(50).divide('length').gt(1).ifError(0); * ``` * - * @param catchValue The value that will be returned if this expression + * @param catchValue - The value that will be returned if this expression * produces an error. - * @return A new {@code Expr} representing the 'ifError' operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ifError' operation. */ ifError(catchValue: unknown): FunctionExpression; ifError(catchValue: unknown): unknown { @@ -3165,6 +3290,7 @@ export class BooleanField extends BooleanExpression { * Creates an aggregation that counts the number of stage inputs where the provided * boolean expression evaluates to true. * + * @example * ```typescript * // Count the number of documents where 'is_active' field equals true * countIf(field("is_active").equal(true)).as("numActiveDocuments"); @@ -3183,14 +3309,15 @@ export function countIf(booleanExpr: BooleanExpression): AggregateFunction { * and return the element. If the offset exceeds the array length, an error is * returned. A negative offset, starts from the end. * + * @example * ```typescript * // Return the value in the tags field array at index 1. * arrayGet('tags', 1); * ``` * - * @param arrayField The name of the array field. - * @param offset The index of the element to return. - * @return A new Expr representing the 'arrayGet' operation. + * @param arrayField - The name of the array field. + * @param offset - The index of the element to return. + * @returns A new `Expression` representing the 'arrayGet' operation. */ export function arrayGet( arrayField: string, @@ -3203,15 +3330,16 @@ export function arrayGet( * and return the element. If the offset exceeds the array length, an error is * returned. A negative offset, starts from the end. * + * @example * ```typescript * // Return the value in the tags field array at index specified by field * // 'favoriteTag'. * arrayGet('tags', field('favoriteTag')); * ``` * - * @param arrayField The name of the array field. - * @param offsetExpr An Expr evaluating to the index of the element to return. - * @return A new Expr representing the 'arrayGet' operation. + * @param arrayField - The name of the array field. + * @param offsetExpr - An `Expression` evaluating to the index of the element to return. + * @returns A new `Expression` representing the 'arrayGet' operation. */ export function arrayGet( arrayField: string, @@ -3224,14 +3352,15 @@ export function arrayGet( * and return the element. If the offset exceeds the array length, an error is * returned. A negative offset, starts from the end. * + * @example * ```typescript * // Return the value in the tags field array at index 1. * arrayGet(field('tags'), 1); * ``` * - * @param arrayExpression An Expr evaluating to an array. - * @param offset The index of the element to return. - * @return A new Expr representing the 'arrayGet' operation. + * @param arrayExpression - An `Expression` evaluating to an array. + * @param offset - The index of the element to return. + * @returns A new `Expression` representing the 'arrayGet' operation. */ export function arrayGet( arrayExpression: Expression, @@ -3244,15 +3373,16 @@ export function arrayGet( * and return the element. If the offset exceeds the array length, an error is * returned. A negative offset, starts from the end. * + * @example * ```typescript * // Return the value in the tags field array at index specified by field * // 'favoriteTag'. * arrayGet(field('tags'), field('favoriteTag')); * ``` * - * @param arrayExpression An Expr evaluating to an array. - * @param offsetExpr An Expr evaluating to the index of the element to return. - * @return A new Expr representing the 'arrayGet' operation. + * @param arrayExpression - An `Expression` evaluating to an array. + * @param offsetExpr - An `Expression` evaluating to the index of the element to return. + * @returns A new `Expression` representing the 'arrayGet' operation. */ export function arrayGet( arrayExpression: Expression, @@ -3270,13 +3400,14 @@ export function arrayGet( * * Creates an expression that checks if a given expression produces an error. * + * @example * ```typescript * // Check if the result of a calculation is an error * isError(field("title").arrayContains(1)); * ``` * - * @param value The expression to check. - * @return A new {@code Expr} representing the 'isError' check. + * @param value - The expression to check. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'isError' check. */ export function isError(value: Expression): BooleanExpression { return value.isError().asBoolean(); @@ -3290,16 +3421,17 @@ export function isError(value: Expression): BooleanExpression { * * This overload is useful when a BooleanExpression is required. * + * @example * ```typescript * // Create an expression that protects against a divide by zero error * // but always returns a boolean expression. * ifError(constant(50).divide('length').gt(1), constant(false)); * ``` * - * @param tryExpr The try expression. - * @param catchExpr The catch expression that will be evaluated and + * @param tryExpr - The try expression. + * @param catchExpr - The catch expression that will be evaluated and * returned if the tryExpr produces an error. - * @return A new {@code Expr} representing the 'ifError' operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ifError' operation. */ export function ifError( tryExpr: BooleanExpression, @@ -3312,16 +3444,17 @@ export function ifError( * Creates an expression that returns the `catch` argument if there is an * error, else return the result of the `try` argument evaluation. * + * @example * ```typescript * // Returns the first item in the title field arrays, or returns * // the entire title field if the array is empty or the field is another type. * ifError(field("title").arrayGet(0), field("title")); * ``` * - * @param tryExpr The try expression. - * @param catchExpr The catch expression that will be evaluated and + * @param tryExpr - The try expression. + * @param catchExpr - The catch expression that will be evaluated and * returned if the tryExpr produces an error. - * @return A new {@code Expr} representing the 'ifError' operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ifError' operation. */ export function ifError( tryExpr: Expression, @@ -3334,16 +3467,17 @@ export function ifError( * Creates an expression that returns the `catch` argument if there is an * error, else return the result of the `try` argument evaluation. * + * @example * ```typescript * // Returns the first item in the title field arrays, or returns * // "Default Title" * ifError(field("title").arrayGet(0), "Default Title"); * ``` * - * @param tryExpr The try expression. - * @param catchValue The value that will be returned if the tryExpr produces an + * @param tryExpr - The try expression. + * @param catchValue - The value that will be returned if the tryExpr produces an * error. - * @return A new {@code Expr} representing the 'ifError' operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ifError' operation. */ export function ifError( tryExpr: Expression, @@ -3370,13 +3504,14 @@ export function ifError( * Creates an expression that returns `true` if a value is absent. Otherwise, * returns `false` even if the value is `null`. * + * @example * ```typescript * // Check if the field `value` is absent. * isAbsent(field("value")); * ``` * - * @param value The expression to check. - * @return A new {@code Expr} representing the 'isAbsent' check. + * @param value - The expression to check. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'isAbsent' check. */ export function isAbsent(value: Expression): BooleanExpression; @@ -3386,13 +3521,14 @@ export function isAbsent(value: Expression): BooleanExpression; * Creates an expression that returns `true` if a field is absent. Otherwise, * returns `false` even if the field value is `null`. * + * @example * ```typescript * // Check if the field `value` is absent. * isAbsent("value"); * ``` * - * @param field The field to check. - * @return A new {@code Expr} representing the 'isAbsent' check. + * @param field - The field to check. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'isAbsent' check. */ export function isAbsent(field: string): BooleanExpression; export function isAbsent(value: Expression | string): BooleanExpression { @@ -3404,13 +3540,14 @@ export function isAbsent(value: Expression | string): BooleanExpression { * * Creates an expression that removes a key from the map at the specified field name. * + * @example * ``` * // Removes the key 'city' field from the map in the address field of the input document. * mapRemove('address', 'city'); * ``` * - * @param mapField The name of a field containing a map value. - * @param key The name of the key to remove from the input map. + * @param mapField - The name of a field containing a map value. + * @param key - The name of the key to remove from the input map. */ export function mapRemove(mapField: string, key: string): FunctionExpression; /** @@ -3418,13 +3555,15 @@ export function mapRemove(mapField: string, key: string): FunctionExpression; * * Creates an expression that removes a key from the map produced by evaluating an expression. * + * @example * ``` * // Removes the key 'baz' from the input map. * mapRemove(map({foo: 'bar', baz: true}), 'baz'); + * @example * ``` * - * @param mapExpr An expression return a map value. - * @param key The name of the key to remove from the input map. + * @param mapExpr - An expression return a map value. + * @param key - The name of the key to remove from the input map. */ export function mapRemove(mapExpr: Expression, key: string): FunctionExpression; /** @@ -3432,13 +3571,14 @@ export function mapRemove(mapExpr: Expression, key: string): FunctionExpression; * * Creates an expression that removes a key from the map at the specified field name. * + * @example * ``` * // Removes the key 'city' field from the map in the address field of the input document. * mapRemove('address', constant('city')); * ``` * - * @param mapField The name of a field containing a map value. - * @param keyExpr An expression that produces the name of the key to remove from the input map. + * @param mapField - The name of a field containing a map value. + * @param keyExpr - An expression that produces the name of the key to remove from the input map. */ export function mapRemove( mapField: string, @@ -3449,13 +3589,15 @@ export function mapRemove( * * Creates an expression that removes a key from the map produced by evaluating an expression. * + * @example * ``` * // Removes the key 'baz' from the input map. * mapRemove(map({foo: 'bar', baz: true}), constant('baz')); + * @example * ``` * - * @param mapExpr An expression return a map value. - * @param keyExpr An expression that produces the name of the key to remove from the input map. + * @param mapExpr - An expression return a map value. + * @param keyExpr - An expression that produces the name of the key to remove from the input map. */ export function mapRemove( mapExpr: Expression, @@ -3474,16 +3616,17 @@ export function mapRemove( * * 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 * mapMerge('settings', { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) * ``` * - * @param mapField Name of a field containing a map value that will be merged. - * @param secondMap A required second map to merge. Represented as a literal or + * @param mapField - Name of a field containing a map value that will be merged. + * @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 + * @param otherMaps - Optional additional maps to merge. Each map is represented * as a literal or an expression that returns a map. */ export function mapMerge( @@ -3497,16 +3640,17 @@ export function mapMerge( * * 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 * mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) * ``` * - * @param firstMap An expression or literal map value that will be merged. - * @param secondMap A required second map to merge. Represented as a literal or + * @param firstMap - An expression or literal map value that will be merged. + * @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 + * @param otherMaps - Optional additional maps to merge. Each map is represented * as a literal or an expression that returns a map. */ export function mapMerge( @@ -3530,12 +3674,13 @@ export function mapMerge( * * Creates an expression that returns the document ID from a path. * + * @example * ```typescript * // Get the document ID from a path. * documentId(myDocumentReference); * ``` * - * @return A new {@code Expr} representing the documentId operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the documentId operation. */ export function documentId( documentPath: string | DocumentReference @@ -3546,12 +3691,13 @@ export function documentId( * * Creates an expression that returns the document ID from a path. * + * @example * ```typescript * // Get the document ID from a path. * documentId(field("__path__")); * ``` * - * @return A new {@code Expr} representing the documentId operation. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the documentId operation. */ export function documentId(documentPathExpr: Expression): FunctionExpression; @@ -3568,9 +3714,9 @@ export function documentId( * * Creates an expression that returns a substring of a string or byte array. * - * @param field The name of a field containing a string or byte array to compute the substring from. - * @param position Index of the first character of the substring. - * @param length Length of the substring. + * @param field - The name of a field containing a string or byte array to compute the substring from. + * @param position - Index of the first character of the substring. + * @param length - Length of the substring. */ export function substring( field: string, @@ -3583,9 +3729,9 @@ export function substring( * * Creates an expression that returns a substring of a string or byte array. * - * @param input An expression returning a string or byte array to compute the substring from. - * @param position Index of the first character of the substring. - * @param length Length of the substring. + * @param input - An expression returning a string or byte array to compute the substring from. + * @param position - Index of the first character of the substring. + * @param length - Length of the substring. */ export function substring( input: Expression, @@ -3598,9 +3744,9 @@ export function substring( * * Creates an expression that returns a substring of a string or byte array. * - * @param field The name of a field containing a string or byte array to compute the substring from. - * @param position An expression that returns the index of the first character of the substring. - * @param length An expression that returns the length of the substring. + * @param field - The name of a field containing a string or byte array to compute the substring from. + * @param position - An expression that returns the index of the first character of the substring. + * @param length - An expression that returns the length of the substring. */ export function substring( field: string, @@ -3613,9 +3759,9 @@ export function substring( * * Creates an expression that returns a substring of a string or byte array. * - * @param input An expression returning a string or byte array to compute the substring from. - * @param position An expression that returns the index of the first character of the substring. - * @param length An expression that returns the length of the substring. + * @param input - An expression returning a string or byte array to compute the substring from. + * @param position - An expression that returns the index of the first character of the substring. + * @param length - An expression that returns the length of the substring. */ export function substring( input: Expression, @@ -3640,15 +3786,16 @@ export function substring( * * Creates an expression that adds two expressions together. * + * @example * ```typescript * // Add the value of the 'quantity' field and the 'reserve' field. * add(field("quantity"), field("reserve")); * ``` * - * @param first The first expression to add. - * @param second The second expression or literal to add. - * @param others Optional other expressions or literals to add. - * @return A new {@code Expr} representing the addition operation. + * @param first - The first expression to add. + * @param second - The second expression or literal to add. + * @param others - Optional other expressions or literals to add. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the addition operation. */ export function add( first: Expression, @@ -3660,15 +3807,16 @@ export function add( * * Creates an expression that adds a field's value to an expression. * + * @example * ```typescript * // Add the value of the 'quantity' field and the 'reserve' field. * add("quantity", field("reserve")); * ``` * - * @param fieldName The name of the field containing the value to add. - * @param second The second expression or literal to add. - * @param others Optional other expressions or literals to add. - * @return A new {@code Expr} representing the addition operation. + * @param fieldName - The name of the field containing the value to add. + * @param second - The second expression or literal to add. + * @param others - Optional other expressions or literals to add. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the addition operation. */ export function add( fieldName: string, @@ -3687,14 +3835,15 @@ export function add( * * Creates an expression that subtracts two expressions. * + * @example * ```typescript * // Subtract the 'discount' field from the 'price' field * subtract(field("price"), field("discount")); * ``` * - * @param left The expression to subtract from. - * @param right The expression to subtract. - * @return A new {@code Expr} representing the subtraction operation. + * @param left - The expression to subtract from. + * @param right - The expression to subtract. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the subtraction operation. */ export function subtract( left: Expression, @@ -3706,14 +3855,15 @@ export function subtract( * * Creates an expression that subtracts a constant value from an expression. * + * @example * ```typescript * // Subtract the constant value 2 from the 'value' field * subtract(field("value"), 2); * ``` * - * @param expression The expression to subtract from. - * @param value The constant value to subtract. - * @return A new {@code Expr} representing the subtraction operation. + * @param expression - The expression to subtract from. + * @param value - The constant value to subtract. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the subtraction operation. */ export function subtract( expression: Expression, @@ -3725,14 +3875,15 @@ export function subtract( * * Creates an expression that subtracts an expression from a field's value. * + * @example * ```typescript * // Subtract the 'discount' field from the 'price' field * subtract("price", field("discount")); * ``` * - * @param fieldName The field name to subtract from. - * @param expression The expression to subtract. - * @return A new {@code Expr} representing the subtraction operation. + * @param fieldName - The field name to subtract from. + * @param expression - The expression to subtract. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the subtraction operation. */ export function subtract( fieldName: string, @@ -3744,14 +3895,15 @@ export function subtract( * * Creates an expression that subtracts a constant value from a field's value. * + * @example * ```typescript * // Subtract 20 from the value of the 'total' field * subtract("total", 20); * ``` * - * @param fieldName The field name to subtract from. - * @param value The constant value to subtract. - * @return A new {@code Expr} representing the subtraction operation. + * @param fieldName - The field name to subtract from. + * @param value - The constant value to subtract. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the subtraction operation. */ export function subtract(fieldName: string, value: unknown): FunctionExpression; export function subtract( @@ -3768,15 +3920,16 @@ export function subtract( * * Creates an expression that multiplies two expressions together. * + * @example * ```typescript * // Multiply the 'quantity' field by the 'price' field * multiply(field("quantity"), field("price")); * ``` * - * @param first The first expression to multiply. - * @param second The second expression or literal to multiply. - * @param others Optional additional expressions or literals to multiply. - * @return A new {@code Expr} representing the multiplication operation. + * @param first - The first expression to multiply. + * @param second - The second expression or literal to multiply. + * @param others - Optional additional expressions or literals to multiply. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the multiplication operation. */ export function multiply( first: Expression, @@ -3788,15 +3941,16 @@ export function multiply( * * Creates an expression that multiplies a field's value by an expression. * + * @example * ```typescript * // Multiply the 'quantity' field by the 'price' field * multiply("quantity", field("price")); * ``` * - * @param fieldName The name of the field containing the value to add. - * @param second The second expression or literal to add. - * @param others Optional other expressions or literals to add. - * @return A new {@code Expr} representing the multiplication operation. + * @param fieldName - The name of the field containing the value to add. + * @param second - The second expression or literal to add. + * @param others - Optional other expressions or literals to add. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the multiplication operation. */ export function multiply( fieldName: string, @@ -3815,14 +3969,15 @@ export function multiply( * * Creates an expression that divides two expressions. * + * @example * ```typescript * // Divide the 'total' field by the 'count' field * divide(field("total"), field("count")); * ``` * - * @param left The expression to be divided. - * @param right The expression to divide by. - * @return A new {@code Expr} representing the division operation. + * @param left - The expression to be divided. + * @param right - The expression to divide by. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the division operation. */ export function divide(left: Expression, right: Expression): FunctionExpression; @@ -3831,14 +3986,15 @@ export function divide(left: Expression, right: Expression): FunctionExpression; * * Creates an expression that divides an expression by a constant value. * + * @example * ```typescript * // Divide the 'value' field by 10 * divide(field("value"), 10); * ``` * - * @param expression The expression to be divided. - * @param value The constant value to divide by. - * @return A new {@code Expr} representing the division operation. + * @param expression - The expression to be divided. + * @param value - The constant value to divide by. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the division operation. */ export function divide( expression: Expression, @@ -3850,14 +4006,15 @@ export function divide( * * Creates an expression that divides a field's value by an expression. * + * @example * ```typescript * // Divide the 'total' field by the 'count' field * divide("total", field("count")); * ``` * - * @param fieldName The field name to be divided. - * @param expressions The expression to divide by. - * @return A new {@code Expr} representing the division operation. + * @param fieldName - The field name to be divided. + * @param expressions - The expression to divide by. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the division operation. */ export function divide( fieldName: string, @@ -3869,14 +4026,15 @@ export function divide( * * Creates an expression that divides a field's value by a constant value. * + * @example * ```typescript * // Divide the 'value' field by 10 * divide("value", 10); * ``` * - * @param fieldName The field name to be divided. - * @param value The constant value to divide by. - * @return A new {@code Expr} representing the division operation. + * @param fieldName - The field name to be divided. + * @param value - The constant value to divide by. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the division operation. */ export function divide(fieldName: string, value: unknown): FunctionExpression; export function divide( @@ -3893,14 +4051,15 @@ export function divide( * * Creates an expression that calculates the modulo (remainder) of dividing two expressions. * + * @example * ```typescript * // Calculate the remainder of dividing 'field1' by 'field2'. * mod(field("field1"), field("field2")); * ``` * - * @param left The dividend expression. - * @param right The divisor expression. - * @return A new {@code Expr} representing the modulo operation. + * @param left - The dividend expression. + * @param right - The divisor expression. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the modulo operation. */ export function mod(left: Expression, right: Expression): FunctionExpression; @@ -3909,14 +4068,15 @@ export function mod(left: Expression, right: Expression): FunctionExpression; * * Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. * + * @example * ```typescript * // Calculate the remainder of dividing 'field1' by 5. * mod(field("field1"), 5); * ``` * - * @param expression The dividend expression. - * @param value The divisor constant. - * @return A new {@code Expr} representing the modulo operation. + * @param expression - The dividend expression. + * @param value - The divisor constant. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the modulo operation. */ export function mod(expression: Expression, value: unknown): FunctionExpression; @@ -3925,14 +4085,15 @@ export function mod(expression: Expression, value: unknown): FunctionExpression; * * Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. * + * @example * ```typescript * // Calculate the remainder of dividing 'field1' by 'field2'. * mod("field1", field("field2")); * ``` * - * @param fieldName The dividend field name. - * @param expression The divisor expression. - * @return A new {@code Expr} representing the modulo operation. + * @param fieldName - The dividend field name. + * @param expression - The divisor expression. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the modulo operation. */ export function mod( fieldName: string, @@ -3944,14 +4105,15 @@ export function mod( * * Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. * + * @example * ```typescript * // Calculate the remainder of dividing 'field1' by 5. * mod("field1", 5); * ``` * - * @param fieldName The dividend field name. - * @param value The divisor constant. - * @return A new {@code Expr} representing the modulo operation. + * @param fieldName - The dividend field name. + * @param value - The divisor constant. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the modulo operation. */ export function mod(fieldName: string, value: unknown): FunctionExpression; export function mod( @@ -3968,13 +4130,14 @@ export function mod( * * Creates an expression that creates a Firestore map value from an input object. * + * @example * ```typescript * // Create a map from the input object and reference the 'baz' field value from the input document. * map({foo: 'bar', baz: Field.of('baz')}).as('data'); * ``` * - * @param elements The input map to evaluate in the expression. - * @return A new {@code Expr} representing the map function. + * @param elements - The input map to evaluate in the expression. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the map function. */ export function map(elements: Record): FunctionExpression { return _map(elements, 'map'); @@ -4021,13 +4184,14 @@ export function _mapValue(plainObject: Record): MapValue { * * Creates an expression that creates a Firestore array value from an input array. * + * @example * ```typescript * // Create an array value from the input array and reference the 'baz' field value from the input document. * array(['bar', Field.of('baz')]).as('foo'); * ``` * - * @param elements The input array to evaluate in the expression. - * @return A new {@code Expr} representing the array function. + * @param elements - The input array to evaluate in the expression. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the array function. */ export function array(elements: unknown[]): FunctionExpression { return _array(elements, 'array'); @@ -4048,14 +4212,15 @@ export function _array( * * Creates an expression that checks if two expressions are equal. * + * @example * ```typescript * // Check if the 'age' field is equal to an expression * equal(field("age"), field("minAge").add(10)); * ``` * - * @param left The first expression to compare. - * @param right The second expression to compare. - * @return A new `Expr` representing the equality comparison. + * @param left - The first expression to compare. + * @param right - The second expression to compare. + * @returns A new `Expression` representing the equality comparison. */ export function equal(left: Expression, right: Expression): BooleanExpression; @@ -4064,14 +4229,15 @@ export function equal(left: Expression, right: Expression): BooleanExpression; * * Creates an expression that checks if an expression is equal to a constant value. * + * @example * ```typescript * // Check if the 'age' field is equal to 21 * equal(field("age"), 21); * ``` * - * @param expression The expression to compare. - * @param value The constant value to compare to. - * @return A new `Expr` representing the equality comparison. + * @param expression - The expression to compare. + * @param value - The constant value to compare to. + * @returns A new `Expression` representing the equality comparison. */ export function equal( expression: Expression, @@ -4083,14 +4249,15 @@ export function equal( * * Creates an expression that checks if a field's value is equal to an expression. * + * @example * ```typescript * // Check if the 'age' field is equal to the 'limit' field * equal("age", field("limit")); * ``` * - * @param fieldName The field name to compare. - * @param expression The expression to compare to. - * @return A new `Expr` representing the equality comparison. + * @param fieldName - The field name to compare. + * @param expression - The expression to compare to. + * @returns A new `Expression` representing the equality comparison. */ export function equal( fieldName: string, @@ -4102,14 +4269,15 @@ export function equal( * * Creates an expression that checks if a field's value is equal to a constant value. * + * @example * ```typescript * // Check if the 'city' field is equal to string constant "London" * equal("city", "London"); * ``` * - * @param fieldName The field name to compare. - * @param value The constant value to compare to. - * @return A new `Expr` representing the equality comparison. + * @param fieldName - The field name to compare. + * @param value - The constant value to compare to. + * @returns A new `Expression` representing the equality comparison. */ export function equal(fieldName: string, value: unknown): BooleanExpression; export function equal( @@ -4126,14 +4294,15 @@ export function equal( * * Creates an expression that checks if two expressions are not equal. * + * @example * ```typescript * // Check if the 'status' field is not equal to field 'finalState' * notEqual(field("status"), field("finalState")); * ``` * - * @param left The first expression to compare. - * @param right The second expression to compare. - * @return A new `Expr` representing the inequality comparison. + * @param left - The first expression to compare. + * @param right - The second expression to compare. + * @returns A new `Expression` representing the inequality comparison. */ export function notEqual( left: Expression, @@ -4145,14 +4314,15 @@ export function notEqual( * * Creates an expression that checks if an expression is not equal to a constant value. * + * @example * ```typescript * // Check if the 'status' field is not equal to "completed" * notEqual(field("status"), "completed"); * ``` * - * @param expression The expression to compare. - * @param value The constant value to compare to. - * @return A new `Expr` representing the inequality comparison. + * @param expression - The expression to compare. + * @param value - The constant value to compare to. + * @returns A new `Expression` representing the inequality comparison. */ export function notEqual( expression: Expression, @@ -4164,14 +4334,15 @@ export function notEqual( * * Creates an expression that checks if a field's value is not equal to an expression. * + * @example * ```typescript * // Check if the 'status' field is not equal to the value of 'expectedStatus' * notEqual("status", field("expectedStatus")); * ``` * - * @param fieldName The field name to compare. - * @param expression The expression to compare to. - * @return A new `Expr` representing the inequality comparison. + * @param fieldName - The field name to compare. + * @param expression - The expression to compare to. + * @returns A new `Expression` representing the inequality comparison. */ export function notEqual( fieldName: string, @@ -4183,14 +4354,15 @@ export function notEqual( * * Creates an expression that checks if a field's value is not equal to a constant value. * + * @example * ```typescript * // Check if the 'country' field is not equal to "USA" * notEqual("country", "USA"); * ``` * - * @param fieldName The field name to compare. - * @param value The constant value to compare to. - * @return A new `Expr` representing the inequality comparison. + * @param fieldName - The field name to compare. + * @param value - The constant value to compare to. + * @returns A new `Expression` representing the inequality comparison. */ export function notEqual(fieldName: string, value: unknown): BooleanExpression; export function notEqual( @@ -4207,14 +4379,15 @@ export function notEqual( * * Creates an expression that checks if the first expression is less than the second expression. * + * @example * ```typescript * // Check if the 'age' field is less than 30 * lessThan(field("age"), field("limit")); * ``` * - * @param left The first expression to compare. - * @param right The second expression to compare. - * @return A new `Expr` representing the less than comparison. + * @param left - The first expression to compare. + * @param right - The second expression to compare. + * @returns A new `Expression` representing the less than comparison. */ export function lessThan( left: Expression, @@ -4226,14 +4399,15 @@ export function lessThan( * * Creates an expression that checks if an expression is less than a constant value. * + * @example * ```typescript * // Check if the 'age' field is less than 30 * lessThan(field("age"), 30); * ``` * - * @param expression The expression to compare. - * @param value The constant value to compare to. - * @return A new `Expr` representing the less than comparison. + * @param expression - The expression to compare. + * @param value - The constant value to compare to. + * @returns A new `Expression` representing the less than comparison. */ export function lessThan( expression: Expression, @@ -4245,14 +4419,15 @@ export function lessThan( * * Creates an expression that checks if a field's value is less than an expression. * + * @example * ```typescript * // Check if the 'age' field is less than the 'limit' field * lessThan("age", field("limit")); * ``` * - * @param fieldName The field name to compare. - * @param expression The expression to compare to. - * @return A new `Expr` representing the less than comparison. + * @param fieldName - The field name to compare. + * @param expression - The expression to compare to. + * @returns A new `Expression` representing the less than comparison. */ export function lessThan( fieldName: string, @@ -4264,14 +4439,15 @@ export function lessThan( * * Creates an expression that checks if a field's value is less than a constant value. * + * @example * ```typescript * // Check if the 'price' field is less than 50 * lessThan("price", 50); * ``` * - * @param fieldName The field name to compare. - * @param value The constant value to compare to. - * @return A new `Expr` representing the less than comparison. + * @param fieldName - The field name to compare. + * @param value - The constant value to compare to. + * @returns A new `Expression` representing the less than comparison. */ export function lessThan(fieldName: string, value: unknown): BooleanExpression; export function lessThan( @@ -4289,14 +4465,15 @@ export function lessThan( * Creates an expression that checks if the first expression is less than or equal to the second * expression. * + * @example * ```typescript * // Check if the 'quantity' field is less than or equal to 20 * lessThan(field("quantity"), field("limit")); * ``` * - * @param left The first expression to compare. - * @param right The second expression to compare. - * @return A new `Expr` representing the less than or equal to comparison. + * @param left - The first expression to compare. + * @param right - The second expression to compare. + * @returns A new `Expression` representing the less than or equal to comparison. */ export function lessThanOrEqual( left: Expression, @@ -4308,14 +4485,15 @@ export function lessThanOrEqual( * * Creates an expression that checks if an expression is less than or equal to a constant value. * + * @example * ```typescript * // Check if the 'quantity' field is less than or equal to 20 * lessThan(field("quantity"), 20); * ``` * - * @param expression The expression to compare. - * @param value The constant value to compare to. - * @return A new `Expr` representing the less than or equal to comparison. + * @param expression - The expression to compare. + * @param value - The constant value to compare to. + * @returns A new `Expression` representing the less than or equal to comparison. */ export function lessThanOrEqual( expression: Expression, @@ -4326,14 +4504,15 @@ export function lessThanOrEqual( * @beta * Creates an expression that checks if a field's value is less than or equal to an expression. * + * @example * ```typescript * // Check if the 'quantity' field is less than or equal to the 'limit' field * lessThan("quantity", field("limit")); * ``` * - * @param fieldName The field name to compare. - * @param expression The expression to compare to. - * @return A new `Expr` representing the less than or equal to comparison. + * @param fieldName - The field name to compare. + * @param expression - The expression to compare to. + * @returns A new `Expression` representing the less than or equal to comparison. */ export function lessThanOrEqual( fieldName: string, @@ -4345,14 +4524,15 @@ export function lessThanOrEqual( * * Creates an expression that checks if a field's value is less than or equal to a constant value. * + * @example * ```typescript * // Check if the 'score' field is less than or equal to 70 * lessThan("score", 70); * ``` * - * @param fieldName The field name to compare. - * @param value The constant value to compare to. - * @return A new `Expr` representing the less than or equal to comparison. + * @param fieldName - The field name to compare. + * @param value - The constant value to compare to. + * @returns A new `Expression` representing the less than or equal to comparison. */ export function lessThanOrEqual( fieldName: string, @@ -4373,14 +4553,15 @@ export function lessThanOrEqual( * Creates an expression that checks if the first expression is greater than the second * expression. * + * @example * ```typescript * // Check if the 'age' field is greater than 18 * greaterThan(field("age"), Constant(9).add(9)); * ``` * - * @param left The first expression to compare. - * @param right The second expression to compare. - * @return A new `Expr` representing the greater than comparison. + * @param left - The first expression to compare. + * @param right - The second expression to compare. + * @returns A new `Expression` representing the greater than comparison. */ export function greaterThan( left: Expression, @@ -4392,14 +4573,15 @@ export function greaterThan( * * Creates an expression that checks if an expression is greater than a constant value. * + * @example * ```typescript * // Check if the 'age' field is greater than 18 * greaterThan(field("age"), 18); * ``` * - * @param expression The expression to compare. - * @param value The constant value to compare to. - * @return A new `Expr` representing the greater than comparison. + * @param expression - The expression to compare. + * @param value - The constant value to compare to. + * @returns A new `Expression` representing the greater than comparison. */ export function greaterThan( expression: Expression, @@ -4411,14 +4593,15 @@ export function greaterThan( * * Creates an expression that checks if a field's value is greater than an expression. * + * @example * ```typescript * // Check if the value of field 'age' is greater than the value of field 'limit' * greaterThan("age", field("limit")); * ``` * - * @param fieldName The field name to compare. - * @param expression The expression to compare to. - * @return A new `Expr` representing the greater than comparison. + * @param fieldName - The field name to compare. + * @param expression - The expression to compare to. + * @returns A new `Expression` representing the greater than comparison. */ export function greaterThan( fieldName: string, @@ -4430,14 +4613,15 @@ export function greaterThan( * * Creates an expression that checks if a field's value is greater than a constant value. * + * @example * ```typescript * // Check if the 'price' field is greater than 100 * greaterThan("price", 100); * ``` * - * @param fieldName The field name to compare. - * @param value The constant value to compare to. - * @return A new `Expr` representing the greater than comparison. + * @param fieldName - The field name to compare. + * @param value - The constant value to compare to. + * @returns A new `Expression` representing the greater than comparison. */ export function greaterThan( fieldName: string, @@ -4458,14 +4642,15 @@ export function greaterThan( * Creates an expression that checks if the first expression is greater than or equal to the * second expression. * + * @example * ```typescript * // Check if the 'quantity' field is greater than or equal to the field "threshold" * greaterThanOrEqual(field("quantity"), field("threshold")); * ``` * - * @param left The first expression to compare. - * @param right The second expression to compare. - * @return A new `Expr` representing the greater than or equal to comparison. + * @param left - The first expression to compare. + * @param right - The second expression to compare. + * @returns A new `Expression` representing the greater than or equal to comparison. */ export function greaterThanOrEqual( left: Expression, @@ -4478,14 +4663,15 @@ export function greaterThanOrEqual( * Creates an expression that checks if an expression is greater than or equal to a constant * value. * + * @example * ```typescript * // Check if the 'quantity' field is greater than or equal to 10 * greaterThanOrEqual(field("quantity"), 10); * ``` * - * @param expression The expression to compare. - * @param value The constant value to compare to. - * @return A new `Expr` representing the greater than or equal to comparison. + * @param expression - The expression to compare. + * @param value - The constant value to compare to. + * @returns A new `Expression` representing the greater than or equal to comparison. */ export function greaterThanOrEqual( expression: Expression, @@ -4497,14 +4683,15 @@ export function greaterThanOrEqual( * * Creates an expression that checks if a field's value is greater than or equal to an expression. * + * @example * ```typescript * // Check if the value of field 'age' is greater than or equal to the value of field 'limit' * greaterThanOrEqual("age", field("limit")); * ``` * - * @param fieldName The field name to compare. - * @param value The expression to compare to. - * @return A new `Expr` representing the greater than or equal to comparison. + * @param fieldName - The field name to compare. + * @param value - The expression to compare to. + * @returns A new `Expression` representing the greater than or equal to comparison. */ export function greaterThanOrEqual( fieldName: string, @@ -4517,14 +4704,15 @@ export function greaterThanOrEqual( * Creates an expression that checks if a field's value is greater than or equal to a constant * value. * + * @example * ```typescript * // Check if the 'score' field is greater than or equal to 80 * greaterThanOrEqual("score", 80); * ``` * - * @param fieldName The field name to compare. - * @param value The constant value to compare to. - * @return A new `Expr` representing the greater than or equal to comparison. + * @param fieldName - The field name to compare. + * @param value - The constant value to compare to. + * @returns A new `Expression` representing the greater than or equal to comparison. */ export function greaterThanOrEqual( fieldName: string, @@ -4544,15 +4732,16 @@ export function greaterThanOrEqual( * * Creates an expression that concatenates an array expression with other arrays. * + * @example * ```typescript * // Combine the 'items' array with two new item arrays * arrayConcat(field("items"), [field("newItems"), field("otherItems")]); * ``` * - * @param firstArray The first array expression to concatenate to. - * @param secondArray The second array expression or array literal to concatenate to. - * @param otherArrays Optional additional array expressions or array literals to concatenate. - * @return A new {@code Expr} representing the concatenated array. + * @param firstArray - The first array expression to concatenate to. + * @param secondArray - The second array expression or array literal to concatenate to. + * @param otherArrays - Optional additional array expressions or array literals to concatenate. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the concatenated array. */ export function arrayConcat( firstArray: Expression, @@ -4565,15 +4754,16 @@ export function arrayConcat( * * Creates an expression that concatenates a field's array value with other arrays. * + * @example * ```typescript * // Combine the 'items' array with two new item arrays * arrayConcat("items", [field("newItems"), field("otherItems")]); * ``` * - * @param firstArrayField The first array to concatenate to. - * @param secondArray The second array expression or array literal to concatenate to. - * @param otherArrays Optional additional array expressions or array literals to concatenate. - * @return A new {@code Expr} representing the concatenated array. + * @param firstArrayField - The first array to concatenate to. + * @param secondArray - The second array expression or array literal to concatenate to. + * @param otherArrays - Optional additional array expressions or array literals to concatenate. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the concatenated array. */ export function arrayConcat( firstArrayField: string, @@ -4598,14 +4788,15 @@ export function arrayConcat( * * Creates an expression that checks if an array expression contains a specific element. * + * @example * ```typescript * // Check if the 'colors' array contains the value of field 'selectedColor' * arrayContains(field("colors"), field("selectedColor")); * ``` * - * @param array The array expression to check. - * @param element The element to search for in the array. - * @return A new {@code Expr} representing the 'array_contains' comparison. + * @param array - The array expression to check. + * @param element - The element to search for in the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'array_contains' comparison. */ export function arrayContains( array: Expression, @@ -4617,14 +4808,15 @@ export function arrayContains( * * Creates an expression that checks if an array expression contains a specific element. * + * @example * ```typescript * // Check if the 'colors' array contains "red" * arrayContains(field("colors"), "red"); * ``` * - * @param array The array expression to check. - * @param element The element to search for in the array. - * @return A new {@code Expr} representing the 'array_contains' comparison. + * @param array - The array expression to check. + * @param element - The element to search for in the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'array_contains' comparison. */ export function arrayContains( array: Expression, @@ -4636,14 +4828,15 @@ export function arrayContains( * * Creates an expression that checks if a field's array value contains a specific element. * + * @example * ```typescript * // Check if the 'colors' array contains the value of field 'selectedColor' * arrayContains("colors", field("selectedColor")); * ``` * - * @param fieldName The field name to check. - * @param element The element to search for in the array. - * @return A new {@code Expr} representing the 'array_contains' comparison. + * @param fieldName - The field name to check. + * @param element - The element to search for in the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'array_contains' comparison. */ export function arrayContains( fieldName: string, @@ -4655,14 +4848,15 @@ export function arrayContains( * * Creates an expression that checks if a field's array value contains a specific value. * + * @example * ```typescript * // Check if the 'colors' array contains "red" * arrayContains("colors", "red"); * ``` * - * @param fieldName The field name to check. - * @param element The element to search for in the array. - * @return A new {@code Expr} representing the 'array_contains' comparison. + * @param fieldName - The field name to check. + * @param element - The element to search for in the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'array_contains' comparison. */ export function arrayContains( fieldName: string, @@ -4683,14 +4877,15 @@ export function arrayContains( * Creates an expression that checks if an array expression contains any of the specified * elements. * + * @example * ```typescript * // Check if the 'categories' array contains either values from field "cate1" or "Science" * arrayContainsAny(field("categories"), [field("cate1"), "Science"]); * ``` * - * @param array The array expression to check. - * @param values The elements to check for in the array. - * @return A new {@code Expr} representing the 'array_contains_any' comparison. + * @param array - The array expression to check. + * @param values - The elements to check for in the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'array_contains_any' comparison. */ export function arrayContainsAny( array: Expression, @@ -4703,15 +4898,16 @@ export function arrayContainsAny( * Creates an expression that checks if a field's array value contains any of the specified * elements. * + * @example * ```typescript * // Check if the 'groups' array contains either the value from the 'userGroup' field * // or the value "guest" * arrayContainsAny("categories", [field("cate1"), "Science"]); * ``` * - * @param fieldName The field name to check. - * @param values The elements to check for in the array. - * @return A new {@code Expr} representing the 'array_contains_any' comparison. + * @param fieldName - The field name to check. + * @param values - The elements to check for in the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'array_contains_any' comparison. */ export function arrayContainsAny( fieldName: string, @@ -4724,14 +4920,15 @@ export function arrayContainsAny( * Creates an expression that checks if an array expression contains any of the specified * elements. * + * @example * ```typescript * // Check if the 'categories' array contains either values from field "cate1" or "Science" * arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); * ``` * - * @param array The array expression to check. - * @param values An expression that evaluates to an array, whose elements to check for in the array. - * @return A new {@code Expr} representing the 'array_contains_any' comparison. + * @param array - The array expression to check. + * @param values - An expression that evaluates to an array, whose elements to check for in the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'array_contains_any' comparison. */ export function arrayContainsAny( array: Expression, @@ -4744,15 +4941,16 @@ export function arrayContainsAny( * Creates an expression that checks if a field's array value contains any of the specified * elements. * + * @example * ```typescript * // Check if the 'groups' array contains either the value from the 'userGroup' field * // or the value "guest" * arrayContainsAny("categories", array([field("cate1"), "Science"])); * ``` * - * @param fieldName The field name to check. - * @param values An expression that evaluates to an array, whose elements to check for in the array field. - * @return A new {@code Expr} representing the 'array_contains_any' comparison. + * @param fieldName - The field name to check. + * @param values - An expression that evaluates to an array, whose elements to check for in the array field. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'array_contains_any' comparison. */ export function arrayContainsAny( fieldName: string, @@ -4771,14 +4969,15 @@ export function arrayContainsAny( * * Creates an expression that checks if an array expression contains all the specified elements. * + * @example * ```typescript * // Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" * arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); * ``` * - * @param array The array expression to check. - * @param values The elements to check for in the array. - * @return A new {@code Expr} representing the 'array_contains_all' comparison. + * @param array - The array expression to check. + * @param values - The elements to check for in the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'array_contains_all' comparison. */ export function arrayContainsAll( array: Expression, @@ -4791,14 +4990,15 @@ export function arrayContainsAll( * Creates an expression that checks if a field's array value contains all the specified values or * expressions. * + * @example * ```typescript * // Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" * arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); * ``` * - * @param fieldName The field name to check. - * @param values The elements to check for in the array. - * @return A new {@code Expr} representing the 'array_contains_all' comparison. + * @param fieldName - The field name to check. + * @param values - The elements to check for in the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'array_contains_all' comparison. */ export function arrayContainsAll( fieldName: string, @@ -4810,14 +5010,15 @@ export function arrayContainsAll( * * Creates an expression that checks if an array expression contains all the specified elements. * + * @example * ```typescript * // Check if the "tags" array contains all of the values: "SciFi", "Adventure", and the value from field "tag1" * arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]); * ``` * - * @param array The array expression to check. - * @param arrayExpression The elements to check for in the array. - * @return A new {@code Expr} representing the 'array_contains_all' comparison. + * @param array - The array expression to check. + * @param arrayExpression - The elements to check for in the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'array_contains_all' comparison. */ export function arrayContainsAll( array: Expression, @@ -4830,14 +5031,15 @@ export function arrayContainsAll( * Creates an expression that checks if a field's array value contains all the specified values or * expressions. * + * @example * ```typescript * // Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" * arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); * ``` * - * @param fieldName The field name to check. - * @param arrayExpression The elements to check for in the array. - * @return A new {@code Expr} representing the 'array_contains_all' comparison. + * @param fieldName - The field name to check. + * @param arrayExpression - The elements to check for in the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'array_contains_all' comparison. */ export function arrayContainsAll( fieldName: string, @@ -4856,13 +5058,14 @@ export function arrayContainsAll( * * Creates an expression that calculates the length of an array in a specified field. * + * @example * ```typescript * // Get the number of items in field 'cart' * arrayLength('cart'); * ``` * - * @param fieldName The name of the field containing an array to calculate the length of. - * @return A new {@code Expr} representing the length of the array. + * @param fieldName - The name of the field containing an array to calculate the length of. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the length of the array. */ export function arrayLength(fieldName: string): FunctionExpression; @@ -4871,13 +5074,14 @@ export function arrayLength(fieldName: string): FunctionExpression; * * Creates an expression that calculates the length of an array expression. * + * @example * ```typescript * // Get the number of items in the 'cart' array * arrayLength(field("cart")); * ``` * - * @param array The array expression to calculate the length of. - * @return A new {@code Expr} representing the length of the array. + * @param array - The array expression to calculate the length of. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the length of the array. */ export function arrayLength(array: Expression): FunctionExpression; export function arrayLength(array: Expression | string): FunctionExpression { @@ -4890,14 +5094,15 @@ export function arrayLength(array: Expression | string): FunctionExpression { * Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or * expressions. * + * @example * ```typescript * // Check if the 'category' field is either "Electronics" or value of field 'primaryType' * equalAny(field("category"), [constant("Electronics"), field("primaryType")]); * ``` * - * @param expression The expression whose results to compare. - * @param values The values to check against. - * @return A new {@code Expr} representing the 'IN' comparison. + * @param expression - The expression whose results to compare. + * @param values - The values to check against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'IN' comparison. */ export function equalAny( expression: Expression, @@ -4909,14 +5114,15 @@ export function equalAny( * * Creates an expression that checks if an expression is equal to any of the provided values. * + * @example * ```typescript * // Check if the 'category' field is set to a value in the disabledCategories field * equalAny(field("category"), field('disabledCategories')); * ``` * - * @param expression The expression whose results to compare. - * @param arrayExpression An expression that evaluates to an array, whose elements to check for equality to the input. - * @return A new {@code Expr} representing the 'IN' comparison. + * @param expression - The expression whose results to compare. + * @param arrayExpression - An expression that evaluates to an array, whose elements to check for equality to the input. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'IN' comparison. */ export function equalAny( expression: Expression, @@ -4929,14 +5135,15 @@ export function equalAny( * Creates an expression that checks if a field's value is equal to any of the provided values or * expressions. * + * @example * ```typescript * // Check if the 'category' field is either "Electronics" or value of field 'primaryType' * equalAny("category", [constant("Electronics"), field("primaryType")]); * ``` * - * @param fieldName The field to compare. - * @param values The values to check against. - * @return A new {@code Expr} representing the 'IN' comparison. + * @param fieldName - The field to compare. + * @param values - The values to check against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'IN' comparison. */ export function equalAny( fieldName: string, @@ -4949,14 +5156,15 @@ export function equalAny( * Creates an expression that checks if a field's value is equal to any of the provided values or * expressions. * + * @example * ```typescript * // Check if the 'category' field is either "Electronics" or value of field 'primaryType' * equalAny("category", ["Electronics", field("primaryType")]); * ``` * - * @param fieldName The field to compare. - * @param arrayExpression An expression that evaluates to an array, whose elements to check for equality to the input field. - * @return A new {@code Expr} representing the 'IN' comparison. + * @param fieldName - The field to compare. + * @param arrayExpression - An expression that evaluates to an array, whose elements to check for equality to the input field. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'IN' comparison. */ export function equalAny( fieldName: string, @@ -4976,14 +5184,15 @@ export function equalAny( * Creates an expression that checks if an expression is not equal to any of the provided values * or expressions. * + * @example * ```typescript * // Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' * notEqualAny(field("status"), ["pending", field("rejectedStatus")]); * ``` * - * @param element The expression to compare. - * @param values The values to check against. - * @return A new {@code Expr} representing the 'NOT IN' comparison. + * @param element - The expression to compare. + * @param values - The values to check against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'NOT IN' comparison. */ export function notEqualAny( element: Expression, @@ -4996,14 +5205,15 @@ export function notEqualAny( * Creates an expression that checks if a field's value is not equal to any of the provided values * or expressions. * + * @example * ```typescript * // Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' * notEqualAny("status", [constant("pending"), field("rejectedStatus")]); * ``` * - * @param fieldName The field name to compare. - * @param values The values to check against. - * @return A new {@code Expr} representing the 'NOT IN' comparison. + * @param fieldName - The field name to compare. + * @param values - The values to check against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'NOT IN' comparison. */ export function notEqualAny( fieldName: string, @@ -5016,14 +5226,15 @@ export function notEqualAny( * Creates an expression that checks if an expression is not equal to any of the provided values * or expressions. * + * @example * ```typescript * // Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' * notEqualAny(field("status"), ["pending", field("rejectedStatus")]); * ``` * - * @param element The expression to compare. - * @param arrayExpression The values to check against. - * @return A new {@code Expr} representing the 'NOT IN' comparison. + * @param element - The expression to compare. + * @param arrayExpression - The values to check against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'NOT IN' comparison. */ export function notEqualAny( element: Expression, @@ -5035,14 +5246,15 @@ export function notEqualAny( * * Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. * + * @example * ```typescript * // Check if the 'status' field is not equal to any value in the field 'rejectedStatuses' * notEqualAny("status", field("rejectedStatuses")); * ``` * - * @param fieldName The field name to compare. - * @param arrayExpression The values to check against. - * @return A new {@code Expr} representing the 'NOT IN' comparison. + * @param fieldName - The field name to compare. + * @param arrayExpression - The values to check against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'NOT IN' comparison. */ export function notEqualAny( fieldName: string, @@ -5062,6 +5274,7 @@ export function notEqualAny( * * Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. * + * @example * ```typescript * // Check if only one of the conditions is true: 'age' greater than 18, 'city' is "London", * // or 'status' is "active". @@ -5071,10 +5284,10 @@ export function notEqualAny( * equal("status", "active")); * ``` * - * @param first The first condition. - * @param second The second condition. - * @param additionalConditions Additional conditions to 'XOR' together. - * @return A new {@code Expr} representing the logical 'XOR' operation. + * @param first - The first condition. + * @param second - The second condition. + * @param additionalConditions - Additional conditions to 'XOR' together. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logical 'XOR' operation. */ export function xor( first: BooleanExpression, @@ -5094,16 +5307,17 @@ export function xor( * Creates a conditional expression that evaluates to a 'then' expression if a condition is true * and an 'else' expression if the condition is false. * + * @example * ```typescript * // If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". * conditional( * greaterThan("age", 18), constant("Adult"), constant("Minor")); * ``` * - * @param condition The condition to evaluate. - * @param thenExpr The expression to evaluate if the condition is true. - * @param elseExpr The expression to evaluate if the condition is false. - * @return A new {@code Expr} representing the conditional expression. + * @param condition - The condition to evaluate. + * @param thenExpr - The expression to evaluate if the condition is true. + * @param elseExpr - The expression to evaluate if the condition is false. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the conditional expression. */ export function conditional( condition: BooleanExpression, @@ -5122,13 +5336,14 @@ export function conditional( * * Creates an expression that negates a filter condition. * + * @example * ```typescript * // Find documents where the 'completed' field is NOT true * not(equal("completed", true)); * ``` * - * @param booleanExpr The filter condition to negate. - * @return A new {@code Expr} representing the negated filter condition. + * @param booleanExpr - The filter condition to negate. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the negated filter condition. */ export function not(booleanExpr: BooleanExpression): BooleanExpression { return booleanExpr.not(); @@ -5140,16 +5355,17 @@ export function not(booleanExpr: BooleanExpression): BooleanExpression { * Creates an expression that returns the largest value between multiple input * expressions or literal values. Based on Firestore's value type ordering. * + * @example * ```typescript * // Returns the largest value between the 'field1' field, the 'field2' field, * // and 1000 * logicalMaximum(field("field1"), field("field2"), 1000); * ``` * - * @param first The first operand expression. - * @param second The second expression or literal. - * @param others Optional additional expressions or literals. - * @return A new {@code Expr} representing the logical maximum operation. + * @param first - The first operand expression. + * @param second - The second expression or literal. + * @param others - Optional additional expressions or literals. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logical maximum operation. */ export function logicalMaximum( first: Expression, @@ -5163,16 +5379,17 @@ export function logicalMaximum( * Creates an expression that returns the largest value between multiple input * expressions or literal values. Based on Firestore's value type ordering. * + * @example * ```typescript * // Returns the largest value between the 'field1' field, the 'field2' field, * // and 1000. * logicalMaximum("field1", field("field2"), 1000); * ``` * - * @param fieldName The first operand field name. - * @param second The second expression or literal. - * @param others Optional additional expressions or literals. - * @return A new {@code Expr} representing the logical maximum operation. + * @param fieldName - The first operand field name. + * @param second - The second expression or literal. + * @param others - Optional additional expressions or literals. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logical maximum operation. */ export function logicalMaximum( fieldName: string, @@ -5197,16 +5414,17 @@ export function logicalMaximum( * Creates an expression that returns the smallest value between multiple input * expressions and literal values. Based on Firestore's value type ordering. * + * @example * ```typescript * // Returns the smallest value between the 'field1' field, the 'field2' field, * // and 1000. * logicalMinimum(field("field1"), field("field2"), 1000); * ``` * - * @param first The first operand expression. - * @param second The second expression or literal. - * @param others Optional additional expressions or literals. - * @return A new {@code Expr} representing the logical minimum operation. + * @param first - The first operand expression. + * @param second - The second expression or literal. + * @param others - Optional additional expressions or literals. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logical minimum operation. */ export function logicalMinimum( first: Expression, @@ -5221,16 +5439,17 @@ export function logicalMinimum( * and other input expressions or literal values. * Based on Firestore's value type ordering. * + * @example * ```typescript * // Returns the smallest value between the 'field1' field, the 'field2' field, * // and 1000. * logicalMinimum("field1", field("field2"), 1000); * ``` * - * @param fieldName The first operand field name. - * @param second The second expression or literal. - * @param others Optional additional expressions or literals. - * @return A new {@code Expr} representing the logical minimum operation. + * @param fieldName - The first operand field name. + * @param second - The second expression or literal. + * @param others - Optional additional expressions or literals. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logical minimum operation. */ export function logicalMinimum( fieldName: string, @@ -5254,13 +5473,14 @@ export function logicalMinimum( * * Creates an expression that checks if a field exists. * + * @example * ```typescript * // Check if the document has a field named "phoneNumber" * exists(field("phoneNumber")); * ``` * - * @param value An expression evaluates to the name of the field to check. - * @return A new {@code Expr} representing the 'exists' check. + * @param value - An expression evaluates to the name of the field to check. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'exists' check. */ export function exists(value: Expression): BooleanExpression; @@ -5269,13 +5489,14 @@ export function exists(value: Expression): BooleanExpression; * * Creates an expression that checks if a field exists. * + * @example * ```typescript * // Check if the document has a field named "phoneNumber" * exists("phoneNumber"); * ``` * - * @param fieldName The field name to check. - * @return A new {@code Expr} representing the 'exists' check. + * @param fieldName - The field name to check. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'exists' check. */ export function exists(fieldName: string): BooleanExpression; export function exists(valueOrField: Expression | string): BooleanExpression { @@ -5287,13 +5508,14 @@ export function exists(valueOrField: Expression | string): BooleanExpression { * * Creates an expression that reverses a string. * + * @example * ```typescript * // Reverse the value of the 'myString' field. * reverse(field("myString")); * ``` * - * @param stringExpression An expression evaluating to a string value, which will be reversed. - * @return A new {@code Expr} representing the reversed string. + * @param stringExpression - An expression evaluating to a string value, which will be reversed. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the reversed string. */ export function reverse(stringExpression: Expression): FunctionExpression; @@ -5302,13 +5524,14 @@ export function reverse(stringExpression: Expression): FunctionExpression; * * Creates an expression that reverses a string value in the specified field. * + * @example * ```typescript * // Reverse the value of the 'myString' field. * reverse("myString"); * ``` * - * @param field The name of the field representing the string to reverse. - * @return A new {@code Expr} representing the reversed string. + * @param field - The name of the field representing the string to reverse. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the reversed string. */ export function reverse(field: string): FunctionExpression; export function reverse(expr: Expression | string): FunctionExpression { @@ -5320,13 +5543,14 @@ export function reverse(expr: Expression | string): FunctionExpression { * * Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. * + * @example * ```typescript * // Calculate the length of the 'myString' field in bytes. * byteLength(field("myString")); * ``` * - * @param expr The expression representing the string. - * @return A new {@code Expr} representing the length of the string in bytes. + * @param expr - The expression representing the string. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the length of the string in bytes. */ export function byteLength(expr: Expression): FunctionExpression; @@ -5335,13 +5559,14 @@ export function byteLength(expr: Expression): FunctionExpression; * * Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. * + * @example * ```typescript * // Calculate the length of the 'myString' field in bytes. * byteLength("myString"); * ``` * - * @param fieldName The name of the field containing the string. - * @return A new {@code Expr} representing the length of the string in bytes. + * @param fieldName - The name of the field containing the string. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the length of the string in bytes. */ export function byteLength(fieldName: string): FunctionExpression; export function byteLength(expr: Expression | string): FunctionExpression { @@ -5353,13 +5578,14 @@ export function byteLength(expr: Expression | string): FunctionExpression { * @beta * Creates an expression that reverses an array. * + * @example * ```typescript * // Reverse the value of the 'myArray' field. * arrayReverse("myArray"); * ``` * - * @param fieldName The name of the field to reverse. - * @return A new {@code Expr} representing the reversed array. + * @param fieldName - The name of the field to reverse. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the reversed array. */ export function arrayReverse(fieldName: string): FunctionExpression; @@ -5367,13 +5593,14 @@ export function arrayReverse(fieldName: string): FunctionExpression; * @beta * Creates an expression that reverses an array. * + * @example * ```typescript * // Reverse the value of the 'myArray' field. * arrayReverse(field("myArray")); * ``` * - * @param arrayExpression An expression evaluating to an array value, which will be reversed. - * @return A new {@code Expr} representing the reversed array. + * @param arrayExpression - An expression evaluating to an array value, which will be reversed. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the reversed array. */ export function arrayReverse(arrayExpression: Expression): FunctionExpression; export function arrayReverse(expr: Expression | string): FunctionExpression { @@ -5384,12 +5611,13 @@ export function arrayReverse(expr: Expression | string): FunctionExpression { * @beta * Creates an expression that computes e to the power of the expression's result. * + * @example * ```typescript * // Compute e to the power of 2. * exp(constant(2)); * ``` * - * @return A new {@code Expr} representing the exp of the numeric value. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the exp of the numeric value. */ export function exp(expression: Expression): FunctionExpression; @@ -5397,12 +5625,13 @@ export function exp(expression: Expression): FunctionExpression; * @beta * Creates an expression that computes e to the power of the expression's result. * + * @example * ```typescript * // Compute e to the power of the 'value' field. * exp('value'); * ``` * - * @return A new {@code Expr} representing the exp of the numeric value. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the exp of the numeric value. */ export function exp(fieldName: string): FunctionExpression; @@ -5416,13 +5645,14 @@ export function exp( * @beta * Creates an expression that computes the ceiling of a numeric value. * + * @example * ```typescript * // Compute the ceiling of the 'price' field. * ceil("price"); * ``` * - * @param fieldName The name of the field to compute the ceiling of. - * @return A new {@code Expr} representing the ceiling of the numeric value. + * @param fieldName - The name of the field to compute the ceiling of. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the ceiling of the numeric value. */ export function ceil(fieldName: string): FunctionExpression; @@ -5430,13 +5660,14 @@ export function ceil(fieldName: string): FunctionExpression; * @beta * Creates an expression that computes the ceiling of a numeric value. * + * @example * ```typescript * // Compute the ceiling of the 'price' field. * ceil(field("price")); * ``` * - * @param expression An expression evaluating to a numeric value, which the ceiling will be computed for. - * @return A new {@code Expr} representing the ceiling of the numeric value. + * @param expression - An expression evaluating to a numeric value, which the ceiling will be computed for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the ceiling of the numeric value. */ export function ceil(expression: Expression): FunctionExpression; export function ceil(expr: Expression | string): FunctionExpression { @@ -5447,8 +5678,8 @@ export function ceil(expr: Expression | string): FunctionExpression { * @beta * Creates an expression that computes the floor of a numeric value. * - * @param expr The expression to compute the floor of. - * @return A new {@code Expr} representing the floor of the numeric value. + * @param expr - The expression to compute the floor of. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the floor of the numeric value. */ export function floor(expr: Expression): FunctionExpression; @@ -5456,8 +5687,8 @@ export function floor(expr: Expression): FunctionExpression; * @beta * Creates an expression that computes the floor of a numeric value. * - * @param fieldName The name of the field to compute the floor of. - * @return A new {@code Expr} representing the floor of the numeric value. + * @param fieldName - The name of the field to compute the floor of. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the floor of the numeric value. */ export function floor(fieldName: string): FunctionExpression; export function floor(expr: Expression | string): FunctionExpression { @@ -5468,8 +5699,8 @@ export function floor(expr: Expression | string): FunctionExpression { * @beta * Creates an aggregation that counts the number of distinct values of a field. * - * @param expr The expression or field to count distinct values of. - * @return A new `AggregateFunction` representing the 'count_distinct' aggregation. + * @param expr - The expression or field to count distinct values of. + * @returns A new `AggregateFunction` representing the 'count_distinct' aggregation. */ export function countDistinct(expr: Expression | string): AggregateFunction { return fieldOrExpression(expr).countDistinct(); @@ -5480,13 +5711,14 @@ export function countDistinct(expr: Expression | string): AggregateFunction { * * Creates an expression that calculates the character length of a string field in UTF8. * + * @example * ```typescript * // Get the character length of the 'name' field in UTF-8. * strLength("name"); * ``` * - * @param fieldName The name of the field containing the string. - * @return A new {@code Expr} representing the length of the string. + * @param fieldName - The name of the field containing the string. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the length of the string. */ export function charLength(fieldName: string): FunctionExpression; @@ -5495,13 +5727,14 @@ export function charLength(fieldName: string): FunctionExpression; * * Creates an expression that calculates the character length of a string expression in UTF-8. * + * @example * ```typescript * // Get the character length of the 'name' field in UTF-8. * strLength(field("name")); * ``` * - * @param stringExpression The expression representing the string to calculate the length of. - * @return A new {@code Expr} representing the length of the string. + * @param stringExpression - The expression representing the string to calculate the length of. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the length of the string. */ export function charLength(stringExpression: Expression): FunctionExpression; export function charLength(value: Expression | string): FunctionExpression { @@ -5515,14 +5748,15 @@ export function charLength(value: Expression | string): FunctionExpression { * Creates an expression that performs a case-sensitive wildcard string comparison against a * field. * + * @example * ```typescript * // Check if the 'title' field contains the string "guide" * like("title", "%guide%"); * ``` * - * @param fieldName The name of the field containing the string. - * @param pattern The pattern to search for. You can use "%" as a wildcard character. - * @return A new {@code Expr} representing the 'like' comparison. + * @param fieldName - The name of the field containing the string. + * @param pattern - The pattern to search for. You can use "%" as a wildcard character. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'like' comparison. */ export function like(fieldName: string, pattern: string): BooleanExpression; @@ -5532,14 +5766,15 @@ export function like(fieldName: string, pattern: string): BooleanExpression; * Creates an expression that performs a case-sensitive wildcard string comparison against a * field. * + * @example * ```typescript * // Check if the 'title' field contains the string "guide" * like("title", field("pattern")); * ``` * - * @param fieldName The name of the field containing the string. - * @param pattern The pattern to search for. You can use "%" as a wildcard character. - * @return A new {@code Expr} representing the 'like' comparison. + * @param fieldName - The name of the field containing the string. + * @param pattern - The pattern to search for. You can use "%" as a wildcard character. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'like' comparison. */ export function like(fieldName: string, pattern: Expression): BooleanExpression; @@ -5548,14 +5783,15 @@ export function like(fieldName: string, pattern: Expression): BooleanExpression; * * Creates an expression that performs a case-sensitive wildcard string comparison. * + * @example * ```typescript * // Check if the 'title' field contains the string "guide" * like(field("title"), "%guide%"); * ``` * - * @param stringExpression The expression representing the string to perform the comparison on. - * @param pattern The pattern to search for. You can use "%" as a wildcard character. - * @return A new {@code Expr} representing the 'like' comparison. + * @param stringExpression - The expression representing the string to perform the comparison on. + * @param pattern - The pattern to search for. You can use "%" as a wildcard character. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'like' comparison. */ export function like( stringExpression: Expression, @@ -5567,14 +5803,15 @@ export function like( * * Creates an expression that performs a case-sensitive wildcard string comparison. * + * @example * ```typescript * // Check if the 'title' field contains the string "guide" * like(field("title"), field("pattern")); * ``` * - * @param stringExpression The expression representing the string to perform the comparison on. - * @param pattern The pattern to search for. You can use "%" as a wildcard character. - * @return A new {@code Expr} representing the 'like' comparison. + * @param stringExpression - The expression representing the string to perform the comparison on. + * @param pattern - The pattern to search for. You can use "%" as a wildcard character. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'like' comparison. */ export function like( stringExpression: Expression, @@ -5595,14 +5832,15 @@ export function like( * Creates an expression that checks if a string field contains a specified regular expression as * a substring. * + * @example * ```typescript * // Check if the 'description' field contains "example" (case-insensitive) * regexContains("description", "(?i)example"); * ``` * - * @param fieldName The name of the field containing the string. - * @param pattern The regular expression to use for the search. - * @return A new {@code Expr} representing the 'contains' comparison. + * @param fieldName - The name of the field containing the string. + * @param pattern - The regular expression to use for the search. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'contains' comparison. */ export function regexContains( fieldName: string, @@ -5615,14 +5853,15 @@ export function regexContains( * Creates an expression that checks if a string field contains a specified regular expression as * a substring. * + * @example * ```typescript * // Check if the 'description' field contains "example" (case-insensitive) * regexContains("description", field("pattern")); * ``` * - * @param fieldName The name of the field containing the string. - * @param pattern The regular expression to use for the search. - * @return A new {@code Expr} representing the 'contains' comparison. + * @param fieldName - The name of the field containing the string. + * @param pattern - The regular expression to use for the search. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'contains' comparison. */ export function regexContains( fieldName: string, @@ -5635,14 +5874,15 @@ export function regexContains( * Creates an expression that checks if a string expression contains a specified regular * expression as a substring. * + * @example * ```typescript * // Check if the 'description' field contains "example" (case-insensitive) * regexContains(field("description"), "(?i)example"); * ``` * - * @param stringExpression The expression representing the string to perform the comparison on. - * @param pattern The regular expression to use for the search. - * @return A new {@code Expr} representing the 'contains' comparison. + * @param stringExpression - The expression representing the string to perform the comparison on. + * @param pattern - The regular expression to use for the search. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'contains' comparison. */ export function regexContains( stringExpression: Expression, @@ -5655,14 +5895,15 @@ export function regexContains( * Creates an expression that checks if a string expression contains a specified regular * expression as a substring. * + * @example * ```typescript * // Check if the 'description' field contains "example" (case-insensitive) * regexContains(field("description"), field("pattern")); * ``` * - * @param stringExpression The expression representing the string to perform the comparison on. - * @param pattern The regular expression to use for the search. - * @return A new {@code Expr} representing the 'contains' comparison. + * @param stringExpression - The expression representing the string to perform the comparison on. + * @param pattern - The regular expression to use for the search. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'contains' comparison. */ export function regexContains( stringExpression: Expression, @@ -5682,14 +5923,15 @@ export function regexContains( * * Creates an expression that checks if a string field matches a specified regular expression. * + * @example * ```typescript * // Check if the 'email' field matches a valid email pattern * regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); * ``` * - * @param fieldName The name of the field containing the string. - * @param pattern The regular expression to use for the match. - * @return A new {@code Expr} representing the regular expression match. + * @param fieldName - The name of the field containing the string. + * @param pattern - The regular expression to use for the match. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the regular expression match. */ export function regexMatch( fieldName: string, @@ -5701,14 +5943,15 @@ export function regexMatch( * * Creates an expression that checks if a string field matches a specified regular expression. * + * @example * ```typescript * // Check if the 'email' field matches a valid email pattern * regexMatch("email", field("pattern")); * ``` * - * @param fieldName The name of the field containing the string. - * @param pattern The regular expression to use for the match. - * @return A new {@code Expr} representing the regular expression match. + * @param fieldName - The name of the field containing the string. + * @param pattern - The regular expression to use for the match. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the regular expression match. */ export function regexMatch( fieldName: string, @@ -5721,14 +5964,15 @@ export function regexMatch( * Creates an expression that checks if a string expression matches a specified regular * expression. * + * @example * ```typescript * // Check if the 'email' field matches a valid email pattern * regexMatch(field("email"), "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); * ``` * - * @param stringExpression The expression representing the string to match against. - * @param pattern The regular expression to use for the match. - * @return A new {@code Expr} representing the regular expression match. + * @param stringExpression - The expression representing the string to match against. + * @param pattern - The regular expression to use for the match. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the regular expression match. */ export function regexMatch( stringExpression: Expression, @@ -5741,14 +5985,15 @@ export function regexMatch( * Creates an expression that checks if a string expression matches a specified regular * expression. * + * @example * ```typescript * // Check if the 'email' field matches a valid email pattern * regexMatch(field("email"), field("pattern")); * ``` * - * @param stringExpression The expression representing the string to match against. - * @param pattern The regular expression to use for the match. - * @return A new {@code Expr} representing the regular expression match. + * @param stringExpression - The expression representing the string to match against. + * @param pattern - The regular expression to use for the match. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the regular expression match. */ export function regexMatch( stringExpression: Expression, @@ -5768,14 +6013,15 @@ export function regexMatch( * * Creates an expression that checks if a string field contains a specified substring. * + * @example * ```typescript * // Check if the 'description' field contains "example". * stringContains("description", "example"); * ``` * - * @param fieldName The name of the field containing the string. - * @param substring The substring to search for. - * @return A new {@code Expr} representing the 'contains' comparison. + * @param fieldName - The name of the field containing the string. + * @param substring - The substring to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'contains' comparison. */ export function stringContains( fieldName: string, @@ -5787,14 +6033,15 @@ export function stringContains( * * Creates an expression that checks if a string field contains a substring specified by an expression. * + * @example * ```typescript * // Check if the 'description' field contains the value of the 'keyword' field. * stringContains("description", field("keyword")); * ``` * - * @param fieldName The name of the field containing the string. - * @param substring The expression representing the substring to search for. - * @return A new {@code Expr} representing the 'contains' comparison. + * @param fieldName - The name of the field containing the string. + * @param substring - The expression representing the substring to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'contains' comparison. */ export function stringContains( fieldName: string, @@ -5806,14 +6053,15 @@ export function stringContains( * * Creates an expression that checks if a string expression contains a specified substring. * + * @example * ```typescript * // Check if the 'description' field contains "example". * stringContains(field("description"), "example"); * ``` * - * @param stringExpression The expression representing the string to perform the comparison on. - * @param substring The substring to search for. - * @return A new {@code Expr} representing the 'contains' comparison. + * @param stringExpression - The expression representing the string to perform the comparison on. + * @param substring - The substring to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'contains' comparison. */ export function stringContains( stringExpression: Expression, @@ -5825,14 +6073,15 @@ export function stringContains( * * Creates an expression that checks if a string expression contains a substring specified by another expression. * + * @example * ```typescript * // Check if the 'description' field contains the value of the 'keyword' field. * stringContains(field("description"), field("keyword")); * ``` * - * @param stringExpression The expression representing the string to perform the comparison on. - * @param substring The expression representing the substring to search for. - * @return A new {@code Expr} representing the 'contains' comparison. + * @param stringExpression - The expression representing the string to perform the comparison on. + * @param substring - The expression representing the substring to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'contains' comparison. */ export function stringContains( stringExpression: Expression, @@ -5852,14 +6101,15 @@ export function stringContains( * * Creates an expression that checks if a field's value starts with a given prefix. * + * @example * ```typescript * // Check if the 'name' field starts with "Mr." * startsWith("name", "Mr."); * ``` * - * @param fieldName The field name to check. - * @param prefix The prefix to check for. - * @return A new {@code Expr} representing the 'starts with' comparison. + * @param fieldName - The field name to check. + * @param prefix - The prefix to check for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'starts with' comparison. */ export function startsWith( fieldName: string, @@ -5871,14 +6121,15 @@ export function startsWith( * * Creates an expression that checks if a field's value starts with a given prefix. * + * @example * ```typescript * // Check if the 'fullName' field starts with the value of the 'firstName' field * startsWith("fullName", field("firstName")); * ``` * - * @param fieldName The field name to check. - * @param prefix The expression representing the prefix. - * @return A new {@code Expr} representing the 'starts with' comparison. + * @param fieldName - The field name to check. + * @param prefix - The expression representing the prefix. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'starts with' comparison. */ export function startsWith( fieldName: string, @@ -5890,14 +6141,15 @@ export function startsWith( * * Creates an expression that checks if a string expression starts with a given prefix. * + * @example * ```typescript * // Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." * startsWith(field("fullName"), "Mr."); * ``` * - * @param stringExpression The expression to check. - * @param prefix The prefix to check for. - * @return A new {@code Expr} representing the 'starts with' comparison. + * @param stringExpression - The expression to check. + * @param prefix - The prefix to check for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'starts with' comparison. */ export function startsWith( stringExpression: Expression, @@ -5909,14 +6161,15 @@ export function startsWith( * * Creates an expression that checks if a string expression starts with a given prefix. * + * @example * ```typescript * // Check if the result of concatenating 'firstName' and 'lastName' fields starts with "Mr." * startsWith(field("fullName"), field("prefix")); * ``` * - * @param stringExpression The expression to check. - * @param prefix The prefix to check for. - * @return A new {@code Expr} representing the 'starts with' comparison. + * @param stringExpression - The expression to check. + * @param prefix - The prefix to check for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'starts with' comparison. */ export function startsWith( stringExpression: Expression, @@ -5934,14 +6187,15 @@ export function startsWith( * * Creates an expression that checks if a field's value ends with a given postfix. * + * @example * ```typescript * // Check if the 'filename' field ends with ".txt" * endsWith("filename", ".txt"); * ``` * - * @param fieldName The field name to check. - * @param suffix The postfix to check for. - * @return A new {@code Expr} representing the 'ends with' comparison. + * @param fieldName - The field name to check. + * @param suffix - The postfix to check for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ends with' comparison. */ export function endsWith(fieldName: string, suffix: string): BooleanExpression; @@ -5950,14 +6204,15 @@ export function endsWith(fieldName: string, suffix: string): BooleanExpression; * * Creates an expression that checks if a field's value ends with a given postfix. * + * @example * ```typescript * // Check if the 'url' field ends with the value of the 'extension' field * endsWith("url", field("extension")); * ``` * - * @param fieldName The field name to check. - * @param suffix The expression representing the postfix. - * @return A new {@code Expr} representing the 'ends with' comparison. + * @param fieldName - The field name to check. + * @param suffix - The expression representing the postfix. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ends with' comparison. */ export function endsWith( fieldName: string, @@ -5969,14 +6224,15 @@ export function endsWith( * * Creates an expression that checks if a string expression ends with a given postfix. * + * @example * ```typescript * // Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." * endsWith(field("fullName"), "Jr."); * ``` * - * @param stringExpression The expression to check. - * @param suffix The postfix to check for. - * @return A new {@code Expr} representing the 'ends with' comparison. + * @param stringExpression - The expression to check. + * @param suffix - The postfix to check for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ends with' comparison. */ export function endsWith( stringExpression: Expression, @@ -5988,14 +6244,15 @@ export function endsWith( * * Creates an expression that checks if a string expression ends with a given postfix. * + * @example * ```typescript * // Check if the result of concatenating 'firstName' and 'lastName' fields ends with "Jr." * endsWith(field("fullName"), constant("Jr.")); * ``` * - * @param stringExpression The expression to check. - * @param suffix The postfix to check for. - * @return A new {@code Expr} representing the 'ends with' comparison. + * @param stringExpression - The expression to check. + * @param suffix - The postfix to check for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'ends with' comparison. */ export function endsWith( stringExpression: Expression, @@ -6013,13 +6270,14 @@ export function endsWith( * * Creates an expression that converts a string field to lowercase. * + * @example * ```typescript * // Convert the 'name' field to lowercase * toLower("name"); * ``` * - * @param fieldName The name of the field containing the string. - * @return A new {@code Expr} representing the lowercase string. + * @param fieldName - The name of the field containing the string. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the lowercase string. */ export function toLower(fieldName: string): FunctionExpression; @@ -6028,13 +6286,14 @@ export function toLower(fieldName: string): FunctionExpression; * * Creates an expression that converts a string expression to lowercase. * + * @example * ```typescript * // Convert the 'name' field to lowercase * toLower(field("name")); * ``` * - * @param stringExpression The expression representing the string to convert to lowercase. - * @return A new {@code Expr} representing the lowercase string. + * @param stringExpression - The expression representing the string to convert to lowercase. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the lowercase string. */ export function toLower(stringExpression: Expression): FunctionExpression; export function toLower(expr: Expression | string): FunctionExpression { @@ -6046,13 +6305,14 @@ export function toLower(expr: Expression | string): FunctionExpression { * * Creates an expression that converts a string field to uppercase. * + * @example * ```typescript * // Convert the 'title' field to uppercase * toUpper("title"); * ``` * - * @param fieldName The name of the field containing the string. - * @return A new {@code Expr} representing the uppercase string. + * @param fieldName - The name of the field containing the string. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the uppercase string. */ export function toUpper(fieldName: string): FunctionExpression; @@ -6061,13 +6321,14 @@ export function toUpper(fieldName: string): FunctionExpression; * * Creates an expression that converts a string expression to uppercase. * + * @example * ```typescript * // Convert the 'title' field to uppercase * toUppercase(field("title")); * ``` * - * @param stringExpression The expression representing the string to convert to uppercase. - * @return A new {@code Expr} representing the uppercase string. + * @param stringExpression - The expression representing the string to convert to uppercase. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the uppercase string. */ export function toUpper(stringExpression: Expression): FunctionExpression; export function toUpper(expr: Expression | string): FunctionExpression { @@ -6079,6 +6340,7 @@ export function toUpper(expr: Expression | string): FunctionExpression { * * Creates an expression that removes leading and trailing whitespace from a string or byte array. * + * @example * ```typescript * // Trim whitespace from the 'userInput' field * trim("userInput"); @@ -6087,10 +6349,10 @@ export function toUpper(expr: Expression | string): FunctionExpression { * trim("userInput", '"'); * ``` * - * @param fieldName The name of the field containing the string or byte array. - * @param valueToTrim Optional This parameter is treated as a set of characters or bytes that will be + * @param fieldName - The name of the field containing the string or byte array. + * @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. - * @return A new {@code Expr} representing the trimmed string. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the trimmed string. */ export function trim( fieldName: string, @@ -6102,6 +6364,7 @@ export function trim( * * Creates an expression that removes leading and trailing characters from a string or byte array expression. * + * @example * ```typescript * // Trim whitespace from the 'userInput' field * trim(field("userInput")); @@ -6110,10 +6373,10 @@ export function trim( * trim(field("userInput"), '"'); * ``` * - * @param stringExpression The expression representing the string or byte array to trim. - * @param valueToTrim Optional This parameter is treated as a set of characters or bytes that will be + * @param stringExpression - The expression representing the string or byte array to 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. - * @return A new {@code Expr} representing the trimmed string or byte array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the trimmed string or byte array. */ export function trim( stringExpression: Expression, @@ -6131,15 +6394,16 @@ export function trim( * * Creates an expression that concatenates string functions, fields or constants together. * + * @example * ```typescript * // Combine the 'firstName', " ", and 'lastName' fields into a single string * stringConcat("firstName", " ", field("lastName")); * ``` * - * @param fieldName The field name containing the initial string value. - * @param secondString An expression or string literal to concatenate. - * @param otherStrings Optional additional expressions or literals (typically strings) to concatenate. - * @return A new {@code Expr} representing the concatenated string. + * @param fieldName - The field name containing the initial string value. + * @param secondString - An expression or string literal to concatenate. + * @param otherStrings - Optional additional expressions or literals (typically strings) to concatenate. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the concatenated string. */ export function stringConcat( fieldName: string, @@ -6151,15 +6415,16 @@ export function stringConcat( * @beta * Creates an expression that concatenates string expressions together. * + * @example * ```typescript * // Combine the 'firstName', " ", and 'lastName' fields into a single string * stringConcat(field("firstName"), " ", field("lastName")); * ``` * - * @param firstString The initial string expression to concatenate to. - * @param secondString An expression or string literal to concatenate. - * @param otherStrings Optional additional expressions or literals (typically strings) to concatenate. - * @return A new {@code Expr} representing the concatenated string. + * @param firstString - The initial string expression to concatenate to. + * @param secondString - An expression or string literal to concatenate. + * @param otherStrings - Optional additional expressions or literals (typically strings) to concatenate. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the concatenated string. */ export function stringConcat( firstString: Expression, @@ -6182,14 +6447,15 @@ export function stringConcat( * * Accesses a value from a map (object) field using the provided key. * + * @example * ```typescript * // Get the 'city' value from the 'address' map field * mapGet("address", "city"); * ``` * - * @param fieldName The field name of the map field. - * @param subField The key to access in the map. - * @return A new {@code Expr} representing the value associated with the given key in the map. + * @param fieldName - The field name of the map field. + * @param subField - The key to access in the map. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the value associated with the given key in the map. */ export function mapGet(fieldName: string, subField: string): FunctionExpression; @@ -6198,14 +6464,15 @@ export function mapGet(fieldName: string, subField: string): FunctionExpression; * * Accesses a value from a map (object) expression using the provided key. * + * @example * ```typescript * // Get the 'city' value from the 'address' map field * mapGet(field("address"), "city"); * ``` * - * @param mapExpression The expression representing the map. - * @param subField The key to access in the map. - * @return A new {@code Expr} representing the value associated with the given key in the map. + * @param mapExpression - The expression representing the map. + * @param subField - The key to access in the map. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the value associated with the given key in the map. */ export function mapGet( mapExpression: Expression, @@ -6223,12 +6490,13 @@ export function mapGet( * * Creates an aggregation that counts the total number of stage inputs. * + * @example * ```typescript * // Count the total number of input documents * countAll().as("totalDocument"); * ``` * - * @return A new {@code AggregateFunction} representing the 'countAll' aggregation. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'countAll' aggregation. */ export function countAll(): AggregateFunction { return AggregateFunction._create('count', [], 'count'); @@ -6240,13 +6508,14 @@ export function countAll(): AggregateFunction { * Creates an aggregation that counts the number of stage inputs with valid evaluations of the * provided expression. * + * @example * ```typescript * // Count the number of items where the price is greater than 10 * count(field("price").greaterThan(10)).as("expensiveItemCount"); * ``` * - * @param expression The expression to count. - * @return A new {@code AggregateFunction} representing the 'count' aggregation. + * @param expression - The expression to count. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'count' aggregation. */ export function count(expression: Expression): AggregateFunction; @@ -6254,13 +6523,14 @@ export function count(expression: Expression): AggregateFunction; * @beta * Creates an aggregation that counts the number of stage inputs where the input field exists. * + * @example * ```typescript * // Count the total number of products * count("productId").as("totalProducts"); * ``` * - * @param fieldName The name of the field to count. - * @return A new {@code AggregateFunction} representing the 'count' aggregation. + * @param fieldName - The name of the field to count. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'count' aggregation. */ export function count(fieldName: string): AggregateFunction; export function count(value: Expression | string): AggregateFunction { @@ -6273,13 +6543,14 @@ export function count(value: Expression | string): AggregateFunction { * Creates an aggregation that calculates the sum of values from an expression across multiple * stage inputs. * + * @example * ```typescript * // Calculate the total revenue from a set of orders * sum(field("orderAmount")).as("totalRevenue"); * ``` * - * @param expression The expression to sum up. - * @return A new {@code AggregateFunction} representing the 'sum' aggregation. + * @param expression - The expression to sum up. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'sum' aggregation. */ export function sum(expression: Expression): AggregateFunction; @@ -6289,13 +6560,14 @@ export function sum(expression: Expression): AggregateFunction; * Creates an aggregation that calculates the sum of a field's values across multiple stage * inputs. * + * @example * ```typescript * // Calculate the total revenue from a set of orders * sum("orderAmount").as("totalRevenue"); * ``` * - * @param fieldName The name of the field containing numeric values to sum up. - * @return A new {@code AggregateFunction} representing the 'sum' aggregation. + * @param fieldName - The name of the field containing numeric values to sum up. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'sum' aggregation. */ export function sum(fieldName: string): AggregateFunction; export function sum(value: Expression | string): AggregateFunction { @@ -6308,13 +6580,14 @@ export function sum(value: Expression | string): AggregateFunction { * Creates an aggregation that calculates the average (mean) of values from an expression across * multiple stage inputs. * + * @example * ```typescript * // Calculate the average age of users * average(field("age")).as("averageAge"); * ``` * - * @param expression The expression representing the values to average. - * @return A new {@code AggregateFunction} representing the 'average' aggregation. + * @param expression - The expression representing the values to average. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'average' aggregation. */ export function average(expression: Expression): AggregateFunction; @@ -6324,13 +6597,14 @@ export function average(expression: Expression): AggregateFunction; * Creates an aggregation that calculates the average (mean) of a field's values across multiple * stage inputs. * + * @example * ```typescript * // Calculate the average age of users * average("age").as("averageAge"); * ``` * - * @param fieldName The name of the field containing numeric values to average. - * @return A new {@code AggregateFunction} representing the 'average' aggregation. + * @param fieldName - The name of the field containing numeric values to average. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'average' aggregation. */ export function average(fieldName: string): AggregateFunction; export function average(value: Expression | string): AggregateFunction { @@ -6343,13 +6617,14 @@ export function average(value: Expression | string): AggregateFunction { * Creates an aggregation that finds the minimum value of an expression across multiple stage * inputs. * + * @example * ```typescript * // Find the lowest price of all products * minimum(field("price")).as("lowestPrice"); * ``` * - * @param expression The expression to find the minimum value of. - * @return A new {@code AggregateFunction} representing the 'minimum' aggregation. + * @param expression - The expression to find the minimum value of. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'minimum' aggregation. */ export function minimum(expression: Expression): AggregateFunction; @@ -6358,13 +6633,14 @@ export function minimum(expression: Expression): AggregateFunction; * * Creates an aggregation that finds the minimum value of a field across multiple stage inputs. * + * @example * ```typescript * // Find the lowest price of all products * minimum("price").as("lowestPrice"); * ``` * - * @param fieldName The name of the field to find the minimum value of. - * @return A new {@code AggregateFunction} representing the 'minimum' aggregation. + * @param fieldName - The name of the field to find the minimum value of. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'minimum' aggregation. */ export function minimum(fieldName: string): AggregateFunction; export function minimum(value: Expression | string): AggregateFunction { @@ -6377,13 +6653,14 @@ export function minimum(value: Expression | string): AggregateFunction { * Creates an aggregation that finds the maximum value of an expression across multiple stage * inputs. * + * @example * ```typescript * // Find the highest score in a leaderboard * maximum(field("score")).as("highestScore"); * ``` * - * @param expression The expression to find the maximum value of. - * @return A new {@code AggregateFunction} representing the 'maximum' aggregation. + * @param expression - The expression to find the maximum value of. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'maximum' aggregation. */ export function maximum(expression: Expression): AggregateFunction; @@ -6392,13 +6669,14 @@ export function maximum(expression: Expression): AggregateFunction; * * Creates an aggregation that finds the maximum value of a field across multiple stage inputs. * + * @example * ```typescript * // Find the highest score in a leaderboard * maximum("score").as("highestScore"); * ``` * - * @param fieldName The name of the field to find the maximum value of. - * @return A new {@code AggregateFunction} representing the 'maximum' aggregation. + * @param fieldName - The name of the field to find the maximum value of. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'maximum' aggregation. */ export function maximum(fieldName: string): AggregateFunction; export function maximum(value: Expression | string): AggregateFunction { @@ -6410,14 +6688,15 @@ export function maximum(value: Expression | string): AggregateFunction { * * Calculates the Cosine distance between a field's vector value and a literal vector value. * + * @example * ```typescript * // Calculate the Cosine distance between the 'location' field and a target location * cosineDistance("location", [37.7749, -122.4194]); * ``` * - * @param fieldName The name of the field containing the first vector. - * @param vector The other vector (as an array of doubles) or {@link VectorValue} to compare against. - * @return A new {@code Expr} representing the Cosine distance between the two vectors. + * @param fieldName - The name of the field containing the first vector. + * @param vector - The other vector (as an array of doubles) or {@link VectorValue} to compare against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the Cosine distance between the two vectors. */ export function cosineDistance( fieldName: string, @@ -6429,14 +6708,15 @@ export function cosineDistance( * * Calculates the Cosine distance between a field's vector value and a vector expression. * + * @example * ```typescript * // Calculate the cosine distance between the 'userVector' field and the 'itemVector' field * cosineDistance("userVector", field("itemVector")); * ``` * - * @param fieldName The name of the field containing the first vector. - * @param vectorExpression The other vector (represented as an Expr) to compare against. - * @return A new {@code Expr} representing the cosine distance between the two vectors. + * @param fieldName - The name of the field containing the first vector. + * @param vectorExpression - The other vector (represented as an `Expression`) to compare against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the cosine distance between the two vectors. */ export function cosineDistance( fieldName: string, @@ -6448,14 +6728,15 @@ export function cosineDistance( * * Calculates the Cosine distance between a vector expression and a vector literal. * + * @example * ```typescript * // Calculate the cosine distance between the 'location' field and a target location * cosineDistance(field("location"), [37.7749, -122.4194]); * ``` * - * @param vectorExpression The first vector (represented as an Expr) to compare against. - * @param vector The other vector (as an array of doubles or VectorValue) to compare against. - * @return A new {@code Expr} representing the cosine distance between the two vectors. + * @param vectorExpression - The first vector (represented as an `Expression`) to compare against. + * @param vector - The other vector (as an array of doubles or VectorValue) to compare against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the cosine distance between the two vectors. */ export function cosineDistance( vectorExpression: Expression, @@ -6467,14 +6748,15 @@ export function cosineDistance( * * Calculates the Cosine distance between two vector expressions. * + * @example * ```typescript * // Calculate the cosine distance between the 'userVector' field and the 'itemVector' field * cosineDistance(field("userVector"), field("itemVector")); * ``` * - * @param vectorExpression The first vector (represented as an Expr) to compare against. - * @param otherVectorExpression The other vector (represented as an Expr) to compare against. - * @return A new {@code Expr} representing the cosine distance between the two vectors. + * @param vectorExpression - The first vector (represented as an `Expression`) to compare against. + * @param otherVectorExpression - The other vector (represented as an `Expression`) to compare against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the cosine distance between the two vectors. */ export function cosineDistance( vectorExpression: Expression, @@ -6494,14 +6776,15 @@ export function cosineDistance( * * Calculates the dot product between a field's vector value and a double array. * + * @example * ```typescript * // Calculate the dot product distance between a feature vector and a target vector * dotProduct("features", [0.5, 0.8, 0.2]); * ``` * - * @param fieldName The name of the field containing the first vector. - * @param vector The other vector (as an array of doubles or VectorValue) to calculate with. - * @return A new {@code Expr} representing the dot product between the two vectors. + * @param fieldName - The name of the field containing the first vector. + * @param vector - The other vector (as an array of doubles or VectorValue) to calculate with. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the dot product between the two vectors. */ export function dotProduct( fieldName: string, @@ -6513,14 +6796,15 @@ export function dotProduct( * * Calculates the dot product between a field's vector value and a vector expression. * + * @example * ```typescript * // Calculate the dot product distance between two document vectors: 'docVector1' and 'docVector2' * dotProduct("docVector1", field("docVector2")); * ``` * - * @param fieldName The name of the field containing the first vector. - * @param vectorExpression The other vector (represented as an Expr) to calculate with. - * @return A new {@code Expr} representing the dot product between the two vectors. + * @param fieldName - The name of the field containing the first vector. + * @param vectorExpression - The other vector (represented as an `Expression`) to calculate with. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the dot product between the two vectors. */ export function dotProduct( fieldName: string, @@ -6532,14 +6816,15 @@ export function dotProduct( * * Calculates the dot product between a vector expression and a double array. * + * @example * ```typescript * // Calculate the dot product between a feature vector and a target vector * dotProduct(field("features"), [0.5, 0.8, 0.2]); * ``` * - * @param vectorExpression The first vector (represented as an Expr) to calculate with. - * @param vector The other vector (as an array of doubles or VectorValue) to calculate with. - * @return A new {@code Expr} representing the dot product between the two vectors. + * @param vectorExpression - The first vector (represented as an `Expression`) to calculate with. + * @param vector - The other vector (as an array of doubles or VectorValue) to calculate with. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the dot product between the two vectors. */ export function dotProduct( vectorExpression: Expression, @@ -6551,14 +6836,15 @@ export function dotProduct( * * Calculates the dot product between two vector expressions. * + * @example * ```typescript * // Calculate the dot product between two document vectors: 'docVector1' and 'docVector2' * dotProduct(field("docVector1"), field("docVector2")); * ``` * - * @param vectorExpression The first vector (represented as an Expr) to calculate with. - * @param otherVectorExpression The other vector (represented as an Expr) to calculate with. - * @return A new {@code Expr} representing the dot product between the two vectors. + * @param vectorExpression - The first vector (represented as an `Expression`) to calculate with. + * @param otherVectorExpression - The other vector (represented as an `Expression`) to calculate with. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the dot product between the two vectors. */ export function dotProduct( vectorExpression: Expression, @@ -6578,14 +6864,15 @@ export function dotProduct( * * Calculates the Euclidean distance between a field's vector value and a double array. * + * @example * ```typescript * // Calculate the Euclidean distance between the 'location' field and a target location * euclideanDistance("location", [37.7749, -122.4194]); * ``` * - * @param fieldName The name of the field containing the first vector. - * @param vector The other vector (as an array of doubles or VectorValue) to compare against. - * @return A new {@code Expr} representing the Euclidean distance between the two vectors. + * @param fieldName - The name of the field containing the first vector. + * @param vector - The other vector (as an array of doubles or VectorValue) to compare against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the Euclidean distance between the two vectors. */ export function euclideanDistance( fieldName: string, @@ -6597,14 +6884,15 @@ export function euclideanDistance( * * Calculates the Euclidean distance between a field's vector value and a vector expression. * + * @example * ```typescript * // Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' * euclideanDistance("pointA", field("pointB")); * ``` * - * @param fieldName The name of the field containing the first vector. - * @param vectorExpression The other vector (represented as an Expr) to compare against. - * @return A new {@code Expr} representing the Euclidean distance between the two vectors. + * @param fieldName - The name of the field containing the first vector. + * @param vectorExpression - The other vector (represented as an `Expression`) to compare against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the Euclidean distance between the two vectors. */ export function euclideanDistance( fieldName: string, @@ -6616,15 +6904,16 @@ export function euclideanDistance( * * Calculates the Euclidean distance between a vector expression and a double array. * + * @example * ```typescript * // Calculate the Euclidean distance between the 'location' field and a target location * * euclideanDistance(field("location"), [37.7749, -122.4194]); * ``` * - * @param vectorExpression The first vector (represented as an Expr) to compare against. - * @param vector The other vector (as an array of doubles or VectorValue) to compare against. - * @return A new {@code Expr} representing the Euclidean distance between the two vectors. + * @param vectorExpression - The first vector (represented as an `Expression`) to compare against. + * @param vector - The other vector (as an array of doubles or VectorValue) to compare against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the Euclidean distance between the two vectors. */ export function euclideanDistance( vectorExpression: Expression, @@ -6636,14 +6925,15 @@ export function euclideanDistance( * * Calculates the Euclidean distance between two vector expressions. * + * @example * ```typescript * // Calculate the Euclidean distance between two vector fields: 'pointA' and 'pointB' * euclideanDistance(field("pointA"), field("pointB")); * ``` * - * @param vectorExpression The first vector (represented as an Expr) to compare against. - * @param otherVectorExpression The other vector (represented as an Expr) to compare against. - * @return A new {@code Expr} representing the Euclidean distance between the two vectors. + * @param vectorExpression - The first vector (represented as an `Expression`) to compare against. + * @param otherVectorExpression - The other vector (represented as an `Expression`) to compare against. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the Euclidean distance between the two vectors. */ export function euclideanDistance( vectorExpression: Expression, @@ -6663,13 +6953,14 @@ export function euclideanDistance( * * Creates an expression that calculates the length of a Firestore Vector. * + * @example * ```typescript * // Get the vector length (dimension) of the field 'embedding'. * vectorLength(field("embedding")); * ``` * - * @param vectorExpression The expression representing the Firestore Vector. - * @return A new {@code Expr} representing the length of the array. + * @param vectorExpression - The expression representing the Firestore Vector. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the length of the array. */ export function vectorLength(vectorExpression: Expression): FunctionExpression; @@ -6678,13 +6969,14 @@ export function vectorLength(vectorExpression: Expression): FunctionExpression; * * Creates an expression that calculates the length of a Firestore Vector represented by a field. * + * @example * ```typescript * // Get the vector length (dimension) of the field 'embedding'. * vectorLength("embedding"); * ``` * - * @param fieldName The name of the field representing the Firestore Vector. - * @return A new {@code Expr} representing the length of the array. + * @param fieldName - The name of the field representing the Firestore Vector. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the length of the array. */ export function vectorLength(fieldName: string): FunctionExpression; export function vectorLength(expr: Expression | string): FunctionExpression { @@ -6697,13 +6989,14 @@ export function vectorLength(expr: Expression | string): FunctionExpression { * Creates an expression that interprets an 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. * unixMicrosToTimestamp(field("microseconds")); * ``` * - * @param expr The expression representing the number of microseconds since epoch. - * @return A new {@code Expr} representing the timestamp. + * @param expr - The expression representing the number of microseconds since epoch. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the timestamp. */ export function unixMicrosToTimestamp(expr: Expression): FunctionExpression; @@ -6713,13 +7006,14 @@ export function unixMicrosToTimestamp(expr: Expression): FunctionExpression; * Creates an expression that interprets a field's value 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. * unixMicrosToTimestamp("microseconds"); * ``` * - * @param fieldName The name of the field representing the number of microseconds since epoch. - * @return A new {@code Expr} representing the timestamp. + * @param fieldName - The name of the field representing the number of microseconds since epoch. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the timestamp. */ export function unixMicrosToTimestamp(fieldName: string): FunctionExpression; export function unixMicrosToTimestamp( @@ -6733,13 +7027,14 @@ export function unixMicrosToTimestamp( * * Creates an expression that converts a 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. * timestampToUnixMicros(field("timestamp")); * ``` * - * @param expr The expression representing the timestamp. - * @return A new {@code Expr} representing the number of microseconds since epoch. + * @param expr - The expression representing the timestamp. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the number of microseconds since epoch. */ export function timestampToUnixMicros(expr: Expression): FunctionExpression; @@ -6748,13 +7043,14 @@ export function timestampToUnixMicros(expr: Expression): FunctionExpression; * * Creates an expression that converts a timestamp field 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. * timestampToUnixMicros("timestamp"); * ``` * - * @param fieldName The name of the field representing the timestamp. - * @return A new {@code Expr} representing the number of microseconds since epoch. + * @param fieldName - The name of the field representing the timestamp. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the number of microseconds since epoch. */ export function timestampToUnixMicros(fieldName: string): FunctionExpression; export function timestampToUnixMicros( @@ -6769,13 +7065,14 @@ export function timestampToUnixMicros( * Creates an expression that interprets an 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. * unixMillisToTimestamp(field("milliseconds")); * ``` * - * @param expr The expression representing the number of milliseconds since epoch. - * @return A new {@code Expr} representing the timestamp. + * @param expr - The expression representing the number of milliseconds since epoch. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the timestamp. */ export function unixMillisToTimestamp(expr: Expression): FunctionExpression; @@ -6785,13 +7082,14 @@ export function unixMillisToTimestamp(expr: Expression): FunctionExpression; * Creates an expression that interprets a field's value 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. * unixMillisToTimestamp("milliseconds"); * ``` * - * @param fieldName The name of the field representing the number of milliseconds since epoch. - * @return A new {@code Expr} representing the timestamp. + * @param fieldName - The name of the field representing the number of milliseconds since epoch. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the timestamp. */ export function unixMillisToTimestamp(fieldName: string): FunctionExpression; export function unixMillisToTimestamp( @@ -6806,13 +7104,14 @@ export function unixMillisToTimestamp( * * Creates an expression that converts a 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. * timestampToUnixMillis(field("timestamp")); * ``` * - * @param expr The expression representing the timestamp. - * @return A new {@code Expr} representing the number of milliseconds since epoch. + * @param expr - The expression representing the timestamp. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the number of milliseconds since epoch. */ export function timestampToUnixMillis(expr: Expression): FunctionExpression; @@ -6821,13 +7120,14 @@ export function timestampToUnixMillis(expr: Expression): FunctionExpression; * * Creates an expression that converts a timestamp field 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. * timestampToUnixMillis("timestamp"); * ``` * - * @param fieldName The name of the field representing the timestamp. - * @return A new {@code Expr} representing the number of milliseconds since epoch. + * @param fieldName - The name of the field representing the timestamp. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the number of milliseconds since epoch. */ export function timestampToUnixMillis(fieldName: string): FunctionExpression; export function timestampToUnixMillis( @@ -6843,13 +7143,14 @@ export function timestampToUnixMillis( * Creates an expression that interprets an 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. * unixSecondsToTimestamp(field("seconds")); * ``` * - * @param expr The expression representing the number of seconds since epoch. - * @return A new {@code Expr} representing the timestamp. + * @param expr - The expression representing the number of seconds since epoch. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the timestamp. */ export function unixSecondsToTimestamp(expr: Expression): FunctionExpression; @@ -6859,13 +7160,14 @@ export function unixSecondsToTimestamp(expr: Expression): FunctionExpression; * Creates an expression that interprets a field's value 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. * unixSecondsToTimestamp("seconds"); * ``` * - * @param fieldName The name of the field representing the number of seconds since epoch. - * @return A new {@code Expr} representing the timestamp. + * @param fieldName - The name of the field representing the number of seconds since epoch. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the timestamp. */ export function unixSecondsToTimestamp(fieldName: string): FunctionExpression; export function unixSecondsToTimestamp( @@ -6880,13 +7182,14 @@ export function unixSecondsToTimestamp( * * Creates an expression that converts a 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. * timestampToUnixSeconds(field("timestamp")); * ``` * - * @param expr The expression representing the timestamp. - * @return A new {@code Expr} representing the number of seconds since epoch. + * @param expr - The expression representing the timestamp. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the number of seconds since epoch. */ export function timestampToUnixSeconds(expr: Expression): FunctionExpression; @@ -6895,13 +7198,14 @@ export function timestampToUnixSeconds(expr: Expression): FunctionExpression; * * Creates an expression that converts a timestamp field 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. * timestampToUnixSeconds("timestamp"); * ``` * - * @param fieldName The name of the field representing the timestamp. - * @return A new {@code Expr} representing the number of seconds since epoch. + * @param fieldName - The name of the field representing the timestamp. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the number of seconds since epoch. */ export function timestampToUnixSeconds(fieldName: string): FunctionExpression; export function timestampToUnixSeconds( @@ -6916,15 +7220,16 @@ export function timestampToUnixSeconds( * * Creates an expression that adds a specified amount of time to a timestamp. * + * @example * ```typescript * // Add some duration determined by field 'unit' and 'amount' to the 'timestamp' field. * timestampAdd(field("timestamp"), field("unit"), field("amount")); * ``` * - * @param timestamp The expression representing the timestamp. - * @param unit The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. - * @param amount The expression evaluates to amount of the unit. - * @return A new {@code Expr} representing the resulting timestamp. + * @param timestamp - The expression representing the timestamp. + * @param unit - The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. + * @param amount - The expression evaluates to amount of the unit. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the resulting timestamp. */ export function timestampAdd( timestamp: Expression, @@ -6937,15 +7242,16 @@ export function timestampAdd( * * Creates an expression that adds a specified amount of time to a timestamp. * + * @example * ```typescript * // Add 1 day to the 'timestamp' field. * timestampAdd(field("timestamp"), "day", 1); * ``` * - * @param timestamp The expression representing the timestamp. - * @param unit The unit of time to add (e.g., "day", "hour"). - * @param amount The amount of time to add. - * @return A new {@code Expr} representing the resulting timestamp. + * @param timestamp - The expression representing the timestamp. + * @param unit - The unit of time to add (e.g., "day", "hour"). + * @param amount - The amount of time to add. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the resulting timestamp. */ export function timestampAdd( timestamp: Expression, @@ -6958,15 +7264,16 @@ export function timestampAdd( * * Creates an expression that adds a specified amount of time to a timestamp represented by a field. * + * @example * ```typescript * // Add 1 day to the 'timestamp' field. * timestampAdd("timestamp", "day", 1); * ``` * - * @param fieldName The name of the field representing the timestamp. - * @param unit The unit of time to add (e.g., "day", "hour"). - * @param amount The amount of time to add. - * @return A new {@code Expr} representing the resulting timestamp. + * @param fieldName - The name of the field representing the timestamp. + * @param unit - The unit of time to add (e.g., "day", "hour"). + * @param amount - The amount of time to add. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the resulting timestamp. */ export function timestampAdd( fieldName: string, @@ -6996,15 +7303,16 @@ export function timestampAdd( * * Creates an expression that subtracts a specified amount of time from a timestamp. * + * @example * ```typescript * // Subtract some duration determined by field 'unit' and 'amount' from the 'timestamp' field. * timestampSubtract(field("timestamp"), field("unit"), field("amount")); * ``` * - * @param timestamp The expression representing the timestamp. - * @param unit The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. - * @param amount The expression evaluates to amount of the unit. - * @return A new {@code Expr} representing the resulting timestamp. + * @param timestamp - The expression representing the timestamp. + * @param unit - The expression evaluates to unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. + * @param amount - The expression evaluates to amount of the unit. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the resulting timestamp. */ export function timestampSubtract( timestamp: Expression, @@ -7017,15 +7325,16 @@ export function timestampSubtract( * * Creates an expression that subtracts a specified amount of time from a timestamp. * + * @example * ```typescript * // Subtract 1 day from the 'timestamp' field. * timestampSubtract(field("timestamp"), "day", 1); * ``` * - * @param timestamp The expression representing the timestamp. - * @param unit The unit of time to subtract (e.g., "day", "hour"). - * @param amount The amount of time to subtract. - * @return A new {@code Expr} representing the resulting timestamp. + * @param timestamp - The expression representing the timestamp. + * @param unit - The unit of time to subtract (e.g., "day", "hour"). + * @param amount - The amount of time to subtract. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the resulting timestamp. */ export function timestampSubtract( timestamp: Expression, @@ -7038,15 +7347,16 @@ export function timestampSubtract( * * Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. * + * @example * ```typescript * // Subtract 1 day from the 'timestamp' field. * timestampSubtract("timestamp", "day", 1); * ``` * - * @param fieldName The name of the field representing the timestamp. - * @param unit The unit of time to subtract (e.g., "day", "hour"). - * @param amount The amount of time to subtract. - * @return A new {@code Expr} representing the resulting timestamp. + * @param fieldName - The name of the field representing the timestamp. + * @param unit - The unit of time to subtract (e.g., "day", "hour"). + * @param amount - The amount of time to subtract. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the resulting timestamp. */ export function timestampSubtract( fieldName: string, @@ -7079,12 +7389,13 @@ export function timestampSubtract( * * Creates an expression that evaluates to the current server timestamp. * + * @example * ```typescript * // Get the current server timestamp * currentTimestamp() * ``` * - * @return A new Expression representing the current server timestamp. + * @returns A new Expression representing the current server timestamp. */ export function currentTimestamp(): FunctionExpression { return new FunctionExpression('current_timestamp', [], 'currentTimestamp'); @@ -7095,16 +7406,17 @@ export function currentTimestamp(): FunctionExpression { * * Creates an expression that performs a logical 'AND' operation on multiple filter conditions. * + * @example * ```typescript * // Check if the 'age' field is greater than 18 AND the 'city' field is "London" AND * // the 'status' field is "active" * const condition = and(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); * ``` * - * @param first The first filter condition. - * @param second The second filter condition. - * @param more Additional filter conditions to 'AND' together. - * @return A new {@code Expr} representing the logical 'AND' operation. + * @param first - The first filter condition. + * @param second - The second filter condition. + * @param more - Additional filter conditions to 'AND' together. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logical 'AND' operation. */ export function and( first: BooleanExpression, @@ -7123,16 +7435,17 @@ export function and( * * Creates an expression that performs a logical 'OR' operation on multiple filter conditions. * + * @example * ```typescript * // Check if the 'age' field is greater than 18 OR the 'city' field is "London" OR * // the 'status' field is "active" * const condition = or(greaterThan("age", 18), equal("city", "London"), equal("status", "active")); * ``` * - * @param first The first filter condition. - * @param second The second filter condition. - * @param more Additional filter conditions to 'OR' together. - * @return A new {@code Expr} representing the logical 'OR' operation. + * @param first - The first filter condition. + * @param second - The second filter condition. + * @param more - Additional filter conditions to 'OR' together. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logical 'OR' operation. */ export function or( first: BooleanExpression, @@ -7150,14 +7463,15 @@ export function or( * @beta * Creates an expression that returns the value of the base expression raised to the power of the exponent expression. * + * @example * ```typescript * // Raise the value of the 'base' field to the power of the 'exponent' field. * pow(field("base"), field("exponent")); * ``` * - * @param base The expression to raise to the power of the exponent. - * @param exponent The expression to raise the base to the power of. - * @return A new `Expr` representing the power operation. + * @param base - The expression to raise to the power of the exponent. + * @param exponent - The expression to raise the base to the power of. + * @returns A new `Expression` representing the power operation. */ export function pow(base: Expression, exponent: Expression): FunctionExpression; @@ -7165,14 +7479,15 @@ export function pow(base: Expression, exponent: Expression): FunctionExpression; * @beta * Creates an expression that returns the value of the base expression raised to the power of the exponent. * + * @example * ```typescript * // Raise the value of the 'base' field to the power of 2. * pow(field("base"), 2); * ``` * - * @param base The expression to raise to the power of the exponent. - * @param exponent The constant value to raise the base to the power of. - * @return A new `Expr` representing the power operation. + * @param base - The expression to raise to the power of the exponent. + * @param exponent - The constant value to raise the base to the power of. + * @returns A new `Expression` representing the power operation. */ export function pow(base: Expression, exponent: number): FunctionExpression; @@ -7180,14 +7495,15 @@ export function pow(base: Expression, exponent: number): FunctionExpression; * @beta * Creates an expression that returns the value of the base field raised to the power of the exponent expression. * + * @example * ```typescript * // Raise the value of the 'base' field to the power of the 'exponent' field. * pow("base", field("exponent")); * ``` * - * @param base The name of the field to raise to the power of the exponent. - * @param exponent The expression to raise the base to the power of. - * @return A new `Expr` representing the power operation. + * @param base - The name of the field to raise to the power of the exponent. + * @param exponent - The expression to raise the base to the power of. + * @returns A new `Expression` representing the power operation. */ export function pow(base: string, exponent: Expression): FunctionExpression; @@ -7195,14 +7511,15 @@ export function pow(base: string, exponent: Expression): FunctionExpression; * @beta * Creates an expression that returns the value of the base field raised to the power of the exponent. * + * @example * ```typescript * // Raise the value of the 'base' field to the power of 2. * pow("base", 2); * ``` * - * @param base The name of the field to raise to the power of the exponent. - * @param exponent The constant value to raise the base to the power of. - * @return A new `Expr` representing the power operation. + * @param base - The name of the field to raise to the power of the exponent. + * @param exponent - The constant value to raise the base to the power of. + * @returns A new `Expression` representing the power operation. */ export function pow(base: string, exponent: number): FunctionExpression; export function pow( @@ -7216,13 +7533,14 @@ export function pow( * @beta * Creates an expression that rounds a numeric value to the nearest whole number. * + * @example * ```typescript * // Round the value of the 'price' field. * round("price"); * ``` * - * @param fieldName The name of the field to round. - * @return A new `Expr` representing the rounded value. + * @param fieldName - The name of the field to round. + * @returns A new `Expression` representing the rounded value. */ export function round(fieldName: string): FunctionExpression; @@ -7230,13 +7548,14 @@ export function round(fieldName: string): FunctionExpression; * @beta * Creates an expression that rounds a numeric value to the nearest whole number. * + * @example * ```typescript * // Round the value of the 'price' field. * round(field("price")); * ``` * - * @param expression An expression evaluating to a numeric value, which will be rounded. - * @return A new `Expr` representing the rounded value. + * @param expression - An expression evaluating to a numeric value, which will be rounded. + * @returns A new `Expression` representing the rounded value. */ export function round(expression: Expression): FunctionExpression; @@ -7244,14 +7563,15 @@ export function round(expression: Expression): FunctionExpression; * @beta * Creates an expression that rounds a numeric value to the specified number of decimal places. * + * @example * ```typescript * // Round the value of the 'price' field to two decimal places. * round("price", 2); * ``` * - * @param fieldName The name of the field to round. - * @param decimalPlaces A constant or expression specifying the rounding precision in decimal places. - * @return A new `Expr` representing the rounded value. + * @param fieldName - The name of the field to round. + * @param decimalPlaces - A constant or expression specifying the rounding precision in decimal places. + * @returns A new `Expression` representing the rounded value. */ export function round( fieldName: string, @@ -7262,14 +7582,15 @@ export function round( * @beta * Creates an expression that rounds a numeric value to the specified number of decimal places. * + * @example * ```typescript * // Round the value of the 'price' field to two decimal places. * round(field("price"), constant(2)); * ``` * - * @param expression An expression evaluating to a numeric value, which will be rounded. - * @param decimalPlaces A constant or expression specifying the rounding precision in decimal places. - * @return A new `Expr` representing the rounded value. + * @param expression - An expression evaluating to a numeric value, which will be rounded. + * @param decimalPlaces - A constant or expression specifying the rounding precision in decimal places. + * @returns A new `Expression` representing the rounded value. */ export function round( expression: Expression, @@ -7290,13 +7611,14 @@ export function round( * @beta * Creates an expression that returns the collection ID from a path. * + * @example * ```typescript * // Get the collection ID from a path. * collectionId("__name__"); * ``` * - * @param fieldName The name of the field to get the collection ID from. - * @return A new {@code Expr} representing the collectionId operation. + * @param fieldName - The name of the field to get the collection ID from. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the collectionId operation. */ export function collectionId(fieldName: string): FunctionExpression; @@ -7304,13 +7626,14 @@ export function collectionId(fieldName: string): FunctionExpression; * @beta * Creates an expression that returns the collection ID from a path. * + * @example * ```typescript * // Get the collection ID from a path. * collectionId(field("__name__")); * ``` * - * @param expression An expression evaluating to a path, which the collection ID will be extracted from. - * @return A new {@code Expr} representing the collectionId operation. + * @param expression - An expression evaluating to a path, which the collection ID will be extracted from. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the collectionId operation. */ export function collectionId(expression: Expression): FunctionExpression; export function collectionId(expr: Expression | string): FunctionExpression { @@ -7321,6 +7644,7 @@ export function collectionId(expr: Expression | string): FunctionExpression { * @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. * length("name"); @@ -7329,8 +7653,8 @@ export function collectionId(expr: Expression | string): FunctionExpression { * length("cart"); * ``` * - * @param fieldName The name of the field to calculate the length of. - * @return A new `Expr` representing the length of the string, array, map, vector, or bytes. + * @param fieldName - The name of the field to calculate the length of. + * @returns A new `Expression` representing the length of the string, array, map, vector, or bytes. */ export function length(fieldName: string): FunctionExpression; @@ -7338,6 +7662,7 @@ export function length(fieldName: string): FunctionExpression; * @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. * length(field("name")); @@ -7346,8 +7671,8 @@ export function length(fieldName: string): FunctionExpression; * length(field("cart")); * ``` * - * @param expression An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. - * @return A new `Expr` representing the length of the string, array, map, vector, or bytes. + * @param expression - An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. + * @returns A new `Expression` representing the length of the string, array, map, vector, or bytes. */ export function length(expression: Expression): FunctionExpression; export function length(expr: Expression | string): FunctionExpression { @@ -7358,13 +7683,14 @@ export function length(expr: Expression | string): FunctionExpression { * @beta * Creates an expression that computes the natural logarithm of a numeric value. * + * @example * ```typescript * // Compute the natural logarithm of the 'value' field. * ln("value"); * ``` * - * @param fieldName The name of the field to compute the natural logarithm of. - * @return A new `Expr` representing the natural logarithm of the numeric value. + * @param fieldName - The name of the field to compute the natural logarithm of. + * @returns A new `Expression` representing the natural logarithm of the numeric value. */ export function ln(fieldName: string): FunctionExpression; @@ -7372,13 +7698,14 @@ export function ln(fieldName: string): FunctionExpression; * @beta * Creates an expression that computes the natural logarithm of a numeric value. * + * @example * ```typescript * // Compute the natural logarithm of the 'value' field. * ln(field("value")); * ``` * - * @param expression An expression evaluating to a numeric value, which the natural logarithm will be computed for. - * @return A new `Expr` representing the natural logarithm of the numeric value. + * @param expression - An expression evaluating to a numeric value, which the natural logarithm will be computed for. + * @returns A new `Expression` representing the natural logarithm of the numeric value. */ export function ln(expression: Expression): FunctionExpression; export function ln(expr: Expression | string): FunctionExpression { @@ -7389,28 +7716,30 @@ export function ln(expr: Expression | string): FunctionExpression { * @beta * Creates an expression that computes the logarithm of an expression to a given base. * + * @example * ```typescript * // Compute the logarithm of the 'value' field with base 10. * log(field("value"), 10); * ``` * - * @param expression An expression evaluating to a numeric value, which the logarithm will be computed for. - * @param base The base of the logarithm. - * @return A new {@code Expr} representing the logarithm of the numeric value. + * @param expression - An expression evaluating to a numeric value, which the logarithm will be computed for. + * @param base - The base of the logarithm. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logarithm of the numeric value. */ export function log(expression: Expression, base: number): FunctionExpression; /** * @beta * Creates an expression that computes the logarithm of an expression to a given base. * + * @example * ```typescript * // Compute the logarithm of the 'value' field with the base in the 'base' field. * log(field("value"), field("base")); * ``` * - * @param expression An expression evaluating to a numeric value, which the logarithm will be computed for. - * @param base The base of the logarithm. - * @return A new {@code Expr} representing the logarithm of the numeric value. + * @param expression - An expression evaluating to a numeric value, which the logarithm will be computed for. + * @param base - The base of the logarithm. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logarithm of the numeric value. */ export function log( expression: Expression, @@ -7420,28 +7749,30 @@ export function log( * @beta * Creates an expression that computes the logarithm of a field to a given base. * + * @example * ```typescript * // Compute the logarithm of the 'value' field with base 10. * log("value", 10); * ``` * - * @param fieldName The name of the field to compute the logarithm of. - * @param base The base of the logarithm. - * @return A new {@code Expr} representing the logarithm of the numeric value. + * @param fieldName - The name of the field to compute the logarithm of. + * @param base - The base of the logarithm. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logarithm of the numeric value. */ export function log(fieldName: string, base: number): FunctionExpression; /** * @beta * Creates an expression that computes the logarithm of a field to a given base. * + * @example * ```typescript * // Compute the logarithm of the 'value' field with the base in the 'base' field. * log("value", field("base")); * ``` * - * @param fieldName The name of the field to compute the logarithm of. - * @param base The base of the logarithm. - * @return A new {@code Expr} representing the logarithm of the numeric value. + * @param fieldName - The name of the field to compute the logarithm of. + * @param base - The base of the logarithm. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logarithm of the numeric value. */ export function log(fieldName: string, base: Expression): FunctionExpression; export function log( @@ -7458,26 +7789,28 @@ export function log( * @beta * Creates an expression that computes the square root of a numeric value. * + * @example * ```typescript * // Compute the square root of the 'value' field. * sqrt(field("value")); * ``` * - * @param expression An expression evaluating to a numeric value, which the square root will be computed for. - * @return A new {@code Expr} representing the square root of the numeric value. + * @param expression - An expression evaluating to a numeric value, which the square root will be computed for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the square root of the numeric value. */ export function sqrt(expression: Expression): FunctionExpression; /** * @beta * Creates an expression that computes the square root of a numeric value. * + * @example * ```typescript * // Compute the square root of the 'value' field. * sqrt("value"); * ``` * - * @param fieldName The name of the field to compute the square root of. - * @return A new {@code Expr} representing the square root of the numeric value. + * @param fieldName - The name of the field to compute the square root of. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the square root of the numeric value. */ export function sqrt(fieldName: string): FunctionExpression; export function sqrt(expr: Expression | string): FunctionExpression { @@ -7488,13 +7821,14 @@ export function sqrt(expr: Expression | string): FunctionExpression { * @beta * Creates an expression that reverses a string. * + * @example * ```typescript * // Reverse the value of the 'myString' field. * strReverse(field("myString")); * ``` * - * @param stringExpression An expression evaluating to a string value, which will be reversed. - * @return A new {@code Expr} representing the reversed string. + * @param stringExpression - An expression evaluating to a string value, which will be reversed. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the reversed string. */ export function stringReverse(stringExpression: Expression): FunctionExpression; @@ -7502,13 +7836,14 @@ export function stringReverse(stringExpression: Expression): FunctionExpression; * @beta * Creates an expression that reverses a string value in the specified field. * + * @example * ```typescript * // Reverse the value of the 'myString' field. * strReverse("myString"); * ``` * - * @param field The name of the field representing the string to reverse. - * @return A new {@code Expr} representing the reversed string. + * @param field - The name of the field representing the string to reverse. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the reversed string. */ export function stringReverse(field: string): FunctionExpression; export function stringReverse(expr: Expression | string): FunctionExpression { @@ -7519,15 +7854,16 @@ export function stringReverse(expr: Expression | string): FunctionExpression { * @beta * Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. * + * @example * ```typescript * // Concatenate the 'firstName' and 'lastName' fields with a space in between. * concat(field("firstName"), " ", field("lastName")) * ``` * - * @param first The first expressions to concatenate. - * @param second The second literal or expression to concatenate. - * @param others Additional literals or expressions to concatenate. - * @return A new `Expression` representing the concatenation. + * @param first - The first expressions to concatenate. + * @param second - The second literal or expression to concatenate. + * @param others - Additional literals or expressions to concatenate. + * @returns A new `Expression` representing the concatenation. */ export function concat( first: Expression, @@ -7539,15 +7875,16 @@ export function concat( * @beta * Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. * + * @example * ```typescript * // Concatenate a field with a literal string. * concat(field("firstName"), "Doe") * ``` * - * @param fieldName The name of a field to concatenate. - * @param second The second literal or expression to concatenate. - * @param others Additional literal or expressions to concatenate. - * @return A new `Expression` representing the concatenation. + * @param fieldName - The name of a field to concatenate. + * @param second - The second literal or expression to concatenate. + * @param others - Additional literal or expressions to concatenate. + * @returns A new `Expression` representing the concatenation. */ export function concat( fieldName: string, @@ -7571,8 +7908,8 @@ export function concat( * @beta * Creates an expression that computes the absolute value of a numeric value. * - * @param expr The expression to compute the absolute value of. - * @return A new {@code Expr} representing the absolute value of the numeric value. + * @param expr - The expression to compute the absolute value of. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the absolute value of the numeric value. */ export function abs(expr: Expression): FunctionExpression; @@ -7580,8 +7917,8 @@ export function abs(expr: Expression): FunctionExpression; * @beta * Creates an expression that computes the absolute value of a numeric value. * - * @param fieldName The field to compute the absolute value of. - * @return A new {@code Expr} representing the absolute value of the numeric value. + * @param fieldName - The field to compute the absolute value of. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the absolute value of the numeric value. */ export function abs(fieldName: string): FunctionExpression; export function abs(expr: Expression | string): FunctionExpression { @@ -7593,15 +7930,16 @@ export function abs(expr: Expression | string): FunctionExpression { * Creates an expression that returns the `elseExpr` argument if `ifExpr` is absent, else return * the result of the `ifExpr` argument evaluation. * + * @example * ```typescript * // Returns the value of the optional field 'optional_field', or returns 'default_value' * // if the field is absent. * ifAbsent(field("optional_field"), constant("default_value")) * ``` * - * @param ifExpr The expression to check for absence. - * @param elseExpr The expression that will be evaluated and returned if [ifExpr] is absent. - * @return A new Expression representing the ifAbsent operation. + * @param ifExpr - The expression to check for absence. + * @param elseExpr - The expression that will be evaluated and returned if [ifExpr] is absent. + * @returns A new Expression representing the ifAbsent operation. */ export function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expression; @@ -7610,15 +7948,16 @@ export function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expression; * Creates an expression that returns the `elseValue` argument if `ifExpr` is absent, else * return the result of the `ifExpr` argument evaluation. * + * @example * ```typescript * // Returns the value of the optional field 'optional_field', or returns 'default_value' * // if the field is absent. * ifAbsent(field("optional_field"), "default_value") * ``` * - * @param ifExpr The expression to check for absence. - * @param elseValue The value that will be returned if `ifExpr` evaluates to an absent value. - * @return A new [Expression] representing the ifAbsent operation. + * @param ifExpr - The expression to check for absence. + * @param elseValue - The value that will be returned if `ifExpr` evaluates to an absent value. + * @returns A new [Expression] representing the ifAbsent operation. */ export function ifAbsent(ifExpr: Expression, elseValue: unknown): Expression; @@ -7627,16 +7966,17 @@ export function ifAbsent(ifExpr: Expression, elseValue: unknown): Expression; * Creates an expression that returns the `elseExpr` argument if `ifFieldName` is absent, else * return the value of the field. * + * @example * ```typescript * // Returns the value of the optional field 'optional_field', or returns the value of * // 'default_field' if 'optional_field' is absent. * ifAbsent("optional_field", field("default_field")) * ``` * - * @param ifFieldName The field to check for absence. - * @param elseExpr The expression that will be evaluated and returned if `ifFieldName` is + * @param ifFieldName - The field to check for absence. + * @param elseExpr - The expression that will be evaluated and returned if `ifFieldName` is * absent. - * @return A new Expression representing the ifAbsent operation. + * @returns A new Expression representing the ifAbsent operation. */ export function ifAbsent(ifFieldName: string, elseExpr: Expression): Expression; @@ -7645,15 +7985,16 @@ export function ifAbsent(ifFieldName: string, elseExpr: Expression): Expression; * Creates an expression that returns the `elseValue` argument if `ifFieldName` is absent, else * return the value of the field. * + * @example * ```typescript * // Returns the value of the optional field 'optional_field', or returns 'default_value' * // if the field is absent. * ifAbsent("optional_field", "default_value") * ``` * - * @param ifFieldName The field to check for absence. - * @param elseValue The value that will be returned if [ifFieldName] is absent. - * @return A new Expression representing the ifAbsent operation. + * @param ifFieldName - The field to check for absence. + * @param elseValue - The value that will be returned if [ifFieldName] is absent. + * @returns A new Expression representing the ifAbsent operation. */ export function ifAbsent( ifFieldName: string | Expression, @@ -7672,14 +8013,15 @@ export function ifAbsent( * @beta * Creates an expression that joins the elements of an array into a string. * + * @example * ```typescript * // Join the elements of the 'tags' field with a comma and space. * join("tags", ", ") * ``` * - * @param arrayFieldName The name of the field containing the array. - * @param delimiter The string to use as a delimiter. - * @return A new Expression representing the join operation. + * @param arrayFieldName - The name of the field containing the array. + * @param delimiter - The string to use as a delimiter. + * @returns A new Expression representing the join operation. */ export function join(arrayFieldName: string, delimiter: string): Expression; @@ -7687,14 +8029,15 @@ export function join(arrayFieldName: string, delimiter: string): Expression; * @beta * Creates an expression that joins the elements of an array into a string. * + * @example * ```typescript * // Join an array of string using the delimiter from the 'separator' field. * join(array(['foo', 'bar']), field("separator")) * ``` * - * @param arrayExpression An expression that evaluates to an array. - * @param delimiterExpression The expression that evaluates to the delimiter string. - * @return A new Expression representing the join operation. + * @param arrayExpression - An expression that evaluates to an array. + * @param delimiterExpression - The expression that evaluates to the delimiter string. + * @returns A new Expression representing the join operation. */ export function join( arrayExpression: Expression, @@ -7705,14 +8048,15 @@ export function join( * @beta * Creates an expression that joins the elements of an array into a string. * + * @example * ```typescript * // Join the elements of the 'tags' field with a comma and space. * join(field("tags"), ", ") * ``` * - * @param arrayExpression An expression that evaluates to an array. - * @param delimiter The string to use as a delimiter. - * @return A new Expression representing the join operation. + * @param arrayExpression - An expression that evaluates to an array. + * @param delimiter - The string to use as a delimiter. + * @returns A new Expression representing the join operation. */ export function join( arrayExpression: Expression, @@ -7723,14 +8067,15 @@ export function join( * @beta * Creates an expression that joins the elements of an array into a string. * + * @example * ```typescript * // Join the elements of the 'tags' field with the delimiter from the 'separator' field. * join('tags', field("separator")) * ``` * - * @param arrayFieldName The name of the field containing the array. - * @param delimiterExpression The expression that evaluates to the delimiter string. - * @return A new Expression representing the join operation. + * @param arrayFieldName - The name of the field containing the array. + * @param delimiterExpression - The expression that evaluates to the delimiter string. + * @returns A new Expression representing the join operation. */ export function join( arrayFieldName: string, @@ -7749,13 +8094,14 @@ export function 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. * log10("value"); * ``` * - * @param fieldName The name of the field to compute the base-10 logarithm of. - * @return A new `Expr` representing the base-10 logarithm of the numeric value. + * @param fieldName - The name of the field to compute the base-10 logarithm of. + * @returns A new `Expression` representing the base-10 logarithm of the numeric value. */ export function log10(fieldName: string): FunctionExpression; @@ -7763,13 +8109,14 @@ export function log10(fieldName: string): FunctionExpression; * @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. * log10(field("value")); * ``` * - * @param expression An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. - * @return A new `Expr` representing the base-10 logarithm of the numeric value. + * @param expression - An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. + * @returns A new `Expression` representing the base-10 logarithm of the numeric value. */ export function log10(expression: Expression): FunctionExpression; export function log10(expr: Expression | string): FunctionExpression { @@ -7780,13 +8127,14 @@ export function log10(expr: Expression | string): FunctionExpression { * @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. * arraySum("scores"); * ``` * - * @param fieldName The name of the field to compute the sum of. - * @return A new `Expr` representing the sum of the elements in the array. + * @param fieldName - The name of the field to compute the sum of. + * @returns A new `Expression` representing the sum of the elements in the array. */ export function arraySum(fieldName: string): FunctionExpression; @@ -7794,13 +8142,14 @@ export function arraySum(fieldName: string): FunctionExpression; * @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. * arraySum(field("scores")); * ``` * - * @param expression An expression evaluating to a numeric array, which the sum will be computed for. - * @return A new `Expr` representing the sum of the elements in the array. + * @param expression - An expression evaluating to a numeric array, which the sum will be computed for. + * @returns A new `Expression` representing the sum of the elements in the array. */ export function arraySum(expression: Expression): FunctionExpression; export function arraySum(expr: Expression | string): FunctionExpression { @@ -7817,10 +8166,10 @@ export function arraySum(expr: Expression | string): FunctionExpression { * split('scoresCsv', ',') * ``` * - * @param fieldName Split the value in this field. - * @param delimiter Split on this delimiter. + * @param fieldName - Split the value in this field. + * @param delimiter - Split on this delimiter. * - * @return A new {@code Expression} representing the split function. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the split function. */ export function split(fieldName: string, delimiter: string): FunctionExpression; @@ -7834,10 +8183,10 @@ export function split(fieldName: string, delimiter: string): FunctionExpression; * split('scores', conditional(field('format').equal('csv'), constant(','), constant(':')) * ``` * - * @param fieldName Split the value in this field. - * @param delimiter Split on this delimiter returned by evaluating this expression. + * @param fieldName - Split the value in this field. + * @param delimiter - Split on this delimiter returned by evaluating this expression. * - * @return A new {@code Expression} representing the split function. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the split function. */ export function split( fieldName: string, @@ -7854,10 +8203,10 @@ export function split( * split(field('scoresCsv'), ',') * ``` * - * @param expression Split the result of this expression. - * @param delimiter Split on this delimiter. + * @param expression - Split the result of this expression. + * @param delimiter - Split on this delimiter. * - * @return A new {@code Expression} representing the split function. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the split function. */ export function split( expression: Expression, @@ -7874,10 +8223,10 @@ export function split( * split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':')) * ``` * - * @param expression Split the result of this expression. - * @param delimiter Split on this delimiter returned by evaluating this expression. + * @param expression - Split the result of this expression. + * @param delimiter - Split on this delimiter returned by evaluating this expression. * - * @return A new {@code Expression} representing the split function. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the split function. */ export function split( expression: Expression, @@ -7902,11 +8251,11 @@ export function split( * field('createdAt').timestampTruncate('day') * ``` * - * @param fieldName Truncate the timestamp value contained in this field. - * @param granularity The granularity to truncate to. - * @param timezone The timezone to use for truncation. Valid values are from + * @param fieldName - Truncate the timestamp value contained in this field. + * @param granularity - The granularity to truncate to. + * @param timezone - The timezone to use for truncation. Valid values are from * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". - * @return A new {Expression} representing the truncated timestamp. + * @returns A new `Expression` representing the truncated timestamp. */ export function timestampTruncate( fieldName: string, @@ -7924,11 +8273,11 @@ export function timestampTruncate( * field('createdAt').timestampTruncate(field('granularity')) * ``` * - * @param fieldName Truncate the timestamp value contained in this field. - * @param granularity The granularity to truncate to. - * @param timezone The timezone to use for truncation. Valid values are from + * @param fieldName - Truncate the timestamp value contained in this field. + * @param granularity - The granularity to truncate to. + * @param timezone - The timezone to use for truncation. Valid values are from * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". - * @return A new {Expression} representing the truncated timestamp. + * @returns A new `Expression` representing the truncated timestamp. */ export function timestampTruncate( fieldName: string, @@ -7946,11 +8295,11 @@ export function timestampTruncate( * field('createdAt').timestampTruncate('day') * ``` * - * @param timestampExpression Truncate the timestamp value that is returned by this expression. - * @param granularity The granularity to truncate to. - * @param timezone The timezone to use for truncation. Valid values are from + * @param timestampExpression - Truncate the timestamp value that is returned by this expression. + * @param granularity - The granularity to truncate to. + * @param timezone - The timezone to use for truncation. Valid values are from * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". - * @return A new {Expression} representing the truncated timestamp. + * @returns A new `Expression` representing the truncated timestamp. */ export function timestampTruncate( timestampExpression: Expression, @@ -7968,11 +8317,11 @@ export function timestampTruncate( * field('createdAt').timestampTruncate(field('granularity')) * ``` * - * @param timestampExpression Truncate the timestamp value that is returned by this expression. - * @param granularity The granularity to truncate to. - * @param timezone The timezone to use for truncation. Valid values are from + * @param timestampExpression - Truncate the timestamp value that is returned by this expression. + * @param granularity - The granularity to truncate to. + * @param timezone - The timezone to use for truncation. Valid values are from * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". - * @return A new {Expression} representing the truncated timestamp. + * @returns A new `Expression` representing the truncated timestamp. */ export function timestampTruncate( timestampExpression: Expression, @@ -8003,7 +8352,7 @@ export function timestampTruncate( * type('title') * ``` * - * @return A new {Expression} representing the data type. + * @returns A new `Expression` representing the data type. */ export function type(fieldName: string): FunctionExpression; /** @@ -8016,7 +8365,7 @@ export function type(fieldName: string): FunctionExpression; * type(conditional(exists('foo'), constant(1), constant(true))) * ``` * - * @return A new {Expression} representing the data type. + * @returns A new `Expression` representing the data type. */ export function type(expression: Expression): FunctionExpression; export function type( @@ -8030,32 +8379,34 @@ export function type( /** * @beta * - * Creates an {@link Ordering} that sorts documents in ascending order based on an expression. + * Creates an {@link @firebase/firestore/pipelines#Ordering} that sorts documents in ascending order based on an expression. * + * @example * ```typescript * // Sort documents by the 'name' field in lowercase in ascending order * firestore.pipeline().collection("users") * .sort(ascending(field("name").toLower())); * ``` * - * @param expr The expression to create an ascending ordering for. - * @return A new `Ordering` for ascending sorting. + * @param expr - The expression to create an ascending ordering for. + * @returns A new `Ordering` for ascending sorting. */ export function ascending(expr: Expression): Ordering; /** * @beta * - * Creates an {@link Ordering} that sorts documents in ascending order based on a field. + * Creates an {@link @firebase/firestore/pipelines#Ordering} that sorts documents in ascending order based on a field. * + * @example * ```typescript * // Sort documents by the 'name' field in ascending order * firestore.pipeline().collection("users") * .sort(ascending("name")); * ``` * - * @param fieldName The field to create an ascending ordering for. - * @return A new `Ordering` for ascending sorting. + * @param fieldName - The field to create an ascending ordering for. + * @returns A new `Ordering` for ascending sorting. */ export function ascending(fieldName: string): Ordering; export function ascending(field: Expression | string): Ordering { @@ -8065,32 +8416,34 @@ export function ascending(field: Expression | string): Ordering { /** * @beta * - * Creates an {@link Ordering} that sorts documents in descending order based on an expression. + * Creates an {@link @firebase/firestore/pipelines#Ordering} that sorts documents in descending order based on an expression. * + * @example * ```typescript * // Sort documents by the 'name' field in lowercase in descending order * firestore.pipeline().collection("users") * .sort(descending(field("name").toLower())); * ``` * - * @param expr The expression to create a descending ordering for. - * @return A new `Ordering` for descending sorting. + * @param expr - The expression to create a descending ordering for. + * @returns A new `Ordering` for descending sorting. */ export function descending(expr: Expression): Ordering; /** * @beta * - * Creates an {@link Ordering} that sorts documents in descending order based on a field. + * Creates an {@link @firebase/firestore/pipelines#Ordering} that sorts documents in descending order based on a field. * + * @example * ```typescript * // Sort documents by the 'name' field in descending order * firestore.pipeline().collection("users") * .sort(descending("name")); * ``` * - * @param fieldName The field to create a descending ordering for. - * @return A new `Ordering` for descending sorting. + * @param fieldName - The field to create a descending ordering for. + * @returns A new `Ordering` for descending sorting. */ export function descending(fieldName: string): Ordering; export function descending(field: Expression | string): Ordering { diff --git a/packages/firestore/src/lite-api/geo_point.ts b/packages/firestore/src/lite-api/geo_point.ts index 75194049f8..0545f8bbc3 100644 --- a/packages/firestore/src/lite-api/geo_point.ts +++ b/packages/firestore/src/lite-api/geo_point.ts @@ -116,7 +116,7 @@ export class GeoPoint { /** * Builds a `GeoPoint` instance from a JSON object created by {@link GeoPoint.toJSON}. * - * @param json a JSON object represention of a `GeoPoint` instance + * @param json - a JSON object represention of a `GeoPoint` instance * @returns an instance of {@link GeoPoint} if the JSON object could be parsed. Throws a * {@link FirestoreError} if an error occurs. */ diff --git a/packages/firestore/src/lite-api/pipeline-result.ts b/packages/firestore/src/lite-api/pipeline-result.ts index a853a65299..219d2abb8a 100644 --- a/packages/firestore/src/lite-api/pipeline-result.ts +++ b/packages/firestore/src/lite-api/pipeline-result.ts @@ -31,7 +31,7 @@ import { AbstractUserDataWriter } from './user_data_writer'; * @beta * Represents the results of a Firestore pipeline execution. * - * A `PipelineSnapshot` contains zero or more {@link PipelineResult} objects + * A `PipelineSnapshot` contains zero or more {@link @firebase/firestore/pipelines#PipelineResult} objects * representing the documents returned by a pipeline query. It provides methods * to iterate over the documents and access metadata about the query results. * @@ -73,7 +73,6 @@ export class PipelineSnapshot { * @beta * The time at which the pipeline producing this result is executed. * - * @type {Timestamp} * @readonly * */ @@ -91,7 +90,7 @@ export class PipelineSnapshot { * @beta * * A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the - * {@link #data()} or {@link #get(String)} methods. + * {@link @firebase/firestore/pipelines#PipelineResult.data} or {@link @firebase/firestore/pipelines#PipelineResult.(get:1)} methods. * *

If the PipelineResult represents a non-document result, `ref` will return a undefined * value. @@ -118,12 +117,12 @@ export class PipelineResult { * @private * @internal * - * @param userDataWriter The serializer used to encode/decode protobuf. - * @param ref The reference to the document. - * @param fields The fields of the Firestore `Document` Protobuf backing + * @param userDataWriter - The serializer used to encode/decode protobuf. + * @param ref - The reference to the document. + * @param fields - The fields of the Firestore `Document` Protobuf backing * this document. - * @param createTime The time when the document was created if the result is a document, undefined otherwise. - * @param updateTime The time when the document was last updated if the result is a document, undefined otherwise. + * @param createTime - The time when the document was created if the result is a document, undefined otherwise. + * @param updateTime - The time when the document was last updated if the result is a document, undefined otherwise. */ constructor( userDataWriter: AbstractUserDataWriter, @@ -151,7 +150,6 @@ export class PipelineResult { * @beta * The ID of the document for which this PipelineResult contains data, if it is a document; otherwise `undefined`. * - * @type {string} * @readonly * */ @@ -163,7 +161,6 @@ export class PipelineResult { * @beta * The time the document was created. Undefined if this result is not a document. * - * @type {Timestamp|undefined} * @readonly */ get createTime(): Timestamp | undefined { @@ -175,7 +172,6 @@ export class PipelineResult { * The time the document was last updated (at the time the snapshot was * generated). Undefined if this result is not a document. * - * @type {Timestamp|undefined} * @readonly */ get updateTime(): Timestamp | undefined { @@ -186,7 +182,7 @@ export class PipelineResult { * @beta * Retrieves all fields in the result as an object. * - * @returns {T} An object containing all fields in the document or + * @returns An object containing all fields in the document or * 'undefined' if the document doesn't exist. * * @example @@ -222,9 +218,9 @@ export class PipelineResult { * @beta * Retrieves the field specified by `field`. * - * @param {string|FieldPath|Field} field The field path + * @param field - The field path * (e.g. 'foo' or 'foo.bar') to a specific field. - * @returns {*} The data at the specified field location or undefined if no + * @returns The data at the specified field location or `undefined` if no * such field exists. * * @example @@ -260,8 +256,8 @@ export class PipelineResult { /** * @beta * Test equality of two PipelineResults. - * @param left - * @param right + * @param left - First PipelineResult to compare. + * @param right - Second PipelineResult to compare. */ export function pipelineResultEqual( left: PipelineResult, diff --git a/packages/firestore/src/lite-api/pipeline-source.ts b/packages/firestore/src/lite-api/pipeline-source.ts index 0186ca3526..87f5a6a882 100644 --- a/packages/firestore/src/lite-api/pipeline-source.ts +++ b/packages/firestore/src/lite-api/pipeline-source.ts @@ -44,10 +44,10 @@ import { UserDataReader, UserDataSource } from './user_data_reader'; /** * @beta - * Provides the entry point for defining the data source of a Firestore {@link Pipeline}. + * Provides the entry point for defining the data source of a Firestore {@link @firebase/firestore/pipelines#Pipeline}. * - * Use the methods of this class (e.g., {@link PipelineSource#collection}, {@link PipelineSource#collectionGroup}, - * {@link PipelineSource#database}, or {@link PipelineSource#documents}) to specify the initial data + * Use the methods of this class (e.g., {@link @firebase/firestore/pipelines#PipelineSource.(collection:1)}, {@link @firebase/firestore/pipelines#PipelineSource.(collectionGroup:1)}, + * {@link @firebase/firestore/pipelines#PipelineSource.(database:1)}, or {@link @firebase/firestore/pipelines#PipelineSource.(documents:1)}) to specify the initial data * for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. */ export class PipelineSource { @@ -194,10 +194,10 @@ export class PipelineSource { * @beta * Set the pipeline's source to the documents specified by the given paths and DocumentReferences. * - * @param docs An array of paths and DocumentReferences specifying the individual documents that will be the source of this pipeline. + * @param docs - An array of paths and DocumentReferences specifying the individual documents that will be the source of this pipeline. * The converters for these DocumentReferences will be ignored and not have an effect on this pipeline. * - * @throws {@FirestoreError} Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. + * @throws `FirestoreError` Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. */ documents(docs: Array): PipelineType; @@ -207,7 +207,7 @@ export class PipelineSource { * * @param options - Options defining how this DocumentsStage is evaluated. * - * @throws {@FirestoreError} Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. + * @throws `FirestoreError` Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. */ documents(options: DocumentsStageOptions): PipelineType; documents( @@ -252,9 +252,9 @@ export class PipelineSource { * @beta * Convert the given Query into an equivalent Pipeline. * - * @param query A Query to be converted into a Pipeline. + * @param query - A Query to be converted into a Pipeline. * - * @throws {@FirestoreError} Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. + * @throws `FirestoreError` Thrown if any of the provided DocumentReferences target a different project or database than the pipeline. */ createFrom(query: Query): Pipeline { return toPipeline(query._query, query.firestore); diff --git a/packages/firestore/src/lite-api/pipeline.ts b/packages/firestore/src/lite-api/pipeline.ts index 4352e30f4c..2dda90eaa4 100644 --- a/packages/firestore/src/lite-api/pipeline.ts +++ b/packages/firestore/src/lite-api/pipeline.ts @@ -107,6 +107,7 @@ import { AbstractUserDataWriter } from './user_data_writer'; * * Usage Examples: * + * @example * ```typescript * const db: Firestore; // Assumes a valid firestore instance. * @@ -167,14 +168,15 @@ export class Pipeline implements ProtoSerializable { * stages or constants. You can use this to create new fields or overwrite existing ones (if there * is name overlaps). * - * The added fields are defined using {@link Selectable}s, which can be: + * The added fields are defined using {@link @firebase/firestore/pipelines#Selectable}s, which can be: * - * - {@link Field}: References an existing document field. - * - {@link Expression}: Either a literal value (see {@link Constant}) or a computed value - * (see {@FunctionExpr}) with an assigned alias using {@link Expression#as}. + * - {@link @firebase/firestore/pipelines#Field}: References an existing document field. + * - {@link @firebase/firestore/pipelines#Expression}: Either a literal value (see {@link @firebase/firestore/pipelines#(constant:1)}) or a computed value + * with an assigned alias using {@link @firebase/firestore/pipelines#Expression.(as:1)}. * * Example: * + * @example * ```typescript * firestore.pipeline().collection("books") * .addFields( @@ -183,9 +185,9 @@ export class Pipeline implements ProtoSerializable { * ); * ``` * - * @param field The first field to add to the documents, specified as a {@link Selectable}. - * @param additionalFields Optional additional fields to add to the documents, specified as {@link Selectable}s. - * @return A new Pipeline object with this stage appended to the stage list. + * @param field - The first field to add to the documents, specified as a {@link @firebase/firestore/pipelines#Selectable}. + * @param additionalFields - Optional additional fields to add to the documents, specified as {@link @firebase/firestore/pipelines#Selectable}s. + * @returns A new Pipeline object with this stage appended to the stage list. */ addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; /** @@ -196,14 +198,15 @@ export class Pipeline implements ProtoSerializable { * stages or constants. You can use this to create new fields or overwrite existing ones (if there * is name overlaps). * - * The added fields are defined using {@link Selectable}s, which can be: + * The added fields are defined using {@link @firebase/firestore/pipelines#Selectable}s, which can be: * - * - {@link Field}: References an existing document field. - * - {@link Expression}: Either a literal value (see {@link Constant}) or a computed value - * (see {@FunctionExpr}) with an assigned alias using {@link Expression#as}. + * - {@link @firebase/firestore/pipelines#Field}: References an existing document field. + * - {@link @firebase/firestore/pipelines#Expression}: Either a literal value (see {@link @firebase/firestore/pipelines#(constant:1)}) or a computed value + * with an assigned alias using {@link @firebase/firestore/pipelines#Expression.(as:1)}. * * Example: * + * @example * ```typescript * firestore.pipeline().collection("books") * .addFields( @@ -213,7 +216,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new Pipeline object with this stage appended to the stage list. + * @returns A new Pipeline object with this stage appended to the stage list. */ addFields(options: AddFieldsStageOptions): Pipeline; addFields( @@ -254,6 +257,7 @@ export class Pipeline implements ProtoSerializable { * * Example: * + * @example * ```typescript * firestore.pipeline().collection('books') * // removes field 'rating' and 'cost' from the previous stage outputs. @@ -263,9 +267,9 @@ export class Pipeline implements ProtoSerializable { * ); * ``` * - * @param fieldValue The first field to remove. - * @param additionalFields Optional additional fields to remove. - * @return A new Pipeline object with this stage appended to the stage list. + * @param fieldValue - The first field to remove. + * @param additionalFields - Optional additional fields to remove. + * @returns A new Pipeline object with this stage appended to the stage list. */ removeFields( fieldValue: Field | string, @@ -277,6 +281,7 @@ export class Pipeline implements ProtoSerializable { * * Example: * + * @example * ```typescript * firestore.pipeline().collection('books') * // removes field 'rating' and 'cost' from the previous stage outputs. @@ -287,7 +292,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new Pipeline object with this stage appended to the stage list. + * @returns A new Pipeline object with this stage appended to the stage list. */ removeFields(options: RemoveFieldsStageOptions): Pipeline; removeFields( @@ -326,21 +331,22 @@ export class Pipeline implements ProtoSerializable { * @beta * Selects or creates a set of fields from the outputs of previous stages. * - *

The selected fields are defined using {@link Selectable} expressions, which can be: + *

The selected fields are defined using {@link @firebase/firestore/pipelines#Selectable} expressions, which can be: * *

    - *
  • {@code string}: Name of an existing field
  • - *
  • {@link Field}: References an existing field.
  • - *
  • {@link Function}: Represents the result of a function with an assigned alias name using - * {@link Expression#as}
  • + *
  • `string` : Name of an existing field
  • + *
  • {@link @firebase/firestore/pipelines#Field}: References an existing field.
  • + *
  • {@link @firebase/firestore/pipelines#AliasedExpression}: Represents the result of a function with an assigned alias name using + * {@link @firebase/firestore/pipelines#Expression.(as:1)}
  • *
* *

If no selections are provided, the output of this stage is empty. Use {@link - * Pipeline#addFields} instead if only additions are + * @firebase/firestore/pipelines#Pipeline.(addFields:1)} instead if only additions are * desired. * *

Example: * + * @example * ```typescript * db.pipeline().collection("books") * .select( @@ -350,11 +356,11 @@ export class Pipeline implements ProtoSerializable { * ); * ``` * - * @param selection The first field to include in the output documents, specified as {@link - * Selectable} expression or string value representing the field name. - * @param additionalSelections Optional additional fields to include in the output documents, specified as {@link - * Selectable} expressions or {@code string} values representing field names. - * @return A new Pipeline object with this stage appended to the stage list. + * @param selection - The first field to include in the output documents, specified as {@link + * @firebase/firestore/pipelines#Selectable} expression or string value representing the field name. + * @param additionalSelections - Optional additional fields to include in the output documents, specified as {@link + * @firebase/firestore/pipelines#Selectable} expressions or `string` values representing field names. + * @returns A new Pipeline object with this stage appended to the stage list. */ select( selection: Selectable | string, @@ -364,21 +370,22 @@ export class Pipeline implements ProtoSerializable { * @beta * Selects or creates a set of fields from the outputs of previous stages. * - *

The selected fields are defined using {@link Selectable} expressions, which can be: + *

The selected fields are defined using {@link @firebase/firestore/pipelines#Selectable} expressions, which can be: * *

    - *
  • {@code string}: Name of an existing field
  • - *
  • {@link Field}: References an existing field.
  • - *
  • {@link Function}: Represents the result of a function with an assigned alias name using - * {@link Expression#as}
  • + *
  • `string`: Name of an existing field
  • + *
  • {@link @firebase/firestore/pipelines#Field}: References an existing field.
  • + *
  • {@link @firebase/firestore/pipelines#AliasedExpression}: Represents the result of a function with an assigned alias name using + * {@link @firebase/firestore/pipelines#Expression.(as:1)}
  • *
* *

If no selections are provided, the output of this stage is empty. Use {@link - * Pipeline#addFields} instead if only additions are + * @firebase/firestore/pipelines#Pipeline.(addFields:1)} instead if only additions are * desired. * *

Example: * + * @example * ```typescript * db.pipeline().collection("books") * .select( @@ -389,7 +396,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new Pipeline object with this stage appended to the stage list. + * @returns A new Pipeline object with this stage appended to the stage list. */ select(options: SelectStageOptions): Pipeline; select( @@ -429,22 +436,23 @@ export class Pipeline implements ProtoSerializable { /** * @beta * Filters the documents from previous stages to only include those matching the specified {@link - * BooleanExpression}. + * @firebase/firestore/pipelines#BooleanExpression}. * *

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. * You can filter documents based on their field values, using implementations of {@link - * BooleanExpression}, typically including but not limited to: + * @firebase/firestore/pipelines#BooleanExpression}, typically including but not limited to: * *

    - *
  • field comparators: {@link Function#eq}, {@link Function#lt} (less than), {@link - * Function#gt} (greater than), etc.
  • - *
  • logical operators: {@link Function#and}, {@link Function#or}, {@link Function#not}, etc.
  • - *
  • advanced functions: {@link Function#regexMatch}, {@link - * Function#arrayContains}, etc.
  • + *
  • field comparators: {@link @firebase/firestore/pipelines#Expression.(equal:1)}, {@link @firebase/firestore/pipelines#Expression.(lessThan:1)}, {@link + * @firebase/firestore/pipelines#Expression.(greaterThan:1)}, etc.
  • + *
  • logical operators: {@link @firebase/firestore/pipelines#Expression.(and:1)}, {@link @firebase/firestore/pipelines#Expression.(or:1)}, {@link @firebase/firestore/pipelines#Expression.(not:1)}, etc.
  • + *
  • advanced functions: {@link @firebase/firestore/pipelines#Expression.(regexMatch:1)}, {@link + * @firebase/firestore/pipelines#Expression.(arrayContains:1)}, etc.
  • *
* *

Example: * + * @example * ```typescript * firestore.pipeline().collection("books") * .where( @@ -455,29 +463,30 @@ export class Pipeline implements ProtoSerializable { * ); * ``` * - * @param condition The {@link BooleanExpression} to apply. - * @return A new Pipeline object with this stage appended to the stage list. + * @param condition - The {@link @firebase/firestore/pipelines#BooleanExpression} to apply. + * @returns A new Pipeline object with this stage appended to the stage list. */ where(condition: BooleanExpression): Pipeline; /** * @beta * Filters the documents from previous stages to only include those matching the specified {@link - * BooleanExpression}. + * @firebase/firestore/pipelines#BooleanExpression}. * *

This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. * You can filter documents based on their field values, using implementations of {@link - * BooleanExpression}, typically including but not limited to: + * @firebase/firestore/pipelines#BooleanExpression}, typically including but not limited to: * *

    - *
  • field comparators: {@link Function#eq}, {@link Function#lt} (less than), {@link - * Function#gt} (greater than), etc.
  • - *
  • logical operators: {@link Function#and}, {@link Function#or}, {@link Function#not}, etc.
  • - *
  • advanced functions: {@link Function#regexMatch}, {@link - * Function#arrayContains}, etc.
  • + *
  • field comparators: {@link @firebase/firestore/pipelines#Expression.(eq:1)}, {@link @firebase/firestore/pipelines#Expression.(lt:1)} (less than), {@link + * @firebase/firestore/pipelines#Expression.(greaterThan:1)}, etc.
  • + *
  • logical operators: {@link @firebase/firestore/pipelines#Expression.(and:1)}, {@link @firebase/firestore/pipelines#Expression.(or:1)}, {@link @firebase/firestore/pipelines#Expression.(not:1)}, etc.
  • + *
  • advanced functions: {@link @firebase/firestore/pipelines#Expression.(regexMatch:1)}, {@link + * @firebase/firestore/pipelines#Expression.(arrayContains:1)}, etc.
  • *
* *

Example: * + * @example * ```typescript * firestore.pipeline().collection("books") * .where( @@ -489,7 +498,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new Pipeline object with this stage appended to the stage list. + * @returns A new Pipeline object with this stage appended to the stage list. */ where(options: WhereStageOptions): Pipeline; where(conditionOrOptions: BooleanExpression | WhereStageOptions): Pipeline { @@ -519,11 +528,12 @@ export class Pipeline implements ProtoSerializable { * Skips the first `offset` number of documents from the results of previous stages. * *

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve - * results in chunks. It is typically used in conjunction with {@link #limit} to control the + * results in chunks. It is typically used in conjunction with {@link @firebase/firestore/pipelines#Pipeline.limit} to control the * size of each page. * *

Example: * + * @example * ```typescript * // Retrieve the second page of 20 results * firestore.pipeline().collection('books') @@ -532,8 +542,8 @@ export class Pipeline implements ProtoSerializable { * .limit(20); // Take the next 20 results * ``` * - * @param offset The number of documents to skip. - * @return A new Pipeline object with this stage appended to the stage list. + * @param offset - The number of documents to skip. + * @returns A new Pipeline object with this stage appended to the stage list. */ offset(offset: number): Pipeline; /** @@ -541,11 +551,12 @@ export class Pipeline implements ProtoSerializable { * Skips the first `offset` number of documents from the results of previous stages. * *

This stage is useful for implementing pagination in your pipelines, allowing you to retrieve - * results in chunks. It is typically used in conjunction with {@link #limit} to control the + * results in chunks. It is typically used in conjunction with {@link @firebase/firestore/pipelines#Pipeline.limit} to control the * size of each page. * *

Example: * + * @example * ```typescript * // Retrieve the second page of 20 results * firestore.pipeline().collection('books') @@ -555,7 +566,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new Pipeline object with this stage appended to the stage list. + * @returns A new Pipeline object with this stage appended to the stage list. */ offset(options: OffsetStageOptions): Pipeline; offset(offsetOrOptions: number | OffsetStageOptions): Pipeline { @@ -593,7 +604,7 @@ export class Pipeline implements ProtoSerializable { * a potentially large result set. It's often used for: * *

    - *
  • **Pagination:** In combination with {@link #offset} to retrieve specific pages of + *
  • **Pagination:** In combination with {@link @firebase/firestore/pipelines#Pipeline.offset} to retrieve specific pages of * results.
  • *
  • **Limiting Data Retrieval:** To prevent excessive data transfer and improve performance, * especially when dealing with large collections.
  • @@ -601,6 +612,7 @@ export class Pipeline implements ProtoSerializable { * *

    Example: * + * @example * ```typescript * // Limit the results to the top 10 highest-rated books * firestore.pipeline().collection('books') @@ -608,8 +620,8 @@ export class Pipeline implements ProtoSerializable { * .limit(10); * ``` * - * @param limit The maximum number of documents to return. - * @return A new Pipeline object with this stage appended to the stage list. + * @param limit - The maximum number of documents to return. + * @returns A new Pipeline object with this stage appended to the stage list. */ limit(limit: number): Pipeline; /** @@ -620,7 +632,7 @@ export class Pipeline implements ProtoSerializable { * a potentially large result set. It's often used for: * *

      - *
    • **Pagination:** In combination with {@link #offset} to retrieve specific pages of + *
    • **Pagination:** In combination with {@link @firebase/firestore/pipelines#Pipeline.offset} to retrieve specific pages of * results.
    • *
    • **Limiting Data Retrieval:** To prevent excessive data transfer and improve performance, * especially when dealing with large collections.
    • @@ -628,6 +640,7 @@ export class Pipeline implements ProtoSerializable { * *

      Example: * + * @example * ```typescript * // Limit the results to the top 10 highest-rated books * firestore.pipeline().collection('books') @@ -636,7 +649,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new Pipeline object with this stage appended to the stage list. + * @returns A new Pipeline object with this stage appended to the stage list. */ limit(options: LimitStageOptions): Pipeline; limit(limitOrOptions: number | LimitStageOptions): Pipeline { @@ -666,17 +679,18 @@ export class Pipeline implements ProtoSerializable { * Returns a set of distinct values from the inputs to this stage. * * This stage runs through the results from previous stages to include only results with - * unique combinations of {@link Expression} values ({@link Field}, {@link Function}, etc). + * unique combinations of {@link @firebase/firestore/pipelines#Expression} values ({@link @firebase/firestore/pipelines#Field}, {@link @firebase/firestore/pipelines#AliasedExpression}, etc). * - * The parameters to this stage are defined using {@link Selectable} expressions or strings: + * The parameters to this stage are defined using {@link @firebase/firestore/pipelines#Selectable} expressions or strings: * - * - {@code string}: Name of an existing field - * - {@link Field}: References an existing document field. - * - {@link AliasedExpr}: Represents the result of a function with an assigned alias name - * using {@link Expression#as}. + * - `string`: Name of an existing field + * - {@link @firebase/firestore/pipelines#Field}: References an existing document field. + * - {@link @firebase/firestore/pipelines#AliasedExpression}: Represents the result of a function with an assigned alias name + * using {@link @firebase/firestore/pipelines#Expression.(as:1)}. * * Example: * + * @example * ```typescript * // Get a list of unique author names in uppercase and genre combinations. * firestore.pipeline().collection("books") @@ -684,11 +698,11 @@ export class Pipeline implements ProtoSerializable { * .select("authorName"); * ``` * - * @param group The {@link Selectable} expression or field name to consider when determining + * @param group - The {@link @firebase/firestore/pipelines#Selectable} expression or field name to consider when determining * distinct value combinations. - * @param additionalGroups Optional additional {@link Selectable} expressions to consider when determining distinct + * @param additionalGroups - Optional additional {@link @firebase/firestore/pipelines#Selectable} expressions to consider when determining distinct * value combinations or strings representing field names. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ distinct( group: string | Selectable, @@ -699,17 +713,18 @@ export class Pipeline implements ProtoSerializable { * Returns a set of distinct values from the inputs to this stage. * * This stage runs through the results from previous stages to include only results with - * unique combinations of {@link Expression} values ({@link Field}, {@link Function}, etc). + * unique combinations of {@link @firebase/firestore/pipelines#Expression} values ({@link @firebase/firestore/pipelines#Field}, {@link @firebase/firestore/pipelines#AliasedExpression}, etc). * - * The parameters to this stage are defined using {@link Selectable} expressions or strings: + * The parameters to this stage are defined using {@link @firebase/firestore/pipelines#Selectable} expressions or strings: * - * - {@code string}: Name of an existing field - * - {@link Field}: References an existing document field. - * - {@link AliasedExpr}: Represents the result of a function with an assigned alias name - * using {@link Expression#as}. + * - `string`: Name of an existing field + * - {@link @firebase/firestore/pipelines#Field}: References an existing document field. + * - {@link @firebase/firestore/pipelines#AliasedExpression}: Represents the result of a function with an assigned alias name + * using {@link @firebase/firestore/pipelines#Expression.(as:1)}. * * Example: * + * @example * ```typescript * // Get a list of unique author names in uppercase and genre combinations. * firestore.pipeline().collection("books") @@ -718,7 +733,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ distinct(options: DistinctStageOptions): Pipeline; distinct( @@ -758,11 +773,12 @@ export class Pipeline implements ProtoSerializable { * Performs aggregation operations on the documents from previous stages. * *

      This stage allows you to calculate aggregate values over a set of documents. You define the - * aggregations to perform using {@link AliasedAggregate} expressions which are typically results of - * calling {@link Expression#as} on {@link AggregateFunction} instances. + * aggregations to perform using {@link @firebase/firestore/pipelines#AliasedAggregate} expressions which are typically results of + * calling {@link @firebase/firestore/pipelines#Expression.(as:1)} on {@link @firebase/firestore/pipelines#AggregateFunction} instances. * *

      Example: * + * @example * ```typescript * // Calculate the average rating and the total number of books * firestore.pipeline().collection("books") @@ -772,11 +788,11 @@ export class Pipeline implements ProtoSerializable { * ); * ``` * - * @param accumulator The first {@link AliasedAggregate}, wrapping an {@link AggregateFunction} + * @param accumulator - The first {@link @firebase/firestore/pipelines#AliasedAggregate}, wrapping an {@link @firebase/firestore/pipelines#AggregateFunction} * and providing a name for the accumulated results. - * @param additionalAccumulators Optional additional {@link AliasedAggregate}, each wrapping an {@link AggregateFunction} + * @param additionalAccumulators - Optional additional {@link @firebase/firestore/pipelines#AliasedAggregate}, each wrapping an {@link @firebase/firestore/pipelines#AggregateFunction} * and providing a name for the accumulated results. - * @return A new Pipeline object with this stage appended to the stage list. + * @returns A new Pipeline object with this stage appended to the stage list. */ aggregate( accumulator: AliasedAggregate, @@ -795,13 +811,14 @@ export class Pipeline implements ProtoSerializable { * If no grouping fields are provided, a single group containing all documents is used. Not * specifying groups is the same as putting the entire inputs into one group. *

    • **Accumulators:** One or more accumulation operations to perform within each group. These - * are defined using {@link AliasedAggregate} expressions, which are typically created by - * calling {@link Expression#as} on {@link AggregateFunction} instances. Each aggregation + * are defined using {@link @firebase/firestore/pipelines#AliasedAggregate} expressions, which are typically created by + * calling {@link @firebase/firestore/pipelines#Expression.(as:1)} on {@link @firebase/firestore/pipelines#AggregateFunction} instances. Each aggregation * calculates a value (e.g., sum, average, count) based on the documents within its group.
    • *
    * *

    Example: * + * @example * ```typescript * // Calculate the average rating for each genre. * firestore.pipeline().collection("books") @@ -812,7 +829,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new {@code Pipeline} object with this stage appended to the stage + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage * list. */ aggregate(options: AggregateStageOptions): Pipeline; @@ -879,7 +896,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ findNearest(options: FindNearestStageOptions): Pipeline { // Convert user land convenience types to internal types @@ -916,16 +933,17 @@ export class Pipeline implements ProtoSerializable { /** * @beta - * Sorts the documents from previous stages based on one or more {@link Ordering} criteria. + * Sorts the documents from previous stages based on one or more {@link @firebase/firestore/pipelines#Ordering} criteria. * *

    This stage allows you to order the results of your pipeline. You can specify multiple {@link - * Ordering} instances to sort by multiple fields in ascending or descending order. If documents + * @firebase/firestore/pipelines#Ordering} instances to sort by multiple fields in ascending or descending order. If documents * have the same value for a field used for sorting, the next specified ordering will be used. If * all orderings result in equal comparison, the documents are considered equal and the order is * unspecified. * *

    Example: * + * @example * ```typescript * // Sort books by rating in descending order, and then by title in ascending order for books * // with the same rating @@ -936,23 +954,24 @@ export class Pipeline implements ProtoSerializable { * ); * ``` * - * @param ordering The first {@link Ordering} instance specifying the sorting criteria. - * @param additionalOrderings Optional additional {@link Ordering} instances specifying the additional sorting criteria. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @param ordering - The first {@link @firebase/firestore/pipelines#Ordering} instance specifying the sorting criteria. + * @param additionalOrderings - Optional additional {@link @firebase/firestore/pipelines#Ordering} instances specifying the additional sorting criteria. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; /** * @beta - * Sorts the documents from previous stages based on one or more {@link Ordering} criteria. + * Sorts the documents from previous stages based on one or more {@link @firebase/firestore/pipelines#Ordering} criteria. * *

    This stage allows you to order the results of your pipeline. You can specify multiple {@link - * Ordering} instances to sort by multiple fields in ascending or descending order. If documents + * @firebase/firestore/pipelines#Ordering} instances to sort by multiple fields in ascending or descending order. If documents * have the same value for a field used for sorting, the next specified ordering will be used. If * all orderings result in equal comparison, the documents are considered equal and the order is * unspecified. * *

    Example: * + * @example * ```typescript * // Sort books by rating in descending order, and then by title in ascending order for books * // with the same rating @@ -964,7 +983,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ sort(options: SortStageOptions): Pipeline; sort( @@ -1001,6 +1020,7 @@ export class Pipeline implements ProtoSerializable { * *

    Example: * + * @example * ```typescript * // Input. * // { @@ -1021,8 +1041,8 @@ export class Pipeline implements ProtoSerializable { * // } * ``` * - * @param fieldName The {@link Field} field containing the nested map. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @param fieldName - The {@link @firebase/firestore/pipelines#Field} field containing the nested map. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ replaceWith(fieldName: string): Pipeline; /** @@ -1034,6 +1054,7 @@ export class Pipeline implements ProtoSerializable { * *

    Example: * + * @example * ```typescript * // Input. * // { @@ -1059,8 +1080,8 @@ export class Pipeline implements ProtoSerializable { * // } * ``` * - * @param expr An {@link Expression} that when returned evaluates to a map. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @param expr - An {@link @firebase/firestore/pipelines#Expression} that when returned evaluates to a map. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ replaceWith(expr: Expression): Pipeline; /** @@ -1072,6 +1093,7 @@ export class Pipeline implements ProtoSerializable { * *

    Example: * + * @example * ```typescript * // Input. * // { @@ -1098,7 +1120,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ replaceWith(options: ReplaceWithStageOptions): Pipeline; replaceWith( @@ -1139,14 +1161,15 @@ export class Pipeline implements ProtoSerializable { * *

    Examples: * + * @example * ```typescript * // Sample 25 books, if available. * firestore.pipeline().collection('books') * .sample(25); * ``` * - * @param documents The number of documents to sample. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @param documents - The number of documents to sample. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ sample(documents: number): Pipeline; @@ -1155,10 +1178,10 @@ export class Pipeline implements ProtoSerializable { * Performs a pseudo-random sampling of the documents from the previous stage. * *

    This stage will filter documents pseudo-randomly. The 'options' parameter specifies how - * sampling will be performed. See {@code SampleOptions} for more information. - * - *

    Examples: + * sampling will be performed. See {@link @firebase/firestore/pipelines#SampleStageOptions} for more information. * + * @example + * ```typescript * // Sample 10 books, if available. * firestore.pipeline().collection("books") * .sample({ documents: 10 }); @@ -1166,9 +1189,10 @@ export class Pipeline implements ProtoSerializable { * // Sample 50% of books. * firestore.pipeline().collection("books") * .sample({ percentage: 0.5 }); + * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ sample(options: SampleStageOptions): Pipeline; sample(documentsOrOptions: number | SampleStageOptions): Pipeline { @@ -1207,19 +1231,20 @@ export class Pipeline implements ProtoSerializable { * Performs union of all documents from two pipelines, including duplicates. * *

    This stage will pass through documents from previous stage, and also pass through documents - * from previous stage of the `other` {@code Pipeline} given in parameter. The order of documents + * from previous stage of the `other` {@link @firebase/firestore/pipelines#Pipeline} given in parameter. The order of documents * emitted from this stage is undefined. * *

    Example: * + * @example * ```typescript * // Emit documents from books collection and magazines collection. * firestore.pipeline().collection('books') * .union(firestore.pipeline().collection('magazines')); * ``` * - * @param other The other {@code Pipeline} that is part of union. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @param other - The other {@link @firebase/firestore/pipelines#Pipeline} that is part of union. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ union(other: Pipeline): Pipeline; /** @@ -1227,11 +1252,12 @@ export class Pipeline implements ProtoSerializable { * Performs union of all documents from two pipelines, including duplicates. * *

    This stage will pass through documents from previous stage, and also pass through documents - * from previous stage of the `other` {@code Pipeline} given in parameter. The order of documents + * from previous stage of the `other` {@link @firebase/firestore/pipelines#Pipeline} given in parameter. The order of documents * emitted from this stage is undefined. * *

    Example: * + * @example * ```typescript * // Emit documents from books collection and magazines collection. * firestore.pipeline().collection('books') @@ -1239,7 +1265,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ union(options: UnionStageOptions): Pipeline; union(otherOrOptions: Pipeline | UnionStageOptions): Pipeline { @@ -1283,6 +1309,7 @@ export class Pipeline implements ProtoSerializable { * * Example: * + * @example * ```typescript * // Input: * // { "title": "The Hitchhiker's Guide to the Galaxy", "tags": [ "comedy", "space", "adventure" ], ... } @@ -1297,9 +1324,9 @@ export class Pipeline implements ProtoSerializable { * // { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "adventure", "tagIndex": 2, ... } * ``` * - * @param selectable A selectable expression defining the field to unnest and the alias to use for each un-nested element in the output documents. - * @param indexField An optional string value specifying the field path to write the offset (starting at zero) into the array the un-nested element is from - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @param selectable - A selectable expression defining the field to unnest and the alias to use for each un-nested element in the output documents. + * @param indexField - An optional string value specifying the field path to write the offset (starting at zero) into the array the un-nested element is from + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ unnest(selectable: Selectable, indexField?: string): Pipeline; /** @@ -1317,6 +1344,7 @@ export class Pipeline implements ProtoSerializable { * * Example: * + * @example * ```typescript * // Input: * // { "title": "The Hitchhiker's Guide to the Galaxy", "tags": [ "comedy", "space", "adventure" ], ... } @@ -1332,7 +1360,7 @@ export class Pipeline implements ProtoSerializable { * ``` * * @param options - An object that specifies required and optional parameters for the stage. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ unnest(options: UnnestStageOptions): Pipeline; unnest( @@ -1387,6 +1415,7 @@ export class Pipeline implements ProtoSerializable { * *

    Example (Assuming there is no 'where' stage available in SDK): * + * @example * ```typescript * // Assume we don't have a built-in 'where' stage * firestore.pipeline().collection('books') @@ -1397,7 +1426,7 @@ export class Pipeline implements ProtoSerializable { * @param name - The unique name of the raw stage to add. * @param params - A list of parameters to configure the raw stage's behavior. * @param options - An object of key value pairs that specifies optional parameters for the stage. - * @return A new {@code Pipeline} object with this stage appended to the stage list. + * @returns A new {@link @firebase/firestore/pipelines#Pipeline} object with this stage appended to the stage list. */ rawStage( name: string, diff --git a/packages/firestore/src/lite-api/pipeline_impl.ts b/packages/firestore/src/lite-api/pipeline_impl.ts index dbfe96a099..fa0d480221 100644 --- a/packages/firestore/src/lite-api/pipeline_impl.ts +++ b/packages/firestore/src/lite-api/pipeline_impl.ts @@ -39,7 +39,7 @@ declare module './database' { interface Firestore { /** * @beta - * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link Pipeline}. + * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link @firebase/firestore/pipelines#Pipeline}. * * @example * ``` @@ -57,23 +57,22 @@ declare module './database' { * The returned Promise can be used to track the progress of the pipeline execution * and retrieve the results (or handle any errors) asynchronously. * - * The pipeline results are returned as a {@link PipelineSnapshot} that contains - * a list of {@link PipelineResult} objects. Each {@link PipelineResult} typically + * The pipeline results are returned as a {@link @firebase/firestore/pipelines#PipelineSnapshot} that contains + * a list of {@link @firebase/firestore/pipelines#PipelineResult} objects. Each {@link @firebase/firestore/pipelines#PipelineResult} typically * represents a single key/value map that has passed through all the * stages of the pipeline, however this might differ depending on the stages involved in the * pipeline. For example: * *

      - *
    • If there are no stages or only transformation stages, each {@link PipelineResult} + *
    • If there are no stages or only transformation stages, each {@link @firebase/firestore/pipelines#PipelineResult} * represents a single document.
    • - *
    • If there is an aggregation, only a single {@link PipelineResult} is returned, + *
    • If there is an aggregation, only a single {@link @firebase/firestore/pipelines#PipelineResult} is returned, * representing the aggregated results over the entire dataset .
    • - *
    • If there is an aggregation stage with grouping, each {@link PipelineResult} represents a + *
    • If there is an aggregation stage with grouping, each {@link @firebase/firestore/pipelines#PipelineResult} represents a * distinct group and its associated aggregated values.
    • *
    * - *

    Example: - * + * @example * ```typescript * const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") * .where(gt(field("rating"), 4.5)) @@ -82,8 +81,8 @@ declare module './database' { * const results: PipelineResults = snapshot.results; * ``` * - * @param pipeline The pipeline to execute. - * @return A Promise representing the asynchronous pipeline execution. + * @param pipeline - The pipeline to execute. + * @returns A Promise representing the asynchronous pipeline execution. */ export function execute(pipeline: Pipeline): Promise { const datastore = getDatastore(pipeline._db); @@ -132,7 +131,7 @@ export function execute(pipeline: Pipeline): Promise { /** * @beta - * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link Pipeline}. + * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link @firebase/firestore/pipelines#Pipeline}. * * @example * ``` diff --git a/packages/firestore/src/lite-api/pipeline_options.ts b/packages/firestore/src/lite-api/pipeline_options.ts index c46f42c856..8f8f9d6238 100644 --- a/packages/firestore/src/lite-api/pipeline_options.ts +++ b/packages/firestore/src/lite-api/pipeline_options.ts @@ -50,6 +50,7 @@ export interface PipelineExecuteOptions { * Values specified in rawOptions will take precedence over any options * with the same name set by the SDK. * + * @example * Override the `example_option`: * ``` * execute({ diff --git a/packages/firestore/src/lite-api/reference.ts b/packages/firestore/src/lite-api/reference.ts index 43eedecf8b..51bd24fefa 100644 --- a/packages/firestore/src/lite-api/reference.ts +++ b/packages/firestore/src/lite-api/reference.ts @@ -305,7 +305,7 @@ export class DocumentReference< * {@link DocumentReference.toJSON}. * * @param firestore - The {@link Firestore} instance the snapshot should be loaded for. - * @param json a JSON object represention of a `DocumentReference` instance + * @param json - a JSON object represention of a `DocumentReference` instance * @returns an instance of {@link DocumentReference} if the JSON object could be parsed. Throws a * {@link FirestoreError} if an error occurs. */ @@ -315,7 +315,7 @@ export class DocumentReference< * {@link DocumentReference.toJSON}. * * @param firestore - The {@link Firestore} instance the snapshot should be loaded for. - * @param json a JSON object represention of a `DocumentReference` instance + * @param json - a JSON object represention of a `DocumentReference` instance * @param converter - Converts objects to and from Firestore. * @returns an instance of {@link DocumentReference} if the JSON object could be parsed. Throws a * {@link FirestoreError} if an error occurs. diff --git a/packages/firestore/src/lite-api/stage.ts b/packages/firestore/src/lite-api/stage.ts index 5dd30eedba..1cca37d4f6 100644 --- a/packages/firestore/src/lite-api/stage.ts +++ b/packages/firestore/src/lite-api/stage.ts @@ -745,9 +745,9 @@ export class RawStage extends Stage { /** * Helper to read user data across a number of different formats. - * @param name Name of the calling function. Used for error messages when invalid user data is encountered. + * @param name - Name of the calling function. Used for error messages when invalid user data is encountered. * @param expressionMap - * @return the expressionMap argument. + * @returns the expressionMap argument. * @private */ function readUserDataHelper< diff --git a/packages/firestore/src/lite-api/stage_options.ts b/packages/firestore/src/lite-api/stage_options.ts index ea9ff08823..ba53580bd1 100644 --- a/packages/firestore/src/lite-api/stage_options.ts +++ b/packages/firestore/src/lite-api/stage_options.ts @@ -59,7 +59,7 @@ export interface StageOptions { } /** * @beta - * Options defining how a CollectionStage is evaluated. See {@link PipelineSource.collection}. + * Options defining how a CollectionStage is evaluated. See {@link @firebase/firestore/pipelines#PipelineSource.(collection:1)}. */ export type CollectionStageOptions = StageOptions & { /** @@ -81,11 +81,11 @@ export type CollectionStageOptions = StageOptions & { /** * @beta - * Defines the configuration options for a {@link CollectionGroupStage} within a pipeline. - * This type extends {@link StageOptions} and provides specific settings for how a collection group + * Defines the configuration options for a CollectionGroupStage within a pipeline. + * This type extends {@link @firebase/firestore/pipelines#StageOptions} and provides specific settings for how a collection group * is identified and processed during pipeline execution. * - * @see {@link PipelineSource.collectionGroup} to create a collection group stage. + * See {@link @firebase/firestore/pipelines#PipelineSource.(collectionGroup:1)} to create a collection group stage. */ export type CollectionGroupStageOptions = StageOptions & { /** @@ -106,12 +106,12 @@ export type CollectionGroupStageOptions = StageOptions & { }; /** * @beta - * Options defining how a DatabaseStage is evaluated. See {@link PipelineSource.database}. + * Options defining how a DatabaseStage is evaluated. See {@link @firebase/firestore/pipelines#PipelineSource.(database:1)}. */ export type DatabaseStageOptions = StageOptions & {}; /** * @beta - * Options defining how a DocumentsStage is evaluated. See {@link PipelineSource.documents}. + * Options defining how a DocumentsStage is evaluated. See {@link @firebase/firestore/pipelines#PipelineSource.(documents:1)}. */ export type DocumentsStageOptions = StageOptions & { /** @@ -124,19 +124,19 @@ export type DocumentsStageOptions = StageOptions & { }; /** * @beta - * Options defining how an AddFieldsStage is evaluated. See {@link Pipeline.addFields}. + * Options defining how an AddFieldsStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(addFields:1)}. */ export type AddFieldsStageOptions = StageOptions & { /** * @beta - * The fields to add to each document, specified as a {@link Selectable}. + * The fields to add to each document, specified as a {@link @firebase/firestore/pipelines#Selectable}. * At least one field is required. */ fields: Selectable[]; }; /** * @beta - * Options defining how a RemoveFieldsStage is evaluated. See {@link Pipeline.removeFields}. + * Options defining how a RemoveFieldsStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(removeFields:1)}. */ export type RemoveFieldsStageOptions = StageOptions & { /** @@ -147,30 +147,30 @@ export type RemoveFieldsStageOptions = StageOptions & { }; /** * @beta - * Options defining how a SelectStage is evaluated. See {@link Pipeline.select}. + * Options defining how a SelectStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(select:1)}. */ export type SelectStageOptions = StageOptions & { /** * @beta - * The fields to include in the output documents, specified as {@link Selectable} expression + * The fields to include in the output documents, specified as {@link @firebase/firestore/pipelines#Selectable} expression * or as a string value indicating the field name. */ selections: Array; }; /** * @beta - * Options defining how a WhereStage is evaluated. See {@link Pipeline.where}. + * Options defining how a WhereStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(where:1)}. */ export type WhereStageOptions = StageOptions & { /** * @beta - * The {@link BooleanExpression} to apply as a filter for each input document to this stage. + * The {@link @firebase/firestore/pipelines#BooleanExpression} to apply as a filter for each input document to this stage. */ condition: BooleanExpression; }; /** * @beta - * Options defining how an OffsetStage is evaluated. See {@link Pipeline.offset}. + * Options defining how an OffsetStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(offset:1)}. */ export type OffsetStageOptions = StageOptions & { /** @@ -181,7 +181,7 @@ export type OffsetStageOptions = StageOptions & { }; /** * @beta - * Options defining how a LimitStage is evaluated. See {@link Pipeline.limit}. + * Options defining how a LimitStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(limit:1)}. */ export type LimitStageOptions = StageOptions & { /** @@ -192,12 +192,12 @@ export type LimitStageOptions = StageOptions & { }; /** * @beta - * Options defining how a DistinctStage is evaluated. See {@link Pipeline.distinct}. + * Options defining how a DistinctStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(distinct:1)}. */ export type DistinctStageOptions = StageOptions & { /** * @beta - * The {@link Selectable} expressions or field names to consider when determining + * The {@link @firebase/firestore/pipelines#Selectable} expressions or field names to consider when determining * distinct value combinations (groups). */ groups: Array; @@ -205,31 +205,31 @@ export type DistinctStageOptions = StageOptions & { /** * @beta - * Options defining how an AggregateStage is evaluated. See {@link Pipeline.aggregate}. + * Options defining how an AggregateStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(aggregate:1)}. */ export type AggregateStageOptions = StageOptions & { /** * @beta - * The {@link AliasedAggregate} values specifying aggregate operations to + * The {@link @firebase/firestore/pipelines#AliasedAggregate} values specifying aggregate operations to * perform on the input documents. */ accumulators: AliasedAggregate[]; /** * @beta - * The {@link Selectable} expressions or field names to consider when determining + * The {@link @firebase/firestore/pipelines#Selectable} expressions or field names to consider when determining * distinct value combinations (groups), which will be aggregated over. */ groups?: Array; }; /** * @beta - * Options defining how a FindNearestStage is evaluated. See {@link Pipeline.findNearest}. + * Options defining how a FindNearestStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(findNearest:1)}. */ export type FindNearestStageOptions = StageOptions & { /** * @beta * Specifies the field to be used. This can be a string representing the field path - * (e.g., 'fieldName', 'nested.fieldName') or an object of type {@link Field} + * (e.g., 'fieldName', 'nested.fieldName') or an object of type {@link @firebase/firestore/pipelines#Field} * representing a more complex field expression. */ field: Field | string; @@ -263,12 +263,12 @@ export type FindNearestStageOptions = StageOptions & { }; /** * @beta - * Options defining how a ReplaceWithStage is evaluated. See {@link Pipeline.replaceWith}. + * Options defining how a ReplaceWithStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(replaceWith:1)}. */ export type ReplaceWithStageOptions = StageOptions & { /** * @beta - * The name of a field that contains a map or an {@link Expression} that + * The name of a field that contains a map or an {@link @firebase/firestore/pipelines#Expression} that * evaluates to a map. */ map: Expression | string; @@ -276,10 +276,10 @@ export type ReplaceWithStageOptions = StageOptions & { /** * @beta * Defines the options for evaluating a sample stage within a pipeline. - * This type combines common {@link StageOptions} with a specific configuration + * This type combines common {@link @firebase/firestore/pipelines#StageOptions} with a specific configuration * where only one of the defined sampling methods can be applied. * - * See {@link Pipeline.sample} to create a sample stage.. + * See {@link @firebase/firestore/pipelines#Pipeline.(sample:1)} to create a sample stage.. */ export type SampleStageOptions = StageOptions & OneOf<{ @@ -302,7 +302,7 @@ export type SampleStageOptions = StageOptions & }>; /** * @beta - * Options defining how a UnionStage is evaluated. See {@link Pipeline.union}. + * Options defining how a UnionStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(union:1)}. */ export type UnionStageOptions = StageOptions & { /** @@ -333,7 +333,7 @@ export type UnnestStageOptions = StageOptions & { /** * @beta * @beta - * Options defining how a SortStage is evaluated. See {@link Pipeline.sort}. + * Options defining how a SortStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(sort:1)}. */ export type SortStageOptions = StageOptions & { /** diff --git a/packages/firestore/src/lite-api/vector_value.ts b/packages/firestore/src/lite-api/vector_value.ts index c48feaeff3..96bf9d5fe5 100644 --- a/packages/firestore/src/lite-api/vector_value.ts +++ b/packages/firestore/src/lite-api/vector_value.ts @@ -24,8 +24,6 @@ import { Property, property, validateJSON } from '../util/json_validation'; /** * Represents a vector type in Firestore documents. * Create an instance with {@link vector}. - * - * @class VectorValue */ export class VectorValue { private readonly _values: number[]; @@ -74,7 +72,7 @@ export class VectorValue { /** * Builds a `VectorValue` instance from a JSON object created by {@link VectorValue.toJSON}. * - * @param json a JSON object represention of a `VectorValue` instance. + * @param json - a JSON object represention of a `VectorValue` instance. * @returns an instance of {@link VectorValue} if the JSON object could be parsed. Throws a * {@link FirestoreError} if an error occurs. */ diff --git a/packages/firestore/src/local/document_overlay_cache.ts b/packages/firestore/src/local/document_overlay_cache.ts index 8cfb5412d5..471b1b7538 100644 --- a/packages/firestore/src/local/document_overlay_cache.ts +++ b/packages/firestore/src/local/document_overlay_cache.ts @@ -96,7 +96,7 @@ export interface DocumentOverlayCache { * Only overlays that contain a change past `sinceBatchId` are returned. * @param count - The number of overlays to return. Can be exceeded if the last * batch contains more entries. - * @return Mapping of each document key in the collection group to its overlay. + * @returns Mapping of each document key in the collection group to its overlay. */ getOverlaysForCollectionGroup( transaction: PersistenceTransaction, diff --git a/packages/firestore/src/local/index_manager.ts b/packages/firestore/src/local/index_manager.ts index d81693acc6..e0ab95f19a 100644 --- a/packages/firestore/src/local/index_manager.ts +++ b/packages/firestore/src/local/index_manager.ts @@ -120,9 +120,9 @@ export interface IndexManager { * Returns a list of field indexes that correspond to the specified collection * group. * - * @param collectionGroup The collection group to get matching field indexes + * @param collectionGroup - The collection group to get matching field indexes * for. - * @return A collection of field indexes for the specified collection group. + * @returns A collection of field indexes for the specified collection group. */ getFieldIndexes( transaction: PersistenceTransaction, diff --git a/packages/firestore/src/local/local_documents_view.ts b/packages/firestore/src/local/local_documents_view.ts index fa64ed76eb..5010e9b800 100644 --- a/packages/firestore/src/local/local_documents_view.ts +++ b/packages/firestore/src/local/local_documents_view.ts @@ -210,7 +210,7 @@ export class LocalDocumentsView { * @param existenceStateChanged - A set of documents whose existence states * might have changed. This is used to determine if we need to re-calculate * overlays from mutation queues. - * @return A map represents the local documents view. + * @returns A map represents the local documents view. */ computeViews( transaction: PersistenceTransaction, @@ -394,10 +394,10 @@ export class LocalDocumentsView { * returned together, the total number of documents returned can exceed {@code count}. * * @param transaction - * @param collectionGroup The collection group for the documents. - * @param offset The offset to index into. - * @param count The number of documents to return - * @return A LocalWriteResult with the documents that follow the provided offset and the last processed batch id. + * @param collectionGroup - The collection group for the documents. + * @param offset - The offset to index into. + * @param count - The number of documents to return + * @returns A LocalWriteResult with the documents that follow the provided offset and the last processed batch id. */ getNextDocuments( transaction: PersistenceTransaction, diff --git a/packages/firestore/src/local/shared_client_state.ts b/packages/firestore/src/local/shared_client_state.ts index 1000e63a0f..5829d5ee8d 100644 --- a/packages/firestore/src/local/shared_client_state.ts +++ b/packages/firestore/src/local/shared_client_state.ts @@ -182,7 +182,7 @@ export interface SharedClientState { * Notifies other clients when remote documents have changed due to loading * a bundle. * - * @param collectionGroups The collection groups affected by this bundle. + * @param collectionGroups - The collection groups affected by this bundle. */ notifyBundleLoaded(collectionGroups: Set): void; } diff --git a/packages/firestore/src/util/array.ts b/packages/firestore/src/util/array.ts index 3427abcf67..9695ae1cb4 100644 --- a/packages/firestore/src/util/array.ts +++ b/packages/firestore/src/util/array.ts @@ -117,9 +117,9 @@ export function diffArrays( * * @private * @internal - * @param left Array of objects supporting `isEqual`. - * @param right Array of objects supporting `isEqual`. - * @return True if arrays are equal. + * @param left - Array of objects supporting `isEqual`. + * @param right - Array of objects supporting `isEqual`. + * @returns True if arrays are equal. */ export function isArrayEqual boolean }>( left: T[], @@ -143,9 +143,9 @@ export function isArrayEqual boolean }>( * * @private * @internal - * @param left Array of primitives. - * @param right Array of primitives. - * @return True if arrays are equal. + * @param left - Array of primitives. + * @param right - Array of primitives. + * @returns True if arrays are equal. */ export function isPrimitiveArrayEqual( left: T[], diff --git a/packages/firestore/src/util/assert.ts b/packages/firestore/src/util/assert.ts index 07ebe775e9..7c9c570695 100644 --- a/packages/firestore/src/util/assert.ts +++ b/packages/firestore/src/util/assert.ts @@ -27,7 +27,7 @@ import { logError } from './log'; * @example * let futureVar = fail('not implemented yet'); * - * @param code generate a new unique value with `yarn assertion-id:generate` + * @param code - generate a new unique value with `yarn assertion-id:generate` * Search for an existing value using `yarn assertion-id:find X` */ export function fail( @@ -44,7 +44,7 @@ export function fail( * @example * let futureVar = fail('not implemented yet'); * - * @param id generate a new unique value with `yarn assertion-id:generate` + * @param id - generate a new unique value with `yarn assertion-id:generate` * Search for an existing value using `yarn assertion-id:find X` */ export function fail(id: number, context?: Record): never; @@ -95,7 +95,7 @@ function _fail( * * Messages are stripped in production builds. * - * @param id generate a new unique value with `yarn assertion-idgenerate`. + * @param id - generate a new unique value with `yarn assertion-idgenerate`. * Search for an existing value using `yarn assertion-id:find X` */ export function hardAssert( @@ -111,7 +111,7 @@ export function hardAssert( * * Messages are stripped in production builds. * - * @param id generate a new unique value with `yarn assertion-id:generate`. + * @param id - generate a new unique value with `yarn assertion-id:generate`. * Search for an existing value using `yarn assertion-id:find X` */ export function hardAssert( diff --git a/packages/firestore/src/util/async_queue.ts b/packages/firestore/src/util/async_queue.ts index 09171a9f03..2d07ffb815 100644 --- a/packages/firestore/src/util/async_queue.ts +++ b/packages/firestore/src/util/async_queue.ts @@ -235,7 +235,7 @@ export interface AsyncQueue { * only possible way to request running an operation is through * `enqueueEvenWhileRestricted()`. * - * @param purgeExistingTasks Whether already enqueued tasked should be + * @param purgeExistingTasks - Whether already enqueued tasked should be * rejected (unless enqueued with `enqueueEvenWhileRestricted()`). Defaults * to false. */ diff --git a/packages/firestore/src/util/bundle_builder_impl.ts b/packages/firestore/src/util/bundle_builder_impl.ts index dc94ebca49..a57d53f130 100644 --- a/packages/firestore/src/util/bundle_builder_impl.ts +++ b/packages/firestore/src/util/bundle_builder_impl.ts @@ -86,10 +86,10 @@ export class BundleBuilder { /** * Adds data from a DocumentSnapshot to the bundle. * @internal - * @param docBundleData A DocumentSnapshotBundleData containing information from the + * @param docBundleData - A DocumentSnapshotBundleData containing information from the * DocumentSnapshot. Note we cannot accept a DocumentSnapshot directly due to a circular * dependency error. - * @param queryName The name of the QuerySnapshot if this document is part of a Query. + * @param queryName - The name of the QuerySnapshot if this document is part of a Query. */ addBundleDocument( docBundleData: DocumentSnapshotBundleData, @@ -134,7 +134,7 @@ export class BundleBuilder { /** * Adds data from a QuerySnapshot to the bundle. * @internal - * @param docBundleData A QuerySnapshotBundleData containing information from the + * @param docBundleData - A QuerySnapshotBundleData containing information from the * QuerySnapshot. Note we cannot accept a QuerySnapshot directly due to a circular * dependency error. */ @@ -168,7 +168,7 @@ export class BundleBuilder { * Convert data from a DocumentSnapshot into the serialized form within a bundle. * @private * @internal - * @param docBundleData a DocumentSnapshotBundleData containing the data required to + * @param docBundleData - a DocumentSnapshotBundleData containing the data required to * serialize a document. */ private toBundleDocument( @@ -195,7 +195,7 @@ export class BundleBuilder { * of the element. * @private * @internal - * @param bundleElement A ProtoBundleElement that is expected to be Proto3 JSON compatible. + * @param bundleElement - A ProtoBundleElement that is expected to be Proto3 JSON compatible. */ private lengthPrefixedString(bundleElement: ProtoBundleElement): string { const str = JSON.stringify(bundleElement); diff --git a/packages/firestore/src/util/bundle_reader_sync_impl.ts b/packages/firestore/src/util/bundle_reader_sync_impl.ts index 9379bb5a5a..b1f0db2e44 100644 --- a/packages/firestore/src/util/bundle_reader_sync_impl.ts +++ b/packages/firestore/src/util/bundle_reader_sync_impl.ts @@ -80,7 +80,7 @@ export class BundleReaderSyncImpl implements BundleReaderSync { * Reads from a specified position from the bundleData string, for a specified * number of bytes. * - * @param length how many characters to read. + * @param length - how many characters to read. * @returns a string parsed from the bundle. */ private readJsonString(length: number): string { diff --git a/packages/firestore/src/util/debug_uid.ts b/packages/firestore/src/util/debug_uid.ts index d5dac6a134..da035fcf3c 100644 --- a/packages/firestore/src/util/debug_uid.ts +++ b/packages/firestore/src/util/debug_uid.ts @@ -49,7 +49,7 @@ function generateInitialUniqueDebugId(): number { * "debug ID" string in all of its log messages to help trace a specific * connection over time. * - * @return the 10-character generated ID (e.g. "0xa1b2c3d4"). + * @returns the 10-character generated ID (e.g. "0xa1b2c3d4"). */ export function generateUniqueDebugId(): string { if (lastUniqueDebugId === null) { diff --git a/packages/firestore/src/util/json_validation.ts b/packages/firestore/src/util/json_validation.ts index 771a7f91ef..b4bc4f6018 100644 --- a/packages/firestore/src/util/json_validation.ts +++ b/packages/firestore/src/util/json_validation.ts @@ -103,8 +103,8 @@ export function property( * @private * @internal * - * @param json A JSON object to validate. - * @param scheme a {@link JsonSchema} that defines the properties to validate. + * @param json - A JSON object to validate. + * @param scheme - a {@link JsonSchema} that defines the properties to validate. * @returns true if the JSON schema exists within the object. Throws a FirestoreError otherwise. */ export function validateJSON( diff --git a/packages/firestore/src/util/logic_utils.ts b/packages/firestore/src/util/logic_utils.ts index b2167c385e..f9fed07786 100644 --- a/packages/firestore/src/util/logic_utils.ts +++ b/packages/firestore/src/util/logic_utils.ts @@ -77,8 +77,8 @@ export function computeInExpansion(filter: Filter): Filter { * with two elements: a composite filter that performs (A && C), and a composite filter that * performs (B && C). * - * @param filter the composite filter to calculate DNF transform for. - * @return the terms in the DNF transform. + * @param filter - the composite filter to calculate DNF transform for. + * @returns the terms in the DNF transform. */ export function getDnfTerms(filter: CompositeFilter): Filter[] { if (filter.getFilters().length === 0) { diff --git a/packages/firestore/src/util/pipeline_util.ts b/packages/firestore/src/util/pipeline_util.ts index a7400828fd..d191e08e10 100644 --- a/packages/firestore/src/util/pipeline_util.ts +++ b/packages/firestore/src/util/pipeline_util.ts @@ -88,7 +88,7 @@ export function aliasedAggregateToMap( } /** - * Converts a value to an Expr, Returning either a Constant, MapFunction, + * Converts a value to an Expression, Returning either a Constant, MapFunction, * ArrayFunction, or the input itself (if it's already an expression). * * @private @@ -112,7 +112,7 @@ export function vectorToExpr( } /** - * Converts a value to an Expr, Returning either a Constant, MapFunction, + * 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. @@ -130,7 +130,7 @@ export function fieldOrExpression(value: unknown): Expression { } } /** - * Converts a value to an Expr, Returning either a Constant, MapFunction, + * Converts a value to an Expression, Returning either a Constant, MapFunction, * ArrayFunction, or the input itself (if it's already an expression). * * @private diff --git a/packages/firestore/src/util/testing_hooks.ts b/packages/firestore/src/util/testing_hooks.ts index 36422172a4..6c9aa955f7 100644 --- a/packages/firestore/src/util/testing_hooks.ts +++ b/packages/firestore/src/util/testing_hooks.ts @@ -43,9 +43,9 @@ export class TestingHooks { * rely on any particular ordering. If a given callback is registered multiple * times then it will be notified multiple times, once per registration. * - * @param callback the callback to invoke upon existence filter mismatch. + * @param callback - the callback to invoke upon existence filter mismatch. * - * @return a function that, when called, unregisters the given callback; only + * @returns a function that, when called, unregisters the given callback; only * the first invocation of the returned function does anything; all subsequent * invocations do nothing. */ diff --git a/packages/firestore/src/util/testing_hooks_spi.ts b/packages/firestore/src/util/testing_hooks_spi.ts index e6c729e366..3abcf50e3f 100644 --- a/packages/firestore/src/util/testing_hooks_spi.ts +++ b/packages/firestore/src/util/testing_hooks_spi.ts @@ -26,7 +26,7 @@ export let testingHooksSpi: TestingHooksSpi | null = null; /** * Sets the value of the `testingHooksSpi` object. - * @param instance the instance to set. + * @param instance - the instance to set. */ export function setTestingHooksSpi(instance: TestingHooksSpi): void { if (testingHooksSpi) { diff --git a/packages/firestore/src/util/types.ts b/packages/firestore/src/util/types.ts index ad272991ff..b5dd09fbbc 100644 --- a/packages/firestore/src/util/types.ts +++ b/packages/firestore/src/util/types.ts @@ -79,10 +79,13 @@ export interface DocumentLike { * Utility type to create an type that only allows one * property of the Type param T to be set. * - * type XorY = OneOf<{ x: unknown, y: unknown}> + * @example + * ``` + * type XorY = OneOf<{ x: unknown, y: unknown }> * let a = { x: "foo" } // OK * let b = { y: "foo" } // OK * let c = { a: "foo", y: "foo" } // Not OK + * ``` */ export type OneOf = { [K in keyof T]: Pick & { From f044045fcde44bf040d62c494712d5d24cdae4b9 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 8 Jan 2026 15:55:36 -0800 Subject: [PATCH 034/174] fix(ai): update hybrid in-cloud default model to gemini 2.5 flash lite (#9440) --- .changeset/spicy-ways-yawn.md | 6 ++++++ packages/ai/src/constants.ts | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 .changeset/spicy-ways-yawn.md diff --git a/.changeset/spicy-ways-yawn.md b/.changeset/spicy-ways-yawn.md new file mode 100644 index 0000000000..c18413247c --- /dev/null +++ b/.changeset/spicy-ways-yawn.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +Update default hybrid-in-cloud model to `gemini-2.5-flash-lite`. diff --git a/packages/ai/src/constants.ts b/packages/ai/src/constants.ts index 0a6f7e9143..82ea4c7a9f 100644 --- a/packages/ai/src/constants.ts +++ b/packages/ai/src/constants.ts @@ -37,4 +37,4 @@ export const DEFAULT_FETCH_TIMEOUT_MS = 180 * 1000; /** * Defines the name of the default in-cloud model to use for hybrid inference. */ -export const DEFAULT_HYBRID_IN_CLOUD_MODEL = 'gemini-2.0-flash-lite'; +export const DEFAULT_HYBRID_IN_CLOUD_MODEL = 'gemini-2.5-flash-lite'; From 6b3aecfe74293b1763686b351502cc0eb31c2fe5 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Fri, 9 Jan 2026 09:57:56 -0800 Subject: [PATCH 035/174] build(firestore): Strip forgotten export warnings from pipelines api reports (#9443) --- .../firestore-lite-pipelines.api.md | 18 --------------- common/api-review/firestore-pipelines.api.md | 18 --------------- packages/firestore/package.json | 4 ++-- repo-scripts/prune-dts/extract-public-api.ts | 23 ++++++++++++++----- 4 files changed, 19 insertions(+), 44 deletions(-) diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index b19de978f9..bc30c5c449 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -211,31 +211,21 @@ export function constant(value: boolean): BooleanExpression; // @beta export function constant(value: null): Expression; -// Warning: (ae-forgotten-export) The symbol "GeoPoint" needs to be exported by the entry point pipelines.d.ts -// // @beta export function constant(value: GeoPoint): Expression; -// Warning: (ae-forgotten-export) The symbol "Timestamp" needs to be exported by the entry point pipelines.d.ts -// // @beta export function constant(value: Timestamp): Expression; // @beta export function constant(value: Date): Expression; -// Warning: (ae-forgotten-export) The symbol "Bytes" needs to be exported by the entry point pipelines.d.ts -// // @beta export function constant(value: Bytes): Expression; -// Warning: (ae-forgotten-export) The symbol "DocumentReference" needs to be exported by the entry point pipelines.d.ts -// // @beta export function constant(value: DocumentReference): Expression; -// Warning: (ae-forgotten-export) The symbol "VectorValue" needs to be exported by the entry point pipelines.d.ts -// // @beta export function constant(value: VectorValue): Expression; @@ -649,8 +639,6 @@ export class Field extends Expression implements Selectable { // @beta export function field(name: string): Field; -// Warning: (ae-forgotten-export) The symbol "FieldPath" needs to be exported by the entry point pipelines.d.ts -// // @beta export function field(path: FieldPath): Field; @@ -976,8 +964,6 @@ export class Pipeline { where(options: WhereStageOptions): Pipeline; } -// Warning: (ae-forgotten-export) The symbol "DocumentData" needs to be exported by the entry point pipelines.d.ts -// // @beta export class PipelineResult { /* Excluded from this release type: _ref */ @@ -1307,10 +1293,6 @@ export type WhereStageOptions = StageOptions & { export function xor(first: BooleanExpression, second: BooleanExpression, ...additionalConditions: BooleanExpression[]): BooleanExpression; -// Warnings were encountered during analysis: -// -// /Users/markduckworth/projects/firebase-js-sdk/packages/firestore/dist/lite/pipelines.d.ts:830:5 - (ae-forgotten-export) The symbol "Query" needs to be exported by the entry point pipelines.d.ts - // (No @packageDocumentation comment for this package) ``` diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 2d701d9058..38e61acd96 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -211,31 +211,21 @@ export function constant(value: boolean): BooleanExpression; // @beta export function constant(value: null): Expression; -// Warning: (ae-forgotten-export) The symbol "GeoPoint" needs to be exported by the entry point pipelines.d.ts -// // @beta export function constant(value: GeoPoint): Expression; -// Warning: (ae-forgotten-export) The symbol "Timestamp" needs to be exported by the entry point pipelines.d.ts -// // @beta export function constant(value: Timestamp): Expression; // @beta export function constant(value: Date): Expression; -// Warning: (ae-forgotten-export) The symbol "Bytes" needs to be exported by the entry point pipelines.d.ts -// // @beta export function constant(value: Bytes): Expression; -// Warning: (ae-forgotten-export) The symbol "DocumentReference" needs to be exported by the entry point pipelines.d.ts -// // @beta export function constant(value: DocumentReference): Expression; -// Warning: (ae-forgotten-export) The symbol "VectorValue" needs to be exported by the entry point pipelines.d.ts -// // @beta export function constant(value: VectorValue): Expression; @@ -652,8 +642,6 @@ export class Field extends Expression implements Selectable { // @beta export function field(name: string): Field; -// Warning: (ae-forgotten-export) The symbol "FieldPath" needs to be exported by the entry point pipelines.d.ts -// // @beta export function field(path: FieldPath): Field; @@ -1010,8 +998,6 @@ export interface PipelineExecuteOptions { }; } -// Warning: (ae-forgotten-export) The symbol "DocumentData" needs to be exported by the entry point pipelines.d.ts -// // @beta export class PipelineResult { /* Excluded from this release type: _ref */ @@ -1344,10 +1330,6 @@ export type WhereStageOptions = StageOptions & { export function xor(first: BooleanExpression, second: BooleanExpression, ...additionalConditions: BooleanExpression[]): BooleanExpression; -// Warnings were encountered during analysis: -// -// /Users/markduckworth/projects/firebase-js-sdk/packages/firestore/dist/pipelines.d.ts:827:5 - (ae-forgotten-export) The symbol "Query" needs to be exported by the entry point pipelines.d.ts - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 9eef54816a..9311f404c9 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -51,9 +51,9 @@ "test:minified": "(cd ../../integration/firestore ; yarn test)", "trusted-type-check": "tsec -p tsconfig.json --noEmit", "api-report:main": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore --packageRoot . --typescriptDts ./dist/firestore/src/index.d.ts --rollupDts ./dist/private.d.ts --untrimmedRollupDts ./dist/internal.d.ts --publicDts ./dist/index.d.ts", - "api-report:pipelines": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-pipelines --packageRoot . --typescriptDts ./dist/firestore/pipelines/pipelines.d.ts --rollupDts ./dist/private.pipelines.d.ts --untrimmedRollupDts ./dist/internal.pipelines.d.ts --publicDts ./dist/pipelines.d.ts --otherExportsPublicDtsFiles ./dist/index.d.ts", + "api-report:pipelines": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-pipelines --packageRoot . --typescriptDts ./dist/firestore/pipelines/pipelines.d.ts --rollupDts ./dist/private.pipelines.d.ts --untrimmedRollupDts ./dist/internal.pipelines.d.ts --publicDts ./dist/pipelines.d.ts --otherExportsPublicDtsFiles ./dist/index.d.ts --excludeForgottenExportWarning", "api-report:lite": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-lite --packageRoot . --typescriptDts ./dist/firestore/lite/index.d.ts --rollupDts ./dist/lite/private.d.ts --untrimmedRollupDts ./dist/lite/internal.d.ts --publicDts ./dist/lite/index.d.ts", - "api-report:lite:pipelines": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-lite-pipelines --packageRoot . --typescriptDts ./dist/firestore/lite/pipelines/pipelines.d.ts --rollupDts ./dist/lite/private.pipelines.d.ts --untrimmedRollupDts ./dist/lite/internal.pipelines.d.ts --publicDts ./dist/lite/pipelines.d.ts --otherExportsPublicDtsFiles ./dist/lite/index.d.ts", + "api-report:lite:pipelines": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-lite-pipelines --packageRoot . --typescriptDts ./dist/firestore/lite/pipelines/pipelines.d.ts --rollupDts ./dist/lite/private.pipelines.d.ts --untrimmedRollupDts ./dist/lite/internal.pipelines.d.ts --publicDts ./dist/lite/pipelines.d.ts --otherExportsPublicDtsFiles ./dist/lite/index.d.ts --excludeForgottenExportWarning", "api-report:api-json": "rm -rf temp && api-extractor run --local --verbose", "api-report": "run-s --npm-path npm api-report:main api-report:pipelines api-report:lite api-report:lite:pipelines && yarn api-report:api-json", "doc": "api-documenter markdown --input temp --output docs", diff --git a/repo-scripts/prune-dts/extract-public-api.ts b/repo-scripts/prune-dts/extract-public-api.ts index 4e3c0c3c1f..ac64dae653 100644 --- a/repo-scripts/prune-dts/extract-public-api.ts +++ b/repo-scripts/prune-dts/extract-public-api.ts @@ -69,7 +69,8 @@ function loadApiExtractorConfig( rollupDtsPath: string, untrimmedRollupDtsPath: string, dtsRollupEnabled: boolean, - apiReportEnabled: boolean + apiReportEnabled: boolean, + excludeForgottenExportWarning: boolean ): ExtractorConfig { const apiExtractorJsonPath = path.resolve(tmpDir, 'api-extractor.json'); const apiExtractorJson = { @@ -102,7 +103,8 @@ function loadApiExtractorConfig( 'logLevel': 'none' }, 'ae-forgotten-export': { - 'logLevel': apiReportEnabled ? 'error' : 'none' + 'logLevel': apiReportEnabled ? 'error' : 'none', + 'addToApiReportFile': !excludeForgottenExportWarning } }, 'tsdocMessageReporting': { @@ -142,7 +144,8 @@ export async function generateApi( rollupDtsPath: string, untrimmedRollupDtsPath: string, publicDtsPath: string, - otherExportDtsPaths: string[] + otherExportDtsPaths: string[], + excludeForgottenExportWarning: boolean ): Promise { console.log(`Configuring API Extractor for ${packageName}`); writeTypeScriptConfig(packageRoot); @@ -154,7 +157,8 @@ export async function generateApi( rollupDtsPath, untrimmedRollupDtsPath, /* dtsRollupEnabled= */ true, - /* apiReportEnabled= */ false + /* apiReportEnabled= */ false, + excludeForgottenExportWarning ); Extractor.invoke(extractorConfig, { localBuild: true @@ -174,7 +178,8 @@ export async function generateApi( rollupDtsPath, untrimmedRollupDtsPath, /* dtsRollupEnabled= */ false, - /* apiReportEnabled= */ true + /* apiReportEnabled= */ true, + excludeForgottenExportWarning ); Extractor.invoke(extractorConfig, { localBuild: true }); console.log(`API report for ${packageName} written to ${reportFolder}`); @@ -229,6 +234,11 @@ const argv = yargs 'Optional. A comma-separated list of customer-facing of .d.ts' + 'files for other exports from this package.', require: false + }, + excludeForgottenExportWarning: { + type: 'boolean', + desc: 'Optional. Do not write ae-forgotten-export warnings into the api-report', + require: false } }) .parseSync(); @@ -244,5 +254,6 @@ void generateApi( ? argv.otherExportsPublicDtsFiles .split(',') .map(filePath => path.resolve(filePath)) - : [] + : [], + !!argv.excludeForgottenExportWarning ); From 2ecf78b4f049b2e937cda911c00d549f25c628a8 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Fri, 9 Jan 2026 13:51:43 -0600 Subject: [PATCH 036/174] feat(ai): Add support for `AbortSignal` (#8890) --- .changeset/long-keys-watch.md | 6 + common/api-review/ai.api.md | 25 +- docs-devsite/_toc.yaml | 2 + docs-devsite/ai.chatsession.md | 10 +- docs-devsite/ai.generativemodel.md | 15 +- docs-devsite/ai.imagenmodel.md | 5 +- docs-devsite/ai.md | 1 + docs-devsite/ai.singlerequestoptions.md | 61 +++ docs-devsite/ai.templategenerativemodel.md | 10 +- docs-devsite/ai.templateimagenmodel.md | 5 +- packages/ai/integration/constants.ts | 13 +- .../ai/integration/generate-content.test.ts | 165 +++++++- packages/ai/src/methods/chat-session.test.ts | 221 +++++++++++ packages/ai/src/methods/chat-session.ts | 52 ++- packages/ai/src/methods/count-tokens.test.ts | 8 +- packages/ai/src/methods/count-tokens.ts | 5 +- .../ai/src/methods/generate-content.test.ts | 32 +- packages/ai/src/methods/generate-content.ts | 32 +- .../ai/src/models/generative-model.test.ts | 243 ++++++++++-- packages/ai/src/models/generative-model.ts | 33 +- packages/ai/src/models/imagen-model.test.ts | 151 +++++++- packages/ai/src/models/imagen-model.ts | 21 +- .../models/template-generative-model.test.ts | 90 +++++ .../src/models/template-generative-model.ts | 22 +- .../src/models/template-imagen-model.test.ts | 60 ++- .../ai/src/models/template-imagen-model.ts | 11 +- packages/ai/src/requests/request.test.ts | 351 ++++++++++++++++-- packages/ai/src/requests/request.ts | 67 +++- packages/ai/src/requests/stream-reader.ts | 24 +- packages/ai/src/types/requests.ts | 41 ++ 30 files changed, 1578 insertions(+), 204 deletions(-) create mode 100644 .changeset/long-keys-watch.md create mode 100644 docs-devsite/ai.singlerequestoptions.md diff --git a/.changeset/long-keys-watch.md b/.changeset/long-keys-watch.md new file mode 100644 index 0000000000..fb13ed7498 --- /dev/null +++ b/.changeset/long-keys-watch.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/ai': minor +--- + +Add support for `AbortSignal`, allowing requests to be aborted. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 2bf194fbaf..215d89e4f3 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -150,8 +150,8 @@ export class ChatSession { params?: StartChatParams | undefined; // (undocumented) requestOptions?: RequestOptions | undefined; - sendMessage(request: string | Array): Promise; - sendMessageStream(request: string | Array): Promise; + sendMessage(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; + sendMessageStream(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; } // @beta @@ -539,9 +539,9 @@ export interface GenerativeContentBlob { export class GenerativeModel extends AIModel { // Warning: (ae-incompatible-release-tags) The symbol "__constructor" is marked as @public, but its signature references "ChromeAdapter" which is marked as @beta constructor(ai: AI, modelParams: ModelParams, requestOptions?: RequestOptions, chromeAdapter?: ChromeAdapter | undefined); - countTokens(request: CountTokensRequest | string | Array): Promise; - generateContent(request: GenerateContentRequest | string | Array): Promise; - generateContentStream(request: GenerateContentRequest | string | Array): Promise; + countTokens(request: CountTokensRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; + generateContent(request: GenerateContentRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; + generateContentStream(request: GenerateContentRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; // (undocumented) generationConfig: GenerationConfig; // (undocumented) @@ -784,9 +784,9 @@ export interface ImagenInlineImage { // @public export class ImagenModel extends AIModel { constructor(ai: AI, modelParams: ImagenModelParams, requestOptions?: RequestOptions | undefined); - generateImages(prompt: string): Promise>; + generateImages(prompt: string, singleRequestOptions?: SingleRequestOptions): Promise>; // @internal - generateImagesGCS(prompt: string, gcsURI: string): Promise>; + generateImagesGCS(prompt: string, gcsURI: string, singleRequestOptions?: SingleRequestOptions): Promise>; generationConfig?: ImagenGenerationConfig; // (undocumented) requestOptions?: RequestOptions | undefined; @@ -1294,6 +1294,11 @@ export interface Segment { text: string; } +// @public +export interface SingleRequestOptions extends RequestOptions { + signal?: AbortSignal; +} + // @beta export interface SpeechConfig { voiceConfig?: VoiceConfig; @@ -1333,8 +1338,8 @@ export class TemplateGenerativeModel { constructor(ai: AI, requestOptions?: RequestOptions); // @internal (undocumented) _apiSettings: ApiSettings; - generateContent(templateId: string, templateVariables: object): Promise; - generateContentStream(templateId: string, templateVariables: object): Promise; + generateContent(templateId: string, templateVariables: object, singleRequestOptions?: SingleRequestOptions): Promise; + generateContentStream(templateId: string, templateVariables: object, singleRequestOptions?: SingleRequestOptions): Promise; requestOptions?: RequestOptions; } @@ -1343,7 +1348,7 @@ export class TemplateImagenModel { constructor(ai: AI, requestOptions?: RequestOptions); // @internal (undocumented) _apiSettings: ApiSettings; - generateImages(templateId: string, templateVariables: object): Promise>; + generateImages(templateId: string, templateVariables: object, singleRequestOptions?: SingleRequestOptions): Promise>; requestOptions?: RequestOptions; } diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index 401bcb3bc1..b59430a2dc 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -190,6 +190,8 @@ toc: path: /docs/reference/js/ai.searchentrypoint.md - title: Segment path: /docs/reference/js/ai.segment.md + - title: SingleRequestOptions + path: /docs/reference/js/ai.singlerequestoptions.md - title: SpeechConfig path: /docs/reference/js/ai.speechconfig.md - title: StartAudioConversationOptions diff --git a/docs-devsite/ai.chatsession.md b/docs-devsite/ai.chatsession.md index 4e4358898a..2062f9868f 100644 --- a/docs-devsite/ai.chatsession.md +++ b/docs-devsite/ai.chatsession.md @@ -37,8 +37,8 @@ export declare class ChatSession | Method | Modifiers | Description | | --- | --- | --- | | [getHistory()](./ai.chatsession.md#chatsessiongethistory) | | Gets the chat history so far. Blocked prompts are not added to history. Neither blocked candidates nor the prompts that generated them are added to history. | -| [sendMessage(request)](./ai.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface) | -| [sendMessageStream(request)](./ai.chatsession.md#chatsessionsendmessagestream) | | Sends a chat message and receives the response as a [GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. | +| [sendMessage(request, singleRequestOptions)](./ai.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface) | +| [sendMessageStream(request, singleRequestOptions)](./ai.chatsession.md#chatsessionsendmessagestream) | | Sends a chat message and receives the response as a [GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. | ## ChatSession.(constructor) @@ -104,7 +104,7 @@ Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.g Signature: ```typescript -sendMessage(request: string | Array): Promise; +sendMessage(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -112,6 +112,7 @@ sendMessage(request: string | Array): Promise> | | +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: @@ -124,7 +125,7 @@ Sends a chat message and receives the response as a [GenerateContentStreamResult Signature: ```typescript -sendMessageStream(request: string | Array): Promise; +sendMessageStream(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -132,6 +133,7 @@ sendMessageStream(request: string | Array): Promise> | | +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: diff --git a/docs-devsite/ai.generativemodel.md b/docs-devsite/ai.generativemodel.md index 323fcfe9d7..4b1c71b8d2 100644 --- a/docs-devsite/ai.generativemodel.md +++ b/docs-devsite/ai.generativemodel.md @@ -40,9 +40,9 @@ export declare class GenerativeModel extends AIModel | Method | Modifiers | Description | | --- | --- | --- | -| [countTokens(request)](./ai.generativemodel.md#generativemodelcounttokens) | | Counts the tokens in the provided request. | -| [generateContent(request)](./ai.generativemodel.md#generativemodelgeneratecontent) | | Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | -| [generateContentStream(request)](./ai.generativemodel.md#generativemodelgeneratecontentstream) | | Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. | +| [countTokens(request, singleRequestOptions)](./ai.generativemodel.md#generativemodelcounttokens) | | Counts the tokens in the provided request. | +| [generateContent(request, singleRequestOptions)](./ai.generativemodel.md#generativemodelgeneratecontent) | | Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | +| [generateContentStream(request, singleRequestOptions)](./ai.generativemodel.md#generativemodelgeneratecontentstream) | | Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. | | [startChat(startChatParams)](./ai.generativemodel.md#generativemodelstartchat) | | Gets a new [ChatSession](./ai.chatsession.md#chatsession_class) instance which can be used for multi-turn chats. | ## GenerativeModel.(constructor) @@ -119,7 +119,7 @@ Counts the tokens in the provided request. Signature: ```typescript -countTokens(request: CountTokensRequest | string | Array): Promise; +countTokens(request: CountTokensRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -127,6 +127,7 @@ countTokens(request: CountTokensRequest | string | Array): Promis | Parameter | Type | Description | | --- | --- | --- | | request | [CountTokensRequest](./ai.counttokensrequest.md#counttokensrequest_interface) \| string \| Array<string \| [Part](./ai.md#part)> | | +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: @@ -139,7 +140,7 @@ Makes a single non-streaming call to the model and returns an object containing Signature: ```typescript -generateContent(request: GenerateContentRequest | string | Array): Promise; +generateContent(request: GenerateContentRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -147,6 +148,7 @@ generateContent(request: GenerateContentRequest | string | Array) | Parameter | Type | Description | | --- | --- | --- | | request | [GenerateContentRequest](./ai.generatecontentrequest.md#generatecontentrequest_interface) \| string \| Array<string \| [Part](./ai.md#part)> | | +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: @@ -159,7 +161,7 @@ Makes a single streaming call to the model and returns an object containing an i Signature: ```typescript -generateContentStream(request: GenerateContentRequest | string | Array): Promise; +generateContentStream(request: GenerateContentRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -167,6 +169,7 @@ generateContentStream(request: GenerateContentRequest | string | Array> | | +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: diff --git a/docs-devsite/ai.imagenmodel.md b/docs-devsite/ai.imagenmodel.md index 68375972cb..6559723878 100644 --- a/docs-devsite/ai.imagenmodel.md +++ b/docs-devsite/ai.imagenmodel.md @@ -39,7 +39,7 @@ export declare class ImagenModel extends AIModel | Method | Modifiers | Description | | --- | --- | --- | -| [generateImages(prompt)](./ai.imagenmodel.md#imagenmodelgenerateimages) | | Generates images using the Imagen model and returns them as base64-encoded strings. | +| [generateImages(prompt, singleRequestOptions)](./ai.imagenmodel.md#imagenmodelgenerateimages) | | Generates images using the Imagen model and returns them as base64-encoded strings. | ## ImagenModel.(constructor) @@ -100,7 +100,7 @@ If the prompt was not blocked, but one or more of the generated images were filt Signature: ```typescript -generateImages(prompt: string): Promise>; +generateImages(prompt: string, singleRequestOptions?: SingleRequestOptions): Promise>; ``` #### Parameters @@ -108,6 +108,7 @@ generateImages(prompt: string): PromiseReturns: diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index 53e4057cad..482c49c3cd 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -133,6 +133,7 @@ The Firebase AI Web SDK. | [SchemaShared](./ai.schemashared.md#schemashared_interface) | Basic [Schema](./ai.schema.md#schema_class) properties shared across several Schema-related types. | | [SearchEntrypoint](./ai.searchentrypoint.md#searchentrypoint_interface) | Google search entry point. | | [Segment](./ai.segment.md#segment_interface) | Represents a specific segment within a [Content](./ai.content.md#content_interface) object, often used to pinpoint the exact location of text or data that grounding information refers to. | +| [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | Options that can be provided per-request. Extends the base [RequestOptions](./ai.requestoptions.md#requestoptions_interface) (like timeout and baseUrl) with request-specific controls like cancellation via AbortSignal.Options specified here will override any default [RequestOptions](./ai.requestoptions.md#requestoptions_interface) configured on a model (for example, [GenerativeModel](./ai.generativemodel.md#generativemodel_class)). | | [SpeechConfig](./ai.speechconfig.md#speechconfig_interface) | (Public Preview) Configures speech synthesis. | | [StartAudioConversationOptions](./ai.startaudioconversationoptions.md#startaudioconversationoptions_interface) | (Public Preview) Options for [startAudioConversation()](./ai.md#startaudioconversation_01c8e7f). | | [StartChatParams](./ai.startchatparams.md#startchatparams_interface) | Params for [GenerativeModel.startChat()](./ai.generativemodel.md#generativemodelstartchat). | diff --git a/docs-devsite/ai.singlerequestoptions.md b/docs-devsite/ai.singlerequestoptions.md new file mode 100644 index 0000000000..a55bd3c2f3 --- /dev/null +++ b/docs-devsite/ai.singlerequestoptions.md @@ -0,0 +1,61 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# SingleRequestOptions interface +Options that can be provided per-request. Extends the base [RequestOptions](./ai.requestoptions.md#requestoptions_interface) (like `timeout` and `baseUrl`) with request-specific controls like cancellation via `AbortSignal`. + +Options specified here will override any default [RequestOptions](./ai.requestoptions.md#requestoptions_interface) configured on a model (for example, [GenerativeModel](./ai.generativemodel.md#generativemodel_class)). + +Signature: + +```typescript +export interface SingleRequestOptions extends RequestOptions +``` +Extends: [RequestOptions](./ai.requestoptions.md#requestoptions_interface) + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [signal](./ai.singlerequestoptions.md#singlerequestoptionssignal) | AbortSignal | An AbortSignal instance that allows cancelling ongoing requests (like generateContent or generateImages).If provided, calling abort() on the corresponding AbortController will attempt to cancel the underlying HTTP request. An AbortError will be thrown if cancellation is successful.Note that this will not cancel the request in the backend, so any applicable billing charges will still be applied despite cancellation. | + +## SingleRequestOptions.signal + +An `AbortSignal` instance that allows cancelling ongoing requests (like `generateContent` or `generateImages`). + +If provided, calling `abort()` on the corresponding `AbortController` will attempt to cancel the underlying HTTP request. An `AbortError` will be thrown if cancellation is successful. + +Note that this will not cancel the request in the backend, so any applicable billing charges will still be applied despite cancellation. + +Signature: + +```typescript +signal?: AbortSignal; +``` + +### Example + + +```javascript +const controller = new AbortController(); +const model = getGenerativeModel({ + // ... +}); +model.generateContent( + "Write a story about a magic backpack.", + { signal: controller.signal } +); + +// To cancel request: +controller.abort(); + +``` + diff --git a/docs-devsite/ai.templategenerativemodel.md b/docs-devsite/ai.templategenerativemodel.md index c115af62b1..9410443f61 100644 --- a/docs-devsite/ai.templategenerativemodel.md +++ b/docs-devsite/ai.templategenerativemodel.md @@ -39,8 +39,8 @@ export declare class TemplateGenerativeModel | Method | Modifiers | Description | | --- | --- | --- | -| [generateContent(templateId, templateVariables)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontent) | | (Public Preview) Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | -| [generateContentStream(templateId, templateVariables)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontentstream) | | (Public Preview) Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. | +| [generateContent(templateId, templateVariables, singleRequestOptions)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontent) | | (Public Preview) Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | +| [generateContentStream(templateId, templateVariables, singleRequestOptions)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontentstream) | | (Public Preview) Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. | ## TemplateGenerativeModel.(constructor) @@ -85,7 +85,7 @@ Makes a single non-streaming call to the model and returns an object containing Signature: ```typescript -generateContent(templateId: string, templateVariables: object): Promise; +generateContent(templateId: string, templateVariables: object, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -94,6 +94,7 @@ generateContent(templateId: string, templateVariables: object): PromiseReturns: @@ -109,7 +110,7 @@ Makes a single streaming call to the model and returns an object containing an i Signature: ```typescript -generateContentStream(templateId: string, templateVariables: object): Promise; +generateContentStream(templateId: string, templateVariables: object, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -118,6 +119,7 @@ generateContentStream(templateId: string, templateVariables: object): PromiseReturns: diff --git a/docs-devsite/ai.templateimagenmodel.md b/docs-devsite/ai.templateimagenmodel.md index 2d86071993..3b33d94f71 100644 --- a/docs-devsite/ai.templateimagenmodel.md +++ b/docs-devsite/ai.templateimagenmodel.md @@ -39,7 +39,7 @@ export declare class TemplateImagenModel | Method | Modifiers | Description | | --- | --- | --- | -| [generateImages(templateId, templateVariables)](./ai.templateimagenmodel.md#templateimagenmodelgenerateimages) | | (Public Preview) Makes a single call to the model and returns an object containing a single [ImagenGenerationResponse](./ai.imagengenerationresponse.md#imagengenerationresponse_interface). | +| [generateImages(templateId, templateVariables, singleRequestOptions)](./ai.templateimagenmodel.md#templateimagenmodelgenerateimages) | | (Public Preview) Makes a single call to the model and returns an object containing a single [ImagenGenerationResponse](./ai.imagengenerationresponse.md#imagengenerationresponse_interface). | ## TemplateImagenModel.(constructor) @@ -84,7 +84,7 @@ Makes a single call to the model and returns an object containing a single [Imag Signature: ```typescript -generateImages(templateId: string, templateVariables: object): Promise>; +generateImages(templateId: string, templateVariables: object, singleRequestOptions?: SingleRequestOptions): Promise>; ``` #### Parameters @@ -93,6 +93,7 @@ generateImages(templateId: string, templateVariables: object): PromiseReturns: diff --git a/packages/ai/integration/constants.ts b/packages/ai/integration/constants.ts index 2c942e44f8..1b6994e01f 100644 --- a/packages/ai/integration/constants.ts +++ b/packages/ai/integration/constants.ts @@ -22,7 +22,8 @@ import { BackendType, GoogleAIBackend, VertexAIBackend, - getAI + getAI, + getGenerativeModel } from '../src'; import { FIREBASE_CONFIG } from './firebase-config'; @@ -69,6 +70,16 @@ const modelNames: readonly string[] = [ 'gemini-3-pro-preview' ]; +// Used for testing non-AI behavior (e.g. Network requests). Configured to minimize cost. +export const cheapestModel = 'gemini-2.0-flash'; +export const defaultAIInstance = getAI(app, { backend: new VertexAIBackend() }); +export const defaultGenerativeModel = getGenerativeModel(defaultAIInstance, { + model: cheapestModel, + generationConfig: { + maxOutputTokens: 10 // Just enough to confirm we actually get something back. + } +}); + // The Live API requires a different set of models, and they're different for each backend. const liveModelNames: Map = new Map([ [BackendType.GOOGLE_AI, ['gemini-2.5-flash-native-audio-preview-09-2025']], diff --git a/packages/ai/integration/generate-content.test.ts b/packages/ai/integration/generate-content.test.ts index ce52a1f68f..6cd6640285 100644 --- a/packages/ai/integration/generate-content.test.ts +++ b/packages/ai/integration/generate-content.test.ts @@ -15,7 +15,11 @@ * limitations under the License. */ -import { expect } from 'chai'; +import chai, { AssertionError } from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +chai.use(chaiAsPromised); +const expect = chai.expect; + import { BackendType, Content, @@ -29,7 +33,14 @@ import { URLRetrievalStatus, getGenerativeModel } from '../src'; -import { testConfigs } from './constants'; +import { + cheapestModel, + defaultAIInstance, + defaultGenerativeModel, + testConfigs +} from './constants'; +import { TIMEOUT_EXPIRED_MESSAGE } from '../src/requests/request'; +import { isNode } from '@firebase/util'; describe('Generate Content', function () { this.timeout(90_000); // gemini 3 requests take a long time, especially when using google search and url context. @@ -355,4 +366,154 @@ describe('Generate Content', function () { }); }); }); + + describe('Request Options', async () => { + const defaultAbortReason = isNode() + ? 'This operation was aborted' + : 'signal is aborted without reason'; + describe('unary', async () => { + it('timeout cancels request', async () => { + await expect( + defaultGenerativeModel.generateContent('hello', { timeout: 100 }) + ).to.be.rejectedWith(DOMException, TIMEOUT_EXPIRED_MESSAGE); + }); + + it('long timeout does not cancel request', async () => { + const result = await defaultGenerativeModel.generateContent('hello', { + timeout: 50_000 + }); + expect(result.response.text().length).to.be.greaterThan(0); + }); + + it('abort signal with no reason causes request to throw AbortError', async () => { + const abortController = new AbortController(); + const responsePromise = defaultGenerativeModel.generateContent( + 'hello', + { signal: abortController.signal } + ); + abortController.abort(); + await expect(responsePromise) + .to.be.rejectedWith(DOMException, defaultAbortReason) + .and.eventually.have.property('name', 'AbortError'); + }); + + it('abort signal with string reason causes request to throw reason string', async () => { + const abortController = new AbortController(); + const responsePromise = defaultGenerativeModel.generateContent( + 'hello', + { signal: abortController.signal } + ); + const reason = 'Cancelled'; + abortController.abort(reason); + await expect(responsePromise).to.be.rejectedWith(reason); + }); + + it('abort signal with error reason causes request to throw reason error', async () => { + const abortController = new AbortController(); + const responsePromise = defaultGenerativeModel.generateContent( + 'hello', + { signal: abortController.signal } + ); + abortController.abort(new Error('Cancelled')); + // `fetch()` will reject with the exact object we passed to `abort()`. Since we throw a generic + // Error, we cannot differentiate between this error and other generic fetch errors, which + // we wrap in an AIError. + await expect(responsePromise) + .to.be.rejectedWith(Error, 'Cancelled') + .and.eventually.have.property('name', 'FirebaseError'); + }); + }); + + describe('streaming', async () => { + it('timeout cancels initial request', async () => { + await expect( + defaultGenerativeModel.generateContent('hello', { timeout: 50 }) + ).to.be.rejectedWith(DOMException, TIMEOUT_EXPIRED_MESSAGE); + }); + + it('timeout does not cancel request once streaming has begun', async () => { + const generativeModel = getGenerativeModel(defaultAIInstance, { + model: cheapestModel + }); + // Setting a timeout that will be in the interval between the stream starting and ending. + // Since the timeout will expire once the stream has begun, it should have already been + // cleared, and so it shouldn't abort the stream. + const { stream, response } = + await generativeModel.generateContentStream( + 'tell me a short story with 200 words.', + { timeout: 1_000 } + ); + + // We should be able to get through the entire stream without an error being thrown + // from the async generator. + for await (const chunk of stream) { + expect(chunk.text().length).to.be.greaterThan(0); + } + + expect((await response).text().length).to.be.greaterThan(0); + }); + + it('abort signal without reason should cancel stream with default abort reason', async () => { + const abortController = new AbortController(); + const generativeModel = getGenerativeModel(defaultAIInstance, { + model: cheapestModel + }); + const { stream, response } = + await generativeModel.generateContentStream( + 'tell me a short story with 200 words.', + { signal: abortController.signal } + ); + + // As soon as the initial request resolves and the stream starts, abort the stream. + abortController.abort(); + + try { + for await (const _ of stream) { + expect.fail('Expected stream to throw an error'); + } + expect.fail('Expected stream to throw an error'); + } catch (err) { + if ((err as Error) instanceof AssertionError) { + throw err; + } + expect(err).to.be.instanceof(DOMException); + expect((err as Error).name).to.equal('AbortError'); + expect((err as Error).message).to.equal(defaultAbortReason); + } + + await expect(response) + .to.be.rejectedWith(DOMException, defaultAbortReason) + .and.to.eventually.have.property('name', 'AbortError'); + }); + + it('abort signal with reason string should cancel stream with string abort reason', async () => { + const abortController = new AbortController(); + const generativeModel = getGenerativeModel(defaultAIInstance, { + model: cheapestModel + }); + const { stream, response } = + await generativeModel.generateContentStream( + 'tell me a short story with 200 words.', + { signal: abortController.signal } + ); + + // As soon as the initial request resolves and the stream starts, abort the stream. + abortController.abort('Cancelled'); + + try { + for await (const _ of stream) { + expect.fail('Expected stream to throw an error'); + } + expect.fail('Expected stream to throw an error'); + } catch (err) { + if ((err as Error) instanceof AssertionError) { + throw err; + } + expect(err).to.equal('Cancelled'); + } + + await expect(response).to.be.rejectedWith('Cancelled'); + }); + }); + }); }); diff --git a/packages/ai/src/methods/chat-session.test.ts b/packages/ai/src/methods/chat-session.test.ts index 1273d02876..1f084d0b1e 100644 --- a/packages/ai/src/methods/chat-session.test.ts +++ b/packages/ai/src/methods/chat-session.test.ts @@ -25,6 +25,7 @@ import { ChatSession } from './chat-session'; import { ApiSettings } from '../types/internal'; import { VertexAIBackend } from '../backend'; import { fakeChromeAdapter } from '../../test-utils/get-fake-firebase-services'; +import { logger } from '../logger'; use(sinonChai); use(chaiAsPromised); @@ -59,6 +60,68 @@ describe('ChatSession', () => { match.any ); }); + it('singleRequestOptions overrides requestOptions', async () => { + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + ).rejects('generateContent failed'); // not important + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + timeout: 2000 + }; + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + undefined, + requestOptions + ); + await expect(chatSession.sendMessage('hello', singleRequestOptions)).to.be + .rejected; + expect(generateContentStub).to.be.calledWith( + fakeApiSettings, + 'a-model', + match.any, + match.any, + match({ + timeout: singleRequestOptions.timeout + }) + ); + }); + it('singleRequestOptions is merged with requestOptions', async () => { + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + ).rejects('generateContent failed'); // not important + const abortController = new AbortController(); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + signal: abortController.signal + }; + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + undefined, + requestOptions + ); + await expect(chatSession.sendMessage('hello', singleRequestOptions)).to.be + .rejected; + expect(generateContentStub).to.be.calledWith( + fakeApiSettings, + 'a-model', + match.any, + match.any, + match({ + timeout: requestOptions.timeout, + signal: singleRequestOptions.signal + }) + ); + }); it('adds message and response to history', async () => { const fakeContent: Content = { role: 'model', @@ -124,6 +187,7 @@ describe('ChatSession', () => { expect(generateContentStreamStub).to.be.calledWith( fakeApiSettings, 'a-model', + match.any, match.any ); await clock.runAllAsync(); @@ -147,6 +211,7 @@ describe('ChatSession', () => { expect(generateContentStreamStub).to.be.calledWith( fakeApiSettings, 'a-model', + match.any, match.any ); await clock.runAllAsync(); @@ -156,5 +221,161 @@ describe('ChatSession', () => { ); clock.restore(); }); + it('logs error and rejects user promise when response aggregation fails', async () => { + const loggerStub = stub(logger, 'error'); + const error = new Error('Aggregation failed'); + + // Simulate stream returning, but the response promise failing (e.g. parsing error) + stub(generateContentMethods, 'generateContentStream').resolves({ + stream: (async function* () {})(), + response: Promise.reject(error) + } as unknown as GenerateContentStreamResult); + + const chatSession = new ChatSession(fakeApiSettings, 'a-model'); + const initialHistoryLength = (await chatSession.getHistory()).length; + + // Immediate call resolves with the stream object + const result = await chatSession.sendMessageStream('hello'); + + // User's response promise should reject + await expect(result.response).to.be.rejectedWith(error); + + // Wait for the internal _sendPromise chain to settle + await new Promise(resolve => setTimeout(resolve, 0)); + + expect(loggerStub).to.have.been.calledWith(error); + + // History should NOT have been updated (no response appended) + const finalHistory = await chatSession.getHistory(); + expect(finalHistory.length).to.equal(initialHistoryLength); + }); + it('logs error but resolves user promise when history appending logic fails', async () => { + const loggerStub = stub(logger, 'error'); + + // Simulate a response that is technically valid enough to resolve aggregation, + // but malformed in a way that causes the history update logic to throw. + // Passing `null` as a candidate causes `{ ...response.candidates[0].content }` to throw. + const malformedResponse = { + candidates: [null] + }; + + stub(generateContentMethods, 'generateContentStream').resolves({ + stream: (async function* () {})(), + response: Promise.resolve(malformedResponse) + } as unknown as GenerateContentStreamResult); + + const chatSession = new ChatSession(fakeApiSettings, 'a-model'); + const initialHistoryLength = (await chatSession.getHistory()).length; + + const result = await chatSession.sendMessageStream('hello'); + + // The user's response promise SHOULD resolve, because aggregation succeeded. + // The error is purely internal side-effect (history update). + await expect(result.response).to.eventually.equal(malformedResponse); + + // Wait for internal chain + await new Promise(resolve => setTimeout(resolve, 0)); + + expect(loggerStub).to.have.been.called; + const errorArg = loggerStub.firstCall.args[0]; + expect(errorArg).to.be.instanceOf(TypeError); + + // The user message WAS added before the crash, but the response wasn't. + const finalHistory = await chatSession.getHistory(); + expect(finalHistory.length).to.equal(initialHistoryLength + 1); + expect(finalHistory[finalHistory.length - 1].role).to.equal('user'); + }); + it('error from stream promise should not be logged', async () => { + const consoleStub = stub(console, 'error'); + stub(generateContentMethods, 'generateContentStream').rejects('foo'); + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + fakeChromeAdapter + ); + try { + // This will throw since generateContentStream will reject immediately. + await chatSession.sendMessageStream('hello'); + } catch (e) { + expect((e as unknown as any).name).to.equal('foo'); + } + + expect(consoleStub).to.not.have.been.called; + }); + it('error from final response promise should not be logged', async () => { + const consoleStub = stub(console, 'error'); + stub(generateContentMethods, 'generateContentStream').resolves({ + response: new Promise((_, reject) => reject(new Error())) + } as unknown as GenerateContentStreamResult); + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + fakeChromeAdapter + ); + await chatSession.sendMessageStream('hello'); + expect(consoleStub).to.not.have.been.called; + }); + it('singleRequestOptions overrides requestOptions', async () => { + const generateContentStreamStub = stub( + generateContentMethods, + 'generateContentStream' + ).rejects('generateContentStream failed'); // not important + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + timeout: 2000 + }; + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + undefined, + requestOptions + ); + await expect(chatSession.sendMessageStream('hello', singleRequestOptions)) + .to.be.rejected; + expect(generateContentStreamStub).to.be.calledWith( + fakeApiSettings, + 'a-model', + match.any, + match.any, + match({ + timeout: singleRequestOptions.timeout + }) + ); + }); + it('singleRequestOptions is merged with requestOptions', async () => { + const generateContentStreamStub = stub( + generateContentMethods, + 'generateContentStream' + ).rejects('generateContentStream failed'); // not important + const abortController = new AbortController(); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + signal: abortController.signal + }; + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + undefined, + requestOptions + ); + await expect(chatSession.sendMessageStream('hello', singleRequestOptions)) + .to.be.rejected; + expect(generateContentStreamStub).to.be.calledWith( + fakeApiSettings, + 'a-model', + match.any, + match.any, + match({ + timeout: requestOptions.timeout, + signal: singleRequestOptions.signal + }) + ); + }); }); }); diff --git a/packages/ai/src/methods/chat-session.ts b/packages/ai/src/methods/chat-session.ts index dac16430b7..f4015607f8 100644 --- a/packages/ai/src/methods/chat-session.ts +++ b/packages/ai/src/methods/chat-session.ts @@ -22,6 +22,7 @@ import { GenerateContentStreamResult, Part, RequestOptions, + SingleRequestOptions, StartChatParams } from '../types'; import { formatNewContent } from '../requests/request-helpers'; @@ -33,7 +34,8 @@ import { logger } from '../logger'; import { ChromeAdapter } from '../types/chrome-adapter'; /** - * Do not log a message for this error. + * Used to break the internal promise chain when an error is already handled + * by the user, preventing duplicate console logs. */ const SILENT_ERROR = 'SILENT_ERROR'; @@ -46,6 +48,11 @@ const SILENT_ERROR = 'SILENT_ERROR'; export class ChatSession { private _apiSettings: ApiSettings; private _history: Content[] = []; + + /** + * Ensures sequential execution of chat messages to maintain history order. + * Each call waits for the previous one to settle before proceeding. + */ private _sendPromise: Promise = Promise.resolve(); constructor( @@ -77,7 +84,8 @@ export class ChatSession { * {@link GenerateContentResult} */ async sendMessage( - request: string | Array + request: string | Array, + singleRequestOptions?: SingleRequestOptions ): Promise { await this._sendPromise; const newContent = formatNewContent(request); @@ -90,7 +98,7 @@ export class ChatSession { contents: [...this._history, newContent] }; let finalResult = {} as GenerateContentResult; - // Add onto the chain. + this._sendPromise = this._sendPromise .then(() => generateContent( @@ -98,10 +106,16 @@ export class ChatSession { this.model, generateContentRequest, this.chromeAdapter, - this.requestOptions + { + ...this.requestOptions, + ...singleRequestOptions + } ) ) .then(result => { + // TODO: Make this update atomic. If creating `responseContent` throws, + // history will contain the user message but not the response, causing + // validation errors on the next request. if ( result.response.candidates && result.response.candidates.length > 0 @@ -109,7 +123,6 @@ export class ChatSession { this._history.push(newContent); const responseContent: Content = { parts: result.response.candidates?.[0].content.parts || [], - // Response seems to come back without a role set. role: result.response.candidates?.[0].content.role || 'model' }; this._history.push(responseContent); @@ -133,7 +146,8 @@ export class ChatSession { * and a response promise. */ async sendMessageStream( - request: string | Array + request: string | Array, + singleRequestOptions?: SingleRequestOptions ): Promise { await this._sendPromise; const newContent = formatNewContent(request); @@ -150,23 +164,31 @@ export class ChatSession { this.model, generateContentRequest, this.chromeAdapter, - this.requestOptions + { + ...this.requestOptions, + ...singleRequestOptions + } ); - // Add onto the chain. + // We hook into the chain to update history, but we don't block the + // return of `streamPromise` to the user. this._sendPromise = this._sendPromise .then(() => streamPromise) - // This must be handled to avoid unhandled rejection, but jump - // to the final catch block with a label to not log this error. .catch(_ignored => { + // If the initial fetch fails, the user's `streamPromise` rejects. + // We swallow the error here to prevent double logging in the final catch. throw new Error(SILENT_ERROR); }) .then(streamResult => streamResult.response) .then(response => { + // This runs after the stream completes. Runtime errors here cannot be + // caught by the user because their promise has likely already resolved. + // TODO: Move response validation logic upstream to `stream-reader` so + // errors propagate to the user's `result.response` promise. if (response.candidates && response.candidates.length > 0) { this._history.push(newContent); + // TODO: Validate that `response.candidates[0].content` is not null. const responseContent = { ...response.candidates[0].content }; - // Response seems to come back without a role set. if (!responseContent.role) { responseContent.role = 'model'; } @@ -181,12 +203,8 @@ export class ChatSession { } }) .catch(e => { - // Errors in streamPromise are already catchable by the user as - // streamPromise is returned. - // Avoid duplicating the error message in logs. - if (e.message !== SILENT_ERROR) { - // Users do not have access to _sendPromise to catch errors - // downstream from streamPromise, so they should not throw. + // Filter out errors already handled by the user or initiated by them. + if (e.message !== SILENT_ERROR && e.name !== 'AbortError') { logger.error(e); } }); diff --git a/packages/ai/src/methods/count-tokens.test.ts b/packages/ai/src/methods/count-tokens.test.ts index b3ed7f7fa4..67eed84ea1 100644 --- a/packages/ai/src/methods/count-tokens.test.ts +++ b/packages/ai/src/methods/count-tokens.test.ts @@ -77,7 +77,7 @@ describe('countTokens()', () => { task: Task.COUNT_TOKENS, apiSettings: fakeApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, match((value: string) => { return value.includes('contents'); @@ -108,7 +108,7 @@ describe('countTokens()', () => { task: Task.COUNT_TOKENS, apiSettings: fakeApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, match((value: string) => { return value.includes('contents'); @@ -137,7 +137,7 @@ describe('countTokens()', () => { task: Task.COUNT_TOKENS, apiSettings: fakeApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, match((value: string) => { return value.includes('contents'); @@ -191,7 +191,7 @@ describe('countTokens()', () => { task: Task.COUNT_TOKENS, apiSettings: fakeGoogleAIApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, JSON.stringify(mapCountTokensRequest(fakeRequestParams, 'model')) ); diff --git a/packages/ai/src/methods/count-tokens.ts b/packages/ai/src/methods/count-tokens.ts index 20c633ee70..1731592a0e 100644 --- a/packages/ai/src/methods/count-tokens.ts +++ b/packages/ai/src/methods/count-tokens.ts @@ -19,6 +19,7 @@ import { AIError } from '../errors'; import { CountTokensRequest, CountTokensResponse, + SingleRequestOptions, InferenceMode, RequestOptions, AIErrorCode @@ -33,7 +34,7 @@ export async function countTokensOnCloud( apiSettings: ApiSettings, model: string, params: CountTokensRequest, - requestOptions?: RequestOptions + singleRequestOptions?: SingleRequestOptions ): Promise { let body: string = ''; if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) { @@ -48,7 +49,7 @@ export async function countTokensOnCloud( task: Task.COUNT_TOKENS, apiSettings, stream: false, - requestOptions + singleRequestOptions }, body ); diff --git a/packages/ai/src/methods/generate-content.test.ts b/packages/ai/src/methods/generate-content.test.ts index be94a7b29a..ea8876b07d 100644 --- a/packages/ai/src/methods/generate-content.test.ts +++ b/packages/ai/src/methods/generate-content.test.ts @@ -117,7 +117,7 @@ describe('generateContent()', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, JSON.stringify(fakeRequestParams) ); @@ -143,7 +143,7 @@ describe('generateContent()', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, JSON.stringify(fakeRequestParams) ); @@ -181,7 +181,7 @@ describe('generateContent()', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, JSON.stringify(fakeRequestParams) ); @@ -211,7 +211,7 @@ describe('generateContent()', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, JSON.stringify(fakeRequestParams) ); @@ -261,7 +261,7 @@ describe('generateContent()', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, JSON.stringify(fakeRequestParams) ); @@ -358,7 +358,7 @@ describe('generateContent()', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, JSON.stringify(fakeRequestParams) ); @@ -383,7 +383,7 @@ describe('generateContent()', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, JSON.stringify(fakeRequestParams) ); @@ -408,7 +408,7 @@ describe('generateContent()', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, JSON.stringify(fakeRequestParams) ); @@ -449,7 +449,7 @@ describe('generateContent()', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: undefined + singleRequestOptions: undefined }, JSON.stringify(fakeRequestParams) ); @@ -544,7 +544,7 @@ describe('generateContent()', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeGoogleAIApiSettings, stream: false, - requestOptions: match.any + singleRequestOptions: match.any }, JSON.stringify(mapGenerateContentRequest(fakeGoogleAIRequestParams)) ); @@ -612,13 +612,13 @@ describe('templateGenerateContent', () => { ); const templateId = 'my-template'; const templateParams = { name: 'world' }; - const requestOptions = { timeout: 5000 }; + const singleRequestOptions = { timeout: 5000 }; const result = await templateGenerateContent( fakeApiSettings, templateId, templateParams, - requestOptions + singleRequestOptions ); expect(makeRequestStub).to.have.been.calledOnceWith( @@ -627,7 +627,7 @@ describe('templateGenerateContent', () => { templateId, apiSettings: fakeApiSettings, stream: false, - requestOptions + singleRequestOptions }, JSON.stringify(templateParams) ); @@ -649,13 +649,13 @@ describe('templateGenerateContentStream', () => { ); const templateId = 'my-stream-template'; const templateParams = { name: 'streaming world' }; - const requestOptions = { timeout: 10000 }; + const singleRequestOptions = { timeout: 10000 }; const result = await templateGenerateContentStream( fakeApiSettings, templateId, templateParams, - requestOptions + singleRequestOptions ); expect(makeRequestStub).to.have.been.calledOnceWith( @@ -664,7 +664,7 @@ describe('templateGenerateContentStream', () => { templateId, apiSettings: fakeApiSettings, stream: true, - requestOptions + singleRequestOptions }, JSON.stringify(templateParams) ); diff --git a/packages/ai/src/methods/generate-content.ts b/packages/ai/src/methods/generate-content.ts index 56f55f1b02..b3065a4917 100644 --- a/packages/ai/src/methods/generate-content.ts +++ b/packages/ai/src/methods/generate-content.ts @@ -20,7 +20,7 @@ import { GenerateContentResponse, GenerateContentResult, GenerateContentStreamResult, - RequestOptions + SingleRequestOptions } from '../types'; import { makeRequest, @@ -39,7 +39,7 @@ async function generateContentStreamOnCloud( apiSettings: ApiSettings, model: string, params: GenerateContentRequest, - requestOptions?: RequestOptions + singleRequestOptions?: SingleRequestOptions ): Promise { if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) { params = GoogleAIMapper.mapGenerateContentRequest(params); @@ -50,7 +50,7 @@ async function generateContentStreamOnCloud( model, apiSettings, stream: true, - requestOptions + singleRequestOptions }, JSON.stringify(params) ); @@ -61,14 +61,19 @@ export async function generateContentStream( model: string, params: GenerateContentRequest, chromeAdapter?: ChromeAdapter, - requestOptions?: RequestOptions + singleRequestOptions?: SingleRequestOptions ): Promise { const callResult = await callCloudOrDevice( params, chromeAdapter, () => chromeAdapter!.generateContentStream(params), () => - generateContentStreamOnCloud(apiSettings, model, params, requestOptions) + generateContentStreamOnCloud( + apiSettings, + model, + params, + singleRequestOptions + ) ); return processStream( callResult.response, @@ -81,7 +86,7 @@ async function generateContentOnCloud( apiSettings: ApiSettings, model: string, params: GenerateContentRequest, - requestOptions?: RequestOptions + singleRequestOptions?: SingleRequestOptions ): Promise { if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) { params = GoogleAIMapper.mapGenerateContentRequest(params); @@ -92,7 +97,7 @@ async function generateContentOnCloud( task: Task.GENERATE_CONTENT, apiSettings, stream: false, - requestOptions + singleRequestOptions }, JSON.stringify(params) ); @@ -102,7 +107,7 @@ export async function templateGenerateContent( apiSettings: ApiSettings, templateId: string, templateParams: object, - requestOptions?: RequestOptions + singleRequestOptions?: SingleRequestOptions ): Promise { const response = await makeRequest( { @@ -110,7 +115,7 @@ export async function templateGenerateContent( templateId, apiSettings, stream: false, - requestOptions + singleRequestOptions }, JSON.stringify(templateParams) ); @@ -130,7 +135,7 @@ export async function templateGenerateContentStream( apiSettings: ApiSettings, templateId: string, templateParams: object, - requestOptions?: RequestOptions + singleRequestOptions?: SingleRequestOptions ): Promise { const response = await makeRequest( { @@ -138,7 +143,7 @@ export async function templateGenerateContentStream( templateId, apiSettings, stream: true, - requestOptions + singleRequestOptions }, JSON.stringify(templateParams) ); @@ -150,13 +155,14 @@ export async function generateContent( model: string, params: GenerateContentRequest, chromeAdapter?: ChromeAdapter, - requestOptions?: RequestOptions + singleRequestOptions?: SingleRequestOptions ): Promise { const callResult = await callCloudOrDevice( params, chromeAdapter, () => chromeAdapter!.generateContent(params), - () => generateContentOnCloud(apiSettings, model, params, requestOptions) + () => + generateContentOnCloud(apiSettings, model, params, singleRequestOptions) ); const generateContentResponse = await processGenerateContentResponse( callResult.response, diff --git a/packages/ai/src/models/generative-model.test.ts b/packages/ai/src/models/generative-model.test.ts index 45430cb5f5..8d8bfc7c54 100644 --- a/packages/ai/src/models/generative-model.test.ts +++ b/packages/ai/src/models/generative-model.test.ts @@ -30,6 +30,8 @@ import { getMockResponseStreaming } from '../../test-utils/mock-response'; import sinonChai from 'sinon-chai'; +import * as generateContentMethods from '../methods/generate-content'; +import * as countTokens from '../methods/count-tokens'; import { VertexAIBackend } from '../backend'; import { AIError } from '../errors'; import chaiAsPromised from 'chai-as-promised'; @@ -53,6 +55,9 @@ const fakeAI: AI = { }; describe('GenerativeModel', () => { + afterEach(() => { + restore(); + }); it('passes params through to generateContent', async () => { const genModel = new GenerativeModel( fakeAI, @@ -97,7 +102,7 @@ describe('GenerativeModel', () => { task: request.Task.GENERATE_CONTENT, apiSettings: match.any, stream: false, - requestOptions: {} + singleRequestOptions: {} }, match((value: string) => { return ( @@ -136,7 +141,7 @@ describe('GenerativeModel', () => { task: request.Task.GENERATE_CONTENT, apiSettings: match.any, stream: false, - requestOptions: {} + singleRequestOptions: {} }, match((value: string) => { return value.includes('be friendly'); @@ -199,7 +204,7 @@ describe('GenerativeModel', () => { task: request.Task.GENERATE_CONTENT, apiSettings: match.any, stream: false, - requestOptions: {} + singleRequestOptions: {} }, match((value: string) => { return ( @@ -213,6 +218,34 @@ describe('GenerativeModel', () => { ); restore(); }); + it('generateContent singleRequestOptions overrides requestOptions', async () => { + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + ).rejects('generateContent failed'); // not important + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + timeout: 2000 + }; + const genModel = new GenerativeModel( + fakeAI, + { model: 'my-model' }, + requestOptions + ); + await expect(genModel.generateContent('hello', singleRequestOptions)).to.be + .rejected; + expect(generateContentStub).to.be.calledWith( + match.any, + match.any, + match.any, + match.any, + match({ + timeout: singleRequestOptions.timeout + }) + ); + }); it('passes base model params through to ChatSession when there are no startChatParams', async () => { const genModel = new GenerativeModel( fakeAI, @@ -231,18 +264,56 @@ describe('GenerativeModel', () => { }); restore(); }); - it('overrides base model params with startChatParams', () => { + it('generateContent singleRequestOptions is merged with requestOptions', async () => { + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + ).rejects('generateContent failed'); // not important + const abortController = new AbortController(); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + signal: abortController.signal + }; const genModel = new GenerativeModel( fakeAI, - { - model: 'my-model', - generationConfig: { - topK: 1 - } - }, - {}, - fakeChromeAdapter + { model: 'my-model' }, + requestOptions + ); + await expect(genModel.generateContent('hello', singleRequestOptions)).to.be + .rejected; + expect(generateContentStub).to.be.calledWith( + match.any, + match.any, + match.any, + match.any, + match({ + timeout: requestOptions.timeout, + signal: singleRequestOptions.signal + }) ); + }); + it('passes base model params through to ChatSession when there are no startChatParams', async () => { + const genModel = new GenerativeModel(fakeAI, { + model: 'my-model', + generationConfig: { + topK: 1 + } + }); + const chatSession = genModel.startChat(); + expect(chatSession.params?.generationConfig).to.deep.equal({ + topK: 1 + }); + restore(); + }); + it('overrides base model params with startChatParams', () => { + const genModel = new GenerativeModel(fakeAI, { + model: 'my-model', + generationConfig: { + topK: 1 + } + }); const chatSession = genModel.startChat({ generationConfig: { topK: 2 @@ -292,7 +363,7 @@ describe('GenerativeModel', () => { task: request.Task.GENERATE_CONTENT, apiSettings: match.any, stream: false, - requestOptions: {} + singleRequestOptions: {} }, match((value: string) => { return ( @@ -332,7 +403,7 @@ describe('GenerativeModel', () => { task: request.Task.GENERATE_CONTENT, apiSettings: match.any, stream: false, - requestOptions: {} + singleRequestOptions: {} }, match((value: string) => { return value.includes('be friendly'); @@ -346,7 +417,9 @@ describe('GenerativeModel', () => { { model: 'my-model', tools: [ - { functionDeclarations: [{ name: 'myfunc', description: 'mydesc' }] } + { functionDeclarations: [{ name: 'myfunc', description: 'mydesc' }] }, + { googleSearch: {} }, + { urlContext: {} } ], toolConfig: { functionCallingConfig: { mode: FunctionCallingMode.NONE } @@ -359,6 +432,80 @@ describe('GenerativeModel', () => { {}, fakeChromeAdapter ); + expect(genModel.tools?.length).to.equal(3); + expect(genModel.toolConfig?.functionCallingConfig?.mode).to.equal( + FunctionCallingMode.NONE + ); + expect(genModel.systemInstruction?.parts[0].text).to.equal('be friendly'); + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-success-basic-reply-short.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + await genModel.startChat().sendMessage('hello'); + expect(makeRequestStub).to.be.calledWith( + { + model: 'publishers/google/models/my-model', + task: request.Task.GENERATE_CONTENT, + apiSettings: match.any, + stream: false, + singleRequestOptions: {} + }, + match((value: string) => { + return ( + value.includes('myfunc') && + value.includes(FunctionCallingMode.NONE) && + value.includes('be friendly') + // value.includes('topK') + ); + }) + ); + restore(); + }); + it('passes text-only systemInstruction through to chat.sendMessage', async () => { + const genModel = new GenerativeModel(fakeAI, { + model: 'my-model', + systemInstruction: 'be friendly' + }); + expect(genModel.systemInstruction?.parts[0].text).to.equal('be friendly'); + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-success-basic-reply-short.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + await genModel.startChat().sendMessage('hello'); + expect(makeRequestStub).to.be.calledWith( + { + model: 'publishers/google/models/my-model', + task: request.Task.GENERATE_CONTENT, + apiSettings: match.any, + stream: false, + singleRequestOptions: {} + }, + match((value: string) => { + return value.includes('be friendly'); + }) + ); + restore(); + }); + it('startChat overrides model values', async () => { + const genModel = new GenerativeModel(fakeAI, { + model: 'my-model', + tools: [ + { functionDeclarations: [{ name: 'myfunc', description: 'mydesc' }] } + ], + toolConfig: { + functionCallingConfig: { mode: FunctionCallingMode.NONE } + }, + systemInstruction: { role: 'system', parts: [{ text: 'be friendly' }] }, + generationConfig: { + responseMimeType: 'image/jpeg' + } + }); expect(genModel.tools?.length).to.equal(1); expect(genModel.toolConfig?.functionCallingConfig?.mode).to.equal( FunctionCallingMode.NONE @@ -378,9 +525,7 @@ describe('GenerativeModel', () => { functionDeclarations: [ { name: 'otherfunc', description: 'otherdesc' } ] - }, - { googleSearch: {} }, - { codeExecution: {} } + } ], toolConfig: { functionCallingConfig: { mode: FunctionCallingMode.AUTO } @@ -397,13 +542,11 @@ describe('GenerativeModel', () => { task: request.Task.GENERATE_CONTENT, apiSettings: match.any, stream: false, - requestOptions: {} + singleRequestOptions: {} }, match((value: string) => { return ( value.includes('otherfunc') && - value.includes('googleSearch') && - value.includes('codeExecution') && value.includes(FunctionCallingMode.AUTO) && value.includes('be formal') && value.includes('image/png') && @@ -434,7 +577,7 @@ describe('GenerativeModel', () => { task: request.Task.COUNT_TOKENS, apiSettings: match.any, stream: false, - requestOptions: undefined + singleRequestOptions: {} }, match((value: string) => { return value.includes('hello'); @@ -442,6 +585,62 @@ describe('GenerativeModel', () => { ); restore(); }); + it('countTokens singleRequestOptions overrides requestOptions', async () => { + const countTokensStub = stub(countTokens, 'countTokens').rejects( + 'countTokens failed' + ); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + timeout: 2000 + }; + const genModel = new GenerativeModel( + fakeAI, + { model: 'my-model' }, + requestOptions + ); + await expect(genModel.countTokens('hello', singleRequestOptions)).to.be + .rejected; + expect(countTokensStub).to.be.calledWith( + match.any, + match.any, + match.any, + match.any, + match({ + timeout: singleRequestOptions.timeout + }) + ); + }); + it('countTokens singleRequestOptions is merged with requestOptions', async () => { + const countTokensStub = stub(countTokens, 'countTokens').rejects( + 'countTokens failed' + ); + const abortController = new AbortController(); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + signal: abortController.signal + }; + const genModel = new GenerativeModel( + fakeAI, + { model: 'my-model' }, + requestOptions + ); + await expect(genModel.countTokens('hello', singleRequestOptions)).to.be + .rejected; + expect(countTokensStub).to.be.calledWith( + match.any, + match.any, + match.any, + match.any, + match({ + timeout: requestOptions.timeout, + signal: singleRequestOptions.signal + }) + ); + }); }); describe('GenerativeModel dispatch logic', () => { diff --git a/packages/ai/src/models/generative-model.ts b/packages/ai/src/models/generative-model.ts index ffce645eeb..8defedd33b 100644 --- a/packages/ai/src/models/generative-model.ts +++ b/packages/ai/src/models/generative-model.ts @@ -29,11 +29,12 @@ import { GenerationConfig, ModelParams, Part, - RequestOptions, SafetySetting, + RequestOptions, StartChatParams, Tool, - ToolConfig + ToolConfig, + SingleRequestOptions } from '../types'; import { ChatSession } from '../methods/chat-session'; import { countTokens } from '../methods/count-tokens'; @@ -79,7 +80,8 @@ export class GenerativeModel extends AIModel { * and returns an object containing a single {@link GenerateContentResponse}. */ async generateContent( - request: GenerateContentRequest | string | Array + request: GenerateContentRequest | string | Array, + singleRequestOptions?: SingleRequestOptions ): Promise { const formattedParams = formatGenerateContentInput(request); return generateContent( @@ -94,7 +96,11 @@ export class GenerativeModel extends AIModel { ...formattedParams }, this.chromeAdapter, - this.requestOptions + // Merge request options + { + ...this.requestOptions, + ...singleRequestOptions + } ); } @@ -105,7 +111,8 @@ export class GenerativeModel extends AIModel { * a promise that returns the final aggregated response. */ async generateContentStream( - request: GenerateContentRequest | string | Array + request: GenerateContentRequest | string | Array, + singleRequestOptions?: SingleRequestOptions ): Promise { const formattedParams = formatGenerateContentInput(request); return generateContentStream( @@ -120,7 +127,11 @@ export class GenerativeModel extends AIModel { ...formattedParams }, this.chromeAdapter, - this.requestOptions + // Merge request options + { + ...this.requestOptions, + ...singleRequestOptions + } ); } @@ -154,14 +165,20 @@ export class GenerativeModel extends AIModel { * Counts the tokens in the provided request. */ async countTokens( - request: CountTokensRequest | string | Array + request: CountTokensRequest | string | Array, + singleRequestOptions?: SingleRequestOptions ): Promise { const formattedParams = formatGenerateContentInput(request); return countTokens( this._apiSettings, this.model, formattedParams, - this.chromeAdapter + this.chromeAdapter, + // Merge request options + { + ...this.requestOptions, + ...singleRequestOptions + } ); } } diff --git a/packages/ai/src/models/imagen-model.test.ts b/packages/ai/src/models/imagen-model.test.ts index 68b6caca09..34470cc1d1 100644 --- a/packages/ai/src/models/imagen-model.test.ts +++ b/packages/ai/src/models/imagen-model.test.ts @@ -47,6 +47,9 @@ const fakeAI: AI = { }; describe('ImagenModel', () => { + afterEach(() => { + restore(); + }); it('generateImages makes a request to predict with default parameters', async () => { const mockResponse = getMockResponse( 'vertexAI', @@ -67,7 +70,7 @@ describe('ImagenModel', () => { task: request.Task.PREDICT, apiSettings: match.any, stream: false, - requestOptions: undefined + singleRequestOptions: {} }, match((value: string) => { return ( @@ -76,7 +79,6 @@ describe('ImagenModel', () => { ); }) ); - restore(); }); it('generateImages makes a request to predict with generation config and safety settings', async () => { const imagenModel = new ImagenModel(fakeAI, { @@ -109,7 +111,7 @@ describe('ImagenModel', () => { task: request.Task.PREDICT, apiSettings: match.any, stream: false, - requestOptions: undefined + singleRequestOptions: {} }, match((value: string) => { return ( @@ -137,7 +139,76 @@ describe('ImagenModel', () => { ); }) ); - restore(); + }); + it('generateImages singleRequestOptions overrides requestOptions', async () => { + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + timeout: 2000 + }; + const imagenModel = new ImagenModel( + fakeAI, + { model: 'my-model' }, + requestOptions + ); + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-success-generate-images-base64.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const prompt = 'A photorealistic image of a toy boat at sea.'; + await imagenModel.generateImages(prompt, singleRequestOptions); + expect(makeRequestStub).to.be.calledWith( + { + model: match.any, + task: request.Task.PREDICT, + apiSettings: match.any, + stream: false, + singleRequestOptions: { + timeout: singleRequestOptions.timeout + } + }, + match.any + ); + }); + it('generateImages singleRequestOptions is merged with requestOptions', async () => { + const abortController = new AbortController(); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + signal: abortController.signal + }; + const imagenModel = new ImagenModel( + fakeAI, + { model: 'my-model' }, + requestOptions + ); + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-success-generate-images-base64.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const prompt = 'A photorealistic image of a toy boat at sea.'; + await imagenModel.generateImages(prompt, singleRequestOptions); + expect(makeRequestStub).to.be.calledWith( + { + model: match.any, + task: request.Task.PREDICT, + apiSettings: match.any, + stream: false, + singleRequestOptions: { + timeout: requestOptions.timeout, + signal: singleRequestOptions.signal + } + }, + match.any + ); }); it('throws if prompt blocked', async () => { const mockResponse = getMockResponse( @@ -163,8 +234,76 @@ describe('ImagenModel', () => { expect((e as AIError).message).to.include( "Image generation failed with the following error: The prompt could not be submitted. This prompt contains sensitive words that violate Google's Responsible AI practices. Try rephrasing the prompt. If you think this was an error, send feedback." ); - } finally { - restore(); } }); + it('generateImagesGCS singleRequestOptions overrides requestOptions', async () => { + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + timeout: 2000 + }; + const imagenModel = new ImagenModel( + fakeAI, + { model: 'my-model' }, + requestOptions + ); + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-success-generate-images-gcs.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const prompt = 'A photorealistic image of a toy boat at sea.'; + await imagenModel.generateImagesGCS(prompt, '', singleRequestOptions); + expect(makeRequestStub).to.be.calledWith( + { + model: match.any, + task: request.Task.PREDICT, + apiSettings: match.any, + stream: false, + singleRequestOptions: { + timeout: singleRequestOptions.timeout + } + }, + match.any + ); + }); + it('generateImages singleRequestOptions is merged with requestOptions', async () => { + const abortController = new AbortController(); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + signal: abortController.signal + }; + const imagenModel = new ImagenModel( + fakeAI, + { model: 'my-model' }, + requestOptions + ); + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-success-generate-images-gcs.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const prompt = 'A photorealistic image of a toy boat at sea.'; + await imagenModel.generateImagesGCS(prompt, '', singleRequestOptions); + expect(makeRequestStub).to.be.calledWith( + { + model: match.any, + task: request.Task.PREDICT, + apiSettings: match.any, + stream: false, + singleRequestOptions: { + timeout: requestOptions.timeout, + signal: singleRequestOptions.signal + } + }, + match.any + ); + }); }); diff --git a/packages/ai/src/models/imagen-model.ts b/packages/ai/src/models/imagen-model.ts index 567333ee64..beeb01ac12 100644 --- a/packages/ai/src/models/imagen-model.ts +++ b/packages/ai/src/models/imagen-model.ts @@ -26,7 +26,8 @@ import { RequestOptions, ImagenModelParams, ImagenGenerationResponse, - ImagenSafetySettings + ImagenSafetySettings, + SingleRequestOptions } from '../types'; import { AIModel } from './ai-model'; @@ -102,7 +103,8 @@ export class ImagenModel extends AIModel { * @public */ async generateImages( - prompt: string + prompt: string, + singleRequestOptions?: SingleRequestOptions ): Promise> { const body = createPredictRequestBody(prompt, { ...this.generationConfig, @@ -114,7 +116,11 @@ export class ImagenModel extends AIModel { model: this.model, apiSettings: this._apiSettings, stream: false, - requestOptions: this.requestOptions + // Merge request options. Single request options overwrite the model's request options. + singleRequestOptions: { + ...this.requestOptions, + ...singleRequestOptions + } }, JSON.stringify(body) ); @@ -142,7 +148,8 @@ export class ImagenModel extends AIModel { */ async generateImagesGCS( prompt: string, - gcsURI: string + gcsURI: string, + singleRequestOptions?: SingleRequestOptions ): Promise> { const body = createPredictRequestBody(prompt, { gcsURI, @@ -155,7 +162,11 @@ export class ImagenModel extends AIModel { model: this.model, apiSettings: this._apiSettings, stream: false, - requestOptions: this.requestOptions + // Merge request options. Single request options overwrite the model's request options. + singleRequestOptions: { + ...this.requestOptions, + ...singleRequestOptions + } }, JSON.stringify(body) ); diff --git a/packages/ai/src/models/template-generative-model.test.ts b/packages/ai/src/models/template-generative-model.test.ts index c3eb43af49..d3f7ec28ff 100644 --- a/packages/ai/src/models/template-generative-model.test.ts +++ b/packages/ai/src/models/template-generative-model.test.ts @@ -73,6 +73,51 @@ describe('TemplateGenerativeModel', () => { { timeout: 5000 } ); }); + + it('singleRequestOptions overrides requestOptions', async () => { + const templateGenerateContentStub = stub( + generateContentMethods, + 'templateGenerateContent' + ).resolves({} as any); + const model = new TemplateGenerativeModel(fakeAI, { timeout: 1000 }); + const singleRequestOptions = { timeout: 2000 }; + + await model.generateContent( + TEMPLATE_ID, + TEMPLATE_VARS, + singleRequestOptions + ); + + expect(templateGenerateContentStub).to.have.been.calledOnceWith( + model._apiSettings, + TEMPLATE_ID, + { inputs: TEMPLATE_VARS }, + { timeout: 2000 } + ); + }); + + it('singleRequestOptions is merged with requestOptions', async () => { + const templateGenerateContentStub = stub( + generateContentMethods, + 'templateGenerateContent' + ).resolves({} as any); + const abortController = new AbortController(); + const model = new TemplateGenerativeModel(fakeAI, { timeout: 1000 }); + const singleRequestOptions = { signal: abortController.signal }; + + await model.generateContent( + TEMPLATE_ID, + TEMPLATE_VARS, + singleRequestOptions + ); + + expect(templateGenerateContentStub).to.have.been.calledOnceWith( + model._apiSettings, + TEMPLATE_ID, + { inputs: TEMPLATE_VARS }, + { timeout: 1000, signal: abortController.signal } + ); + }); }); describe('generateContentStream', () => { @@ -92,5 +137,50 @@ describe('TemplateGenerativeModel', () => { { timeout: 5000 } ); }); + + it('singleRequestOptions overrides requestOptions', async () => { + const templateGenerateContentStreamStub = stub( + generateContentMethods, + 'templateGenerateContentStream' + ).resolves({} as any); + const model = new TemplateGenerativeModel(fakeAI, { timeout: 1000 }); + const singleRequestOptions = { timeout: 2000 }; + + await model.generateContentStream( + TEMPLATE_ID, + TEMPLATE_VARS, + singleRequestOptions + ); + + expect(templateGenerateContentStreamStub).to.have.been.calledOnceWith( + model._apiSettings, + TEMPLATE_ID, + { inputs: TEMPLATE_VARS }, + { timeout: 2000 } + ); + }); + + it('singleRequestOptions is merged with requestOptions', async () => { + const templateGenerateContentStreamStub = stub( + generateContentMethods, + 'templateGenerateContentStream' + ).resolves({} as any); + const abortController = new AbortController(); + const model = new TemplateGenerativeModel(fakeAI, { timeout: 1000 }); + const singleRequestOptions = { signal: abortController.signal }; + + await model.generateContentStream( + TEMPLATE_ID, + TEMPLATE_VARS, + singleRequestOptions + ); + + expect(templateGenerateContentStreamStub).to.have.been.calledOnceWith( + model._apiSettings, + TEMPLATE_ID, + { inputs: TEMPLATE_VARS }, + { timeout: 1000, signal: abortController.signal } + ); + }); }); }); diff --git a/packages/ai/src/models/template-generative-model.ts b/packages/ai/src/models/template-generative-model.ts index ec9e653618..7c3b99062e 100644 --- a/packages/ai/src/models/template-generative-model.ts +++ b/packages/ai/src/models/template-generative-model.ts @@ -20,7 +20,11 @@ import { templateGenerateContentStream } from '../methods/generate-content'; import { GenerateContentResult, RequestOptions } from '../types'; -import { AI, GenerateContentStreamResult } from '../public-types'; +import { + AI, + GenerateContentStreamResult, + SingleRequestOptions +} from '../public-types'; import { ApiSettings } from '../types/internal'; import { initApiSettings } from './utils'; @@ -62,13 +66,17 @@ export class TemplateGenerativeModel { */ async generateContent( templateId: string, - templateVariables: object // anything! + templateVariables: object, + singleRequestOptions?: SingleRequestOptions ): Promise { return templateGenerateContent( this._apiSettings, templateId, { inputs: templateVariables }, - this.requestOptions + { + ...this.requestOptions, + ...singleRequestOptions + } ); } @@ -86,13 +94,17 @@ export class TemplateGenerativeModel { */ async generateContentStream( templateId: string, - templateVariables: object + templateVariables: object, + singleRequestOptions?: SingleRequestOptions ): Promise { return templateGenerateContentStream( this._apiSettings, templateId, { inputs: templateVariables }, - this.requestOptions + { + ...this.requestOptions, + ...singleRequestOptions + } ); } } diff --git a/packages/ai/src/models/template-imagen-model.test.ts b/packages/ai/src/models/template-imagen-model.test.ts index c053753ea0..9451981f83 100644 --- a/packages/ai/src/models/template-imagen-model.test.ts +++ b/packages/ai/src/models/template-imagen-model.test.ts @@ -18,7 +18,7 @@ import { use, expect } from 'chai'; import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; -import { restore, stub } from 'sinon'; +import { restore, stub, match } from 'sinon'; import { AI } from '../public-types'; import { VertexAIBackend } from '../backend'; import { TemplateImagenModel } from './template-imagen-model'; @@ -83,12 +83,68 @@ describe('TemplateImagenModel', () => { templateId: TEMPLATE_ID, apiSettings: model._apiSettings, stream: false, - requestOptions: { timeout: 5000 } + singleRequestOptions: { timeout: 5000 } }, JSON.stringify({ inputs: TEMPLATE_VARS }) ); }); + it('singleRequestOptions overrides requestOptions', async () => { + const mockPrediction = { + 'bytesBase64Encoded': + 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==', + 'mimeType': 'image/png' + }; + const makeRequestStub = stub(request, 'makeRequest').resolves({ + json: () => Promise.resolve({ predictions: [mockPrediction] }) + } as Response); + const model = new TemplateImagenModel(fakeAI, { timeout: 1000 }); + const singleRequestOptions = { timeout: 2000 }; + + await model.generateImages( + TEMPLATE_ID, + TEMPLATE_VARS, + singleRequestOptions + ); + + expect(makeRequestStub).to.have.been.calledOnceWith( + match({ + singleRequestOptions: { timeout: 2000 } + }), + match.any + ); + }); + + it('singleRequestOptions is merged with requestOptions', async () => { + const mockPrediction = { + 'bytesBase64Encoded': + 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==', + 'mimeType': 'image/png' + }; + const makeRequestStub = stub(request, 'makeRequest').resolves({ + json: () => Promise.resolve({ predictions: [mockPrediction] }) + } as Response); + const abortController = new AbortController(); + const model = new TemplateImagenModel(fakeAI, { timeout: 1000 }); + const singleRequestOptions = { signal: abortController.signal }; + + await model.generateImages( + TEMPLATE_ID, + TEMPLATE_VARS, + singleRequestOptions + ); + + expect(makeRequestStub).to.have.been.calledOnceWith( + match({ + singleRequestOptions: { + timeout: 1000, + signal: abortController.signal + } + }), + match.any + ); + }); + it('should return the result of handlePredictResponse', async () => { const mockPrediction = { 'bytesBase64Encoded': diff --git a/packages/ai/src/models/template-imagen-model.ts b/packages/ai/src/models/template-imagen-model.ts index 34325c711b..be4d10f72d 100644 --- a/packages/ai/src/models/template-imagen-model.ts +++ b/packages/ai/src/models/template-imagen-model.ts @@ -19,7 +19,8 @@ import { RequestOptions } from '../types'; import { AI, ImagenGenerationResponse, - ImagenInlineImage + ImagenInlineImage, + SingleRequestOptions } from '../public-types'; import { ApiSettings } from '../types/internal'; import { makeRequest, ServerPromptTemplateTask } from '../requests/request'; @@ -64,7 +65,8 @@ export class TemplateImagenModel { */ async generateImages( templateId: string, - templateVariables: object + templateVariables: object, + singleRequestOptions?: SingleRequestOptions ): Promise> { const response = await makeRequest( { @@ -72,7 +74,10 @@ export class TemplateImagenModel { templateId, apiSettings: this._apiSettings, stream: false, - requestOptions: this.requestOptions + singleRequestOptions: { + ...this.requestOptions, + ...singleRequestOptions + } }, JSON.stringify({ inputs: templateVariables }) ); diff --git a/packages/ai/src/requests/request.test.ts b/packages/ai/src/requests/request.test.ts index a54ff521be..29b5118390 100644 --- a/packages/ai/src/requests/request.test.ts +++ b/packages/ai/src/requests/request.test.ts @@ -16,12 +16,14 @@ */ import { expect, use } from 'chai'; -import { match, restore, stub } from 'sinon'; +import Sinon, { match, restore, stub, useFakeTimers } from 'sinon'; import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; import { + ABORT_ERROR_NAME, RequestURL, ServerPromptTemplateTask, + TIMEOUT_EXPIRED_MESSAGE, Task, getHeaders, makeRequest @@ -55,7 +57,7 @@ describe('request methods', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: true, - requestOptions: {} + singleRequestOptions: undefined }); expect(url.toString()).to.include('models/model-name:generateContent'); expect(url.toString()).to.include('alt=sse'); @@ -66,7 +68,7 @@ describe('request methods', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: {} + singleRequestOptions: undefined }); expect(url.toString()).to.include('models/model-name:generateContent'); expect(url.toString()).to.not.include(fakeApiSettings); @@ -78,7 +80,7 @@ describe('request methods', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: {} + singleRequestOptions: undefined }); expect(url.toString()).to.include(DEFAULT_API_VERSION); }); @@ -88,7 +90,7 @@ describe('request methods', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: { baseUrl: 'https://my.special.endpoint' } + singleRequestOptions: { baseUrl: 'https://my.special.endpoint' } }); expect(url.toString()).to.include('https://my.special.endpoint'); }); @@ -98,7 +100,7 @@ describe('request methods', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: {} + singleRequestOptions: undefined }); expect(url.toString()).to.include( 'tunedModels/model-name:generateContent' @@ -112,7 +114,7 @@ describe('request methods', () => { task: ServerPromptTemplateTask.TEMPLATE_GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: {} + singleRequestOptions: undefined }); expect(url.toString()).to.include( 'templates/my-template:templateGenerateContent' @@ -135,7 +137,7 @@ describe('request methods', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: true, - requestOptions: {} + singleRequestOptions: undefined }); it('adds client headers', async () => { const headers = await getHeaders(fakeUrl); @@ -163,7 +165,7 @@ describe('request methods', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: true, - requestOptions: {} + singleRequestOptions: undefined }); const headers = await getHeaders(fakeUrl); expect(headers.get('X-Firebase-Appid')).to.equal('my-appid'); @@ -188,7 +190,7 @@ describe('request methods', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: true, - requestOptions: {} + singleRequestOptions: undefined }); const headers = await getHeaders(fakeUrl); expect(headers.get('X-Firebase-Appid')).to.be.null; @@ -209,7 +211,7 @@ describe('request methods', () => { backend: new VertexAIBackend() }, stream: true, - requestOptions: {} + singleRequestOptions: undefined }); const headers = await getHeaders(fakeUrl); expect(headers.has('X-Firebase-AppCheck')).to.be.false; @@ -226,7 +228,7 @@ describe('request methods', () => { getAppCheckToken: () => Promise.resolve() }, stream: true, - requestOptions: {} + singleRequestOptions: undefined }); const headers = await getHeaders(fakeUrl); expect(headers.has('X-Firebase-AppCheck')).to.be.false; @@ -245,7 +247,7 @@ describe('request methods', () => { Promise.resolve({ token: 'dummytoken', error: Error('oops') }) }, stream: true, - requestOptions: {} + singleRequestOptions: undefined }); const warnStub = stub(console, 'warn'); const headers = await getHeaders(fakeUrl); @@ -271,7 +273,7 @@ describe('request methods', () => { backend: new VertexAIBackend() }, stream: true, - requestOptions: {} + singleRequestOptions: undefined }); const headers = await getHeaders(fakeUrl); expect(headers.has('Authorization')).to.be.false; @@ -288,15 +290,45 @@ describe('request methods', () => { getAppCheckToken: () => Promise.resolve() }, stream: true, - requestOptions: {} + singleRequestOptions: undefined }); const headers = await getHeaders(fakeUrl); expect(headers.has('Authorization')).to.be.false; }); }); describe('makeRequest', () => { + let fetchStub: Sinon.SinonStub; + let clock: Sinon.SinonFakeTimers; + const fetchAborter = ( + _url: string, + options?: RequestInit + ): Promise => { + expect(options).to.not.be.undefined; + expect(options!.signal).to.not.be.undefined; + const signal = options!.signal; + return new Promise((_resolve, reject): void => { + const abortListener = (): void => { + reject( + new DOMException(signal?.reason || 'Aborted', ABORT_ERROR_NAME) + ); + }; + + signal?.addEventListener('abort', abortListener, { once: true }); + }); + }; + + beforeEach(() => { + fetchStub = stub(globalThis, 'fetch'); + clock = useFakeTimers(); + }); + + afterEach(() => { + restore(); + clock.restore(); + }); + it('no error', async () => { - const fetchStub = stub(globalThis, 'fetch').resolves({ + fetchStub.resolves({ ok: true } as Response); const response = await makeRequest( @@ -312,10 +344,10 @@ describe('request methods', () => { expect(response.ok).to.be.true; }); it('error with timeout', async () => { - const fetchStub = stub(globalThis, 'fetch').resolves({ + fetchStub.resolves({ ok: false, status: 500, - statusText: 'AbortError' + statusText: ABORT_ERROR_NAME } as Response); try { @@ -325,7 +357,7 @@ describe('request methods', () => { task: Task.GENERATE_CONTENT, apiSettings: fakeApiSettings, stream: false, - requestOptions: { + singleRequestOptions: { timeout: 180000 } }, @@ -335,7 +367,7 @@ describe('request methods', () => { expect((e as AIError).code).to.equal(AIErrorCode.FETCH_ERROR); expect((e as AIError).customErrorData?.status).to.equal(500); expect((e as AIError).customErrorData?.statusText).to.equal( - 'AbortError' + ABORT_ERROR_NAME ); expect((e as AIError).message).to.include('500 AbortError'); } @@ -343,7 +375,7 @@ describe('request methods', () => { expect(fetchStub).to.be.calledOnce; }); it('Network error, no response.json()', async () => { - const fetchStub = stub(globalThis, 'fetch').resolves({ + fetchStub.resolves({ ok: false, status: 500, statusText: 'Server Error' @@ -369,7 +401,7 @@ describe('request methods', () => { expect(fetchStub).to.be.calledOnce; }); it('Network error, includes response.json()', async () => { - const fetchStub = stub(globalThis, 'fetch').resolves({ + fetchStub.resolves({ ok: false, status: 500, statusText: 'Server Error', @@ -397,7 +429,7 @@ describe('request methods', () => { expect(fetchStub).to.be.calledOnce; }); it('Network error, includes response.json() and details', async () => { - const fetchStub = stub(globalThis, 'fetch').resolves({ + fetchStub.resolves({ ok: false, status: 500, statusText: 'Server Error', @@ -437,16 +469,209 @@ describe('request methods', () => { } expect(fetchStub).to.be.calledOnce; }); - }); - it('Network error, API not enabled', async () => { - const mockResponse = getMockResponse( - 'vertexAI', - 'unary-failure-firebasevertexai-api-not-enabled.json' - ); - const fetchStub = stub(globalThis, 'fetch').resolves( - mockResponse as Response - ); - try { + it('Network error, API not enabled', async () => { + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-failure-firebasevertexai-api-not-enabled.json' + ); + fetchStub.resolves(mockResponse as Response); + try { + await makeRequest( + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false + }, + '' + ); + } catch (e) { + expect((e as AIError).code).to.equal(AIErrorCode.API_NOT_ENABLED); + expect((e as AIError).message).to.include('my-project'); + expect((e as AIError).message).to.include('googleapis.com'); + } + expect(fetchStub).to.be.calledOnce; + }); + + it('should throw DOMException if external signal is already aborted', async () => { + const controller = new AbortController(); + const abortReason = 'Aborted before request'; + controller.abort(abortReason); + + const requestPromise = makeRequest( + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + singleRequestOptions: { signal: controller.signal } + }, + '{}' + ); + + await expect(requestPromise).to.be.rejectedWith( + DOMException, + abortReason + ); + + expect(fetchStub).not.to.have.been.called; + }); + it('should throw DOMException if external signal aborts during request', async () => { + fetchStub.callsFake(fetchAborter); + const controller = new AbortController(); + const abortReason = 'Aborted during request'; + + const requestPromise = makeRequest( + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + singleRequestOptions: { signal: controller.signal } + }, + '{}' + ); + + await clock.tickAsync(0); + controller.abort(abortReason); + + await expect(requestPromise).to.be.rejectedWith( + DOMException, + abortReason + ); + }); + + it('should abort fetch if timeout expires during request', async () => { + const timeoutDuration = 100; + fetchStub.callsFake(fetchAborter); + + const requestPromise = makeRequest( + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + singleRequestOptions: { timeout: timeoutDuration } + }, + '{}' + ); + + await clock.tickAsync(timeoutDuration + 100); + + await expect(requestPromise).to.be.rejectedWith( + DOMException, + TIMEOUT_EXPIRED_MESSAGE + ); + + expect(fetchStub).to.have.been.calledOnce; + const fetchOptions = fetchStub.firstCall.args[1] as RequestInit; + const internalSignal = fetchOptions.signal; + + expect(internalSignal?.aborted).to.be.true; + expect((internalSignal?.reason as Error).name).to.equal(ABORT_ERROR_NAME); + expect((internalSignal?.reason as Error).message).to.equal( + 'Timeout has expired.' + ); + }); + + it('should succeed and clear timeout if fetch completes before timeout', async () => { + const mockResponse = new Response('{}', { + status: 200, + statusText: 'OK' + }); + const fetchPromise = Promise.resolve(mockResponse); + fetchStub.resolves(fetchPromise); + const clearTimeoutStub = stub(globalThis, 'clearTimeout'); + + const requestPromise = makeRequest( + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + singleRequestOptions: { timeout: 5000 } // Generous timeout + }, + '{}' + ); + + // Advance time slightly, well within timeout + await clock.tickAsync(10); + + const response = await requestPromise; + expect(response.ok).to.be.true; + expect(clearTimeoutStub).to.have.been.calledOnce; + expect(fetchStub).to.have.been.calledOnce; + }); + + it('should use external signal abort reason if it occurs before timeout', async () => { + const controller = new AbortController(); + const abortReason = 'External Abort Wins'; + const timeoutDuration = 500; + fetchStub.callsFake(fetchAborter); + + const requestPromise = makeRequest( + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + singleRequestOptions: { + signal: controller.signal, + timeout: timeoutDuration + } + }, + '{}' + ); + + // Advance time, but less than the timeout + await clock.tickAsync(timeoutDuration / 2); + controller.abort(abortReason); + + await expect(requestPromise).to.be.rejectedWith( + DOMException, + abortReason + ); + }); + + it('should use timeout reason if it occurs before external signal abort', async () => { + const controller = new AbortController(); + const abortReason = 'External Abort Loses'; + const timeoutDuration = 100; + fetchStub.callsFake(fetchAborter); + + const requestPromise = makeRequest( + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + singleRequestOptions: { + signal: controller.signal, + timeout: timeoutDuration + } + }, + '{}' + ); + + // Schedule external abort after timeout + setTimeout(() => controller.abort(abortReason), timeoutDuration * 2); + + // Advance time past the timeout + await clock.tickAsync(timeoutDuration + 1); + + await expect(requestPromise).to.be.rejectedWith( + DOMException, + TIMEOUT_EXPIRED_MESSAGE + ); + }); + + it('should pass internal signal to fetch options', async () => { + const mockResponse = new Response('{}', { + status: 200, + statusText: 'OK' + }); + fetchStub.resolves(mockResponse); + await makeRequest( { model: 'models/model-name', @@ -456,11 +681,59 @@ describe('request methods', () => { }, '' ); - } catch (e) { - expect((e as AIError).code).to.equal(AIErrorCode.API_NOT_ENABLED); - expect((e as AIError).message).to.include('my-project'); - expect((e as AIError).message).to.include('googleapis.com'); - } - expect(fetchStub).to.be.calledOnce; + + expect(fetchStub).to.have.been.calledOnce; + const fetchOptions = fetchStub.firstCall.args[1] as RequestInit; + expect(fetchOptions.signal).to.exist; + expect(fetchOptions.signal).to.be.instanceOf(AbortSignal); + expect(fetchOptions.signal?.aborted).to.be.false; + }); + + it('should abort immediately if timeout is 0', async () => { + fetchStub.callsFake(fetchAborter); + const requestPromise = makeRequest( + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + singleRequestOptions: { timeout: 0 } + }, + '{}' + ); + + // Tick the clock just enough to trigger a timeout(0) + await clock.tickAsync(1); + + await expect(requestPromise).to.be.rejectedWith( + DOMException, + TIMEOUT_EXPIRED_MESSAGE + ); + }); + + it('should not error if signal is aborted after completion', async () => { + const controller = new AbortController(); + const mockResponse = new Response('{}', { + status: 200, + statusText: 'OK' + }); + fetchStub.resolves(mockResponse); + + const response = await makeRequest( + { + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + singleRequestOptions: { signal: controller.signal } + }, + '{}' + ); + + // Listener should be removed, so this abort should do nothing. + controller.abort('Too late'); + + expect(response.ok).to.be.true; + }); }); }); diff --git a/packages/ai/src/requests/request.ts b/packages/ai/src/requests/request.ts index cfd5a180ca..a66b36ac6a 100644 --- a/packages/ai/src/requests/request.ts +++ b/packages/ai/src/requests/request.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { ErrorDetails, RequestOptions, AIErrorCode } from '../types'; +import { SingleRequestOptions, AIErrorCode, ErrorDetails } from '../types'; import { AIError } from '../errors'; import { ApiSettings } from '../types/internal'; import { @@ -27,6 +27,9 @@ import { import { logger } from '../logger'; import { BackendType } from '../public-types'; +export const TIMEOUT_EXPIRED_MESSAGE = 'Timeout has expired.'; +export const ABORT_ERROR_NAME = 'AbortError'; + export const enum Task { GENERATE_CONTENT = 'generateContent', STREAM_GENERATE_CONTENT = 'streamGenerateContent', @@ -43,7 +46,7 @@ export const enum ServerPromptTemplateTask { interface BaseRequestURLParams { apiSettings: ApiSettings; stream: boolean; - requestOptions?: RequestOptions; + singleRequestOptions?: SingleRequestOptions; } /** @@ -94,7 +97,9 @@ export class RequestURL { } private get baseUrl(): string { - return this.params.requestOptions?.baseUrl ?? `https://${DEFAULT_DOMAIN}`; + return ( + this.params.singleRequestOptions?.baseUrl ?? `https://${DEFAULT_DOMAIN}` + ); } private get queryParams(): URLSearchParams { @@ -175,24 +180,48 @@ export async function makeRequest( ): Promise { const url = new RequestURL(requestUrlParams); let response; - let fetchTimeoutId: string | number | NodeJS.Timeout | undefined; + + const externalSignal = requestUrlParams.singleRequestOptions?.signal; + const timeoutMillis = + requestUrlParams.singleRequestOptions?.timeout != null && + requestUrlParams.singleRequestOptions.timeout >= 0 + ? requestUrlParams.singleRequestOptions.timeout + : DEFAULT_FETCH_TIMEOUT_MS; + + const internalAbortController = new AbortController(); + const fetchTimeoutId = setTimeout(() => { + internalAbortController.abort( + new DOMException(TIMEOUT_EXPIRED_MESSAGE, ABORT_ERROR_NAME) + ); + logger.debug( + `Aborting request to ${url} due to timeout (${timeoutMillis}ms)` + ); + }, timeoutMillis); + + // Used to abort the fetch if either the user-defined `externalSignal` is aborted, or if the + // internal signal (triggered by timeouts) is aborted. + const combinedSignal = AbortSignal.any( + externalSignal + ? [externalSignal, internalAbortController.signal] + : [internalAbortController.signal] + ); + + if (externalSignal && externalSignal.aborted) { + clearTimeout(fetchTimeoutId); + throw new DOMException( + externalSignal.reason ?? 'Aborted externally before fetch', + ABORT_ERROR_NAME + ); + } + try { const fetchOptions: RequestInit = { method: 'POST', headers: await getHeaders(url), + signal: combinedSignal, body }; - // Timeout is 180s by default. - const timeoutMillis = - requestUrlParams.requestOptions?.timeout != null && - requestUrlParams.requestOptions.timeout >= 0 - ? requestUrlParams.requestOptions.timeout - : DEFAULT_FETCH_TIMEOUT_MS; - const abortController = new AbortController(); - fetchTimeoutId = setTimeout(() => abortController.abort(), timeoutMillis); - fetchOptions.signal = abortController.signal; - response = await fetch(url.toString(), fetchOptions); if (!response.ok) { let message = ''; @@ -252,7 +281,8 @@ export async function makeRequest( if ( (e as AIError).code !== AIErrorCode.FETCH_ERROR && (e as AIError).code !== AIErrorCode.API_NOT_ENABLED && - e instanceof Error + e instanceof Error && + (e as DOMException).name !== ABORT_ERROR_NAME ) { err = new AIError( AIErrorCode.ERROR, @@ -263,9 +293,10 @@ export async function makeRequest( throw err; } finally { - if (fetchTimeoutId) { - clearTimeout(fetchTimeoutId); - } + // When doing streaming requests, this will clear the timeout once the stream begins. + // If a timeout it 3000ms, and the stream starts after 300ms and ends after 5000ms, the + // timeout will be cleared after 300ms, so it won't abort the request. + clearTimeout(fetchTimeoutId); } return response; } diff --git a/packages/ai/src/requests/stream-reader.ts b/packages/ai/src/requests/stream-reader.ts index b4968969be..7af4d857bc 100644 --- a/packages/ai/src/requests/stream-reader.ts +++ b/packages/ai/src/requests/stream-reader.ts @@ -52,9 +52,14 @@ export function processStream( const inputStream = response.body!.pipeThrough( new TextDecoderStream('utf8', { fatal: true }) ); + const responseStream = getResponseStream(inputStream); + + // We split the stream so the user can iterate over partial results (stream1) + // while we aggregate the full result for history/final response (stream2). const [stream1, stream2] = responseStream.tee(); + return { stream: generateResponseSequence(stream1, apiSettings, inferenceSource), response: getResponsePromise(stream2, apiSettings, inferenceSource) @@ -82,7 +87,6 @@ async function getResponsePromise( inferenceSource ); } - allResponses.push(value); } } @@ -112,7 +116,6 @@ async function* generateResponseSequence( } const firstCandidate = enhancedResponse.candidates?.[0]; - // Don't yield a response with no useful data for the developer. if ( !firstCandidate?.content?.parts && !firstCandidate?.finishReason && @@ -127,9 +130,7 @@ async function* generateResponseSequence( } /** - * Reads a raw stream from the fetch response and join incomplete - * chunks, returning a new stream that provides a single complete - * GenerateContentResponse in each iteration. + * Reads a raw string stream, buffers incomplete chunks, and yields parsed JSON objects. */ export function getResponseStream( inputStream: ReadableStream @@ -153,6 +154,8 @@ export function getResponseStream( } currentText += value; + // SSE events may span chunk boundaries, so we buffer until we match + // the full "data: {json}\n\n" pattern. let match = currentText.match(responseLineRE); let parsedResponse: T; while (match) { @@ -193,8 +196,7 @@ export function aggregateResponses( for (const response of responses) { if (response.candidates) { for (const candidate of response.candidates) { - // Index will be undefined if it's the first index (0), so we should use 0 if it's undefined. - // See: https://github.com/firebase/firebase-js-sdk/issues/8566 + // Use 0 if index is undefined (protobuf default value omission). const i = candidate.index || 0; if (!aggregatedResponse.candidates) { aggregatedResponse.candidates = []; @@ -204,7 +206,8 @@ export function aggregateResponses( index: candidate.index } as GenerateContentCandidate; } - // Keep overwriting, the last one will be final + + // Overwrite with the latest metadata aggregatedResponse.candidates[i].citationMetadata = candidate.citationMetadata; aggregatedResponse.candidates[i].finishReason = candidate.finishReason; @@ -229,12 +232,7 @@ export function aggregateResponses( urlContextMetadata as URLContextMetadata; } - /** - * Candidates should always have content and parts, but this handles - * possible malformed responses. - */ if (candidate.content) { - // Skip a candidate without parts. if (!candidate.content.parts) { continue; } diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index 6e5d214768..991453c53f 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -253,6 +253,47 @@ export interface RequestOptions { baseUrl?: string; } +/** + * Options that can be provided per-request. + * Extends the base {@link RequestOptions} (like `timeout` and `baseUrl`) + * with request-specific controls like cancellation via `AbortSignal`. + * + * Options specified here will override any default {@link RequestOptions} + * configured on a model (for example, {@link GenerativeModel}). + * + * @public + */ +export interface SingleRequestOptions extends RequestOptions { + /** + * An `AbortSignal` instance that allows cancelling ongoing requests (like `generateContent` or + * `generateImages`). + * + * If provided, calling `abort()` on the corresponding `AbortController` + * will attempt to cancel the underlying HTTP request. An `AbortError` will be thrown + * if cancellation is successful. + * + * Note that this will not cancel the request in the backend, so any applicable billing charges + * will still be applied despite cancellation. + * + * @example + * ```javascript + * const controller = new AbortController(); + * const model = getGenerativeModel({ + * // ... + * }); + * model.generateContent( + * "Write a story about a magic backpack.", + * { signal: controller.signal } + * ); + * + * // To cancel request: + * controller.abort(); + * ``` + * @see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal + */ + signal?: AbortSignal; +} + /** * Defines a tool that model can call to access external knowledge. * @public From 5579b387ab697347ecd4a29ffed47c4cf808d544 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 12 Jan 2026 10:41:48 -0800 Subject: [PATCH 037/174] feat(ai): Add thinking levels parameter (#9424) --- .changeset/plenty-bulldogs-complain.md | 6 ++++ common/api-review/ai.api.md | 12 +++++++ docs-devsite/ai.md | 27 +++++++++++++++ docs-devsite/ai.thinkingconfig.md | 27 +++++++++++++-- .../ai/src/models/generative-model.test.ts | 17 +++++++++- packages/ai/src/models/generative-model.ts | 21 +++++++++++- packages/ai/src/types/enums.ts | 23 +++++++++++++ packages/ai/src/types/requests.ts | 33 +++++++++++++++++-- 8 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 .changeset/plenty-bulldogs-complain.md diff --git a/.changeset/plenty-bulldogs-complain.md b/.changeset/plenty-bulldogs-complain.md new file mode 100644 index 0000000000..d8583106e6 --- /dev/null +++ b/.changeset/plenty-bulldogs-complain.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +Added ability to specify thinking levels in `thinkingConfig`. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 215d89e4f3..59b1c715d2 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -1376,8 +1376,20 @@ export interface TextPart { export interface ThinkingConfig { includeThoughts?: boolean; thinkingBudget?: number; + thinkingLevel?: ThinkingLevel; } +// @public +export const ThinkingLevel: { + MINIMAL: string; + LOW: string; + MEDIUM: string; + HIGH: string; +}; + +// @public +export type ThinkingLevel = (typeof ThinkingLevel)[keyof typeof ThinkingLevel]; + // Warning: (ae-incompatible-release-tags) The symbol "Tool" is marked as @public, but its signature references "CodeExecutionTool" which is marked as @beta // Warning: (ae-incompatible-release-tags) The symbol "Tool" is marked as @public, but its signature references "URLContextTool" which is marked as @beta // diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index 482c49c3cd..be3116ca2f 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -177,6 +177,7 @@ The Firebase AI Web SDK. | [POSSIBLE\_ROLES](./ai.md#possible_roles) | Possible roles. | | [ResponseModality](./ai.md#responsemodality) | (Public Preview) Generation modalities to be returned in generation responses. | | [SchemaType](./ai.md#schematype) | Contains the list of OpenAPI data types as defined by the [OpenAPI specification](https://swagger.io/docs/specification/data-models/data-types/) | +| [ThinkingLevel](./ai.md#thinkinglevel) | A preset that controls the model's "thinking" process. Use ThinkingLevel.LOW for faster responses on less complex tasks, and ThinkingLevel.HIGH for better reasoning on more complex tasks. | | [URLRetrievalStatus](./ai.md#urlretrievalstatus) | (Public Preview) The status of a URL retrieval. | ## Type Aliases @@ -209,6 +210,7 @@ The Firebase AI Web SDK. | [ResponseModality](./ai.md#responsemodality) | (Public Preview) Generation modalities to be returned in generation responses. | | [Role](./ai.md#role) | Role is the producer of the content. | | [SchemaType](./ai.md#schematype) | Contains the list of OpenAPI data types as defined by the [OpenAPI specification](https://swagger.io/docs/specification/data-models/data-types/) | +| [ThinkingLevel](./ai.md#thinkinglevel) | A preset that controls the model's "thinking" process. Use ThinkingLevel.LOW for faster responses on less complex tasks, and ThinkingLevel.HIGH for better reasoning on more complex tasks. | | [Tool](./ai.md#tool) | Defines a tool that model can call to access external knowledge. | | [TypedSchema](./ai.md#typedschema) | A type that includes all specific Schema types. | | [URLRetrievalStatus](./ai.md#urlretrievalstatus) | (Public Preview) The status of a URL retrieval. | @@ -828,6 +830,21 @@ SchemaType: { } ``` +## ThinkingLevel + +A preset that controls the model's "thinking" process. Use `ThinkingLevel.LOW` for faster responses on less complex tasks, and `ThinkingLevel.HIGH` for better reasoning on more complex tasks. + +Signature: + +```typescript +ThinkingLevel: { + MINIMAL: string; + LOW: string; + MEDIUM: string; + HIGH: string; +} +``` + ## URLRetrievalStatus > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1143,6 +1160,16 @@ Contains the list of OpenAPI data types as defined by the [OpenAPI specification export type SchemaType = (typeof SchemaType)[keyof typeof SchemaType]; ``` +## ThinkingLevel + +A preset that controls the model's "thinking" process. Use `ThinkingLevel.LOW` for faster responses on less complex tasks, and `ThinkingLevel.HIGH` for better reasoning on more complex tasks. + +Signature: + +```typescript +export type ThinkingLevel = (typeof ThinkingLevel)[keyof typeof ThinkingLevel]; +``` + ## Tool Defines a tool that model can call to access external knowledge. diff --git a/docs-devsite/ai.thinkingconfig.md b/docs-devsite/ai.thinkingconfig.md index 1ddc1626f4..137d154d9e 100644 --- a/docs-devsite/ai.thinkingconfig.md +++ b/docs-devsite/ai.thinkingconfig.md @@ -25,7 +25,8 @@ export interface ThinkingConfig | Property | Type | Description | | --- | --- | --- | | [includeThoughts](./ai.thinkingconfig.md#thinkingconfigincludethoughts) | boolean | Whether to include "thought summaries" in the model's response. | -| [thinkingBudget](./ai.thinkingconfig.md#thinkingconfigthinkingbudget) | number | The thinking budget, in tokens.This parameter sets an upper limit on the number of tokens the model can use for its internal "thinking" process. A higher budget may result in higher quality responses for complex tasks but can also increase latency and cost.If you don't specify a budget, the model will determine the appropriate amount of thinking based on the complexity of the prompt.An error will be thrown if you set a thinking budget for a model that does not support this feature or if the specified budget is not within the model's supported range. | +| [thinkingBudget](./ai.thinkingconfig.md#thinkingconfigthinkingbudget) | number | The thinking budget, in tokens. | +| [thinkingLevel](./ai.thinkingconfig.md#thinkingconfigthinkinglevel) | [ThinkingLevel](./ai.md#thinkinglevel) | If not specified, Gemini will use the model's default dynamic thinking level. | ## ThinkingConfig.includeThoughts @@ -45,12 +46,34 @@ The thinking budget, in tokens. This parameter sets an upper limit on the number of tokens the model can use for its internal "thinking" process. A higher budget may result in higher quality responses for complex tasks but can also increase latency and cost. -If you don't specify a budget, the model will determine the appropriate amount of thinking based on the complexity of the prompt. +The range of supported thinking budget values depends on the model. + +

    • To use the default thinking budget for a model, leave this value undefined.
    • + +
    • To disable thinking, when supported by the model, set this value to `0`.
    • + +
    • To use dynamic thinking, which allows the model to decide on the thinking budget based on the task, set this value to `-1`.
    An error will be thrown if you set a thinking budget for a model that does not support this feature or if the specified budget is not within the model's supported range. +The model will also error if `thinkingLevel` and `thinkingBudget` are both set. + Signature: ```typescript thinkingBudget?: number; ``` + +## ThinkingConfig.thinkingLevel + +If not specified, Gemini will use the model's default dynamic thinking level. + +Note: The model will error if `thinkingLevel` and `thinkingBudget` are both set. + +Important: Gemini 2.5 series models do not support thinking levels; use `thinkingBudget` to set a thinking budget instead. + +Signature: + +```typescript +thinkingLevel?: ThinkingLevel; +``` diff --git a/packages/ai/src/models/generative-model.test.ts b/packages/ai/src/models/generative-model.test.ts index 8d8bfc7c54..a7d8eb3ff1 100644 --- a/packages/ai/src/models/generative-model.test.ts +++ b/packages/ai/src/models/generative-model.test.ts @@ -21,7 +21,8 @@ import { AI, InferenceMode, AIErrorCode, - ChromeAdapter + ChromeAdapter, + ThinkingLevel } from '../public-types'; import * as request from '../requests/request'; import { SinonStub, match, restore, stub } from 'sinon'; @@ -58,6 +59,20 @@ describe('GenerativeModel', () => { afterEach(() => { restore(); }); + it('throws if generationConfig is invalid', () => { + expect( + () => + new GenerativeModel(fakeAI, { + model: 'my-model', + generationConfig: { + thinkingConfig: { + thinkingBudget: 1000, + thinkingLevel: ThinkingLevel.LOW + } + } + }) + ).to.throw(AIErrorCode.UNSUPPORTED); + }); it('passes params through to generateContent', async () => { const genModel = new GenerativeModel( fakeAI, diff --git a/packages/ai/src/models/generative-model.ts b/packages/ai/src/models/generative-model.ts index 8defedd33b..6f04046cf1 100644 --- a/packages/ai/src/models/generative-model.ts +++ b/packages/ai/src/models/generative-model.ts @@ -42,9 +42,10 @@ import { formatGenerateContentInput, formatSystemInstruction } from '../requests/request-helpers'; -import { AI } from '../public-types'; +import { AI, AIErrorCode } from '../public-types'; import { AIModel } from './ai-model'; import { ChromeAdapter } from '../types/chrome-adapter'; +import { AIError } from '../errors'; /** * Class for generative model APIs. @@ -66,6 +67,7 @@ export class GenerativeModel extends AIModel { ) { super(ai, modelParams.model); this.generationConfig = modelParams.generationConfig || {}; + validateGenerationConfig(this.generationConfig); this.safetySettings = modelParams.safetySettings || []; this.tools = modelParams.tools; this.toolConfig = modelParams.toolConfig; @@ -182,3 +184,20 @@ export class GenerativeModel extends AIModel { ); } } + +/** + * Client-side validation of some common `GenerationConfig` pitfalls, in order + * to save the developer a wasted request. + */ +function validateGenerationConfig(generationConfig: GenerationConfig): void { + if ( + // != allows for null and undefined. 0 is considered "set" by the model + generationConfig.thinkingConfig?.thinkingBudget != null && + generationConfig.thinkingConfig?.thinkingLevel + ) { + throw new AIError( + AIErrorCode.UNSUPPORTED, + `Cannot set both thinkingBudget and thinkingLevel in a config.` + ); + } +} diff --git a/packages/ai/src/types/enums.ts b/packages/ai/src/types/enums.ts index f7c55d5e4c..4e4a45805d 100644 --- a/packages/ai/src/types/enums.ts +++ b/packages/ai/src/types/enums.ts @@ -432,3 +432,26 @@ export const Language = { * @beta */ export type Language = (typeof Language)[keyof typeof Language]; + +/** + * A preset that controls the model's "thinking" process. Use + * `ThinkingLevel.LOW` for faster responses on less complex tasks, and + * `ThinkingLevel.HIGH` for better reasoning on more complex tasks. + * + * @public + */ +export const ThinkingLevel = { + MINIMAL: 'MINIMAL', + LOW: 'LOW', + MEDIUM: 'MEDIUM', + HIGH: 'HIGH' +}; + +/** + * A preset that controls the model's "thinking" process. Use + * `ThinkingLevel.LOW` for faster responses on less complex tasks, and + * `ThinkingLevel.HIGH` for better reasoning on more complex tasks. + * + * @public + */ +export type ThinkingLevel = (typeof ThinkingLevel)[keyof typeof ThinkingLevel]; diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index 991453c53f..0692a9cc1d 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -27,7 +27,8 @@ import { HarmBlockThreshold, HarmCategory, InferenceMode, - ResponseModality + ResponseModality, + ThinkingLevel } from './enums'; import { ObjectSchemaRequest, SchemaRequest } from './schema'; @@ -477,18 +478,44 @@ export interface ThinkingConfig { /** * The thinking budget, in tokens. * + * @remarks * This parameter sets an upper limit on the number of tokens the model can use for its internal * "thinking" process. A higher budget may result in higher quality responses for complex tasks * but can also increase latency and cost. * - * If you don't specify a budget, the model will determine the appropriate amount - * of thinking based on the complexity of the prompt. + * The range of supported thinking budget values depends on the model. + * + *
      + *
    • To use the default thinking budget for a model, leave + * this value undefined.
    • + * + *
    • To disable thinking, when supported by the model, set this value + * to `0`.
    • + * + *
    • To use dynamic thinking, which allows the model to decide on the thinking + * budget based on the task, set this value to `-1`.
    • + *
    * * An error will be thrown if you set a thinking budget for a model that does not support this * feature or if the specified budget is not within the model's supported range. + * + * The model will also error if `thinkingLevel` and `thinkingBudget` are + * both set. */ thinkingBudget?: number; + /** + * If not specified, Gemini will use the model's default dynamic thinking level. + * + * @remarks + * Note: The model will error if `thinkingLevel` and `thinkingBudget` are + * both set. + * + * Important: Gemini 2.5 series models do not support thinking levels; use + * `thinkingBudget` to set a thinking budget instead. + */ + thinkingLevel?: ThinkingLevel; + /** * Whether to include "thought summaries" in the model's response. * From b2827448bf8b51e2a1d0343092989a7b79fc0491 Mon Sep 17 00:00:00 2001 From: Athira M Date: Tue, 13 Jan 2026 21:11:24 +0530 Subject: [PATCH 038/174] feat(rc): Web support for ABT & Rollouts (#9449) Co-authored-by: Athira M --- .changeset/wild-snakes-bathe.md | 6 + common/api-review/remote-config.api.md | 17 +++ docs-devsite/_toc.yaml | 2 + docs-devsite/remote-config.fetchresponse.md | 13 ++ ...te-config.firebaseexperimentdescription.md | 78 ++++++++++++ docs-devsite/remote-config.md | 1 + packages/remote-config/src/abt/experiment.ts | 102 +++++++++++++++ packages/remote-config/src/api.ts | 10 +- .../remote-config/src/client/rest_client.ts | 8 +- packages/remote-config/src/errors.ts | 8 +- packages/remote-config/src/public_types.ts | 35 +++++- packages/remote-config/src/register.ts | 4 +- packages/remote-config/src/remote_config.ts | 8 +- packages/remote-config/src/storage/storage.ts | 9 ++ .../remote-config/test/abt/experiment.test.ts | 117 ++++++++++++++++++ packages/remote-config/test/api.test.ts | 14 ++- .../test/client/rest_client.test.ts | 26 +++- .../remote-config/test/remote_config.test.ts | 41 +++++- 18 files changed, 479 insertions(+), 20 deletions(-) create mode 100644 .changeset/wild-snakes-bathe.md create mode 100644 docs-devsite/remote-config.firebaseexperimentdescription.md create mode 100644 packages/remote-config/src/abt/experiment.ts create mode 100644 packages/remote-config/test/abt/experiment.test.ts diff --git a/.changeset/wild-snakes-bathe.md b/.changeset/wild-snakes-bathe.md new file mode 100644 index 0000000000..ffc35b4d3d --- /dev/null +++ b/.changeset/wild-snakes-bathe.md @@ -0,0 +1,6 @@ +--- +'@firebase/remote-config': minor +'firebase': minor +--- + +Web support for ABT and Rollouts diff --git a/common/api-review/remote-config.api.md b/common/api-review/remote-config.api.md index a9f5131e0b..29939b3ac5 100644 --- a/common/api-review/remote-config.api.md +++ b/common/api-review/remote-config.api.md @@ -41,6 +41,7 @@ export function fetchConfig(remoteConfig: RemoteConfig): Promise; export interface FetchResponse { config?: FirebaseRemoteConfigObject; eTag?: string; + experiments?: FirebaseExperimentDescription[]; status: number; templateVersion?: number; } @@ -51,6 +52,22 @@ export type FetchStatus = 'no-fetch-yet' | 'success' | 'failure' | 'throttle'; // @public export type FetchType = 'BASE' | 'REALTIME'; +// @public +export interface FirebaseExperimentDescription { + // (undocumented) + affectedParameterKeys?: string[]; + // (undocumented) + experimentId: string; + // (undocumented) + experimentStartTime: string; + // (undocumented) + timeToLiveMillis: string; + // (undocumented) + triggerTimeoutMillis: string; + // (undocumented) + variantId: string; +} + // @public export interface FirebaseRemoteConfigObject { // (undocumented) diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index b59430a2dc..c7fe59434d 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -791,6 +791,8 @@ toc: path: /docs/reference/js/remote-config.customsignals.md - title: FetchResponse path: /docs/reference/js/remote-config.fetchresponse.md + - title: FirebaseExperimentDescription + path: /docs/reference/js/remote-config.firebaseexperimentdescription.md - title: FirebaseRemoteConfigObject path: /docs/reference/js/remote-config.firebaseremoteconfigobject.md - title: RemoteConfig diff --git a/docs-devsite/remote-config.fetchresponse.md b/docs-devsite/remote-config.fetchresponse.md index 1955dd4749..9c55c50e68 100644 --- a/docs-devsite/remote-config.fetchresponse.md +++ b/docs-devsite/remote-config.fetchresponse.md @@ -26,6 +26,7 @@ export interface FetchResponse | --- | --- | --- | | [config](./remote-config.fetchresponse.md#fetchresponseconfig) | [FirebaseRemoteConfigObject](./remote-config.firebaseremoteconfigobject.md#firebaseremoteconfigobject_interface) | Defines the map of parameters returned as "entries" in the fetch response body.

    Only defined for 200 responses. | | [eTag](./remote-config.fetchresponse.md#fetchresponseetag) | string | Defines the ETag response header value.

    Only defined for 200 and 304 responses. | +| [experiments](./remote-config.fetchresponse.md#fetchresponseexperiments) | [FirebaseExperimentDescription](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescription_interface)\[\] | Metadata for A/B testing and Remote Config Rollout experiments. | | [status](./remote-config.fetchresponse.md#fetchresponsestatus) | number | The HTTP status, which is useful for differentiating success responses with data from those without.

    The Remote Config client is modeled after the native Fetch interface, so HTTP status is first-class.

    Disambiguation: the fetch response returns a legacy "state" value that is redundant with the HTTP status code. The former is normalized into the latter. | | [templateVersion](./remote-config.fetchresponse.md#fetchresponsetemplateversion) | number | The version number of the config template fetched from the server. | @@ -53,6 +54,18 @@ Defines the ETag response header value. eTag?: string; ``` +## FetchResponse.experiments + +Metadata for A/B testing and Remote Config Rollout experiments. + +Only defined for 200 responses. + +Signature: + +```typescript +experiments?: FirebaseExperimentDescription[]; +``` + ## FetchResponse.status The HTTP status, which is useful for differentiating success responses with data from those without. diff --git a/docs-devsite/remote-config.firebaseexperimentdescription.md b/docs-devsite/remote-config.firebaseexperimentdescription.md new file mode 100644 index 0000000000..24c70690a2 --- /dev/null +++ b/docs-devsite/remote-config.firebaseexperimentdescription.md @@ -0,0 +1,78 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FirebaseExperimentDescription interface +Defines experiment and variant attached to a config parameter. + +Signature: + +```typescript +export interface FirebaseExperimentDescription +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [affectedParameterKeys](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptionaffectedparameterkeys) | string\[\] | | +| [experimentId](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptionexperimentid) | string | | +| [experimentStartTime](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptionexperimentstarttime) | string | | +| [timeToLiveMillis](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptiontimetolivemillis) | string | | +| [triggerTimeoutMillis](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptiontriggertimeoutmillis) | string | | +| [variantId](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescriptionvariantid) | string | | + +## FirebaseExperimentDescription.affectedParameterKeys + +Signature: + +```typescript +affectedParameterKeys?: string[]; +``` + +## FirebaseExperimentDescription.experimentId + +Signature: + +```typescript +experimentId: string; +``` + +## FirebaseExperimentDescription.experimentStartTime + +Signature: + +```typescript +experimentStartTime: string; +``` + +## FirebaseExperimentDescription.timeToLiveMillis + +Signature: + +```typescript +timeToLiveMillis: string; +``` + +## FirebaseExperimentDescription.triggerTimeoutMillis + +Signature: + +```typescript +triggerTimeoutMillis: string; +``` + +## FirebaseExperimentDescription.variantId + +Signature: + +```typescript +variantId: string; +``` diff --git a/docs-devsite/remote-config.md b/docs-devsite/remote-config.md index c9f803abf1..c3b5e4b5bf 100644 --- a/docs-devsite/remote-config.md +++ b/docs-devsite/remote-config.md @@ -42,6 +42,7 @@ The Firebase Remote Config Web SDK. This SDK does not work in a Node.js environm | [ConfigUpdateObserver](./remote-config.configupdateobserver.md#configupdateobserver_interface) | Observer interface for receiving real-time Remote Config update notifications.NOTE: Although an complete callback can be provided, it will never be called because the ConfigUpdate stream is never-ending. | | [CustomSignals](./remote-config.customsignals.md#customsignals_interface) | Defines the type for representing custom signals and their values.

    The values in CustomSignals must be one of the following types:

    • string
    • number
    • null
    | | [FetchResponse](./remote-config.fetchresponse.md#fetchresponse_interface) | Defines a successful response (200 or 304).

    Modeled after the native Response interface, but simplified for Remote Config's use case. | +| [FirebaseExperimentDescription](./remote-config.firebaseexperimentdescription.md#firebaseexperimentdescription_interface) | Defines experiment and variant attached to a config parameter. | | [FirebaseRemoteConfigObject](./remote-config.firebaseremoteconfigobject.md#firebaseremoteconfigobject_interface) | Defines a self-descriptive reference for config key-value pairs. | | [RemoteConfig](./remote-config.remoteconfig.md#remoteconfig_interface) | The Firebase Remote Config service interface. | | [RemoteConfigOptions](./remote-config.remoteconfigoptions.md#remoteconfigoptions_interface) | Options for Remote Config initialization. | diff --git a/packages/remote-config/src/abt/experiment.ts b/packages/remote-config/src/abt/experiment.ts new file mode 100644 index 0000000000..d92d762f93 --- /dev/null +++ b/packages/remote-config/src/abt/experiment.ts @@ -0,0 +1,102 @@ +/** + * @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. + */ +import { Storage } from '../storage/storage'; +import { FirebaseExperimentDescription } from '../public_types'; +import { Provider } from '@firebase/component'; +import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types'; +import { Logger } from '@firebase/logger'; +import { RemoteConfig } from '../remote_config'; +import { ERROR_FACTORY, ErrorCode } from '../errors'; + +export class Experiment { + private storage: Storage; + private logger: Logger; + private analyticsProvider: Provider; + + constructor(rc: RemoteConfig) { + this.storage = rc._storage; + this.logger = rc._logger; + this.analyticsProvider = rc._analyticsProvider; + } + + async updateActiveExperiments( + latestExperiments: FirebaseExperimentDescription[] + ): Promise { + const currentActiveExperiments = + (await this.storage.getActiveExperiments()) || new Set(); + const experimentInfoMap = this.createExperimentInfoMap(latestExperiments); + this.addActiveExperiments(experimentInfoMap); + this.removeInactiveExperiments(currentActiveExperiments, experimentInfoMap); + return this.storage.setActiveExperiments(new Set(experimentInfoMap.keys())); + } + + private createExperimentInfoMap( + latestExperiments: FirebaseExperimentDescription[] + ): Map { + const experimentInfoMap = new Map(); + for (const experiment of latestExperiments) { + experimentInfoMap.set(experiment.experimentId, experiment); + } + return experimentInfoMap; + } + + private addActiveExperiments( + experimentInfoMap: Map + ): void { + const customProperty: Record = {}; + for (const [experimentId, experimentInfo] of experimentInfoMap.entries()) { + customProperty[`firebase${experimentId}`] = experimentInfo.variantId; + } + this.addExperimentToAnalytics(customProperty); + } + + private removeInactiveExperiments( + currentActiveExperiments: Set, + experimentInfoMap: Map + ): void { + const customProperty: Record = {}; + for (const experimentId of currentActiveExperiments) { + if (!experimentInfoMap.has(experimentId)) { + customProperty[`firebase${experimentId}`] = null; + } + } + this.addExperimentToAnalytics(customProperty); + } + + private addExperimentToAnalytics( + customProperty: Record + ): void { + if (Object.keys(customProperty).length === 0) { + return; + } + try { + const analytics = this.analyticsProvider.getImmediate({ optional: true }); + if (analytics) { + analytics.setUserProperties(customProperty); + analytics.logEvent(`set_firebase_experiment_state`); + } else { + this.logger.warn( + `Analytics import failed. Verify if you have imported Firebase Analytics in your app code.` + ); + } + } catch (error) { + throw ERROR_FACTORY.create(ErrorCode.ANALYTICS_UNAVAILABLE, { + originalErrorMessage: (error as Error)?.message + }); + } + } +} diff --git a/packages/remote-config/src/api.ts b/packages/remote-config/src/api.ts index 62dc2697a6..5533bf9129 100644 --- a/packages/remote-config/src/api.ts +++ b/packages/remote-config/src/api.ts @@ -36,6 +36,7 @@ import { ERROR_FACTORY, ErrorCode, hasErrorCode } from './errors'; import { RemoteConfig as RemoteConfigImpl } from './remote_config'; import { Value as ValueImpl } from './value'; import { LogLevel as FirebaseLogLevel } from '@firebase/logger'; +import { Experiment } from './abt/experiment'; /** * @@ -110,12 +111,19 @@ export async function activate(remoteConfig: RemoteConfig): Promise { // config. return false; } + const experiment = new Experiment(rc); + const updateActiveExperiments = lastSuccessfulFetchResponse.experiments + ? experiment.updateActiveExperiments( + lastSuccessfulFetchResponse.experiments + ) + : Promise.resolve(); await Promise.all([ rc._storageCache.setActiveConfig(lastSuccessfulFetchResponse.config), rc._storage.setActiveConfigEtag(lastSuccessfulFetchResponse.eTag), rc._storage.setActiveConfigTemplateVersion( lastSuccessfulFetchResponse.templateVersion - ) + ), + updateActiveExperiments ]); return true; } diff --git a/packages/remote-config/src/client/rest_client.ts b/packages/remote-config/src/client/rest_client.ts index 42b0cab27c..d5b0be92c3 100644 --- a/packages/remote-config/src/client/rest_client.ts +++ b/packages/remote-config/src/client/rest_client.ts @@ -18,7 +18,8 @@ import { CustomSignals, FetchResponse, - FirebaseRemoteConfigObject + FirebaseRemoteConfigObject, + FirebaseExperimentDescription } from '../public_types'; import { RemoteConfigFetchClient, @@ -143,6 +144,7 @@ export class RestClient implements RemoteConfigFetchClient { let config: FirebaseRemoteConfigObject | undefined; let state: string | undefined; let templateVersion: number | undefined; + let experiments: FirebaseExperimentDescription[] | undefined; // JSON parsing throws SyntaxError if the response body isn't a JSON string. // Requesting application/json and checking for a 200 ensures there's JSON data. @@ -158,6 +160,7 @@ export class RestClient implements RemoteConfigFetchClient { config = responseBody['entries']; state = responseBody['state']; templateVersion = responseBody['templateVersion']; + experiments = responseBody['experimentDescriptions']; } // Normalizes based on legacy state. @@ -168,6 +171,7 @@ export class RestClient implements RemoteConfigFetchClient { } else if (state === 'NO_TEMPLATE' || state === 'EMPTY_CONFIG') { // These cases can be fixed remotely, so normalize to safe value. config = {}; + experiments = []; } // Normalize to exception-based control flow for non-success cases. @@ -180,6 +184,6 @@ export class RestClient implements RemoteConfigFetchClient { }); } - return { status, eTag: responseEtag, config, templateVersion }; + return { status, eTag: responseEtag, config, templateVersion, experiments }; } } diff --git a/packages/remote-config/src/errors.ts b/packages/remote-config/src/errors.ts index dea9f43e92..06e226a0ab 100644 --- a/packages/remote-config/src/errors.ts +++ b/packages/remote-config/src/errors.ts @@ -37,7 +37,8 @@ export const enum ErrorCode { CONFIG_UPDATE_STREAM_ERROR = 'stream-error', CONFIG_UPDATE_UNAVAILABLE = 'realtime-unavailable', CONFIG_UPDATE_MESSAGE_INVALID = 'update-message-invalid', - CONFIG_UPDATE_NOT_FETCHED = 'update-not-fetched' + CONFIG_UPDATE_NOT_FETCHED = 'update-not-fetched', + ANALYTICS_UNAVAILABLE = 'analytics-unavailable' } const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = { @@ -84,7 +85,9 @@ const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = { [ErrorCode.CONFIG_UPDATE_MESSAGE_INVALID]: 'The stream invalidation message was unparsable: {$originalErrorMessage}', [ErrorCode.CONFIG_UPDATE_NOT_FETCHED]: - 'Unable to fetch the latest config: {$originalErrorMessage}' + 'Unable to fetch the latest config: {$originalErrorMessage}', + [ErrorCode.ANALYTICS_UNAVAILABLE]: + 'Connection to Firebase Analytics failed: {$originalErrorMessage}' }; // Note this is effectively a type system binding a code to params. This approach overlaps with the @@ -108,6 +111,7 @@ interface ErrorParams { [ErrorCode.CONFIG_UPDATE_UNAVAILABLE]: { originalErrorMessage: string }; [ErrorCode.CONFIG_UPDATE_MESSAGE_INVALID]: { originalErrorMessage: string }; [ErrorCode.CONFIG_UPDATE_NOT_FETCHED]: { originalErrorMessage: string }; + [ErrorCode.ANALYTICS_UNAVAILABLE]: { originalErrorMessage: string }; } export const ERROR_FACTORY = new ErrorFactory( diff --git a/packages/remote-config/src/public_types.ts b/packages/remote-config/src/public_types.ts index 964726a51f..fc23974ee3 100644 --- a/packages/remote-config/src/public_types.ts +++ b/packages/remote-config/src/public_types.ts @@ -59,6 +59,33 @@ export interface FirebaseRemoteConfigObject { [key: string]: string; } +/** + * Defines experiment and variant attached to a config parameter. + * + * @public + */ +export interface FirebaseExperimentDescription { + // A string of max length 22 characters and of format: _exp_ + experimentId: string; + + // The variant of the experiment assigned to the app instance. + variantId: string; + + // When the experiment was started. + experimentStartTime: string; + + // How long the experiment can remain in STANDBY state. Valid range from 1 ms + // to 6 months. + triggerTimeoutMillis: string; + + // How long the experiment can remain in ON state. Valid range from 1 ms to 6 + // months. + timeToLiveMillis: string; + + // Which all parameters are affected by this experiment. + affectedParameterKeys?: string[]; +} + /** * Defines a successful response (200 or 304). * @@ -99,8 +126,12 @@ export interface FetchResponse { */ templateVersion?: number; - // Note: we're not extracting experiment metadata until - // ABT and Analytics have Web SDKs. + /** + * Metadata for A/B testing and Remote Config Rollout experiments. + * + * @remarks Only defined for 200 responses. + */ + experiments?: FirebaseExperimentDescription[]; } /** diff --git a/packages/remote-config/src/register.ts b/packages/remote-config/src/register.ts index eade371ca8..0a34024622 100644 --- a/packages/remote-config/src/register.ts +++ b/packages/remote-config/src/register.ts @@ -66,6 +66,7 @@ export function registerRemoteConfig(): void { const installations = container .getProvider('installations-internal') .getImmediate(); + const analyticsProvider = container.getProvider('analytics-internal'); // Normalizes optional inputs. const { projectId, apiKey, appId } = app.options; @@ -127,7 +128,8 @@ export function registerRemoteConfig(): void { storageCache, storage, logger, - realtimeHandler + realtimeHandler, + analyticsProvider ); // Starts warming cache. diff --git a/packages/remote-config/src/remote_config.ts b/packages/remote-config/src/remote_config.ts index bd32c93830..aa9502262f 100644 --- a/packages/remote-config/src/remote_config.ts +++ b/packages/remote-config/src/remote_config.ts @@ -25,6 +25,8 @@ import { StorageCache } from './storage/storage_cache'; import { RemoteConfigFetchClient } from './client/remote_config_fetch_client'; import { Storage } from './storage/storage'; import { Logger } from '@firebase/logger'; +import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types'; +import { Provider } from '@firebase/component'; import { RealtimeHandler } from './client/realtime_handler'; const DEFAULT_FETCH_TIMEOUT_MILLIS = 60 * 1000; // One minute @@ -88,6 +90,10 @@ export class RemoteConfig implements RemoteConfigType { /** * @internal */ - readonly _realtimeHandler: RealtimeHandler + readonly _realtimeHandler: RealtimeHandler, + /** + * @internal + */ + readonly _analyticsProvider: Provider ) {} } diff --git a/packages/remote-config/src/storage/storage.ts b/packages/remote-config/src/storage/storage.ts index bd262d2996..9764b95991 100644 --- a/packages/remote-config/src/storage/storage.ts +++ b/packages/remote-config/src/storage/storage.ts @@ -71,6 +71,7 @@ export interface RealtimeBackoffMetadata { type ProjectNamespaceKeyFieldValue = | 'active_config' | 'active_config_etag' + | 'active_experiments' | 'last_fetch_status' | 'last_successful_fetch_timestamp_millis' | 'last_successful_fetch_response' @@ -165,6 +166,14 @@ export abstract class Storage { return this.set('active_config_etag', etag); } + getActiveExperiments(): Promise | undefined> { + return this.get>('active_experiments'); + } + + setActiveExperiments(experiments: Set): Promise { + return this.set>('active_experiments', experiments); + } + getThrottleMetadata(): Promise { return this.get('throttle_metadata'); } diff --git a/packages/remote-config/test/abt/experiment.test.ts b/packages/remote-config/test/abt/experiment.test.ts new file mode 100644 index 0000000000..43365d31f0 --- /dev/null +++ b/packages/remote-config/test/abt/experiment.test.ts @@ -0,0 +1,117 @@ +/** + * @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. + */ +import '../setup'; +import { expect } from 'chai'; +import * as sinon from 'sinon'; +import { Experiment } from '../../src/abt/experiment'; +import { FirebaseExperimentDescription } from '../../src/public_types'; +import { Storage } from '../../src/storage/storage'; +import { Provider } from '@firebase/component'; +import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types'; +import { Logger } from '@firebase/logger'; +import { RemoteConfig } from '../../src/remote_config'; + +describe('Experiment', () => { + const storage = {} as Storage; + const analyticsProvider = {} as Provider; + const logger = {} as Logger; + const rc = { + _storage: storage, + _analyticsProvider: analyticsProvider, + _logger: logger + } as RemoteConfig; + const experiment = new Experiment(rc); + + describe('updateActiveExperiments', () => { + beforeEach(() => { + storage.getActiveExperiments = sinon.stub(); + storage.setActiveExperiments = sinon.stub(); + analyticsProvider.getImmediate = sinon.stub().returns({ + setUserProperties: sinon.stub(), + logEvent: sinon.stub() + }); + }); + + it('adds new experiments to storage', async () => { + const latestExperiments: FirebaseExperimentDescription[] = [ + { + experimentId: '_exp_3', + variantId: '1', + experimentStartTime: '0', + triggerTimeoutMillis: '0', + timeToLiveMillis: '0' + }, + { + experimentId: '_exp_1', + variantId: '2', + experimentStartTime: '0', + triggerTimeoutMillis: '0', + timeToLiveMillis: '0' + }, + { + experimentId: '_exp_2', + variantId: '1', + experimentStartTime: '0', + triggerTimeoutMillis: '0', + timeToLiveMillis: '0' + } + ]; + const expectedStoredExperiments = new Set(['_exp_3', '_exp_1', '_exp_2']); + storage.getActiveExperiments = sinon + .stub() + .returns(new Set(['_exp_1', '_exp_2'])); + const analytics = analyticsProvider.getImmediate(); + + await experiment.updateActiveExperiments(latestExperiments); + + expect(storage.setActiveExperiments).to.have.been.calledWith( + expectedStoredExperiments + ); + expect(analytics.setUserProperties).to.have.been.calledWith({ + 'firebase_exp_3': '1', + 'firebase_exp_1': '2', + 'firebase_exp_2': '1' + }); + }); + + it('removes missing experiment in fetch response from storage', async () => { + const latestExperiments: FirebaseExperimentDescription[] = [ + { + experimentId: '_exp_1', + variantId: '2', + experimentStartTime: '0', + triggerTimeoutMillis: '0', + timeToLiveMillis: '0' + } + ]; + const expectedStoredExperiments = new Set(['_exp_1']); + storage.getActiveExperiments = sinon + .stub() + .returns(new Set(['_exp_1', '_exp_2'])); + const analytics = analyticsProvider.getImmediate(); + + await experiment.updateActiveExperiments(latestExperiments); + + expect(storage.setActiveExperiments).to.have.been.calledWith( + expectedStoredExperiments + ); + expect(analytics.setUserProperties).to.have.been.calledWith({ + 'firebase_exp_2': null + }); + }); + }); +}); diff --git a/packages/remote-config/test/api.test.ts b/packages/remote-config/test/api.test.ts index f38b4ca0be..54679199a8 100644 --- a/packages/remote-config/test/api.test.ts +++ b/packages/remote-config/test/api.test.ts @@ -68,7 +68,16 @@ describe('Remote Config API', () => { status: 200, eTag: 'asdf', config: { 'foobar': 'hello world' }, - templateVersion: 1 + templateVersion: 1, + experiments: [ + { + experimentId: '_exp_1', + variantId: '1', + experimentStartTime: '2025-04-06T14:13:57.597Z', + triggerTimeoutMillis: '15552000000', + timeToLiveMillis: '15552000000' + } + ] }; let fetchStub: sinon.SinonStub; @@ -106,7 +115,8 @@ describe('Remote Config API', () => { Promise.resolve({ entries: response.config, state: 'OK', - templateVersion: response.templateVersion + templateVersion: response.templateVersion, + experimentDescriptions: response.experiments }) } as Response) ); diff --git a/packages/remote-config/test/client/rest_client.test.ts b/packages/remote-config/test/client/rest_client.test.ts index bda6fbce01..d2284c4f8c 100644 --- a/packages/remote-config/test/client/rest_client.test.ts +++ b/packages/remote-config/test/client/rest_client.test.ts @@ -78,7 +78,16 @@ describe('RestClient', () => { eTag: 'etag', state: 'UPDATE', entries: { color: 'sparkling' }, - templateVersion: 1 + templateVersion: 1, + experimentDescriptions: [ + { + experimentId: '_exp_1', + variantId: '1', + experimentStartTime: '2025-04-06T14:13:57.597Z', + triggerTimeoutMillis: '15552000000', + timeToLiveMillis: '15552000000' + } + ] }; fetchStub.returns( @@ -90,7 +99,8 @@ describe('RestClient', () => { Promise.resolve({ entries: expectedResponse.entries, state: expectedResponse.state, - templateVersion: expectedResponse.templateVersion + templateVersion: expectedResponse.templateVersion, + experimentDescriptions: expectedResponse.experimentDescriptions }) } as Response) ); @@ -101,7 +111,8 @@ describe('RestClient', () => { status: expectedResponse.status, eTag: expectedResponse.eTag, config: expectedResponse.entries, - templateVersion: expectedResponse.templateVersion + templateVersion: expectedResponse.templateVersion, + experiments: expectedResponse.experimentDescriptions }); }); @@ -191,7 +202,8 @@ describe('RestClient', () => { status: 304, eTag: 'response-etag', config: undefined, - templateVersion: undefined + templateVersion: undefined, + experiments: undefined }); }); @@ -230,7 +242,8 @@ describe('RestClient', () => { status: 304, eTag: 'etag', config: undefined, - templateVersion: undefined + templateVersion: undefined, + experiments: undefined }); }); @@ -248,7 +261,8 @@ describe('RestClient', () => { status: 200, eTag: 'etag', config: {}, - templateVersion: undefined + templateVersion: undefined, + experiments: [] }); } }); diff --git a/packages/remote-config/test/remote_config.test.ts b/packages/remote-config/test/remote_config.test.ts index 1cc6b62717..de70e13dfc 100644 --- a/packages/remote-config/test/remote_config.test.ts +++ b/packages/remote-config/test/remote_config.test.ts @@ -46,6 +46,9 @@ import { import * as api from '../src/api'; import { fetchAndActivate } from '../src'; import { restore } from 'sinon'; +import { Experiment } from '../src/abt/experiment'; +import { Provider } from '@firebase/component'; +import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types'; import { RealtimeHandler } from '../src/client/realtime_handler'; describe('RemoteConfig', () => { @@ -70,6 +73,7 @@ describe('RemoteConfig', () => { let logger: Logger; let realtimeHandler: RealtimeHandler; let rc: RemoteConfigType; + let analyticsProvider: Provider; let getActiveConfigStub: sinon.SinonStub; let loggerDebugSpy: sinon.SinonSpy; @@ -81,6 +85,7 @@ describe('RemoteConfig', () => { client = {} as RemoteConfigFetchClient; storageCache = {} as StorageCache; storage = {} as Storage; + analyticsProvider = {} as Provider; realtimeHandler = {} as RealtimeHandler; logger = new Logger('package-name'); getActiveConfigStub = sinon.stub().returns(undefined); @@ -93,7 +98,8 @@ describe('RemoteConfig', () => { storageCache, storage, logger, - realtimeHandler + realtimeHandler, + analyticsProvider ); }); @@ -391,7 +397,18 @@ describe('RemoteConfig', () => { const CONFIG = { key: 'val' }; const NEW_ETAG = 'new_etag'; const TEMPLATE_VERSION = 1; + const EXPERIMENTS = [ + { + 'experimentId': '_exp_1', + 'variantId': '1', + 'experimentStartTime': '2025-04-06T14:13:57.597Z', + 'triggerTimeoutMillis': '15552000000', + 'timeToLiveMillis': '15552000000' + } + ]; + let sandbox: sinon.SinonSandbox; + let updateActiveExperimentsStub: sinon.SinonStub; let getLastSuccessfulFetchResponseStub: sinon.SinonStub; let getActiveConfigEtagStub: sinon.SinonStub; let getActiveConfigTemplateVersionStub: sinon.SinonStub; @@ -400,6 +417,11 @@ describe('RemoteConfig', () => { let setActiveConfigTemplateVersionStub: sinon.SinonStub; beforeEach(() => { + sandbox = sinon.createSandbox(); + updateActiveExperimentsStub = sandbox.stub( + Experiment.prototype, + 'updateActiveExperiments' + ); getLastSuccessfulFetchResponseStub = sinon.stub(); getActiveConfigEtagStub = sinon.stub(); getActiveConfigTemplateVersionStub = sinon.stub(); @@ -418,6 +440,14 @@ describe('RemoteConfig', () => { setActiveConfigTemplateVersionStub; }); + afterEach(() => { + sandbox.restore(); + }); + + afterEach(() => { + sandbox.restore(); + }); + it('does not activate if last successful fetch response is undefined', async () => { getLastSuccessfulFetchResponseStub.returns(Promise.resolve()); getActiveConfigEtagStub.returns(Promise.resolve(ETAG)); @@ -431,6 +461,7 @@ describe('RemoteConfig', () => { expect(storage.setActiveConfigEtag).to.not.have.been.called; expect(storageCache.setActiveConfig).to.not.have.been.called; expect(storage.setActiveConfigTemplateVersion).to.not.have.been.called; + expect(updateActiveExperimentsStub).to.not.have.been.called; }); it('does not activate if fetched and active etags are the same', async () => { @@ -449,6 +480,7 @@ describe('RemoteConfig', () => { expect(storage.setActiveConfigEtag).to.not.have.been.called; expect(storageCache.setActiveConfig).to.not.have.been.called; expect(storage.setActiveConfigTemplateVersion).to.not.have.been.called; + expect(updateActiveExperimentsStub).to.not.have.been.called; }); it('activates if fetched and active etags are different', async () => { @@ -456,7 +488,8 @@ describe('RemoteConfig', () => { Promise.resolve({ config: CONFIG, eTag: NEW_ETAG, - templateVersion: TEMPLATE_VERSION + templateVersion: TEMPLATE_VERSION, + experiments: EXPERIMENTS }) ); getActiveConfigEtagStub.returns(Promise.resolve(ETAG)); @@ -476,7 +509,8 @@ describe('RemoteConfig', () => { Promise.resolve({ config: CONFIG, eTag: NEW_ETAG, - templateVersion: TEMPLATE_VERSION + templateVersion: TEMPLATE_VERSION, + experiments: EXPERIMENTS }) ); getActiveConfigEtagStub.returns(Promise.resolve()); @@ -489,6 +523,7 @@ describe('RemoteConfig', () => { expect(storage.setActiveConfigTemplateVersion).to.have.been.calledWith( TEMPLATE_VERSION ); + expect(updateActiveExperimentsStub).to.have.been.calledWith(EXPERIMENTS); }); }); From d5ff5a4b1d3c9cf0e5f00fa4d3e05e8887fb3573 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 14 Jan 2026 08:07:54 -0800 Subject: [PATCH 039/174] test(e2e): update jest (#9451) --- e2e/smoke-tests/package.json | 8 +- e2e/smoke-tests/yarn.lock | 2293 ++++++++++++++++++++-------------- 2 files changed, 1392 insertions(+), 909 deletions(-) diff --git a/e2e/smoke-tests/package.json b/e2e/smoke-tests/package.json index c957f018b5..2fca5aacd8 100644 --- a/e2e/smoke-tests/package.json +++ b/e2e/smoke-tests/package.json @@ -23,11 +23,11 @@ "@babel/core": "7.26.8", "@babel/preset-env": "7.26.8", "@babel/preset-typescript": "7.26.0", - "@types/jest": "29.5.14", - "babel-jest": "29.7.0", + "@types/jest": "30.0.0", + "babel-jest": "30.2.0", "babel-loader": "8.4.1", - "jest": "29.7.0", - "jest-environment-jsdom": "29.7.0", + "jest": "30.2.0", + "jest-environment-jsdom": "30.2.0", "ts-node": "10.9.2", "typescript": "5.5.4", "webpack": "5.98.0", diff --git a/e2e/smoke-tests/yarn.lock b/e2e/smoke-tests/yarn.lock index b9a6d8e445..63a037e750 100644 --- a/e2e/smoke-tests/yarn.lock +++ b/e2e/smoke-tests/yarn.lock @@ -10,7 +10,18 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.26.2": +"@asamuzakjp/css-color@^3.2.0": + version "3.2.0" + resolved "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz#cc42f5b85c593f79f1fa4f25d2b9b321e61d1794" + integrity sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw== + dependencies: + "@csstools/css-calc" "^2.1.3" + "@csstools/css-color-parser" "^3.0.9" + "@csstools/css-parser-algorithms" "^3.0.4" + "@csstools/css-tokenizer" "^3.0.3" + lru-cache "^10.4.3" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.26.2": version "7.26.2" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz" integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== @@ -28,6 +39,15 @@ js-tokens "^4.0.0" picocolors "^1.0.0" +"@babel/code-frame@^7.27.1", "@babel/code-frame@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz#72499312ec58b1e2245ba4a4f550c132be4982f7" + integrity sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q== + dependencies: + "@babel/helper-validator-identifier" "^7.28.5" + js-tokens "^4.0.0" + picocolors "^1.1.1" + "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.9": version "7.26.0" resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.0.tgz" @@ -38,6 +58,11 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz" integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== +"@babel/compat-data@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz#103f466803fa0f059e82ccac271475470570d74c" + integrity sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg== + "@babel/core@7.26.8": version "7.26.8" resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.8.tgz" @@ -60,7 +85,7 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": +"@babel/core@^7.23.9": version "7.26.0" resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz" integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg== @@ -81,6 +106,27 @@ json5 "^2.2.3" semver "^6.3.1" +"@babel/core@^7.27.4": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz#531bf883a1126e53501ba46eb3bb414047af507f" + integrity sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-compilation-targets" "^7.28.6" + "@babel/helper-module-transforms" "^7.28.6" + "@babel/helpers" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/remapping" "^2.3.5" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/generator@^7.25.9", "@babel/generator@^7.26.0": version "7.26.0" resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.26.0.tgz" @@ -103,15 +149,15 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" -"@babel/generator@^7.7.2": - version "7.26.3" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz" - integrity sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ== +"@babel/generator@^7.27.5", "@babel/generator@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz#48dcc65d98fcc8626a48f72b62e263d25fc3c3f1" + integrity sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw== dependencies: - "@babel/parser" "^7.26.3" - "@babel/types" "^7.26.3" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" jsesc "^3.0.2" "@babel/helper-annotate-as-pure@^7.25.9": @@ -143,6 +189,17 @@ lru-cache "^5.1.1" semver "^6.3.1" +"@babel/helper-compilation-targets@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz#32c4a3f41f12ed1532179b108a4d746e105c2b25" + integrity sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA== + dependencies: + "@babel/compat-data" "^7.28.6" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + "@babel/helper-create-class-features-plugin@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz" @@ -187,6 +244,11 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + "@babel/helper-member-expression-to-functions@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz" @@ -203,6 +265,14 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" +"@babel/helper-module-imports@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz#60632cbd6ffb70b22823187201116762a03e2d5c" + integrity sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw== + dependencies: + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" + "@babel/helper-module-transforms@^7.25.9", "@babel/helper-module-transforms@^7.26.0": version "7.26.0" resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz" @@ -212,6 +282,15 @@ "@babel/helper-validator-identifier" "^7.25.9" "@babel/traverse" "^7.25.9" +"@babel/helper-module-transforms@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz#9312d9d9e56edc35aeb6e95c25d4106b50b9eb1e" + integrity sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA== + dependencies: + "@babel/helper-module-imports" "^7.28.6" + "@babel/helper-validator-identifier" "^7.28.5" + "@babel/traverse" "^7.28.6" + "@babel/helper-optimise-call-expression@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz" @@ -229,6 +308,11 @@ resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz" integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== +"@babel/helper-plugin-utils@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz#6f13ea251b68c8532e985fd532f28741a8af9ac8" + integrity sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug== + "@babel/helper-remap-async-to-generator@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz" @@ -268,16 +352,31 @@ resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz" integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + "@babel/helper-validator-identifier@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz" integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== +"@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + "@babel/helper-validator-option@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz" integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + "@babel/helper-wrap-function@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz" @@ -303,7 +402,15 @@ "@babel/template" "^7.26.9" "@babel/types" "^7.26.9" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.26.3": +"@babel/helpers@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz#fca903a313ae675617936e8998b814c415cbf5d7" + integrity sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw== + dependencies: + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" + +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9": version "7.26.3" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz" integrity sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA== @@ -324,6 +431,13 @@ dependencies: "@babel/types" "^7.26.9" +"@babel/parser@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz#f01a8885b7fa1e56dd8a155130226cd698ef13fd" + integrity sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ== + dependencies: + "@babel/types" "^7.28.6" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz" @@ -424,13 +538,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.25.9", "@babel/plugin-syntax-jsx@^7.7.2": +"@babel/plugin-syntax-jsx@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz" integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA== dependencies: "@babel/helper-plugin-utils" "^7.25.9" +"@babel/plugin-syntax-jsx@^7.27.1": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz#f8ca28bbd84883b5fea0e447c635b81ba73997ee" + integrity sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w== + dependencies: + "@babel/helper-plugin-utils" "^7.28.6" + "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" @@ -487,13 +608,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.25.9", "@babel/plugin-syntax-typescript@^7.7.2": +"@babel/plugin-syntax-typescript@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz" integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ== dependencies: "@babel/helper-plugin-utils" "^7.25.9" +"@babel/plugin-syntax-typescript@^7.27.1": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz#c7b2ddf1d0a811145b1de800d1abd146af92e3a2" + integrity sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A== + dependencies: + "@babel/helper-plugin-utils" "^7.28.6" + "@babel/plugin-syntax-unicode-sets-regex@^7.18.6": version "7.18.6" resolved "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz" @@ -1011,7 +1139,7 @@ dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.25.9", "@babel/template@^7.3.3": +"@babel/template@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz" integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg== @@ -1029,6 +1157,15 @@ "@babel/parser" "^7.26.9" "@babel/types" "^7.26.9" +"@babel/template@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57" + integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + "@babel/traverse@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz" @@ -1055,7 +1192,20 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.26.3", "@babel/types@^7.3.3": +"@babel/traverse@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz#871ddc79a80599a5030c53b1cc48cbe3a5583c2e" + integrity sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" + debug "^4.3.1" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.26.3": version "7.26.3" resolved "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz" integrity sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA== @@ -1079,6 +1229,14 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" +"@babel/types@^7.27.3", "@babel/types@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz#c3e9377f1b155005bcc4c46020e7e394e13089df" + integrity sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" @@ -1091,11 +1249,61 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@csstools/color-helpers@^5.1.0": + version "5.1.0" + resolved "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz#106c54c808cabfd1ab4c602d8505ee584c2996ef" + integrity sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA== + +"@csstools/css-calc@^2.1.3", "@csstools/css-calc@^2.1.4": + version "2.1.4" + resolved "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz#8473f63e2fcd6e459838dd412401d5948f224c65" + integrity sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ== + +"@csstools/css-color-parser@^3.0.9": + version "3.1.0" + resolved "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz#4e386af3a99dd36c46fef013cfe4c1c341eed6f0" + integrity sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA== + dependencies: + "@csstools/color-helpers" "^5.1.0" + "@csstools/css-calc" "^2.1.4" + +"@csstools/css-parser-algorithms@^3.0.4": + version "3.0.5" + resolved "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz#5755370a9a29abaec5515b43c8b3f2cf9c2e3076" + integrity sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ== + +"@csstools/css-tokenizer@^3.0.3": + version "3.0.4" + resolved "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz#333fedabc3fd1a8e5d0100013731cf19e6a8c5d3" + integrity sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw== + "@discoveryjs/json-ext@^0.5.0": version "0.5.7" resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== +"@emnapi/core@^1.4.3": + version "1.8.1" + resolved "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz#fd9efe721a616288345ffee17a1f26ac5dd01349" + integrity sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg== + dependencies: + "@emnapi/wasi-threads" "1.1.0" + tslib "^2.4.0" + +"@emnapi/runtime@^1.4.3": + version "1.8.1" + resolved "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz#550fa7e3c0d49c5fb175a116e8cd70614f9a22a5" + integrity sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg== + dependencies: + tslib "^2.4.0" + +"@emnapi/wasi-threads@1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf" + integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ== + dependencies: + tslib "^2.4.0" + "@firebase/ai@1.3.0-20250512211235": version "1.3.0-20250512211235" resolved "https://registry.npmjs.org/@firebase/ai/-/ai-1.3.0-20250512211235.tgz" @@ -1520,6 +1728,18 @@ protobufjs "^7.2.5" yargs "^17.7.2" +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" @@ -1536,197 +1756,246 @@ resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^29.7.0": - version "29.7.0" - resolved "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz" - integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== +"@jest/console@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz#c52fcd5b58fdd2e8eb66b2fd8ae56f2f64d05b28" + integrity sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ== dependencies: - "@jest/types" "^29.6.3" + "@jest/types" "30.2.0" "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" + chalk "^4.1.2" + jest-message-util "30.2.0" + jest-util "30.2.0" slash "^3.0.0" -"@jest/core@^29.7.0": - version "29.7.0" - resolved "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz" - integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== - dependencies: - "@jest/console" "^29.7.0" - "@jest/reporters" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" +"@jest/core@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz#813d59faa5abd5510964a8b3a7b17cc77b775275" + integrity sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ== + dependencies: + "@jest/console" "30.2.0" + "@jest/pattern" "30.0.1" + "@jest/reporters" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.7.0" - jest-config "^29.7.0" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-resolve-dependencies "^29.7.0" - jest-runner "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - jest-watcher "^29.7.0" - micromatch "^4.0.4" - pretty-format "^29.7.0" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + ci-info "^4.2.0" + exit-x "^0.2.2" + graceful-fs "^4.2.11" + jest-changed-files "30.2.0" + jest-config "30.2.0" + jest-haste-map "30.2.0" + jest-message-util "30.2.0" + jest-regex-util "30.0.1" + jest-resolve "30.2.0" + jest-resolve-dependencies "30.2.0" + jest-runner "30.2.0" + jest-runtime "30.2.0" + jest-snapshot "30.2.0" + jest-util "30.2.0" + jest-validate "30.2.0" + jest-watcher "30.2.0" + micromatch "^4.0.8" + pretty-format "30.2.0" slash "^3.0.0" - strip-ansi "^6.0.0" -"@jest/environment@^29.7.0": - version "29.7.0" - resolved "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz" - integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== +"@jest/diff-sequences@30.0.1": + version "30.0.1" + resolved "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz#0ededeae4d071f5c8ffe3678d15f3a1be09156be" + integrity sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw== + +"@jest/environment-jsdom-abstract@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/environment-jsdom-abstract/-/environment-jsdom-abstract-30.2.0.tgz#1313f9b3b509c31298c241203161b36622865181" + integrity sha512-kazxw2L9IPuZpQ0mEt9lu9Z98SqR74xcagANmMBU16X0lS23yPc0+S6hGLUz8kVRlomZEs/5S/Zlpqwf5yu6OQ== dependencies: - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" + "@jest/environment" "30.2.0" + "@jest/fake-timers" "30.2.0" + "@jest/types" "30.2.0" + "@types/jsdom" "^21.1.7" "@types/node" "*" - jest-mock "^29.7.0" + jest-mock "30.2.0" + jest-util "30.2.0" -"@jest/expect-utils@^29.7.0": - version "29.7.0" - resolved "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz" - integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== +"@jest/environment@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz#1e673cdb8b93ded707cf6631b8353011460831fa" + integrity sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g== dependencies: - jest-get-type "^29.6.3" + "@jest/fake-timers" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + jest-mock "30.2.0" -"@jest/expect@^29.7.0": - version "29.7.0" - resolved "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz" - integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== +"@jest/expect-utils@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz#4f95413d4748454fdb17404bf1141827d15e6011" + integrity sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA== dependencies: - expect "^29.7.0" - jest-snapshot "^29.7.0" + "@jest/get-type" "30.1.0" -"@jest/fake-timers@^29.7.0": - version "29.7.0" - resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz" - integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== +"@jest/expect@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz#9a5968499bb8add2bbb09136f69f7df5ddbf3185" + integrity sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA== dependencies: - "@jest/types" "^29.6.3" - "@sinonjs/fake-timers" "^10.0.2" - "@types/node" "*" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-util "^29.7.0" + expect "30.2.0" + jest-snapshot "30.2.0" -"@jest/globals@^29.7.0": - version "29.7.0" - resolved "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz" - integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== +"@jest/fake-timers@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz#0941ddc28a339b9819542495b5408622dc9e94ec" + integrity sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw== dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/types" "^29.6.3" - jest-mock "^29.7.0" + "@jest/types" "30.2.0" + "@sinonjs/fake-timers" "^13.0.0" + "@types/node" "*" + jest-message-util "30.2.0" + jest-mock "30.2.0" + jest-util "30.2.0" + +"@jest/get-type@30.1.0": + version "30.1.0" + resolved "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz#4fcb4dc2ebcf0811be1c04fd1cb79c2dba431cbc" + integrity sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA== + +"@jest/globals@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz#2f4b696d5862664b89c4ee2e49ae24d2bb7e0988" + integrity sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw== + dependencies: + "@jest/environment" "30.2.0" + "@jest/expect" "30.2.0" + "@jest/types" "30.2.0" + jest-mock "30.2.0" + +"@jest/pattern@30.0.1": + version "30.0.1" + resolved "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz#d5304147f49a052900b4b853dedb111d080e199f" + integrity sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA== + dependencies: + "@types/node" "*" + jest-regex-util "30.0.1" -"@jest/reporters@^29.7.0": - version "29.7.0" - resolved "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz" - integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== +"@jest/reporters@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz#a36b28fcbaf0c4595250b108e6f20e363348fd91" + integrity sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" + "@jest/console" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" + "@jridgewell/trace-mapping" "^0.3.25" "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" + chalk "^4.1.2" + collect-v8-coverage "^1.0.2" + exit-x "^0.2.2" + glob "^10.3.10" + graceful-fs "^4.2.11" istanbul-lib-coverage "^3.0.0" istanbul-lib-instrument "^6.0.0" istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" + istanbul-lib-source-maps "^5.0.0" istanbul-reports "^3.1.3" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - jest-worker "^29.7.0" + jest-message-util "30.2.0" + jest-util "30.2.0" + jest-worker "30.2.0" slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" + string-length "^4.0.2" v8-to-istanbul "^9.0.1" -"@jest/schemas@^29.6.3": - version "29.6.3" - resolved "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz" - integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== +"@jest/schemas@30.0.5": + version "30.0.5" + resolved "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz#7bdf69fc5a368a5abdb49fd91036c55225846473" + integrity sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA== dependencies: - "@sinclair/typebox" "^0.27.8" + "@sinclair/typebox" "^0.34.0" -"@jest/source-map@^29.6.3": - version "29.6.3" - resolved "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz" - integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== +"@jest/snapshot-utils@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz#387858eb90c2f98f67bff327435a532ac5309fbe" + integrity sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug== dependencies: - "@jridgewell/trace-mapping" "^0.3.18" - callsites "^3.0.0" - graceful-fs "^4.2.9" + "@jest/types" "30.2.0" + chalk "^4.1.2" + graceful-fs "^4.2.11" + natural-compare "^1.4.0" + +"@jest/source-map@30.0.1": + version "30.0.1" + resolved "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz#305ebec50468f13e658b3d5c26f85107a5620aaa" + integrity sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.25" + callsites "^3.1.0" + graceful-fs "^4.2.11" -"@jest/test-result@^29.7.0": - version "29.7.0" - resolved "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz" - integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== +"@jest/test-result@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz#9c0124377fb7996cdffb86eda3dbc56eacab363d" + integrity sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg== dependencies: - "@jest/console" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" + "@jest/console" "30.2.0" + "@jest/types" "30.2.0" + "@types/istanbul-lib-coverage" "^2.0.6" + collect-v8-coverage "^1.0.2" -"@jest/test-sequencer@^29.7.0": - version "29.7.0" - resolved "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz" - integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== +"@jest/test-sequencer@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz#bf0066bc72e176d58f5dfa7f212b6e7eee44f221" + integrity sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q== dependencies: - "@jest/test-result" "^29.7.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" + "@jest/test-result" "30.2.0" + graceful-fs "^4.2.11" + jest-haste-map "30.2.0" slash "^3.0.0" -"@jest/transform@^29.7.0": - version "29.7.0" - resolved "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz" - integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== +"@jest/transform@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz#54bef1a4510dcbd58d5d4de4fe2980a63077ef2a" + integrity sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA== dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" + "@babel/core" "^7.27.4" + "@jest/types" "30.2.0" + "@jridgewell/trace-mapping" "^0.3.25" + babel-plugin-istanbul "^7.0.1" + chalk "^4.1.2" convert-source-map "^2.0.0" fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - micromatch "^4.0.4" - pirates "^4.0.4" + graceful-fs "^4.2.11" + jest-haste-map "30.2.0" + jest-regex-util "30.0.1" + jest-util "30.2.0" + micromatch "^4.0.8" + pirates "^4.0.7" slash "^3.0.0" - write-file-atomic "^4.0.2" + write-file-atomic "^5.0.1" -"@jest/types@^29.6.3": - version "29.6.3" - resolved "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz" - integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== +"@jest/types@30.2.0": + version "30.2.0" + resolved "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz#1c678a7924b8f59eafd4c77d56b6d0ba976d62b8" + integrity sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg== dependencies: - "@jest/schemas" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" + "@jest/pattern" "30.0.1" + "@jest/schemas" "30.0.5" + "@types/istanbul-lib-coverage" "^2.0.6" + "@types/istanbul-reports" "^3.0.4" "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" + "@types/yargs" "^17.0.33" + chalk "^4.1.2" + +"@jridgewell/gen-mapping@^0.3.12": + version "0.3.13" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" "@jridgewell/gen-mapping@^0.3.5": version "0.3.5" @@ -1737,6 +2006,14 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.24" +"@jridgewell/remapping@^2.3.5": + version "2.3.5" + resolved "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" @@ -1760,6 +2037,11 @@ resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== +"@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + "@jridgewell/trace-mapping@0.3.9": version "0.3.9" resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" @@ -1768,7 +2050,7 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -1776,6 +2058,14 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@jsonjoy.com/base64@^1.1.1": version "1.1.2" resolved "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz" @@ -1801,6 +2091,25 @@ resolved "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz" integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== +"@napi-rs/wasm-runtime@^0.2.11": + version "0.2.12" + resolved "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz#3e78a8b96e6c33a6c517e1894efbd5385a7cb6f2" + integrity sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ== + dependencies: + "@emnapi/core" "^1.4.3" + "@emnapi/runtime" "^1.4.3" + "@tybys/wasm-util" "^0.10.0" + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@pkgr/core@^0.2.9": + version "0.2.9" + resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" + integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz" @@ -1854,29 +2163,24 @@ resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz" integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== -"@sinclair/typebox@^0.27.8": - version "0.27.8" - resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" - integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== +"@sinclair/typebox@^0.34.0": + version "0.34.47" + resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.47.tgz#61b684d8a20d2890b9f1f7b0d4f76b4b39f5bc0d" + integrity sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw== -"@sinonjs/commons@^3.0.0": +"@sinonjs/commons@^3.0.1": version "3.0.1" - resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz" + resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== dependencies: type-detect "4.0.8" -"@sinonjs/fake-timers@^10.0.2": - version "10.3.0" - resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz" - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== +"@sinonjs/fake-timers@^13.0.0": + version "13.0.5" + resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz#36b9dbc21ad5546486ea9173d6bea063eb1717d5" + integrity sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw== dependencies: - "@sinonjs/commons" "^3.0.0" - -"@tootallnate/once@2": - version "2.0.0" - resolved "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz" - integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + "@sinonjs/commons" "^3.0.1" "@tsconfig/node10@^1.0.7": version "1.0.11" @@ -1898,7 +2202,14 @@ resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== -"@types/babel__core@^7.1.14": +"@tybys/wasm-util@^0.10.0": + version "0.10.1" + resolved "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" + integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg== + dependencies: + tslib "^2.4.0" + +"@types/babel__core@^7.20.5": version "7.20.5" resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz" integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== @@ -1924,7 +2235,7 @@ "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": +"@types/babel__traverse@*": version "7.20.6" resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz" integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== @@ -2027,13 +2338,6 @@ resolved "https://registry.npmjs.org/@types/gensync/-/gensync-1.0.4.tgz" integrity sha512-C3YYeRQWp2fmq9OryX+FoDy8nXS6scQ7dPptD8LnFDAUNcKWJjXQKDNJD3HVm+kOUsXhTOkpi69vI4EuAr95bA== -"@types/graceful-fs@^4.1.3": - version "4.1.9" - resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz" - integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== - dependencies: - "@types/node" "*" - "@types/http-errors@*": version "2.0.4" resolved "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz" @@ -2046,7 +2350,7 @@ dependencies: "@types/node" "*" -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.1", "@types/istanbul-lib-coverage@^2.0.6": version "2.0.6" resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz" integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== @@ -2058,25 +2362,25 @@ dependencies: "@types/istanbul-lib-coverage" "*" -"@types/istanbul-reports@^3.0.0": +"@types/istanbul-reports@^3.0.4": version "3.0.4" resolved "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz" integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@29.5.14": - version "29.5.14" - resolved "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz" - integrity sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ== +"@types/jest@30.0.0": + version "30.0.0" + resolved "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz#5e85ae568006712e4ad66f25433e9bdac8801f1d" + integrity sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA== dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" + expect "^30.0.0" + pretty-format "^30.0.0" -"@types/jsdom@^20.0.0": - version "20.0.1" - resolved "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz" - integrity sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ== +"@types/jsdom@^21.1.7": + version "21.1.7" + resolved "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz#9edcb09e0b07ce876e7833922d3274149c898cfa" + integrity sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA== dependencies: "@types/node" "*" "@types/tough-cookie" "*" @@ -2152,7 +2456,7 @@ dependencies: "@types/node" "*" -"@types/stack-utils@^2.0.0": +"@types/stack-utils@^2.0.3": version "2.0.3" resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== @@ -2174,13 +2478,115 @@ resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz" integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== -"@types/yargs@^17.0.8": - version "17.0.33" - resolved "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz" - integrity sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA== +"@types/yargs@^17.0.33": + version "17.0.35" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz#07013e46aa4d7d7d50a49e15604c1c5340d4eb24" + integrity sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg== dependencies: "@types/yargs-parser" "*" +"@ungap/structured-clone@^1.3.0": + version "1.3.0" + resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" + integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== + +"@unrs/resolver-binding-android-arm-eabi@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz#9f5b04503088e6a354295e8ea8fe3cb99e43af81" + integrity sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw== + +"@unrs/resolver-binding-android-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz#7414885431bd7178b989aedc4d25cccb3865bc9f" + integrity sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g== + +"@unrs/resolver-binding-darwin-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz#b4a8556f42171fb9c9f7bac8235045e82aa0cbdf" + integrity sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g== + +"@unrs/resolver-binding-darwin-x64@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz#fd4d81257b13f4d1a083890a6a17c00de571f0dc" + integrity sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ== + +"@unrs/resolver-binding-freebsd-x64@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz#d2513084d0f37c407757e22f32bd924a78cfd99b" + integrity sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw== + +"@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz#844d2605d057488d77fab09705f2866b86164e0a" + integrity sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw== + +"@unrs/resolver-binding-linux-arm-musleabihf@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz#204892995cefb6bd1d017d52d097193bc61ddad3" + integrity sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw== + +"@unrs/resolver-binding-linux-arm64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz#023eb0c3aac46066a10be7a3f362e7b34f3bdf9d" + integrity sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ== + +"@unrs/resolver-binding-linux-arm64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz#9e6f9abb06424e3140a60ac996139786f5d99be0" + integrity sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w== + +"@unrs/resolver-binding-linux-ppc64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz#b111417f17c9d1b02efbec8e08398f0c5527bb44" + integrity sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA== + +"@unrs/resolver-binding-linux-riscv64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz#92ffbf02748af3e99873945c9a8a5ead01d508a9" + integrity sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ== + +"@unrs/resolver-binding-linux-riscv64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz#0bec6f1258fc390e6b305e9ff44256cb207de165" + integrity sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew== + +"@unrs/resolver-binding-linux-s390x-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz#577843a084c5952f5906770633ccfb89dac9bc94" + integrity sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg== + +"@unrs/resolver-binding-linux-x64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz#36fb318eebdd690f6da32ac5e0499a76fa881935" + integrity sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w== + +"@unrs/resolver-binding-linux-x64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz#bfb9af75f783f98f6a22c4244214efe4df1853d6" + integrity sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA== + +"@unrs/resolver-binding-wasm32-wasi@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz#752c359dd875684b27429500d88226d7cc72f71d" + integrity sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ== + dependencies: + "@napi-rs/wasm-runtime" "^0.2.11" + +"@unrs/resolver-binding-win32-arm64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz#ce5735e600e4c2fbb409cd051b3b7da4a399af35" + integrity sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw== + +"@unrs/resolver-binding-win32-ia32-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz#72fc57bc7c64ec5c3de0d64ee0d1810317bc60a6" + integrity sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ== + +"@unrs/resolver-binding-win32-x64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz#538b1e103bf8d9864e7b85cc96fa8d6fb6c40777" + integrity sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g== + "@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz" @@ -2327,11 +2733,6 @@ resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -abab@^2.0.6: - version "2.0.6" - resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz" - integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== - accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" @@ -2340,22 +2741,14 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-globals@^7.0.0: - version "7.0.1" - resolved "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz" - integrity sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q== - dependencies: - acorn "^8.1.0" - acorn-walk "^8.0.2" - -acorn-walk@^8.0.2, acorn-walk@^8.1.1: +acorn-walk@^8.1.1: version "8.3.4" resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz" integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== dependencies: acorn "^8.11.0" -acorn@^8.1.0, acorn@^8.11.0, acorn@^8.4.1, acorn@^8.8.1: +acorn@^8.11.0, acorn@^8.4.1: version "8.14.0" resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== @@ -2370,12 +2763,10 @@ acorn@^8.8.2: resolved "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz" integrity sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w== -agent-base@6: - version "6.0.2" - resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" +agent-base@^7.1.0, agent-base@^7.1.2: + version "7.1.4" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== ajv-formats@^2.1.1: version "2.1.1" @@ -2416,9 +2807,9 @@ ajv@^8.0.0, ajv@^8.9.0: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" -ansi-escapes@^4.2.1: +ansi-escapes@^4.3.2: version "4.3.2" - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: type-fest "^0.21.3" @@ -2433,6 +2824,11 @@ ansi-regex@^5.0.1: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.2.2" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" @@ -2440,12 +2836,17 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ansi-styles@^5.0.0: +ansi-styles@^5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -anymatch@^3.0.3, anymatch@~3.1.2: +ansi-styles@^6.1.0: + version "6.2.3" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + +anymatch@^3.1.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -2470,22 +2871,17 @@ array-flatten@1.1.1: resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -babel-jest@29.7.0, babel-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz" - integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== - dependencies: - "@jest/transform" "^29.7.0" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.6.3" - chalk "^4.0.0" - graceful-fs "^4.2.9" +babel-jest@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz#fd44a1ec9552be35ead881f7381faa7d8f3b95ac" + integrity sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw== + dependencies: + "@jest/transform" "30.2.0" + "@types/babel__core" "^7.20.5" + babel-plugin-istanbul "^7.0.1" + babel-preset-jest "30.2.0" + chalk "^4.1.2" + graceful-fs "^4.2.11" slash "^3.0.0" babel-loader@8.4.1: @@ -2498,26 +2894,23 @@ babel-loader@8.4.1: make-dir "^3.1.0" schema-utils "^2.6.5" -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== +babel-plugin-istanbul@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz#d8b518c8ea199364cf84ccc82de89740236daf92" + integrity sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-instrument "^6.0.2" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^29.6.3: - version "29.6.3" - resolved "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz" - integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== +babel-plugin-jest-hoist@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz#94c250d36b43f95900f3a219241e0f4648191ce2" + integrity sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA== dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" + "@types/babel__core" "^7.20.5" babel-plugin-polyfill-corejs2@^0.4.10: version "0.4.11" @@ -2543,10 +2936,10 @@ babel-plugin-polyfill-regenerator@^0.6.1: dependencies: "@babel/helper-define-polyfill-provider" "^0.6.2" -babel-preset-current-node-syntax@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz" - integrity sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw== +babel-preset-current-node-syntax@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz#20730d6cdc7dda5d89401cab10ac6a32067acde6" + integrity sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" @@ -2564,13 +2957,13 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" -babel-preset-jest@^29.6.3: - version "29.6.3" - resolved "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz" - integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== +babel-preset-jest@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz#04717843e561347781d6d7f69c81e6bcc3ed11ce" + integrity sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ== dependencies: - babel-plugin-jest-hoist "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" + babel-plugin-jest-hoist "30.2.0" + babel-preset-current-node-syntax "^1.2.0" balanced-match@^1.0.0: version "1.0.2" @@ -2626,6 +3019,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + braces@^3.0.3, braces@~3.0.2: version "3.0.3" resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" @@ -2693,9 +3093,9 @@ call-bind@^1.0.7: get-intrinsic "^1.2.4" set-function-length "^1.2.1" -callsites@^3.0.0: +callsites@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase@^5.3.1: @@ -2703,9 +3103,9 @@ camelcase@^5.3.1: resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.2.0: +camelcase@^6.3.0: version "6.3.0" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001669: @@ -2718,7 +3118,7 @@ caniuse-lite@^1.0.30001688: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001702.tgz" integrity sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA== -chalk@^4.0.0: +chalk@^4.1.2: version "4.1.2" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2751,15 +3151,15 @@ chrome-trace-event@^1.0.2: resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz" integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== -ci-info@^3.2.0: - version "3.9.0" - resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== +ci-info@^4.2.0: + version "4.3.1" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz#355ad571920810b5623e11d40232f443f16f1daa" + integrity sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA== -cjs-module-lexer@^1.0.0: - version "1.4.1" - resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz" - integrity sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA== +cjs-module-lexer@^2.1.0: + version "2.2.0" + resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz#b3ca5101843389259ade7d88c77bd06ce55849ca" + integrity sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ== cliui@^8.0.1: version "8.0.1" @@ -2784,10 +3184,10 @@ co@^4.6.0: resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== -collect-v8-coverage@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz" - integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== +collect-v8-coverage@^1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz#cc1f01eb8d02298cbc9a437c74c70ab4e5210b80" + integrity sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw== color-convert@^2.0.1: version "2.0.1" @@ -2806,13 +3206,6 @@ colorette@^2.0.10, colorette@^2.0.14: resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - commander@^10.0.1: version "10.0.1" resolved "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz" @@ -2897,19 +3290,6 @@ core-util-is@~1.0.0: resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -create-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz" - integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-config "^29.7.0" - jest-util "^29.7.0" - prompts "^2.0.1" - create-require@^1.1.0: version "1.1.1" resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" @@ -2924,31 +3304,30 @@ cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -cssom@^0.5.0: - version "0.5.0" - resolved "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz" - integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== - -cssom@~0.3.6: - version "0.3.8" - resolved "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== +cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" -cssstyle@^2.3.0: - version "2.3.0" - resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz" - integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== +cssstyle@^4.2.1: + version "4.6.0" + resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz#ea18007024e3167f4f105315f3ec2d982bf48ed9" + integrity sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg== dependencies: - cssom "~0.3.6" + "@asamuzakjp/css-color" "^3.2.0" + rrweb-cssom "^0.8.0" -data-urls@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz" - integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== +data-urls@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz#2f76906bce1824429ffecb6920f45a0b30f00dde" + integrity sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg== dependencies: - abab "^2.0.6" - whatwg-mimetype "^3.0.0" - whatwg-url "^11.0.0" + whatwg-mimetype "^4.0.0" + whatwg-url "^14.0.0" debug@2.6.9: version "2.6.9" @@ -2964,19 +3343,26 @@ debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: dependencies: ms "^2.1.3" -decimal.js@^10.4.2: - version "10.4.3" - resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz" - integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== +debug@^4.3.4: + version "4.4.3" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +decimal.js@^10.5.0: + version "10.6.0" + resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a" + integrity sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg== -dedent@^1.0.0: - version "1.5.3" - resolved "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz" - integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== +dedent@^1.6.0: + version "1.7.1" + resolved "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz#364661eea3d73f3faba7089214420ec2f8f13e15" + integrity sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg== -deepmerge@^4.2.2: +deepmerge@^4.3.1: version "4.3.1" - resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== default-browser-id@^5.0.0: @@ -3006,11 +3392,6 @@ define-lazy-prop@^3.0.0: resolved "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz" integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - depd@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" @@ -3026,9 +3407,9 @@ destroy@1.2.0: resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== -detect-newline@^3.0.0: +detect-newline@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" + resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== detect-node@^2.0.4: @@ -3036,11 +3417,6 @@ detect-node@^2.0.4: resolved "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz" integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== -diff-sequences@^29.6.3: - version "29.6.3" - resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz" - integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== - diff@^4.0.1: version "4.0.2" resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" @@ -3053,12 +3429,10 @@ dns-packet@^5.2.2: dependencies: "@leichtgewicht/ip-codec" "^2.0.1" -domexception@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz" - integrity sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw== - dependencies: - webidl-conversions "^7.0.0" +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== ee-first@1.1.1: version "1.1.1" @@ -3085,6 +3459,11 @@ emoji-regex@^8.0.0: resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + emojis-list@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz" @@ -3113,6 +3492,11 @@ entities@^4.5.0: resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== +entities@^6.0.0: + version "6.0.1" + resolved "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz#c28c34a43379ca7f61d074130b2f5f7020a30694" + integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g== + envinfo@^7.7.3: version "7.14.0" resolved "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz" @@ -3157,17 +3541,6 @@ escape-string-regexp@^2.0.0: resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -escodegen@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz" - integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== - dependencies: - esprima "^4.0.1" - estraverse "^5.2.0" - esutils "^2.0.2" - optionalDependencies: - source-map "~0.6.1" - eslint-scope@5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" @@ -3176,7 +3549,7 @@ eslint-scope@5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -esprima@^4.0.0, esprima@^4.0.1: +esprima@^4.0.0: version "4.0.1" resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -3218,9 +3591,9 @@ events@^3.2.0: resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== -execa@^5.0.0: +execa@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== dependencies: cross-spawn "^7.0.3" @@ -3233,21 +3606,22 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" - integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== +exit-x@^0.2.2: + version "0.2.2" + resolved "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz#1f9052de3b8d99a696b10dad5bced9bdd5c3aa64" + integrity sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ== -expect@^29.0.0, expect@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz" - integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== +expect@30.2.0, expect@^30.0.0: + version "30.2.0" + resolved "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz#d4013bed267013c14bc1199cec8aa57cee9b5869" + integrity sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw== dependencies: - "@jest/expect-utils" "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" + "@jest/expect-utils" "30.2.0" + "@jest/get-type" "30.1.0" + jest-matcher-utils "30.2.0" + jest-message-util "30.2.0" + jest-mock "30.2.0" + jest-util "30.2.0" express@^4.21.2: version "4.21.2" @@ -3313,7 +3687,7 @@ faye-websocket@0.11.4, faye-websocket@^0.11.3: dependencies: websocket-driver ">=0.5.1" -fb-watchman@^2.0.0: +fb-watchman@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz" integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== @@ -3401,14 +3775,13 @@ follow-redirects@^1.0.0: resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== -form-data@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz" - integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== +foreground-child@^3.1.0: + version "3.3.1" + resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" + cross-spawn "^7.0.6" + signal-exit "^4.0.1" forwarded@0.2.0: version "0.2.0" @@ -3425,7 +3798,7 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@^2.3.2, fsevents@~2.3.2: +fsevents@^2.3.3, fsevents@~2.3.2: version "2.3.3" resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -3478,7 +3851,19 @@ glob-to-regexp@^0.4.1: resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^7.1.3, glob@^7.1.4: +glob@^10.3.10: + version "10.5.0" + resolved "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz#8ec0355919cd3338c28428a23d4f24ecc5fe738c" + integrity sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +glob@^7.1.4: version "7.2.3" resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -3502,7 +3887,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6: version "4.2.11" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -3551,12 +3936,12 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -html-encoding-sniffer@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz" - integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA== +html-encoding-sniffer@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz#696df529a7cfd82446369dc5193e590a3735b448" + integrity sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ== dependencies: - whatwg-encoding "^2.0.0" + whatwg-encoding "^3.1.1" html-escaper@^2.0.0: version "2.0.2" @@ -3594,14 +3979,13 @@ http-parser-js@>=0.5.1: resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz" integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== -http-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz" - integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== +http-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== dependencies: - "@tootallnate/once" "2" - agent-base "6" - debug "4" + agent-base "^7.1.0" + debug "^4.3.4" http-proxy-middleware@^2.0.7: version "2.0.7" @@ -3623,12 +4007,12 @@ http-proxy@^1.18.1: follow-redirects "^1.0.0" requires-port "^1.0.0" -https-proxy-agent@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== +https-proxy-agent@^7.0.6: + version "7.0.6" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== dependencies: - agent-base "6" + agent-base "^7.1.2" debug "4" human-signals@^2.1.0: @@ -3660,9 +4044,9 @@ idb@7.1.1: resolved "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz" integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== -import-local@^3.0.2: +import-local@^3.0.2, import-local@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz" + resolved "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== dependencies: pkg-dir "^4.2.0" @@ -3740,9 +4124,9 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-generator-fn@^2.0.0: +is-generator-fn@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" + resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== is-glob@^4.0.1, is-glob@~4.0.1: @@ -3818,18 +4202,7 @@ istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz" integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== -istanbul-lib-instrument@^5.0.4: - version "5.2.1" - resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz" - integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" - -istanbul-lib-instrument@^6.0.0: +istanbul-lib-instrument@^6.0.0, istanbul-lib-instrument@^6.0.2: version "6.0.3" resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz" integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== @@ -3849,14 +4222,14 @@ istanbul-lib-report@^3.0.0: make-dir "^4.0.0" supports-color "^7.1.0" -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== +istanbul-lib-source-maps@^5.0.0: + version "5.0.6" + resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz#acaef948df7747c8eb5fbf1265cb980f6353a441" + integrity sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A== dependencies: + "@jridgewell/trace-mapping" "^0.3.23" debug "^4.1.1" istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" istanbul-reports@^3.1.3: version "3.1.7" @@ -3866,386 +4239,390 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-changed-files@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz" - integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== dependencies: - execa "^5.0.0" - jest-util "^29.7.0" + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +jest-changed-files@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz#602266e478ed554e1e1469944faa7efd37cee61c" + integrity sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ== + dependencies: + execa "^5.1.1" + jest-util "30.2.0" p-limit "^3.1.0" -jest-circus@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz" - integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== +jest-circus@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz#98b8198b958748a2f322354311023d1d02e7603f" + integrity sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg== dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" + "@jest/environment" "30.2.0" + "@jest/expect" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/types" "30.2.0" "@types/node" "*" - chalk "^4.0.0" + chalk "^4.1.2" co "^4.6.0" - dedent "^1.0.0" - is-generator-fn "^2.0.0" - jest-each "^29.7.0" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" + dedent "^1.6.0" + is-generator-fn "^2.1.0" + jest-each "30.2.0" + jest-matcher-utils "30.2.0" + jest-message-util "30.2.0" + jest-runtime "30.2.0" + jest-snapshot "30.2.0" + jest-util "30.2.0" p-limit "^3.1.0" - pretty-format "^29.7.0" - pure-rand "^6.0.0" + pretty-format "30.2.0" + pure-rand "^7.0.0" slash "^3.0.0" - stack-utils "^2.0.3" - -jest-cli@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz" - integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== - dependencies: - "@jest/core" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - chalk "^4.0.0" - create-jest "^29.7.0" - exit "^0.1.2" - import-local "^3.0.2" - jest-config "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - yargs "^17.3.1" - -jest-config@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz" - integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.7.0" - "@jest/types" "^29.6.3" - babel-jest "^29.7.0" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.7.0" - jest-environment-node "^29.7.0" - jest-get-type "^29.6.3" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-runner "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - micromatch "^4.0.4" + stack-utils "^2.0.6" + +jest-cli@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz#1780f8e9d66bf84a10b369aea60aeda7697dcc67" + integrity sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA== + dependencies: + "@jest/core" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/types" "30.2.0" + chalk "^4.1.2" + exit-x "^0.2.2" + import-local "^3.2.0" + jest-config "30.2.0" + jest-util "30.2.0" + jest-validate "30.2.0" + yargs "^17.7.2" + +jest-config@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz#29df8c50e2ad801cc59c406b50176c18c362a90b" + integrity sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA== + dependencies: + "@babel/core" "^7.27.4" + "@jest/get-type" "30.1.0" + "@jest/pattern" "30.0.1" + "@jest/test-sequencer" "30.2.0" + "@jest/types" "30.2.0" + babel-jest "30.2.0" + chalk "^4.1.2" + ci-info "^4.2.0" + deepmerge "^4.3.1" + glob "^10.3.10" + graceful-fs "^4.2.11" + jest-circus "30.2.0" + jest-docblock "30.2.0" + jest-environment-node "30.2.0" + jest-regex-util "30.0.1" + jest-resolve "30.2.0" + jest-runner "30.2.0" + jest-util "30.2.0" + jest-validate "30.2.0" + micromatch "^4.0.8" parse-json "^5.2.0" - pretty-format "^29.7.0" + pretty-format "30.2.0" slash "^3.0.0" strip-json-comments "^3.1.1" -jest-diff@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz" - integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.6.3" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-docblock@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz" - integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== - dependencies: - detect-newline "^3.0.0" - -jest-each@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz" - integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - jest-get-type "^29.6.3" - jest-util "^29.7.0" - pretty-format "^29.7.0" - -jest-environment-jsdom@29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz" - integrity sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/jsdom" "^20.0.0" - "@types/node" "*" - jest-mock "^29.7.0" - jest-util "^29.7.0" - jsdom "^20.0.0" - -jest-environment-node@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz" - integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" +jest-diff@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz#e3ec3a6ea5c5747f605c9e874f83d756cba36825" + integrity sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A== + dependencies: + "@jest/diff-sequences" "30.0.1" + "@jest/get-type" "30.1.0" + chalk "^4.1.2" + pretty-format "30.2.0" + +jest-docblock@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz#42cd98d69f887e531c7352309542b1ce4ee10256" + integrity sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA== + dependencies: + detect-newline "^3.1.0" + +jest-each@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz#39e623ae71641c2ac3ee69b3ba3d258fce8e768d" + integrity sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ== + dependencies: + "@jest/get-type" "30.1.0" + "@jest/types" "30.2.0" + chalk "^4.1.2" + jest-util "30.2.0" + pretty-format "30.2.0" + +jest-environment-jsdom@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-30.2.0.tgz#e95e0921ed22be974f1d8a324766d12b1844cb2c" + integrity sha512-zbBTiqr2Vl78pKp/laGBREYzbZx9ZtqPjOK4++lL4BNDhxRnahg51HtoDrk9/VjIy9IthNEWdKVd7H5bqBhiWQ== + dependencies: + "@jest/environment" "30.2.0" + "@jest/environment-jsdom-abstract" "30.2.0" + "@types/jsdom" "^21.1.7" "@types/node" "*" - jest-mock "^29.7.0" - jest-util "^29.7.0" + jsdom "^26.1.0" -jest-get-type@^29.6.3: - version "29.6.3" - resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz" - integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== +jest-environment-node@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz#3def7980ebd2fd86e74efd4d2e681f55ab38da0f" + integrity sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA== + dependencies: + "@jest/environment" "30.2.0" + "@jest/fake-timers" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + jest-mock "30.2.0" + jest-util "30.2.0" + jest-validate "30.2.0" -jest-haste-map@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz" - integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== +jest-haste-map@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz#808e3889f288603ac70ff0ac047598345a66022e" + integrity sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw== dependencies: - "@jest/types" "^29.6.3" - "@types/graceful-fs" "^4.1.3" + "@jest/types" "30.2.0" "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - jest-worker "^29.7.0" - micromatch "^4.0.4" + anymatch "^3.1.3" + fb-watchman "^2.0.2" + graceful-fs "^4.2.11" + jest-regex-util "30.0.1" + jest-util "30.2.0" + jest-worker "30.2.0" + micromatch "^4.0.8" walker "^1.0.8" optionalDependencies: - fsevents "^2.3.2" - -jest-leak-detector@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz" - integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== - dependencies: - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-matcher-utils@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz" - integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== - dependencies: - chalk "^4.0.0" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-message-util@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz" - integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.6.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.7.0" + fsevents "^2.3.3" + +jest-leak-detector@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz#292fdca7b7c9cf594e1e570ace140b01d8beb736" + integrity sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ== + dependencies: + "@jest/get-type" "30.1.0" + pretty-format "30.2.0" + +jest-matcher-utils@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz#69a0d4c271066559ec8b0d8174829adc3f23a783" + integrity sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg== + dependencies: + "@jest/get-type" "30.1.0" + chalk "^4.1.2" + jest-diff "30.2.0" + pretty-format "30.2.0" + +jest-message-util@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz#fc97bf90d11f118b31e6131e2b67fc4f39f92152" + integrity sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@jest/types" "30.2.0" + "@types/stack-utils" "^2.0.3" + chalk "^4.1.2" + graceful-fs "^4.2.11" + micromatch "^4.0.8" + pretty-format "30.2.0" slash "^3.0.0" - stack-utils "^2.0.3" + stack-utils "^2.0.6" -jest-mock@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz" - integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== +jest-mock@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz#69f991614eeb4060189459d3584f710845bff45e" + integrity sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw== dependencies: - "@jest/types" "^29.6.3" + "@jest/types" "30.2.0" "@types/node" "*" - jest-util "^29.7.0" + jest-util "30.2.0" -jest-pnp-resolver@^1.2.2: +jest-pnp-resolver@^1.2.3: version "1.2.3" - resolved "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz" + resolved "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== -jest-regex-util@^29.6.3: - version "29.6.3" - resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz" - integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== - -jest-resolve-dependencies@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz" - integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== - dependencies: - jest-regex-util "^29.6.3" - jest-snapshot "^29.7.0" - -jest-resolve@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz" - integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-pnp-resolver "^1.2.2" - jest-util "^29.7.0" - jest-validate "^29.7.0" - resolve "^1.20.0" - resolve.exports "^2.0.0" - slash "^3.0.0" +jest-regex-util@30.0.1: + version "30.0.1" + resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz#f17c1de3958b67dfe485354f5a10093298f2a49b" + integrity sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA== -jest-runner@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz" - integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== +jest-resolve-dependencies@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz#3370e2c0b49cc560f6a7e8ec3a59dd99525e1a55" + integrity sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w== dependencies: - "@jest/console" "^29.7.0" - "@jest/environment" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" + jest-regex-util "30.0.1" + jest-snapshot "30.2.0" + +jest-resolve@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz#2e2009cbd61e8f1f003355d5ec87225412cebcd7" + integrity sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A== + dependencies: + chalk "^4.1.2" + graceful-fs "^4.2.11" + jest-haste-map "30.2.0" + jest-pnp-resolver "^1.2.3" + jest-util "30.2.0" + jest-validate "30.2.0" + slash "^3.0.0" + unrs-resolver "^1.7.11" + +jest-runner@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz#c62b4c3130afa661789705e13a07bdbcec26a114" + integrity sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ== + dependencies: + "@jest/console" "30.2.0" + "@jest/environment" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" "@types/node" "*" - chalk "^4.0.0" + chalk "^4.1.2" emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.7.0" - jest-environment-node "^29.7.0" - jest-haste-map "^29.7.0" - jest-leak-detector "^29.7.0" - jest-message-util "^29.7.0" - jest-resolve "^29.7.0" - jest-runtime "^29.7.0" - jest-util "^29.7.0" - jest-watcher "^29.7.0" - jest-worker "^29.7.0" + exit-x "^0.2.2" + graceful-fs "^4.2.11" + jest-docblock "30.2.0" + jest-environment-node "30.2.0" + jest-haste-map "30.2.0" + jest-leak-detector "30.2.0" + jest-message-util "30.2.0" + jest-resolve "30.2.0" + jest-runtime "30.2.0" + jest-util "30.2.0" + jest-watcher "30.2.0" + jest-worker "30.2.0" p-limit "^3.1.0" source-map-support "0.5.13" -jest-runtime@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz" - integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/globals" "^29.7.0" - "@jest/source-map" "^29.6.3" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" +jest-runtime@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz#395ea792cde048db1b0cd1a92dc9cb9f1921bf8a" + integrity sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg== + dependencies: + "@jest/environment" "30.2.0" + "@jest/fake-timers" "30.2.0" + "@jest/globals" "30.2.0" + "@jest/source-map" "30.0.1" + "@jest/test-result" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" + chalk "^4.1.2" + cjs-module-lexer "^2.1.0" + collect-v8-coverage "^1.0.2" + glob "^10.3.10" + graceful-fs "^4.2.11" + jest-haste-map "30.2.0" + jest-message-util "30.2.0" + jest-mock "30.2.0" + jest-regex-util "30.0.1" + jest-resolve "30.2.0" + jest-snapshot "30.2.0" + jest-util "30.2.0" slash "^3.0.0" strip-bom "^4.0.0" -jest-snapshot@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz" - integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.7.0" - graceful-fs "^4.2.9" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - natural-compare "^1.4.0" - pretty-format "^29.7.0" - semver "^7.5.3" +jest-snapshot@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz#266fbbb4b95fc4665ce6f32f1f38eeb39f4e26d0" + integrity sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA== + dependencies: + "@babel/core" "^7.27.4" + "@babel/generator" "^7.27.5" + "@babel/plugin-syntax-jsx" "^7.27.1" + "@babel/plugin-syntax-typescript" "^7.27.1" + "@babel/types" "^7.27.3" + "@jest/expect-utils" "30.2.0" + "@jest/get-type" "30.1.0" + "@jest/snapshot-utils" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" + babel-preset-current-node-syntax "^1.2.0" + chalk "^4.1.2" + expect "30.2.0" + graceful-fs "^4.2.11" + jest-diff "30.2.0" + jest-matcher-utils "30.2.0" + jest-message-util "30.2.0" + jest-util "30.2.0" + pretty-format "30.2.0" + semver "^7.7.2" + synckit "^0.11.8" + +jest-util@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz#5142adbcad6f4e53c2776c067a4db3c14f913705" + integrity sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA== + dependencies: + "@jest/types" "30.2.0" + "@types/node" "*" + chalk "^4.1.2" + ci-info "^4.2.0" + graceful-fs "^4.2.11" + picomatch "^4.0.2" -jest-util@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz" - integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== +jest-validate@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz#273eaaed4c0963b934b5b31e96289edda6e0a2ef" + integrity sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw== dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz" - integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== - dependencies: - "@jest/types" "^29.6.3" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.6.3" + "@jest/get-type" "30.1.0" + "@jest/types" "30.2.0" + camelcase "^6.3.0" + chalk "^4.1.2" leven "^3.1.0" - pretty-format "^29.7.0" + pretty-format "30.2.0" -jest-watcher@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz" - integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== +jest-watcher@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz#f9c055de48e18c979e7756a3917e596e2d69b07b" + integrity sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg== dependencies: - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" + "@jest/test-result" "30.2.0" + "@jest/types" "30.2.0" "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" + ansi-escapes "^4.3.2" + chalk "^4.1.2" emittery "^0.13.1" - jest-util "^29.7.0" - string-length "^4.0.1" + jest-util "30.2.0" + string-length "^4.0.2" -jest-worker@^27.4.5: - version "27.5.1" - resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== +jest-worker@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz#fd5c2a36ff6058ec8f74366ec89538cc99539d26" + integrity sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g== dependencies: "@types/node" "*" + "@ungap/structured-clone" "^1.3.0" + jest-util "30.2.0" merge-stream "^2.0.0" - supports-color "^8.0.0" + supports-color "^8.1.1" -jest-worker@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz" - integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== dependencies: "@types/node" "*" - jest-util "^29.7.0" merge-stream "^2.0.0" supports-color "^8.0.0" -jest@29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz" - integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== +jest@30.2.0: + version "30.2.0" + resolved "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz#9f0a71e734af968f26952b5ae4b724af82681630" + integrity sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A== dependencies: - "@jest/core" "^29.7.0" - "@jest/types" "^29.6.3" - import-local "^3.0.2" - jest-cli "^29.7.0" + "@jest/core" "30.2.0" + "@jest/types" "30.2.0" + import-local "^3.2.0" + jest-cli "30.2.0" js-tokens@^4.0.0: version "4.0.0" @@ -4260,37 +4637,31 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -jsdom@^20.0.0: - version "20.0.3" - resolved "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz" - integrity sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ== - dependencies: - abab "^2.0.6" - acorn "^8.8.1" - acorn-globals "^7.0.0" - cssom "^0.5.0" - cssstyle "^2.3.0" - data-urls "^3.0.2" - decimal.js "^10.4.2" - domexception "^4.0.0" - escodegen "^2.0.0" - form-data "^4.0.0" - html-encoding-sniffer "^3.0.0" - http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.1" +jsdom@^26.1.0: + version "26.1.0" + resolved "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz#ab5f1c1cafc04bd878725490974ea5e8bf0c72b3" + integrity sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg== + dependencies: + cssstyle "^4.2.1" + data-urls "^5.0.0" + decimal.js "^10.5.0" + html-encoding-sniffer "^4.0.0" + http-proxy-agent "^7.0.2" + https-proxy-agent "^7.0.6" is-potential-custom-element-name "^1.0.1" - nwsapi "^2.2.2" - parse5 "^7.1.1" + nwsapi "^2.2.16" + parse5 "^7.2.1" + rrweb-cssom "^0.8.0" saxes "^6.0.0" symbol-tree "^3.2.4" - tough-cookie "^4.1.2" - w3c-xmlserializer "^4.0.0" + tough-cookie "^5.1.1" + w3c-xmlserializer "^5.0.0" webidl-conversions "^7.0.0" - whatwg-encoding "^2.0.0" - whatwg-mimetype "^3.0.0" - whatwg-url "^11.0.0" - ws "^8.11.0" - xml-name-validator "^4.0.0" + whatwg-encoding "^3.1.1" + whatwg-mimetype "^4.0.0" + whatwg-url "^14.1.1" + ws "^8.18.0" + xml-name-validator "^5.0.0" jsesc@^3.0.2, jsesc@~3.0.2: version "3.0.2" @@ -4322,11 +4693,6 @@ kind-of@^6.0.2: resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - launch-editor@^2.6.1: version "2.9.1" resolved "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz" @@ -4381,6 +4747,11 @@ long@^5.0.0: resolved "https://registry.npmjs.org/long/-/long-5.2.3.tgz" integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== +lru-cache@^10.2.0, lru-cache@^10.4.3: + version "10.4.3" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" @@ -4444,7 +4815,7 @@ methods@~1.1.2: resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== -micromatch@^4.0.2, micromatch@^4.0.4: +micromatch@^4.0.2, micromatch@^4.0.8: version "4.0.8" resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== @@ -4462,7 +4833,7 @@ mime-db@1.52.0: resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz" integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -4491,6 +4862,18 @@ minimatch@^3.0.4, minimatch@^3.1.1: dependencies: brace-expansion "^1.1.7" +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + ms@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" @@ -4509,6 +4892,11 @@ multicast-dns@^7.2.5: dns-packet "^5.2.2" thunky "^1.0.2" +napi-postinstall@^0.3.0: + version "0.3.4" + resolved "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz#7af256d6588b5f8e952b9190965d6b019653bbb9" + integrity sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" @@ -4556,10 +4944,10 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -nwsapi@^2.2.2: - version "2.2.16" - resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz" - integrity sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ== +nwsapi@^2.2.16: + version "2.2.23" + resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz#59712c3a88e6de2bb0b6ccc1070397267019cf6c" + integrity sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ== object-inspect@^1.13.1: version "1.13.2" @@ -4642,6 +5030,11 @@ p-try@^2.0.0: resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + parse-json@^5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" @@ -4652,13 +5045,20 @@ parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parse5@^7.0.0, parse5@^7.1.1: +parse5@^7.0.0: version "7.2.1" resolved "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz" integrity sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ== dependencies: entities "^4.5.0" +parse5@^7.2.1: + version "7.3.0" + resolved "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz#d7e224fa72399c7a175099f45fc2ad024b05ec05" + integrity sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw== + dependencies: + entities "^6.0.0" + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" @@ -4684,25 +5084,38 @@ path-parse@^1.0.7: resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-to-regexp@0.1.12: version "0.1.12" resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz" integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ== -picocolors@^1.0.0, picocolors@^1.1.0: +picocolors@^1.0.0, picocolors@^1.1.0, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pirates@^4.0.4: - version "4.0.6" - resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== +picomatch@^4.0.2: + version "4.0.3" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + +pirates@^4.0.7: + version "4.0.7" + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" + integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== pkg-dir@^4.1.0, pkg-dir@^4.2.0: version "4.2.0" @@ -4711,28 +5124,20 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pretty-format@^29.0.0, pretty-format@^29.7.0: - version "29.7.0" - resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz" - integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== +pretty-format@30.2.0, pretty-format@^30.0.0: + version "30.2.0" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz#2d44fe6134529aed18506f6d11509d8a62775ebe" + integrity sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA== dependencies: - "@jest/schemas" "^29.6.3" - ansi-styles "^5.0.0" - react-is "^18.0.0" + "@jest/schemas" "30.0.5" + ansi-styles "^5.2.0" + react-is "^18.3.1" process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -prompts@^2.0.1: - version "2.4.2" - resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - protobufjs@^7.2.5: version "7.4.0" resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz" @@ -4759,22 +5164,15 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -psl@^1.1.33: - version "1.15.0" - resolved "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz" - integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== - dependencies: - punycode "^2.3.1" - -punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: +punycode@^2.1.0, punycode@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -pure-rand@^6.0.0: - version "6.1.0" - resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz" - integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== +pure-rand@^7.0.0: + version "7.0.1" + resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz#6f53a5a9e3e4a47445822af96821ca509ed37566" + integrity sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ== qs@6.13.0: version "6.13.0" @@ -4783,11 +5181,6 @@ qs@6.13.0: dependencies: side-channel "^1.0.6" -querystringify@^2.1.1: - version "2.2.0" - resolved "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz" - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== - randombytes@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" @@ -4810,7 +5203,7 @@ raw-body@2.5.2: iconv-lite "0.4.24" unpipe "1.0.0" -react-is@^18.0.0: +react-is@^18.3.1: version "18.3.1" resolved "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== @@ -4926,11 +5319,6 @@ resolve-from@^5.0.0: resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve.exports@^2.0.0: - version "2.0.3" - resolved "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz" - integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A== - resolve@^1.14.2, resolve@^1.20.0: version "1.22.8" resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" @@ -4945,6 +5333,11 @@ retry@^0.13.1: resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== +rrweb-cssom@^0.8.0: + version "0.8.0" + resolved "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz#3021d1b4352fbf3b614aaeed0bc0d5739abe0bc2" + integrity sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw== + run-applescript@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz" @@ -5014,7 +5407,7 @@ selfsigned@^2.4.1: "@types/node-forge" "^1.3.0" node-forge "^1" -semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: +semver@^6.0.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== @@ -5024,6 +5417,11 @@ semver@^7.5.3, semver@^7.5.4: resolved "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +semver@^7.7.2: + version "7.7.3" + resolved "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" + integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== + send@0.19.0: version "0.19.0" resolved "https://registry.npmjs.org/send/-/send-0.19.0.tgz" @@ -5129,15 +5527,15 @@ side-channel@^1.0.6: get-intrinsic "^1.2.4" object-inspect "^1.13.1" -signal-exit@^3.0.3, signal-exit@^3.0.7: +signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== slash@^3.0.0: version "3.0.0" @@ -5169,7 +5567,7 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -5202,7 +5600,7 @@ sprintf-js@~1.0.2: resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -stack-utils@^2.0.3: +stack-utils@^2.0.6: version "2.0.6" resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz" integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== @@ -5219,14 +5617,23 @@ statuses@2.0.1: resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== -string-length@^4.0.1: +string-length@^4.0.2: version "4.0.2" - resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" + resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== dependencies: char-regex "^1.0.2" strip-ansi "^6.0.0" +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" @@ -5236,6 +5643,15 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" @@ -5250,6 +5666,13 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" @@ -5257,6 +5680,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.1: + version "7.1.2" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba" + integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== + dependencies: + ansi-regex "^6.0.1" + strip-bom@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" @@ -5279,7 +5709,7 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-color@^8.0.0: +supports-color@^8.0.0, supports-color@^8.1.1: version "8.1.1" resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -5296,6 +5726,13 @@ symbol-tree@^3.2.4: resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +synckit@^0.11.8: + version "0.11.11" + resolved "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz#c0b619cf258a97faa209155d9cd1699b5c998cb0" + integrity sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw== + dependencies: + "@pkgr/core" "^0.2.9" + tapable@^2.1.1, tapable@^2.2.0: version "2.2.1" resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" @@ -5341,6 +5778,18 @@ thunky@^1.0.2: resolved "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== +tldts-core@^6.1.86: + version "6.1.86" + resolved "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz#a93e6ed9d505cb54c542ce43feb14c73913265d8" + integrity sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA== + +tldts@^6.1.32: + version "6.1.86" + resolved "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz#087e0555b31b9725ee48ca7e77edc56115cd82f7" + integrity sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ== + dependencies: + tldts-core "^6.1.86" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" @@ -5358,22 +5807,19 @@ toidentifier@1.0.1: resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -tough-cookie@^4.1.2: - version "4.1.4" - resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz" - integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== +tough-cookie@^5.1.1: + version "5.1.2" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz#66d774b4a1d9e12dc75089725af3ac75ec31bed7" + integrity sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A== dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.2.0" - url-parse "^1.5.3" + tldts "^6.1.32" -tr46@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz" - integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== +tr46@^5.1.0: + version "5.1.1" + resolved "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz#96ae867cddb8fdb64a49cc3059a8d428bcf238ca" + integrity sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw== dependencies: - punycode "^2.1.1" + punycode "^2.3.1" tree-dump@^1.0.1: version "1.0.2" @@ -5404,6 +5850,11 @@ tslib@^2.0.0, tslib@^2.1.0: resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz" integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA== +tslib@^2.4.0: + version "2.8.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + type-detect@4.0.8: version "4.0.8" resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" @@ -5455,16 +5906,38 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== -universalify@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz" - integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== - unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +unrs-resolver@^1.7.11: + version "1.11.1" + resolved "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz#be9cd8686c99ef53ecb96df2a473c64d304048a9" + integrity sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg== + dependencies: + napi-postinstall "^0.3.0" + optionalDependencies: + "@unrs/resolver-binding-android-arm-eabi" "1.11.1" + "@unrs/resolver-binding-android-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-x64" "1.11.1" + "@unrs/resolver-binding-freebsd-x64" "1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-arm64-musl" "1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl" "1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-musl" "1.11.1" + "@unrs/resolver-binding-wasm32-wasi" "1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc" "1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc" "1.11.1" + "@unrs/resolver-binding-win32-x64-msvc" "1.11.1" + update-browserslist-db@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz" @@ -5480,14 +5953,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-parse@^1.5.3: - version "1.5.10" - resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz" - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" @@ -5522,12 +5987,12 @@ vary@~1.1.2: resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -w3c-xmlserializer@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz" - integrity sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw== +w3c-xmlserializer@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" + integrity sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA== dependencies: - xml-name-validator "^4.0.0" + xml-name-validator "^5.0.0" walker@^1.0.8: version "1.0.8" @@ -5682,24 +6147,24 @@ websocket-extensions@>=0.1.1: resolved "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== -whatwg-encoding@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz" - integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg== +whatwg-encoding@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" + integrity sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ== dependencies: iconv-lite "0.6.3" -whatwg-mimetype@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz" - integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== +whatwg-mimetype@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a" + integrity sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg== -whatwg-url@^11.0.0: - version "11.0.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz" - integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== +whatwg-url@^14.0.0, whatwg-url@^14.1.1: + version "14.2.0" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz#4ee02d5d725155dae004f6ae95c73e7ef5d95663" + integrity sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw== dependencies: - tr46 "^3.0.0" + tr46 "^5.1.0" webidl-conversions "^7.0.0" which@^2.0.1: @@ -5714,6 +6179,15 @@ wildcard@^2.0.0: resolved "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz" integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" @@ -5723,28 +6197,37 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== +write-file-atomic@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" + integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== dependencies: imurmurhash "^0.1.4" - signal-exit "^3.0.7" + signal-exit "^4.0.1" -ws@^8.11.0, ws@^8.18.0: +ws@^8.18.0: version "8.18.0" resolved "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== -xml-name-validator@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz" - integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== +xml-name-validator@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" + integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg== xmlchars@^2.2.0: version "2.2.0" @@ -5766,7 +6249,7 @@ yargs-parser@^21.1.1: resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^17.3.1, yargs@^17.7.2: +yargs@^17.7.2: version "17.7.2" resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From efc0117ae2fd54e78d36134f56e642e53cbe716b Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 14 Jan 2026 10:57:39 -0800 Subject: [PATCH 040/174] test(e2e): force jest to use browser (#9455) --- e2e/smoke-tests/jest-resolver.js | 26 ++++++++++++++++++++++++++ e2e/smoke-tests/jest.config.ts | 3 ++- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 e2e/smoke-tests/jest-resolver.js diff --git a/e2e/smoke-tests/jest-resolver.js b/e2e/smoke-tests/jest-resolver.js new file mode 100644 index 0000000000..bc89a825e0 --- /dev/null +++ b/e2e/smoke-tests/jest-resolver.js @@ -0,0 +1,26 @@ +/** + * @license + * Copyright 2026 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. + */ + +module.exports = (path, options) => { + if (/firebase/.test(path)) { + return options.defaultResolver(path, { + ...options, + conditions: ['browser', 'require'] + }); + } + return options.defaultResolver(path, options); +}; diff --git a/e2e/smoke-tests/jest.config.ts b/e2e/smoke-tests/jest.config.ts index 7d86672c99..cba78717c9 100644 --- a/e2e/smoke-tests/jest.config.ts +++ b/e2e/smoke-tests/jest.config.ts @@ -22,7 +22,8 @@ const config: Config = { testEnvironment: './fix-jsdom-environment.ts', globals: { FIREBASE_APPCHECK_DEBUG_TOKEN: process.env.APP_CHECK_DEBUG_TOKEN - } + }, + resolver: './jest-resolver.js' }; export default config; From 817151ee911d0d040f3951ea1f6adc9c776ada7e Mon Sep 17 00:00:00 2001 From: Google Open Source Bot Date: Wed, 14 Jan 2026 15:18:44 -0800 Subject: [PATCH 041/174] Version Packages (#9453) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/big-pipeline-release.md | 6 ------ .changeset/long-keys-watch.md | 6 ------ .changeset/plenty-bulldogs-complain.md | 6 ------ .changeset/spicy-ways-yawn.md | 6 ------ .changeset/wild-snakes-bathe.md | 6 ------ integration/compat-interop/package.json | 8 +++---- integration/firestore/package.json | 4 ++-- integration/messaging/package.json | 2 +- packages/ai/CHANGELOG.md | 10 +++++++++ packages/ai/package.json | 4 ++-- packages/analytics-compat/package.json | 2 +- packages/analytics/package.json | 2 +- packages/app-check-compat/package.json | 2 +- packages/app-check/package.json | 2 +- packages/app-compat/CHANGELOG.md | 7 ++++++ packages/app-compat/package.json | 4 ++-- packages/app/CHANGELOG.md | 6 ++++++ packages/app/package.json | 2 +- packages/auth-compat/package.json | 2 +- packages/auth/package.json | 2 +- packages/data-connect/package.json | 2 +- packages/database-compat/package.json | 2 +- packages/database/package.json | 2 +- packages/firebase/CHANGELOG.md | 25 ++++++++++++++++++++++ packages/firebase/package.json | 16 +++++++------- packages/firestore-compat/CHANGELOG.md | 7 ++++++ packages/firestore-compat/package.json | 6 +++--- packages/firestore/CHANGELOG.md | 6 ++++++ packages/firestore/package.json | 6 +++--- packages/functions-compat/package.json | 2 +- packages/functions/package.json | 2 +- packages/installations-compat/package.json | 2 +- packages/installations/package.json | 2 +- packages/messaging-compat/package.json | 2 +- packages/messaging/package.json | 2 +- packages/performance-compat/package.json | 2 +- packages/performance/package.json | 2 +- packages/remote-config-compat/CHANGELOG.md | 7 ++++++ packages/remote-config-compat/package.json | 6 +++--- packages/remote-config/CHANGELOG.md | 6 ++++++ packages/remote-config/package.json | 4 ++-- packages/storage-compat/package.json | 2 +- packages/storage/package.json | 2 +- packages/template/package.json | 2 +- repo-scripts/size-analysis/package.json | 2 +- 45 files changed, 126 insertions(+), 82 deletions(-) delete mode 100644 .changeset/big-pipeline-release.md delete mode 100644 .changeset/long-keys-watch.md delete mode 100644 .changeset/plenty-bulldogs-complain.md delete mode 100644 .changeset/spicy-ways-yawn.md delete mode 100644 .changeset/wild-snakes-bathe.md diff --git a/.changeset/big-pipeline-release.md b/.changeset/big-pipeline-release.md deleted file mode 100644 index de771854a3..0000000000 --- a/.changeset/big-pipeline-release.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/firestore': minor -'firebase': minor ---- - -Release Firestore Pipelines for Enterprise edition in public preview. diff --git a/.changeset/long-keys-watch.md b/.changeset/long-keys-watch.md deleted file mode 100644 index fb13ed7498..0000000000 --- a/.changeset/long-keys-watch.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/ai': minor ---- - -Add support for `AbortSignal`, allowing requests to be aborted. diff --git a/.changeset/plenty-bulldogs-complain.md b/.changeset/plenty-bulldogs-complain.md deleted file mode 100644 index d8583106e6..0000000000 --- a/.changeset/plenty-bulldogs-complain.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -Added ability to specify thinking levels in `thinkingConfig`. diff --git a/.changeset/spicy-ways-yawn.md b/.changeset/spicy-ways-yawn.md deleted file mode 100644 index c18413247c..0000000000 --- a/.changeset/spicy-ways-yawn.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -Update default hybrid-in-cloud model to `gemini-2.5-flash-lite`. diff --git a/.changeset/wild-snakes-bathe.md b/.changeset/wild-snakes-bathe.md deleted file mode 100644 index ffc35b4d3d..0000000000 --- a/.changeset/wild-snakes-bathe.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/remote-config': minor -'firebase': minor ---- - -Web support for ABT and Rollouts diff --git a/integration/compat-interop/package.json b/integration/compat-interop/package.json index 070857d141..70530c4216 100644 --- a/integration/compat-interop/package.json +++ b/integration/compat-interop/package.json @@ -8,8 +8,8 @@ "test:debug": "karma start --browsers Chrome --auto-watch" }, "dependencies": { - "@firebase/app": "0.14.6", - "@firebase/app-compat": "0.5.6", + "@firebase/app": "0.14.7", + "@firebase/app-compat": "0.5.7", "@firebase/analytics": "0.10.19", "@firebase/analytics-compat": "0.2.25", "@firebase/auth": "1.12.0", @@ -20,8 +20,8 @@ "@firebase/messaging-compat": "0.2.23", "@firebase/performance": "0.7.9", "@firebase/performance-compat": "0.2.22", - "@firebase/remote-config": "0.7.0", - "@firebase/remote-config-compat": "0.2.20" + "@firebase/remote-config": "0.8.0", + "@firebase/remote-config-compat": "0.2.21" }, "devDependencies": { "typescript": "5.5.4" diff --git a/integration/firestore/package.json b/integration/firestore/package.json index c87a2b1c89..a524cb0fed 100644 --- a/integration/firestore/package.json +++ b/integration/firestore/package.json @@ -15,8 +15,8 @@ "test:memory:debug": "yarn build:memory; karma start --auto-watch --browsers Chrome" }, "dependencies": { - "@firebase/app": "0.14.6", - "@firebase/firestore": "4.9.3" + "@firebase/app": "0.14.7", + "@firebase/firestore": "4.10.0" }, "devDependencies": { "@types/mocha": "9.1.1", diff --git a/integration/messaging/package.json b/integration/messaging/package.json index e1dec05ea2..ff608365f3 100644 --- a/integration/messaging/package.json +++ b/integration/messaging/package.json @@ -9,7 +9,7 @@ "test:manual": "mocha --exit" }, "devDependencies": { - "firebase": "12.7.0", + "firebase": "12.8.0", "chai": "4.5.0", "chromedriver": "119.0.1", "express": "4.21.2", diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index f70be3e194..f908524101 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,5 +1,15 @@ # @firebase/ai +## 2.7.0 + +### Minor Changes + +- [`2ecf78b`](https://github.com/firebase/firebase-js-sdk/commit/2ecf78b4f049b2e937cda911c00d549f25c628a8) [#8890](https://github.com/firebase/firebase-js-sdk/pull/8890) (fixes [#8859](https://github.com/firebase/firebase-js-sdk/issues/8859)) - Add support for `AbortSignal`, allowing requests to be aborted. + +- [`5579b38`](https://github.com/firebase/firebase-js-sdk/commit/5579b387ab697347ecd4a29ffed47c4cf808d544) [#9424](https://github.com/firebase/firebase-js-sdk/pull/9424) - Added ability to specify thinking levels in `thinkingConfig`. + +- [`f044045`](https://github.com/firebase/firebase-js-sdk/commit/f044045fcde44bf040d62c494712d5d24cdae4b9) [#9440](https://github.com/firebase/firebase-js-sdk/pull/9440) - Update default hybrid-in-cloud model to `gemini-2.5-flash-lite`. + ## 2.6.1 ### Patch Changes diff --git a/packages/ai/package.json b/packages/ai/package.json index d75b9fe721..7cf1d2bbf8 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/ai", - "version": "2.6.1", + "version": "2.7.0", "description": "The Firebase AI SDK", "author": "Firebase (https://firebase.google.com/)", "engines": { @@ -60,7 +60,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/analytics-compat/package.json b/packages/analytics-compat/package.json index 2c8ede4f84..bf44c4299e 100644 --- a/packages/analytics-compat/package.json +++ b/packages/analytics-compat/package.json @@ -22,7 +22,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.6", + "@firebase/app-compat": "0.5.7", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/analytics/package.json b/packages/analytics/package.json index 677a9e2580..50519a7150 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -47,7 +47,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "@rollup/plugin-commonjs": "21.1.0", diff --git a/packages/app-check-compat/package.json b/packages/app-check-compat/package.json index b8e73ff73b..0769902e86 100644 --- a/packages/app-check-compat/package.json +++ b/packages/app-check-compat/package.json @@ -43,7 +43,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.6", + "@firebase/app-compat": "0.5.7", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-check/package.json b/packages/app-check/package.json index aacb54e4c1..a38a1935ab 100644 --- a/packages/app-check/package.json +++ b/packages/app-check/package.json @@ -44,7 +44,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-compat/CHANGELOG.md b/packages/app-compat/CHANGELOG.md index c90d1c9fd0..ce994ed1e8 100644 --- a/packages/app-compat/CHANGELOG.md +++ b/packages/app-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/app-compat +## 0.5.7 + +### Patch Changes + +- Updated dependencies []: + - @firebase/app@0.14.7 + ## 0.5.6 ### Patch Changes diff --git a/packages/app-compat/package.json b/packages/app-compat/package.json index 7363ffc438..47520a763f 100644 --- a/packages/app-compat/package.json +++ b/packages/app-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-compat", - "version": "0.5.6", + "version": "0.5.7", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,7 +37,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "@firebase/util": "1.13.0", "@firebase/logger": "0.5.0", "@firebase/component": "0.7.0", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 4cb423c7ca..444f25f479 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/app +## 0.14.7 + +### Patch Changes + +- Update SDK_VERSION. + ## 0.14.6 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index ffb2d04205..7b9392f306 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app", - "version": "0.14.6", + "version": "0.14.7", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index 6af8c73273..c085e94b98 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -57,7 +57,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.6", + "@firebase/app-compat": "0.5.7", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/auth/package.json b/packages/auth/package.json index 03a6426070..209ea283ed 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -131,7 +131,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-strip": "2.1.0", "@types/express": "4.17.21", diff --git a/packages/data-connect/package.json b/packages/data-connect/package.json index e4d540fc4b..7280975814 100644 --- a/packages/data-connect/package.json +++ b/packages/data-connect/package.json @@ -55,7 +55,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/database-compat/package.json b/packages/database-compat/package.json index f27b05590d..422763546f 100644 --- a/packages/database-compat/package.json +++ b/packages/database-compat/package.json @@ -57,7 +57,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.6", + "@firebase/app-compat": "0.5.7", "typescript": "5.5.4" }, "repository": { diff --git a/packages/database/package.json b/packages/database/package.json index e870276bb4..20f17a1bbf 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -57,7 +57,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/firebase/CHANGELOG.md b/packages/firebase/CHANGELOG.md index f1374cf1e9..40f6ae9266 100644 --- a/packages/firebase/CHANGELOG.md +++ b/packages/firebase/CHANGELOG.md @@ -1,5 +1,30 @@ # firebase +## 12.8.0 + +### Minor Changes + +- [`83e6864`](https://github.com/firebase/firebase-js-sdk/commit/83e686478cea10c707909369dcf590cb09c59ef7) [#9356](https://github.com/firebase/firebase-js-sdk/pull/9356) - Release Firestore Pipelines for Enterprise edition in public preview. + +- [`2ecf78b`](https://github.com/firebase/firebase-js-sdk/commit/2ecf78b4f049b2e937cda911c00d549f25c628a8) [#8890](https://github.com/firebase/firebase-js-sdk/pull/8890) (fixes [#8859](https://github.com/firebase/firebase-js-sdk/issues/8859)) - Add support for `AbortSignal`, allowing requests to be aborted. + +- [`5579b38`](https://github.com/firebase/firebase-js-sdk/commit/5579b387ab697347ecd4a29ffed47c4cf808d544) [#9424](https://github.com/firebase/firebase-js-sdk/pull/9424) - Added ability to specify thinking levels in `thinkingConfig`. + +- [`f044045`](https://github.com/firebase/firebase-js-sdk/commit/f044045fcde44bf040d62c494712d5d24cdae4b9) [#9440](https://github.com/firebase/firebase-js-sdk/pull/9440) - Update default hybrid-in-cloud model to `gemini-2.5-flash-lite`. + +- [`b282744`](https://github.com/firebase/firebase-js-sdk/commit/b2827448bf8b51e2a1d0343092989a7b79fc0491) [#9449](https://github.com/firebase/firebase-js-sdk/pull/9449) - Web support for ABT and Rollouts + +### Patch Changes + +- Updated dependencies [[`83e6864`](https://github.com/firebase/firebase-js-sdk/commit/83e686478cea10c707909369dcf590cb09c59ef7), [`2ecf78b`](https://github.com/firebase/firebase-js-sdk/commit/2ecf78b4f049b2e937cda911c00d549f25c628a8), [`5579b38`](https://github.com/firebase/firebase-js-sdk/commit/5579b387ab697347ecd4a29ffed47c4cf808d544), [`f044045`](https://github.com/firebase/firebase-js-sdk/commit/f044045fcde44bf040d62c494712d5d24cdae4b9), [`b282744`](https://github.com/firebase/firebase-js-sdk/commit/b2827448bf8b51e2a1d0343092989a7b79fc0491)]: + - @firebase/firestore@4.10.0 + - @firebase/app@0.14.7 + - @firebase/ai@2.7.0 + - @firebase/remote-config@0.8.0 + - @firebase/firestore-compat@0.4.4 + - @firebase/app-compat@0.5.7 + - @firebase/remote-config-compat@0.2.21 + ## 12.7.0 ### Minor Changes diff --git a/packages/firebase/package.json b/packages/firebase/package.json index d3c6172b18..479bd3c338 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -1,6 +1,6 @@ { "name": "firebase", - "version": "12.7.0", + "version": "12.8.0", "description": "Firebase JavaScript library for web and Node.js", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -423,17 +423,17 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/ai": "2.6.1", - "@firebase/app": "0.14.6", - "@firebase/app-compat": "0.5.6", + "@firebase/ai": "2.7.0", + "@firebase/app": "0.14.7", + "@firebase/app-compat": "0.5.7", "@firebase/app-types": "0.9.3", "@firebase/auth": "1.12.0", "@firebase/auth-compat": "0.6.2", "@firebase/data-connect": "0.3.12", "@firebase/database": "1.1.0", "@firebase/database-compat": "2.1.0", - "@firebase/firestore": "4.9.3", - "@firebase/firestore-compat": "0.4.3", + "@firebase/firestore": "4.10.0", + "@firebase/firestore-compat": "0.4.4", "@firebase/functions": "0.13.1", "@firebase/functions-compat": "0.4.1", "@firebase/installations": "0.6.19", @@ -444,8 +444,8 @@ "@firebase/storage-compat": "0.4.0", "@firebase/performance": "0.7.9", "@firebase/performance-compat": "0.2.22", - "@firebase/remote-config": "0.7.0", - "@firebase/remote-config-compat": "0.2.20", + "@firebase/remote-config": "0.8.0", + "@firebase/remote-config-compat": "0.2.21", "@firebase/analytics": "0.10.19", "@firebase/analytics-compat": "0.2.25", "@firebase/app-check": "0.11.0", diff --git a/packages/firestore-compat/CHANGELOG.md b/packages/firestore-compat/CHANGELOG.md index 90a42aeb7f..0214c7ebab 100644 --- a/packages/firestore-compat/CHANGELOG.md +++ b/packages/firestore-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/firestore-compat +## 0.4.4 + +### Patch Changes + +- Updated dependencies [[`83e6864`](https://github.com/firebase/firebase-js-sdk/commit/83e686478cea10c707909369dcf590cb09c59ef7)]: + - @firebase/firestore@4.10.0 + ## 0.4.3 ### Patch Changes diff --git a/packages/firestore-compat/package.json b/packages/firestore-compat/package.json index 492998f200..e4f62da141 100644 --- a/packages/firestore-compat/package.json +++ b/packages/firestore-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore-compat", - "version": "0.4.3", + "version": "0.4.4", "description": "The Cloud Firestore component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -47,13 +47,13 @@ }, "dependencies": { "@firebase/component": "0.7.0", - "@firebase/firestore": "4.9.3", + "@firebase/firestore": "4.10.0", "@firebase/util": "1.13.0", "@firebase/firestore-types": "3.0.3", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.6", + "@firebase/app-compat": "0.5.7", "@types/eslint": "7.29.0", "rollup": "2.79.2", "rollup-plugin-sourcemaps": "0.6.3", diff --git a/packages/firestore/CHANGELOG.md b/packages/firestore/CHANGELOG.md index 8330a62eef..59dc24ec7d 100644 --- a/packages/firestore/CHANGELOG.md +++ b/packages/firestore/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/firestore +## 4.10.0 + +### Minor Changes + +- [`83e6864`](https://github.com/firebase/firebase-js-sdk/commit/83e686478cea10c707909369dcf590cb09c59ef7) [#9356](https://github.com/firebase/firebase-js-sdk/pull/9356) - Release Firestore Pipelines for Enterprise edition in public preview. + ## 4.9.3 ### Patch Changes diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 9311f404c9..76cc2b3e32 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore", - "version": "4.9.3", + "version": "4.10.0", "engines": { "node": ">=20.0.0" }, @@ -145,8 +145,8 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.6", - "@firebase/app-compat": "0.5.6", + "@firebase/app": "0.14.7", + "@firebase/app-compat": "0.5.7", "@firebase/auth": "1.12.0", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", diff --git a/packages/functions-compat/package.json b/packages/functions-compat/package.json index 81e52d2837..df4dd9ab26 100644 --- a/packages/functions-compat/package.json +++ b/packages/functions-compat/package.json @@ -29,7 +29,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.6", + "@firebase/app-compat": "0.5.7", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/functions/package.json b/packages/functions/package.json index 9c036e347a..3234e0ddb4 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -49,7 +49,7 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/installations-compat/package.json b/packages/installations-compat/package.json index 4fdb6c130a..85abab437b 100644 --- a/packages/installations-compat/package.json +++ b/packages/installations-compat/package.json @@ -44,7 +44,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app-compat": "0.5.6", + "@firebase/app-compat": "0.5.7", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/installations/package.json b/packages/installations/package.json index 2feb17e5d8..fc12ac8a92 100644 --- a/packages/installations/package.json +++ b/packages/installations/package.json @@ -49,7 +49,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/messaging-compat/package.json b/packages/messaging-compat/package.json index f657f90c5e..64cb0ed782 100644 --- a/packages/messaging-compat/package.json +++ b/packages/messaging-compat/package.json @@ -44,7 +44,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.6", + "@firebase/app-compat": "0.5.7", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", "ts-essentials": "9.4.2", diff --git a/packages/messaging/package.json b/packages/messaging/package.json index f2ac7689ce..3f4e7e8941 100644 --- a/packages/messaging/package.json +++ b/packages/messaging/package.json @@ -60,7 +60,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/performance-compat/package.json b/packages/performance-compat/package.json index 4099db0992..4e250140ec 100644 --- a/packages/performance-compat/package.json +++ b/packages/performance-compat/package.json @@ -51,7 +51,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.6" + "@firebase/app-compat": "0.5.7" }, "repository": { "directory": "packages/performance-compat", diff --git a/packages/performance/package.json b/packages/performance/package.json index eaebecb664..80ffab1f8c 100644 --- a/packages/performance/package.json +++ b/packages/performance/package.json @@ -47,7 +47,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/remote-config-compat/CHANGELOG.md b/packages/remote-config-compat/CHANGELOG.md index 08cd52e62d..9205251fc8 100644 --- a/packages/remote-config-compat/CHANGELOG.md +++ b/packages/remote-config-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/remote-config-compat +## 0.2.21 + +### Patch Changes + +- Updated dependencies [[`b282744`](https://github.com/firebase/firebase-js-sdk/commit/b2827448bf8b51e2a1d0343092989a7b79fc0491)]: + - @firebase/remote-config@0.8.0 + ## 0.2.20 ### Patch Changes diff --git a/packages/remote-config-compat/package.json b/packages/remote-config-compat/package.json index d7a28f82db..501f3c1a9d 100644 --- a/packages/remote-config-compat/package.json +++ b/packages/remote-config-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/remote-config-compat", - "version": "0.2.20", + "version": "0.2.21", "description": "The compatibility package of Remote Config", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,7 +37,7 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/remote-config": "0.7.0", + "@firebase/remote-config": "0.8.0", "@firebase/remote-config-types": "0.5.0", "@firebase/util": "1.13.0", "@firebase/logger": "0.5.0", @@ -50,7 +50,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.6" + "@firebase/app-compat": "0.5.7" }, "repository": { "directory": "packages/remote-config-compat", diff --git a/packages/remote-config/CHANGELOG.md b/packages/remote-config/CHANGELOG.md index fcf552b0e3..1799899da6 100644 --- a/packages/remote-config/CHANGELOG.md +++ b/packages/remote-config/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/remote-config +## 0.8.0 + +### Minor Changes + +- [`b282744`](https://github.com/firebase/firebase-js-sdk/commit/b2827448bf8b51e2a1d0343092989a7b79fc0491) [#9449](https://github.com/firebase/firebase-js-sdk/pull/9449) - Web support for ABT and Rollouts + ## 0.7.0 ### Minor Changes diff --git a/packages/remote-config/package.json b/packages/remote-config/package.json index 83d9886b89..5d8c953f62 100644 --- a/packages/remote-config/package.json +++ b/packages/remote-config/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/remote-config", - "version": "0.7.0", + "version": "0.8.0", "description": "The Remote Config package of the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -48,7 +48,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/storage-compat/package.json b/packages/storage-compat/package.json index 762c193638..7003c451bc 100644 --- a/packages/storage-compat/package.json +++ b/packages/storage-compat/package.json @@ -44,7 +44,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.6", + "@firebase/app-compat": "0.5.7", "@firebase/auth-compat": "0.6.2", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", diff --git a/packages/storage/package.json b/packages/storage/package.json index f8061e76e1..ca4af33efa 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -54,7 +54,7 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "@firebase/auth": "1.12.0", "rollup": "2.79.2", "@rollup/plugin-alias": "5.1.1", diff --git a/packages/template/package.json b/packages/template/package.json index 54395dfd17..543eda528c 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -48,7 +48,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index 8653103c7f..4c8caee603 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -40,7 +40,7 @@ "yargs": "17.7.2" }, "devDependencies": { - "@firebase/app": "0.14.6", + "@firebase/app": "0.14.7", "@firebase/logger": "0.5.0", "@types/webpack": "5.28.5" }, From 58ddd6e545643308f5cdaf3ac0ecb3397cbf320c Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Fri, 16 Jan 2026 10:35:56 -0500 Subject: [PATCH 042/174] ci(ai): Only run mock responses check on AI PRs (#9335) --- .github/workflows/check-vertexai-responses.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check-vertexai-responses.yml b/.github/workflows/check-vertexai-responses.yml index 4eceacd61b..c1d6a5a07c 100644 --- a/.github/workflows/check-vertexai-responses.yml +++ b/.github/workflows/check-vertexai-responses.yml @@ -14,7 +14,10 @@ name: Check Vertex AI Responses -on: pull_request +on: + pull_request: + paths: + - 'packages/ai/**' jobs: check-version: From d818df4e8697c70bf9dbf58620e47d40d175ecc8 Mon Sep 17 00:00:00 2001 From: wu-hui <53845758+wu-hui@users.noreply.github.com> Date: Wed, 21 Jan 2026 15:20:40 -0500 Subject: [PATCH 043/174] Remove undesired exists() conditions from query-to-pipeline conversion (#9444) --- packages/firestore/src/core/pipeline-util.ts | 33 +++++---- .../integration/api/query_to_pipeline.test.ts | 67 +++++++++++++++++++ 2 files changed, 82 insertions(+), 18 deletions(-) diff --git a/packages/firestore/src/core/pipeline-util.ts b/packages/firestore/src/core/pipeline-util.ts index b27babf695..49b30e96d1 100644 --- a/packages/firestore/src/core/pipeline-util.ts +++ b/packages/firestore/src/core/pipeline-util.ts @@ -81,10 +81,7 @@ export function toPipelineBooleanExpr(f: FilterInternal): BooleanExpression { fieldValue.equal(Constant._fromProto(value)) ); case Operator.NOT_EQUAL: - return and( - fieldValue.exists(), - fieldValue.notEqual(Constant._fromProto(value)) - ); + return fieldValue.notEqual(Constant._fromProto(value)); case Operator.ARRAY_CONTAINS: return and( fieldValue.exists(), @@ -113,11 +110,11 @@ export function toPipelineBooleanExpr(f: FilterInternal): BooleanExpression { Constant._fromProto(val) ); if (!values) { - return and(fieldValue.exists(), fieldValue.notEqualAny([])); + return fieldValue.notEqualAny([]); } else if (values.length === 1) { - return and(fieldValue.exists(), fieldValue.notEqual(values[0])); + return fieldValue.notEqual(values[0]); } else { - return and(fieldValue.exists(), fieldValue.notEqualAny(values)); + return fieldValue.notEqualAny(values); } } default: @@ -169,19 +166,19 @@ export function toPipeline(query: Query, db: Firestore): Pipeline { // orders const orders = queryNormalizedOrderBy(query); - const existsConditions = orders.map(order => + const existsConditions = query.explicitOrderBy.map(order => field(order.field.canonicalString()).exists() ); - if (existsConditions.length > 1) { - pipeline = pipeline.where( - and( - existsConditions[0], - existsConditions[1], - ...existsConditions.slice(2) - ) - ); - } else { - pipeline = pipeline.where(existsConditions[0]); + if (existsConditions.length > 0) { + const condition = + existsConditions.length === 1 + ? existsConditions[0] + : and( + existsConditions[0], + existsConditions[1], + ...existsConditions.slice(2) + ); + pipeline = pipeline.where(condition); } const orderings = orders.map(order => diff --git a/packages/firestore/test/integration/api/query_to_pipeline.test.ts b/packages/firestore/test/integration/api/query_to_pipeline.test.ts index 34afdc6ab0..42c1663161 100644 --- a/packages/firestore/test/integration/api/query_to_pipeline.test.ts +++ b/packages/firestore/test/integration/api/query_to_pipeline.test.ts @@ -814,4 +814,71 @@ apiDescribe.skipClassic('Query to Pipeline', persistence => { } ); }); + + it('not-in removes existence filter', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + doc1: { field: 2 }, + doc2: { field: 1 }, + doc3: {} + }, + async (collRef, db) => { + const query1 = query(collRef, where('field', 'not-in', [1])); + const snapshot = await execute(db.pipeline().createFrom(query1)); + // doc3 (missing 'field') should be included because 'not-in' (and implicit order by) + // should NOT generate an existence filter. + verifyResults(snapshot, { field: 2 }, {}); + } + ); + }); + + it('not-equal removes existence filter', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + doc1: { field: 2 }, + doc2: { field: 1 }, + doc3: {} + }, + async (collRef, db) => { + const query1 = query(collRef, where('field', '!=', 1)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + // doc3 (missing 'field') should be included. + verifyResults(snapshot, { field: 2 }, {}); + } + ); + }); + + it('inequality maintains existence filter', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + doc1: { field: 0 }, + doc2: {} + }, + async (collRef, db) => { + const query1 = query(collRef, where('field', '<', 1)); + const snapshot = await execute(db.pipeline().createFrom(query1)); + // doc2 (missing 'field') should be EXCLUDED by the inequality filter itself. + verifyResults(snapshot, { field: 0 }); + } + ); + }); + + it('explicit order maintains existence filter', () => { + return withTestCollection( + PERSISTENCE_MODE_UNSPECIFIED, + { + doc1: { field: 1 }, + doc2: {} + }, + async (collRef, db) => { + const query1 = query(collRef, orderBy('field')); + const snapshot = await execute(db.pipeline().createFrom(query1)); + // doc2 (missing 'field') should be EXCLUDED by the explicit orderBy existence filter. + verifyResults(snapshot, { field: 1 }); + } + ); + }); }); From 08e3acdf098dc5499081c610bcbe428f376f9ded Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Mon, 26 Jan 2026 12:56:52 -0500 Subject: [PATCH 044/174] feat(firestore): add support for regexFind and regexFindAll (#9459) --- .changeset/violet-kangaroos-talk.md | 6 + .../firestore-lite-pipelines.api.md | 32 ++ common/api-review/firestore-pipelines.api.md | 32 ++ .../firestore_lite_pipelines.expression.md | 148 +++++++++ docs-devsite/firestore_lite_pipelines.md | 304 ++++++++++++++++++ .../firestore_pipelines.expression.md | 148 +++++++++ docs-devsite/firestore_pipelines.md | 304 ++++++++++++++++++ .../firestore/lite/pipelines/pipelines.ts | 2 + packages/firestore/src/api_pipelines.ts | 2 + .../firestore/src/lite-api/expressions.ts | 288 +++++++++++++++++ .../test/integration/api/pipeline.test.ts | 37 +++ packages/firestore/test/lite/pipeline.test.ts | 38 +++ 12 files changed, 1341 insertions(+) create mode 100644 .changeset/violet-kangaroos-talk.md diff --git a/.changeset/violet-kangaroos-talk.md b/.changeset/violet-kangaroos-talk.md new file mode 100644 index 0000000000..d76e0288f7 --- /dev/null +++ b/.changeset/violet-kangaroos-talk.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/firestore': minor +--- + +Add support for `regexFind` and `regexFindAll` Pipeline expressions. diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index bc30c5c449..5495e6c3a8 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -544,6 +544,14 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ regexContains(pattern: Expression): BooleanExpression; /* Excluded from this release type: _readUserData */ + regexFind(pattern: string): FunctionExpression; + /* Excluded from this release type: _readUserData */ + regexFind(pattern: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + regexFindAll(pattern: string): FunctionExpression; + /* Excluded from this release type: _readUserData */ + regexFindAll(pattern: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ regexMatch(pattern: string): BooleanExpression; /* Excluded from this release type: _readUserData */ regexMatch(pattern: Expression): BooleanExpression; @@ -1021,6 +1029,30 @@ export function regexContains(stringExpression: Expression, pattern: string): Bo // @beta export function regexContains(stringExpression: Expression, pattern: Expression): BooleanExpression; +// @beta +export function regexFind(fieldName: string, pattern: string): FunctionExpression; + +// @beta +export function regexFind(fieldName: string, pattern: Expression): FunctionExpression; + +// @beta +export function regexFind(stringExpression: Expression, pattern: string): FunctionExpression; + +// @beta +export function regexFind(stringExpression: Expression, pattern: Expression): FunctionExpression; + +// @beta +export function regexFindAll(fieldName: string, pattern: string): FunctionExpression; + +// @beta +export function regexFindAll(fieldName: string, pattern: Expression): FunctionExpression; + +// @beta +export function regexFindAll(stringExpression: Expression, pattern: string): FunctionExpression; + +// @beta +export function regexFindAll(stringExpression: Expression, pattern: Expression): FunctionExpression; + // @beta export function regexMatch(fieldName: string, pattern: string): BooleanExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 38e61acd96..366ef7914e 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -547,6 +547,14 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ regexContains(pattern: Expression): BooleanExpression; /* Excluded from this release type: _readUserData */ + regexFind(pattern: string): FunctionExpression; + /* Excluded from this release type: _readUserData */ + regexFind(pattern: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + regexFindAll(pattern: string): FunctionExpression; + /* Excluded from this release type: _readUserData */ + regexFindAll(pattern: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ regexMatch(pattern: string): BooleanExpression; /* Excluded from this release type: _readUserData */ regexMatch(pattern: Expression): BooleanExpression; @@ -1058,6 +1066,30 @@ export function regexContains(stringExpression: Expression, pattern: string): Bo // @beta export function regexContains(stringExpression: Expression, pattern: Expression): BooleanExpression; +// @beta +export function regexFind(fieldName: string, pattern: string): FunctionExpression; + +// @beta +export function regexFind(fieldName: string, pattern: Expression): FunctionExpression; + +// @beta +export function regexFind(stringExpression: Expression, pattern: string): FunctionExpression; + +// @beta +export function regexFind(stringExpression: Expression, pattern: Expression): FunctionExpression; + +// @beta +export function regexFindAll(fieldName: string, pattern: string): FunctionExpression; + +// @beta +export function regexFindAll(fieldName: string, pattern: Expression): FunctionExpression; + +// @beta +export function regexFindAll(stringExpression: Expression, pattern: string): FunctionExpression; + +// @beta +export function regexFindAll(stringExpression: Expression, pattern: Expression): FunctionExpression; + // @beta export function regexMatch(fieldName: string, pattern: string): BooleanExpression; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index b8790f8879..42d7215392 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -128,6 +128,10 @@ field("optional_field").ifAbsent(field('default_field')) | [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of a constant value. | | [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. | | [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. | +| [regexFind(pattern)](./firestore_lite_pipelines.expression.md#expressionregexfind) | | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFind(pattern)](./firestore_lite_pipelines.expression.md#expressionregexfind) | | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(pattern)](./firestore_lite_pipelines.expression.md#expressionregexfindall) | | (Public Preview) Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(pattern)](./firestore_lite_pipelines.expression.md#expressionregexfindall) | | (Public Preview) Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | | [regexMatch(pattern)](./firestore_lite_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. | | [regexMatch(pattern)](./firestore_lite_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. | | [reverse()](./firestore_lite_pipelines.expression.md#expressionreverse) | | (Public Preview) Creates an expression that reverses this string expression. | @@ -2868,6 +2872,150 @@ field("description").regexContains(field("regex")); ``` +## Expression.regexFind() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first substring of a string expression that matches a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +regexFind(pattern: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | string | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression find function. + +### Example + + +```typescript +// Extract the domain from an email address +field("email").regexFind("@.+") + +``` + +## Expression.regexFind() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first substring of a string expression that matches a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +regexFind(pattern: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression find function. + +### Example + + +```typescript +// Extract the domain from an email address +field("email").regexFind(field("domain")) + +``` + +## Expression.regexFindAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +regexFindAll(pattern: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | string | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) that evaluates to an array of matched substrings. + +### Example + + +```typescript +// Extract all hashtags from a post content field +field("content").regexFindAll("#[A-Za-z0-9_]+") + +``` + +## Expression.regexFindAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +regexFindAll(pattern: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) that evaluates to an array of matched substrings. + +### Example + + +```typescript +// Extract all names from a post content field +field("content").regexFindAll(field("names")) + +``` + ## Expression.regexMatch() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 1f2599ce81..763c38a5fc 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -174,6 +174,10 @@ https://github.com/firebase/firebase-js-sdk | [notEqualAny(fieldName, arrayExpression)](./firestore_lite_pipelines.md#notequalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. | | [regexContains(fieldName, pattern)](./firestore_lite_pipelines.md#regexcontains_67f7432) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. | | [regexContains(fieldName, pattern)](./firestore_lite_pipelines.md#regexcontains_cb1318d) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. | +| [regexFind(fieldName, pattern)](./firestore_lite_pipelines.md#regexfind_67f7432) | (Public Preview) Creates an expression that returns the first substring of a string field that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFind(fieldName, pattern)](./firestore_lite_pipelines.md#regexfind_cb1318d) | (Public Preview) Creates an expression that returns the first substring of a string field that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(fieldName, pattern)](./firestore_lite_pipelines.md#regexfindall_67f7432) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(fieldName, pattern)](./firestore_lite_pipelines.md#regexfindall_cb1318d) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | | [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_67f7432) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | | [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_cb1318d) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | | [round(fieldName)](./firestore_lite_pipelines.md#round_e5b0480) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | @@ -263,6 +267,10 @@ https://github.com/firebase/firebase-js-sdk | [like(stringExpression, pattern)](./firestore_lite_pipelines.md#like_b534848) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. | | [regexContains(stringExpression, pattern)](./firestore_lite_pipelines.md#regexcontains_a84c581) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. | | [regexContains(stringExpression, pattern)](./firestore_lite_pipelines.md#regexcontains_b534848) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. | +| [regexFind(stringExpression, pattern)](./firestore_lite_pipelines.md#regexfind_a84c581) | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFind(stringExpression, pattern)](./firestore_lite_pipelines.md#regexfind_b534848) | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(stringExpression, pattern)](./firestore_lite_pipelines.md#regexfindall_a84c581) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(stringExpression, pattern)](./firestore_lite_pipelines.md#regexfindall_b534848) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | | [regexMatch(stringExpression, pattern)](./firestore_lite_pipelines.md#regexmatch_a84c581) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. | | [regexMatch(stringExpression, pattern)](./firestore_lite_pipelines.md#regexmatch_b534848) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. | | [reverse(stringExpression)](./firestore_lite_pipelines.md#reverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. | @@ -5298,6 +5306,154 @@ regexContains("description", field("pattern")); ``` +### regexFind(fieldName, pattern) {:#regexfind_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first substring of a string field that matches a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFind(fieldName: string, pattern: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string to search. | +| pattern | string | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression find function. + +### Example + + +```typescript +// Extract the domain name from an email field +regexFind("email", "@[A-Za-z0-9.-]+"); + +``` + +### regexFind(fieldName, pattern) {:#regexfind_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first substring of a string field that matches a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFind(fieldName: string, pattern: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string to search. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression find function. + +### Example + + +```typescript +// Extract a substring from 'email' based on a pattern stored in another field +regexFind("email", field("pattern")); + +``` + +### regexFindAll(fieldName, pattern) {:#regexfindall_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFindAll(fieldName: string, pattern: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string to search. | +| pattern | string | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) that evaluates to an array of matched substrings. + +### Example + + +```typescript +// Extract all hashtags from a post content field +regexFindAll("content", "#[A-Za-z0-9_]+"); + +``` + +### regexFindAll(fieldName, pattern) {:#regexfindall_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFindAll(fieldName: string, pattern: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string to search. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) that evaluates to an array of matched substrings. + +### Example + + +```typescript +// Extract all matches from 'content' based on a pattern stored in another field +regexFindAll("content", field("pattern")); + +``` + ### regexMatch(fieldName, pattern) {:#regexmatch_67f7432} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -7876,6 +8032,154 @@ regexContains(field("description"), field("pattern")); ``` +### regexFind(stringExpression, pattern) {:#regexfind_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first substring of a string expression that matches a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFind(stringExpression: Expression, pattern: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to search. | +| pattern | string | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression find function. + +### Example + + +```typescript +// Extract the domain from a lower-cased email address +regexFind(field("email"), "@[A-Za-z0-9.-]+"); + +``` + +### regexFind(stringExpression, pattern) {:#regexfind_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first substring of a string expression that matches a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFind(stringExpression: Expression, pattern: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to search. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression find function. + +### Example + + +```typescript +// Extract a substring based on a dynamic pattern field +regexFind(field("email"), field("pattern")); + +``` + +### regexFindAll(stringExpression, pattern) {:#regexfindall_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFindAll(stringExpression: Expression, pattern: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to search. | +| pattern | string | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) that evaluates to an array of matched substrings. + +### Example + + +```typescript +// Extract all mentions from a lower-cased comment +regexFindAll(field("comment"), "@[A-Za-z0-9_]+"); + +``` + +### regexFindAll(stringExpression, pattern) {:#regexfindall_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFindAll(stringExpression: Expression, pattern: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string to search. | +| pattern | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) that evaluates to an array of matched substrings. + +### Example + + +```typescript +// Extract all matches based on a dynamic pattern expression +regexFindAll(field("comment"), field("pattern")); + +``` + ### regexMatch(stringExpression, pattern) {:#regexmatch_a84c581} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 5c74487ae5..b09e0727a5 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -128,6 +128,10 @@ field("optional_field").ifAbsent(field('default_field')) | [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of a constant value. | | [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. | | [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. | +| [regexFind(pattern)](./firestore_pipelines.expression.md#expressionregexfind) | | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFind(pattern)](./firestore_pipelines.expression.md#expressionregexfind) | | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(pattern)](./firestore_pipelines.expression.md#expressionregexfindall) | | (Public Preview) Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(pattern)](./firestore_pipelines.expression.md#expressionregexfindall) | | (Public Preview) Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | | [regexMatch(pattern)](./firestore_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. | | [regexMatch(pattern)](./firestore_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. | | [reverse()](./firestore_pipelines.expression.md#expressionreverse) | | (Public Preview) Creates an expression that reverses this string expression. | @@ -2868,6 +2872,150 @@ field("description").regexContains(field("regex")); ``` +## Expression.regexFind() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first substring of a string expression that matches a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +regexFind(pattern: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | string | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression find function. + +### Example + + +```typescript +// Extract the domain from an email address +field("email").regexFind("@.+") + +``` + +## Expression.regexFind() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first substring of a string expression that matches a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +regexFind(pattern: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression find function. + +### Example + + +```typescript +// Extract the domain from an email address +field("email").regexFind(field("domain")) + +``` + +## Expression.regexFindAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +regexFindAll(pattern: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | string | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) that evaluates to an array of matched substrings. + +### Example + + +```typescript +// Extract all hashtags from a post content field +field("content").regexFindAll("#[A-Za-z0-9_]+") + +``` + +## Expression.regexFindAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +regexFindAll(pattern: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) that evaluates to an array of matched substrings. + +### Example + + +```typescript +// Extract all names from a post content field +field("content").regexFindAll(field("names")) + +``` + ## Expression.regexMatch() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 83f2763dd9..d61d357ce3 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -174,6 +174,10 @@ https://github.com/firebase/firebase-js-sdk | [notEqualAny(fieldName, arrayExpression)](./firestore_pipelines.md#notequalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. | | [regexContains(fieldName, pattern)](./firestore_pipelines.md#regexcontains_67f7432) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. | | [regexContains(fieldName, pattern)](./firestore_pipelines.md#regexcontains_cb1318d) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. | +| [regexFind(fieldName, pattern)](./firestore_pipelines.md#regexfind_67f7432) | (Public Preview) Creates an expression that returns the first substring of a string field that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFind(fieldName, pattern)](./firestore_pipelines.md#regexfind_cb1318d) | (Public Preview) Creates an expression that returns the first substring of a string field that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(fieldName, pattern)](./firestore_pipelines.md#regexfindall_67f7432) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(fieldName, pattern)](./firestore_pipelines.md#regexfindall_cb1318d) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | | [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_67f7432) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | | [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_cb1318d) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | | [round(fieldName)](./firestore_pipelines.md#round_e5b0480) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | @@ -266,6 +270,10 @@ https://github.com/firebase/firebase-js-sdk | [like(stringExpression, pattern)](./firestore_pipelines.md#like_b534848) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. | | [regexContains(stringExpression, pattern)](./firestore_pipelines.md#regexcontains_a84c581) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. | | [regexContains(stringExpression, pattern)](./firestore_pipelines.md#regexcontains_b534848) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. | +| [regexFind(stringExpression, pattern)](./firestore_pipelines.md#regexfind_a84c581) | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFind(stringExpression, pattern)](./firestore_pipelines.md#regexfind_b534848) | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(stringExpression, pattern)](./firestore_pipelines.md#regexfindall_a84c581) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(stringExpression, pattern)](./firestore_pipelines.md#regexfindall_b534848) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | | [regexMatch(stringExpression, pattern)](./firestore_pipelines.md#regexmatch_a84c581) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. | | [regexMatch(stringExpression, pattern)](./firestore_pipelines.md#regexmatch_b534848) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. | | [reverse(stringExpression)](./firestore_pipelines.md#reverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. | @@ -5304,6 +5312,154 @@ regexContains("description", field("pattern")); ``` +### regexFind(fieldName, pattern) {:#regexfind_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first substring of a string field that matches a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFind(fieldName: string, pattern: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string to search. | +| pattern | string | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression find function. + +### Example + + +```typescript +// Extract the domain name from an email field +regexFind("email", "@[A-Za-z0-9.-]+"); + +``` + +### regexFind(fieldName, pattern) {:#regexfind_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first substring of a string field that matches a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFind(fieldName: string, pattern: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string to search. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression find function. + +### Example + + +```typescript +// Extract a substring from 'email' based on a pattern stored in another field +regexFind("email", field("pattern")); + +``` + +### regexFindAll(fieldName, pattern) {:#regexfindall_67f7432} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFindAll(fieldName: string, pattern: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string to search. | +| pattern | string | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) that evaluates to an array of matched substrings. + +### Example + + +```typescript +// Extract all hashtags from a post content field +regexFindAll("content", "#[A-Za-z0-9_]+"); + +``` + +### regexFindAll(fieldName, pattern) {:#regexfindall_cb1318d} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFindAll(fieldName: string, pattern: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string to search. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) that evaluates to an array of matched substrings. + +### Example + + +```typescript +// Extract all matches from 'content' based on a pattern stored in another field +regexFindAll("content", field("pattern")); + +``` + ### regexMatch(fieldName, pattern) {:#regexmatch_67f7432} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -7951,6 +8107,154 @@ regexContains(field("description"), field("pattern")); ``` +### regexFind(stringExpression, pattern) {:#regexfind_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first substring of a string expression that matches a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFind(stringExpression: Expression, pattern: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to search. | +| pattern | string | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression find function. + +### Example + + +```typescript +// Extract the domain from a lower-cased email address +regexFind(field("email"), "@[A-Za-z0-9.-]+"); + +``` + +### regexFind(stringExpression, pattern) {:#regexfind_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first substring of a string expression that matches a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFind(stringExpression: Expression, pattern: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to search. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the regular expression find function. + +### Example + + +```typescript +// Extract a substring based on a dynamic pattern field +regexFind(field("email"), field("pattern")); + +``` + +### regexFindAll(stringExpression, pattern) {:#regexfindall_a84c581} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFindAll(stringExpression: Expression, pattern: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to search. | +| pattern | string | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) that evaluates to an array of matched substrings. + +### Example + + +```typescript +// Extract all mentions from a lower-cased comment +regexFindAll(field("comment"), "@[A-Za-z0-9_]+"); + +``` + +### regexFindAll(stringExpression, pattern) {:#regexfindall_b534848} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression. + +This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. + +Signature: + +```typescript +export declare function regexFindAll(stringExpression: Expression, pattern: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| stringExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string to search. | +| pattern | [Expression](./firestore_pipelines.expression.md#expression_class) | The regular expression to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) that evaluates to an array of matched substrings. + +### Example + + +```typescript +// Extract all matches based on a dynamic pattern expression +regexFindAll(field("comment"), field("pattern")); + +``` + ### regexMatch(stringExpression, pattern) {:#regexmatch_a84c581} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index ba5b3f61d3..5f6faabb54 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -130,6 +130,8 @@ export { charLength, like, regexContains, + regexFind, + regexFindAll, regexMatch, stringContains, startsWith, diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index 693b7f5468..accefdad83 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -85,6 +85,8 @@ export { charLength, like, regexContains, + regexFind, + regexFindAll, regexMatch, stringContains, startsWith, diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index 0bae99b45f..33617ddf06 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -922,6 +922,94 @@ export abstract class Expression implements ProtoValueSerializable, UserData { ).asBoolean(); } + /** + * @beta + * Creates an expression that returns the first substring of a string expression that matches + * a specified regular expression. + * + * This expression uses the {@link https://github.com/google/re2/wiki/Syntax | RE2} regular expression syntax. + * + * @example + * ```typescript + * // Extract the domain from an email address + * field("email").regexFind("@.+") + * ``` + * + * @param pattern - The regular expression to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the regular expression find function. + */ + regexFind(pattern: string): FunctionExpression; + + /** + * @beta + * Creates an expression that returns the first substring of a string expression that matches + * a specified regular expression. + * + * This expression uses the {@link https://github.com/google/re2/wiki/Syntax | RE2} regular expression syntax. + * + * @example + * ```typescript + * // Extract the domain from an email address + * field("email").regexFind(field("domain")) + * ``` + * + * @param pattern - The regular expression to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the regular expression find function. + */ + regexFind(pattern: Expression): FunctionExpression; + regexFind(stringOrExpr: string | Expression): FunctionExpression { + return new FunctionExpression( + 'regex_find', + [this, valueToDefaultExpr(stringOrExpr)], + 'regexFind' + ); + } + + /** + * @beta + * + * Creates an expression that evaluates to a list of all substrings in this string expression that + * match a specified regular expression. + * + * This expression uses the {@link https://github.com/google/re2/wiki/Syntax | RE2} regular expression syntax. + * + * @example + * ```typescript + * // Extract all hashtags from a post content field + * field("content").regexFindAll("#[A-Za-z0-9_]+") + * ``` + * + * @param pattern - The regular expression to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} that evaluates to an array of matched substrings. + */ + regexFindAll(pattern: string): FunctionExpression; + + /** + * @beta + * + * Creates an expression that evaluates to a list of all substrings in this string expression that + * match a specified regular expression. + * + * This expression uses the {@link https://github.com/google/re2/wiki/Syntax | RE2} regular expression syntax. + * + * @example + * ```typescript + * // Extract all names from a post content field + * field("content").regexFindAll(field("names")) + * ``` + * + * @param pattern - The regular expression to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} that evaluates to an array of matched substrings. + */ + regexFindAll(pattern: Expression): FunctionExpression; + regexFindAll(stringOrExpr: string | Expression): FunctionExpression { + return new FunctionExpression( + 'regex_find_all', + [this, valueToDefaultExpr(stringOrExpr)], + 'regexFindAll' + ); + } + /** * @beta * Creates an expression that checks if a string matches a specified regular expression. @@ -5918,6 +6006,206 @@ export function regexContains( return leftExpr.regexContains(patternExpr); } +/** + * @beta + * + * Creates an expression that returns the first substring of a string field that matches a + * specified regular expression. + * + * This expression uses the {@link https://github.com/google/re2/wiki/Syntax | RE2} regular expression syntax. + * + * @example + * ```typescript + * // Extract the domain name from an email field + * regexFind("email", "@[A-Za-z0-9.-]+"); + * ``` + * + * @param fieldName - The name of the field containing the string to search. + * @param pattern - The regular expression to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the regular expression find function. + */ +export function regexFind( + fieldName: string, + pattern: string +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first substring of a string field that matches a + * specified regular expression. + * + * This expression uses the {@link https://github.com/google/re2/wiki/Syntax | RE2} regular expression syntax. + * + * @example + * ```typescript + * // Extract a substring from 'email' based on a pattern stored in another field + * regexFind("email", field("pattern")); + * ``` + * + * @param fieldName - The name of the field containing the string to search. + * @param pattern - The regular expression to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the regular expression find function. + */ +export function regexFind( + fieldName: string, + pattern: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first substring of a string expression that matches + * a specified regular expression. + * + * This expression uses the {@link https://github.com/google/re2/wiki/Syntax | RE2} regular expression syntax. + * + * @example + * ```typescript + * // Extract the domain from a lower-cased email address + * regexFind(field("email"), "@[A-Za-z0-9.-]+"); + * ``` + * + * @param stringExpression - The expression representing the string to search. + * @param pattern - The regular expression to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the regular expression find function. + */ +export function regexFind( + stringExpression: Expression, + pattern: string +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first substring of a string expression that matches + * a specified regular expression. + * + * This expression uses the {@link https://github.com/google/re2/wiki/Syntax | RE2} regular expression syntax. + * + * @example + * ```typescript + * // Extract a substring based on a dynamic pattern field + * regexFind(field("email"), field("pattern")); + * ``` + * + * @param stringExpression - The expression representing the string to search. + * @param pattern - The regular expression to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the regular expression find function. + */ +export function regexFind( + stringExpression: Expression, + pattern: Expression +): FunctionExpression; +export function regexFind( + left: Expression | string, + pattern: Expression | string +): FunctionExpression { + const leftExpr = fieldOrExpression(left); + const patternExpr = valueToDefaultExpr(pattern); + return leftExpr.regexFind(patternExpr); +} + +/** + * @beta + * + * Creates an expression that evaluates to a list of all substrings in a string field that + * match a specified regular expression. + * + * This expression uses the {@link https://github.com/google/re2/wiki/Syntax | RE2} regular expression syntax. + * + * @example + * ```typescript + * // Extract all hashtags from a post content field + * regexFindAll("content", "#[A-Za-z0-9_]+"); + * ``` + * + * @param fieldName - The name of the field containing the string to search. + * @param pattern - The regular expression to search for. + * @returns A new {@link @firebase/firestore/pipelines#FunctionExpression} that evaluates to an array of matched substrings. + */ +export function regexFindAll( + fieldName: string, + pattern: string +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that evaluates to a list of all substrings in a string field that + * match a specified regular expression. + * + * This expression uses the {@link https://github.com/google/re2/wiki/Syntax | RE2} regular expression syntax. + * + * @example + * ```typescript + * // Extract all matches from 'content' based on a pattern stored in another field + * regexFindAll("content", field("pattern")); + * ``` + * + * @param fieldName - The name of the field containing the string to search. + * @param pattern - The regular expression to search for. + * @returns A new {@link @firebase/firestore/pipelines#FunctionExpression} that evaluates to an array of matched substrings. + */ +export function regexFindAll( + fieldName: string, + pattern: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that evaluates to a list of all substrings in a string expression + * that match a specified regular expression. + * + * This expression uses the {@link https://github.com/google/re2/wiki/Syntax | RE2} regular expression syntax. + * + * @example + * ```typescript + * // Extract all mentions from a lower-cased comment + * regexFindAll(field("comment"), "@[A-Za-z0-9_]+"); + * ``` + * + * @param stringExpression - The expression representing the string to search. + * @param pattern - The regular expression to search for. + * @returns A new {@link @firebase/firestore/pipelines#FunctionExpression} that evaluates to an array of matched substrings. + */ +export function regexFindAll( + stringExpression: Expression, + pattern: string +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that evaluates to a list of all substrings in a string expression + * that match a specified regular expression. + * + * This expression uses the {@link https://github.com/google/re2/wiki/Syntax | RE2} regular expression syntax. + * + * @example + * ```typescript + * // Extract all matches based on a dynamic pattern expression + * regexFindAll(field("comment"), field("pattern")); + * ``` + * + * @param stringExpression - The expression representing the string to search. + * @param pattern - The regular expression to search for. + * @returns A new {@link @firebase/firestore/pipelines#FunctionExpression} that evaluates to an array of matched substrings. + */ +export function regexFindAll( + stringExpression: Expression, + pattern: Expression +): FunctionExpression; +export function regexFindAll( + left: Expression | string, + pattern: Expression | string +): FunctionExpression { + const leftExpr = fieldOrExpression(left); + const patternExpr = valueToDefaultExpr(pattern); + return leftExpr.regexFindAll(patternExpr); +} + /** * @beta * diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 22bc3656ba..1015c746a9 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -77,6 +77,8 @@ import { notEqual, or, regexContains, + regexFind, + regexFindAll, regexMatch, startsWith, stringConcat, @@ -2500,6 +2502,41 @@ apiDescribe.skipClassic('Pipelines', persistence => { expect(snapshot.results.length).to.equal(5); }); + it('testRegexFind', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(regexFind('title', '^\\w+').as('firstWordInTitle')) + .select('firstWordInTitle') + .sort(field('firstWordInTitle').ascending()) + .limit(3) + ); + expectResults( + snapshot, + { firstWordInTitle: '1984' }, + { firstWordInTitle: 'Crime' }, + { firstWordInTitle: 'Dune' } + ); + }); + + it('testRegexFindAll', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(regexFindAll('title', '\\w+').as('wordsInTitle')) + .select('wordsInTitle') + .sort(field('wordsInTitle').ascending()) + .limit(3) + ); + expectResults( + snapshot, + { wordsInTitle: ['1984'] }, + { wordsInTitle: ['Crime', 'and', 'Punishment'] }, + { wordsInTitle: ['Dune'] } + ); + }); it('testRegexMatches', async () => { const snapshot = await execute( firestore diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 477d976eb4..8d363c00af 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -89,6 +89,8 @@ import { reverse, like, regexContains, + regexFind, + regexFindAll, regexMatch, stringContains, startsWith, @@ -2470,6 +2472,42 @@ describe.skipClassic('Firestore Pipelines', () => { expect(snapshot.results.length).to.equal(5); }); + it('testRegexFind', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(regexFind('title', '^\\w+').as('firstWordInTitle')) + .select('firstWordInTitle') + .sort(field('firstWordInTitle').ascending()) + .limit(3) + ); + expectResults( + snapshot, + { firstWordInTitle: '1984' }, + { firstWordInTitle: 'Crime' }, + { firstWordInTitle: 'Dune' } + ); + }); + + it('testRegexFindAll', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(regexFindAll('title', '\\w+').as('wordsInTitle')) + .select('wordsInTitle') + .sort(field('wordsInTitle').ascending()) + .limit(3) + ); + expectResults( + snapshot, + { wordsInTitle: ['1984'] }, + { wordsInTitle: ['Crime', 'and', 'Punishment'] }, + { wordsInTitle: ['Dune'] } + ); + }); + it('testRegexMatches', async () => { const snapshot = await execute( firestore From f9aaeca466f3650a1bd1f83d3ee32ceb105faf65 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Mon, 26 Jan 2026 12:59:12 -0500 Subject: [PATCH 045/174] test(firestore): Accept `grep` as an argument to `run_tests.ts` (#9452) --- packages/firestore/scripts/run-tests.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/firestore/scripts/run-tests.ts b/packages/firestore/scripts/run-tests.ts index bd72194464..d456385004 100644 --- a/packages/firestore/scripts/run-tests.ts +++ b/packages/firestore/scripts/run-tests.ts @@ -38,7 +38,11 @@ const argv = yargs }, databaseId: { type: 'string' - } + }, + grep: { + type: 'string', + description: 'Filter tests by name (regex)' + }, }) .parseSync(); @@ -75,6 +79,10 @@ if (argv.databaseId) { process.env.FIRESTORE_TARGET_DB_ID = argv.databaseId; } +if (argv.grep) { + args.push('--grep', argv.grep); +} + args = args.concat(argv._ as string[]); const childProcess = spawn(nyc, args, { From c4a3a5643b79a2165d8b38d35734053dcce8d224 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 27 Jan 2026 10:57:15 -0500 Subject: [PATCH 046/174] test(firestore): silence stack trace output from `run_tests.ts` (#9454) --- packages/firestore/scripts/run-tests.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/firestore/scripts/run-tests.ts b/packages/firestore/scripts/run-tests.ts index d456385004..74644bd93d 100644 --- a/packages/firestore/scripts/run-tests.ts +++ b/packages/firestore/scripts/run-tests.ts @@ -85,10 +85,25 @@ if (argv.grep) { args = args.concat(argv._ as string[]); -const childProcess = spawn(nyc, args, { +const spawnPromise = spawn(nyc, args, { stdio: 'inherit', cwd: process.cwd() -}).childProcess; +}); + +const childProcess = spawnPromise.childProcess; + +spawnPromise.catch(error => { + // When a test fails, there will be a non-zero error code. Simply exit this process, + // and don't print a stack trace. + if (typeof error.code === 'number') { + process.exit(error.code); + } else { + // The error code will not be a number for a real crash (e.g., spawn + // failed to start), so print the entire stack trace for debugging. + console.error(error); + process.exit(1); + } +}); process.once('exit', () => childProcess.kill()); process.once('SIGINT', () => childProcess.kill('SIGINT')); From 2e74329868f90e92ac8a32d131aa9dd9226ccb59 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 29 Jan 2026 11:22:11 -0800 Subject: [PATCH 047/174] feat(ai): implicit caching feature (#9462) --- .changeset/tender-items-pretend.md | 6 ++++++ common/api-review/ai.api.md | 2 ++ docs-devsite/ai.usagemetadata.md | 22 ++++++++++++++++++++++ packages/ai/src/types/responses.ts | 12 ++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 .changeset/tender-items-pretend.md diff --git a/.changeset/tender-items-pretend.md b/.changeset/tender-items-pretend.md new file mode 100644 index 0000000000..8eb25ba9ad --- /dev/null +++ b/.changeset/tender-items-pretend.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +Add params on `UsageMetadata` that provide cache-related usage data when the implicit caching feature is used. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 59b1c715d2..8214230fb4 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -1444,6 +1444,8 @@ export type URLRetrievalStatus = (typeof URLRetrievalStatus)[keyof typeof URLRet // @public export interface UsageMetadata { + cachedContentTokenCount?: number; + cacheTokensDetails?: ModalityTokenCount[]; // (undocumented) candidatesTokenCount: number; // (undocumented) diff --git a/docs-devsite/ai.usagemetadata.md b/docs-devsite/ai.usagemetadata.md index bf45610f4a..17a4b150f4 100644 --- a/docs-devsite/ai.usagemetadata.md +++ b/docs-devsite/ai.usagemetadata.md @@ -22,6 +22,8 @@ export interface UsageMetadata | Property | Type | Description | | --- | --- | --- | +| [cachedContentTokenCount](./ai.usagemetadata.md#usagemetadatacachedcontenttokencount) | number | The number of tokens in the prompt that were served from the cache. If implicit caching is not active or no content was cached, this will be 0. | +| [cacheTokensDetails](./ai.usagemetadata.md#usagemetadatacachetokensdetails) | [ModalityTokenCount](./ai.modalitytokencount.md#modalitytokencount_interface)\[\] | Detailed breakdown of the cached tokens by modality (for example, text or image). This list provides granular insight into which parts of the content were cached. | | [candidatesTokenCount](./ai.usagemetadata.md#usagemetadatacandidatestokencount) | number | | | [candidatesTokensDetails](./ai.usagemetadata.md#usagemetadatacandidatestokensdetails) | [ModalityTokenCount](./ai.modalitytokencount.md#modalitytokencount_interface)\[\] | | | [promptTokenCount](./ai.usagemetadata.md#usagemetadataprompttokencount) | number | | @@ -31,6 +33,26 @@ export interface UsageMetadata | [toolUsePromptTokensDetails](./ai.usagemetadata.md#usagemetadatatooluseprompttokensdetails) | [ModalityTokenCount](./ai.modalitytokencount.md#modalitytokencount_interface)\[\] | A list of tokens used by tools, broken down by modality. | | [totalTokenCount](./ai.usagemetadata.md#usagemetadatatotaltokencount) | number | | +## UsageMetadata.cachedContentTokenCount + +The number of tokens in the prompt that were served from the cache. If implicit caching is not active or no content was cached, this will be 0. + +Signature: + +```typescript +cachedContentTokenCount?: number; +``` + +## UsageMetadata.cacheTokensDetails + +Detailed breakdown of the cached tokens by modality (for example, text or image). This list provides granular insight into which parts of the content were cached. + +Signature: + +```typescript +cacheTokensDetails?: ModalityTokenCount[]; +``` + ## UsageMetadata.candidatesTokenCount Signature: diff --git a/packages/ai/src/types/responses.ts b/packages/ai/src/types/responses.ts index be56d0d2ba..6a8636e4c6 100644 --- a/packages/ai/src/types/responses.ts +++ b/packages/ai/src/types/responses.ts @@ -133,6 +133,18 @@ export interface UsageMetadata { * A list of tokens used by tools, broken down by modality. */ toolUsePromptTokensDetails?: ModalityTokenCount[]; + /** + * The number of tokens in the prompt that were served from the cache. + * If implicit caching is not active or no content was cached, + * this will be 0. + */ + cachedContentTokenCount?: number; + /** + * Detailed breakdown of the cached tokens by modality (for example, text or + * image). This list provides granular insight into which parts of + * the content were cached. + */ + cacheTokensDetails?: ModalityTokenCount[]; } /** From 65a553baf435be2463477ef9ddb114f26a2845ce Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Thu, 29 Jan 2026 14:33:23 -0500 Subject: [PATCH 048/174] fix(firestore): log a warning when `databaseId` is not found (#9472) --- .changeset/serious-files-argue.md | 5 +++++ .../src/platform/browser/webchannel_connection.ts | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 .changeset/serious-files-argue.md diff --git a/.changeset/serious-files-argue.md b/.changeset/serious-files-argue.md new file mode 100644 index 0000000000..64d63c683b --- /dev/null +++ b/.changeset/serious-files-argue.md @@ -0,0 +1,5 @@ +--- +'@firebase/firestore': patch +--- + +Log a warning when `databaseId` is not found. diff --git a/packages/firestore/src/platform/browser/webchannel_connection.ts b/packages/firestore/src/platform/browser/webchannel_connection.ts index b3fdd53340..250ed0e99c 100644 --- a/packages/firestore/src/platform/browser/webchannel_connection.ts +++ b/packages/firestore/src/platform/browser/webchannel_connection.ts @@ -408,6 +408,17 @@ export class WebChannelConnection extends RestConnection { const status: string = error.status; let code = mapCodeFromRpcStatus(status); let message = error.message; + if ( + status === 'NOT_FOUND' && + message.includes('database') && + message.includes('does not exist') && + message.includes(this.databaseId.database) + ) { + logWarn( + `Database '${this.databaseId.database}' not found. Please check your project configuration.` + ); + } + if (code === undefined) { code = Code.INTERNAL; message = From 691a506ecaa10ac3f0354313f5de5a47f4c85199 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 29 Jan 2026 11:59:51 -0800 Subject: [PATCH 049/174] feat(ai): Add tag to log requests made to cloud models while in hybrid mode (#9469) --- .changeset/nasty-squids-push.md | 5 +++++ packages/ai/src/api.ts | 10 +++++++++- packages/ai/src/constants.ts | 2 ++ packages/ai/src/requests/request.test.ts | 22 +++++++++++++++++++--- packages/ai/src/requests/request.ts | 18 +++++++++++++++--- packages/ai/src/types/internal.ts | 2 ++ 6 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 .changeset/nasty-squids-push.md diff --git a/.changeset/nasty-squids-push.md b/.changeset/nasty-squids-push.md new file mode 100644 index 0000000000..c613008d8d --- /dev/null +++ b/.changeset/nasty-squids-push.md @@ -0,0 +1,5 @@ +--- +'@firebase/ai': patch +--- + +Internal: Add tag to log requests made to cloud while in hybrid mode. diff --git a/packages/ai/src/api.ts b/packages/ai/src/api.ts index 29614d88ce..759d02c5b8 100644 --- a/packages/ai/src/api.ts +++ b/packages/ai/src/api.ts @@ -156,7 +156,15 @@ export function getGenerativeModel( hybridParams.onDeviceParams ); - return new GenerativeModel(ai, inCloudParams, requestOptions, chromeAdapter); + const generativeModel = new GenerativeModel( + ai, + inCloudParams, + requestOptions, + chromeAdapter + ); + + generativeModel._apiSettings.inferenceMode = hybridParams.mode; + return generativeModel; } /** diff --git a/packages/ai/src/constants.ts b/packages/ai/src/constants.ts index 82ea4c7a9f..f94a828eea 100644 --- a/packages/ai/src/constants.ts +++ b/packages/ai/src/constants.ts @@ -32,6 +32,8 @@ export const PACKAGE_VERSION = version; export const LANGUAGE_TAG = 'gl-js'; +export const HYBRID_TAG = 'hybrid'; + export const DEFAULT_FETCH_TIMEOUT_MS = 180 * 1000; /** diff --git a/packages/ai/src/requests/request.test.ts b/packages/ai/src/requests/request.test.ts index 29b5118390..dff71debaf 100644 --- a/packages/ai/src/requests/request.test.ts +++ b/packages/ai/src/requests/request.test.ts @@ -30,7 +30,7 @@ import { } from './request'; import { ApiSettings } from '../types/internal'; import { DEFAULT_API_VERSION } from '../constants'; -import { AIErrorCode } from '../types'; +import { AIErrorCode, InferenceMode } from '../types'; import { AIError } from '../errors'; import { getMockResponse } from '../../test-utils/mock-response'; import { VertexAIBackend } from '../backend'; @@ -139,10 +139,26 @@ describe('request methods', () => { stream: true, singleRequestOptions: undefined }); - it('adds client headers', async () => { + it('adds client headers (no hybrid)', async () => { const headers = await getHeaders(fakeUrl); expect(headers.get('x-goog-api-client')).to.match( - /gl-js\/[0-9\.]+ fire\/[0-9\.]+/ + /gl-js\/[0-9\.]+ fire\/[0-9\.]+$/ + ); + }); + it('adds client headers (if hybrid)', async () => { + const fakeUrlWithHybrid = new RequestURL({ + model: 'models/model-name', + task: Task.GENERATE_CONTENT, + apiSettings: { + ...fakeApiSettings, + inferenceMode: InferenceMode.PREFER_ON_DEVICE + }, + stream: true, + singleRequestOptions: undefined + }); + const headers = await getHeaders(fakeUrlWithHybrid); + expect(headers.get('x-goog-api-client')).to.match( + /gl-js\/[0-9\.]+ fire\/[0-9\.]+ hybrid$/ ); }); it('adds api key', async () => { diff --git a/packages/ai/src/requests/request.ts b/packages/ai/src/requests/request.ts index a66b36ac6a..516a28a993 100644 --- a/packages/ai/src/requests/request.ts +++ b/packages/ai/src/requests/request.ts @@ -21,11 +21,12 @@ import { ApiSettings } from '../types/internal'; import { DEFAULT_DOMAIN, DEFAULT_FETCH_TIMEOUT_MS, + HYBRID_TAG, LANGUAGE_TAG, PACKAGE_VERSION } from '../constants'; import { logger } from '../logger'; -import { BackendType } from '../public-types'; +import { BackendType, InferenceMode } from '../public-types'; export const TIMEOUT_EXPIRED_MESSAGE = 'Timeout has expired.'; export const ABORT_ERROR_NAME = 'AbortError'; @@ -137,17 +138,28 @@ export class WebSocketUrl { /** * Log language and "fire/version" to x-goog-api-client */ -function getClientHeaders(): string { +function getClientHeaders(url: RequestURL): string { const loggingTags = []; loggingTags.push(`${LANGUAGE_TAG}/${PACKAGE_VERSION}`); loggingTags.push(`fire/${PACKAGE_VERSION}`); + /** + * No call would be made if ONLY_ON_DEVICE. + * ONLY_IN_CLOUD does not indicate an intention to use hybrid. + */ + if ( + url.params.apiSettings.inferenceMode === InferenceMode.PREFER_ON_DEVICE || + url.params.apiSettings.inferenceMode === InferenceMode.PREFER_IN_CLOUD + ) { + // No version + loggingTags.push(HYBRID_TAG); + } return loggingTags.join(' '); } export async function getHeaders(url: RequestURL): Promise { const headers = new Headers(); headers.append('Content-Type', 'application/json'); - headers.append('x-goog-api-client', getClientHeaders()); + headers.append('x-goog-api-client', getClientHeaders(url)); headers.append('x-goog-api-key', url.params.apiSettings.apiKey); if (url.params.apiSettings.automaticDataCollectionEnabled) { headers.append('X-Firebase-Appid', url.params.apiSettings.appId); diff --git a/packages/ai/src/types/internal.ts b/packages/ai/src/types/internal.ts index a41ec5652d..1f56eff32f 100644 --- a/packages/ai/src/types/internal.ts +++ b/packages/ai/src/types/internal.ts @@ -18,6 +18,7 @@ import { AppCheckTokenResult } from '@firebase/app-check-interop-types'; import { FirebaseAuthTokenData } from '@firebase/auth-interop-types'; import { Backend } from '../backend'; +import { InferenceMode } from './enums'; export * from './imagen/internal'; @@ -33,4 +34,5 @@ export interface ApiSettings { backend: Backend; getAuthToken?: () => Promise; getAppCheckToken?: () => Promise; + inferenceMode?: InferenceMode; } From 8123231a1e7030400ac362e13d4cafb8d40f5d4c Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Thu, 29 Jan 2026 16:06:21 -0500 Subject: [PATCH 050/174] feat(ai) Live Service Going Away notifications (#9461) ### Discussion Support the handling of Going Away notifications in the Live Service. The service may send this event when the session is coming to a close due to timeout or nearing a token limit. ### Testing Unit tests added. Manual testing. ### API Changes See internal [API proposal](https://goto.google.com/fal-firebase-api-live-api-goaway-message). --- .changeset/long-monkeys-prove.md | 7 +++ common/api-review/ai.api.md | 10 +++- docs-devsite/_toc.yaml | 2 + docs-devsite/ai.liveservergoingawaynotice.md | 53 +++++++++++++++++ docs-devsite/ai.livesession.md | 4 +- docs-devsite/ai.md | 2 + packages/ai/integration/live.test.ts | 16 +++++- packages/ai/src/methods/live-session.test.ts | 60 +++++++++++++++++++- packages/ai/src/methods/live-session.ts | 29 +++++++++- packages/ai/src/types/responses.ts | 16 +++++- 10 files changed, 190 insertions(+), 9 deletions(-) create mode 100644 .changeset/long-monkeys-prove.md create mode 100644 docs-devsite/ai.liveservergoingawaynotice.md diff --git a/.changeset/long-monkeys-prove.md b/.changeset/long-monkeys-prove.md new file mode 100644 index 0000000000..03ee821351 --- /dev/null +++ b/.changeset/long-monkeys-prove.md @@ -0,0 +1,7 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +AI Logic: Extend the `LiveSession.receive()` return types to include a `LiveServiceGoingAwayNotice` +which signifies that the service will soon close the session. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 8214230fb4..61db3e04dd 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -990,6 +990,7 @@ export const LiveResponseType: { SERVER_CONTENT: string; TOOL_CALL: string; TOOL_CALL_CANCELLATION: string; + GOING_AWAY_NOTICE: string; }; // @beta @@ -1006,6 +1007,13 @@ export interface LiveServerContent { type: 'serverContent'; } +// @beta +export interface LiveServerGoingAwayNotice { + timeLeft: number; + // (undocumented) + type: 'goingAwayNotice'; +} + // @beta export interface LiveServerToolCall { functionCalls: FunctionCall[]; @@ -1027,7 +1035,7 @@ export class LiveSession { close(): Promise; inConversation: boolean; isClosed: boolean; - receive(): AsyncGenerator; + receive(): AsyncGenerator; send(request: string | Array, turnComplete?: boolean): Promise; sendAudioRealtime(blob: GenerativeContentBlob): Promise; sendFunctionResponses(functionResponses: FunctionResponse[]): Promise; diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index c7fe59434d..3523913cb9 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -146,6 +146,8 @@ toc: path: /docs/reference/js/ai.livemodelparams.md - title: LiveServerContent path: /docs/reference/js/ai.liveservercontent.md + - title: LiveServerGoingAwayNotice + path: /docs/reference/js/ai.liveservergoingawaynotice.md - title: LiveServerToolCall path: /docs/reference/js/ai.liveservertoolcall.md - title: LiveServerToolCallCancellation diff --git a/docs-devsite/ai.liveservergoingawaynotice.md b/docs-devsite/ai.liveservergoingawaynotice.md new file mode 100644 index 0000000000..2d3d3e1f5f --- /dev/null +++ b/docs-devsite/ai.liveservergoingawaynotice.md @@ -0,0 +1,53 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# LiveServerGoingAwayNotice interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Notification that the server will not be able to service the client soon. + +Signature: + +```typescript +export interface LiveServerGoingAwayNotice +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [timeLeft](./ai.liveservergoingawaynotice.md#liveservergoingawaynoticetimeleft) | number | (Public Preview) The remaining time (in seconds) before the connection will be terminated. | +| [type](./ai.liveservergoingawaynotice.md#liveservergoingawaynoticetype) | 'goingAwayNotice' | (Public Preview) | + +## LiveServerGoingAwayNotice.timeLeft + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The remaining time (in seconds) before the connection will be terminated. + +Signature: + +```typescript +timeLeft: number; +``` + +## LiveServerGoingAwayNotice.type + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +type: 'goingAwayNotice'; +``` diff --git a/docs-devsite/ai.livesession.md b/docs-devsite/ai.livesession.md index 2f05fbc924..eb760aed2a 100644 --- a/docs-devsite/ai.livesession.md +++ b/docs-devsite/ai.livesession.md @@ -98,11 +98,11 @@ Yields messages received from the server. This can only be used by one consumer Signature: ```typescript -receive(): AsyncGenerator; +receive(): AsyncGenerator; ``` Returns: -AsyncGenerator<[LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) \| [LiveServerToolCall](./ai.liveservertoolcall.md#liveservertoolcall_interface) \| [LiveServerToolCallCancellation](./ai.liveservertoolcallcancellation.md#liveservertoolcallcancellation_interface)> +AsyncGenerator<[LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) \| [LiveServerToolCall](./ai.liveservertoolcall.md#liveservertoolcall_interface) \| [LiveServerToolCallCancellation](./ai.liveservertoolcallcancellation.md#liveservertoolcallcancellation_interface) \| [LiveServerGoingAwayNotice](./ai.liveservergoingawaynotice.md#liveservergoingawaynotice_interface)> An `AsyncGenerator` that yields server messages as they arrive. diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index be3116ca2f..52198890be 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -115,6 +115,7 @@ The Firebase AI Web SDK. | [LiveGenerationConfig](./ai.livegenerationconfig.md#livegenerationconfig_interface) | (Public Preview) Configuration parameters used by [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) to control live content generation. | | [LiveModelParams](./ai.livemodelparams.md#livemodelparams_interface) | (Public Preview) Params passed to [getLiveGenerativeModel()](./ai.md#getlivegenerativemodel_f2099ac). | | [LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) | (Public Preview) An incremental content update from the model. | +| [LiveServerGoingAwayNotice](./ai.liveservergoingawaynotice.md#liveservergoingawaynotice_interface) | (Public Preview) Notification that the server will not be able to service the client soon. | | [LiveServerToolCall](./ai.liveservertoolcall.md#liveservertoolcall_interface) | (Public Preview) A request from the model for the client to execute one or more functions. | | [LiveServerToolCallCancellation](./ai.liveservertoolcallcancellation.md#liveservertoolcallcancellation_interface) | (Public Preview) Notification to cancel a previous function call triggered by [LiveServerToolCall](./ai.liveservertoolcall.md#liveservertoolcall_interface). | | [ModalityTokenCount](./ai.modalitytokencount.md#modalitytokencount_interface) | Represents token counting info for a single modality. | @@ -748,6 +749,7 @@ LiveResponseType: { SERVER_CONTENT: string; TOOL_CALL: string; TOOL_CALL_CANCELLATION: string; + GOING_AWAY_NOTICE: string; } ``` diff --git a/packages/ai/integration/live.test.ts b/packages/ai/integration/live.test.ts index f8237658ee..4a8f663abe 100644 --- a/packages/ai/integration/live.test.ts +++ b/packages/ai/integration/live.test.ts @@ -22,6 +22,7 @@ import { LiveServerContent, LiveServerToolCall, LiveServerToolCallCancellation, + LiveServerGoingAwayNotice, ResponseModality } from '../src'; import { liveTestConfigs } from './constants'; @@ -30,7 +31,10 @@ import { HELLO_AUDIO_PCM_BASE64 } from './sample-data/hello-audio'; // A helper function to consume the generator and collect text parts from one turn. async function nextTurnData( stream: AsyncGenerator< - LiveServerContent | LiveServerToolCall | LiveServerToolCallCancellation + | LiveServerContent + | LiveServerToolCall + | LiveServerToolCallCancellation + | LiveServerGoingAwayNotice > ): Promise<{ text: string; @@ -48,7 +52,8 @@ async function nextTurnData( const chunk = result.value as | LiveServerContent | LiveServerToolCall - | LiveServerToolCallCancellation; + | LiveServerToolCallCancellation + | LiveServerGoingAwayNotice; switch (chunk.type) { case 'serverContent': if (chunk.turnComplete) { @@ -81,6 +86,10 @@ async function nextTurnData( }); } break; + case 'goingAwayNotice': + // Ignore going away notices for now. It can take 15 minutes before the service + // generates one, which is much too long to test. + break; default: throw new Error(`Unexpected chunk type '${(chunk as any).type}'`); } @@ -323,7 +332,8 @@ describe('Live', function () { const chunk = result.value as | LiveServerContent | LiveServerToolCall - | LiveServerToolCallCancellation; + | LiveServerToolCallCancellation + | LiveServerGoingAwayNotice; if (chunk.type === 'serverContent') { if (chunk.turnComplete) { break; diff --git a/packages/ai/src/methods/live-session.test.ts b/packages/ai/src/methods/live-session.test.ts index 428e92ec77..c4ee675c67 100644 --- a/packages/ai/src/methods/live-session.test.ts +++ b/packages/ai/src/methods/live-session.test.ts @@ -23,6 +23,7 @@ import { FunctionResponse, LiveResponseType, LiveServerContent, + LiveServerGoingAwayNotice, LiveServerToolCall, LiveServerToolCallCancellation } from '../types'; @@ -238,6 +239,9 @@ describe('LiveSession', () => { mockHandler.simulateServerMessage({ toolCallCancellation: { functionIds: ['123'] } }); + mockHandler.simulateServerMessage({ + goAway: { timeLeft: '30s' } + }); mockHandler.simulateServerMessage({ serverContent: { turnComplete: true } }); @@ -245,7 +249,7 @@ describe('LiveSession', () => { mockHandler.endStream(); const responses = await receivePromise; - expect(responses).to.have.lengthOf(4); + expect(responses).to.have.lengthOf(5); expect(responses[0]).to.deep.equal({ type: LiveResponseType.SERVER_CONTENT, modelTurn: { parts: [{ text: 'response 1' }] } @@ -258,6 +262,60 @@ describe('LiveSession', () => { type: LiveResponseType.TOOL_CALL_CANCELLATION, functionIds: ['123'] } as LiveServerToolCallCancellation); + expect(responses[3]).to.deep.equal({ + type: LiveResponseType.GOING_AWAY_NOTICE, + timeLeft: 30 + } as LiveServerGoingAwayNotice); + expect(responses[4]).to.deep.equal({ + type: LiveResponseType.SERVER_CONTENT, + turnComplete: true + } as LiveServerContent); + }); + + it('should correctly parse high precision duration in LiveServerGoingAwayNotice', async () => { + const receivePromise = (async () => { + const responses = []; + for await (const response of session.receive()) { + responses.push(response); + } + return responses; + })(); + + mockHandler.simulateServerMessage({ + goAway: { timeLeft: '3.000000001s' } + }); + await new Promise(r => setTimeout(() => r(), 10)); + mockHandler.endStream(); + + const responses = await receivePromise; + expect(responses).to.have.lengthOf(1); + expect(responses[0]).to.deep.equal({ + type: LiveResponseType.GOING_AWAY_NOTICE, + timeLeft: 3.000000001 + } as LiveServerGoingAwayNotice); + }); + + it('should default timeLeft to 0 if format is invalid', async () => { + const receivePromise = (async () => { + const responses = []; + for await (const response of session.receive()) { + responses.push(response); + } + return responses; + })(); + + mockHandler.simulateServerMessage({ + goAway: { timeLeft: 'invalid' } + }); + await new Promise(r => setTimeout(() => r(), 10)); + mockHandler.endStream(); + + const responses = await receivePromise; + expect(responses).to.have.lengthOf(1); + expect(responses[0]).to.deep.equal({ + type: LiveResponseType.GOING_AWAY_NOTICE, + timeLeft: 0 + } as LiveServerGoingAwayNotice); }); it('should log a warning and skip messages that are not objects', async () => { diff --git a/packages/ai/src/methods/live-session.ts b/packages/ai/src/methods/live-session.ts index 1db5e3d4dd..3af5b67f03 100644 --- a/packages/ai/src/methods/live-session.ts +++ b/packages/ai/src/methods/live-session.ts @@ -21,6 +21,7 @@ import { GenerativeContentBlob, LiveResponseType, LiveServerContent, + LiveServerGoingAwayNotice, LiveServerToolCall, LiveServerToolCallCancellation, Part @@ -227,7 +228,10 @@ export class LiveSession { * @beta */ async *receive(): AsyncGenerator< - LiveServerContent | LiveServerToolCall | LiveServerToolCallCancellation + | LiveServerContent + | LiveServerToolCall + | LiveServerToolCallCancellation + | LiveServerGoingAwayNotice > { if (this.isClosed) { throw new AIError( @@ -261,6 +265,16 @@ export class LiveSession { } ).toolCallCancellation } as LiveServerToolCallCancellation; + } else if ('goAway' in message) { + const notice = ( + message as { + goAway: { timeLeft: string }; + } + ).goAway; + yield { + type: LiveResponseType.GOING_AWAY_NOTICE, + timeLeft: parseDuration(notice.timeLeft) + } as LiveServerGoingAwayNotice; } else { logger.warn( `Received an unknown message type from the server: ${JSON.stringify( @@ -360,3 +374,16 @@ export class LiveSession { } } } + +/** + * Parses a duration string (e.g. "3.000000001s") into a number of seconds. + * + * @param duration - The duration string to parse. + * @returns The duration in seconds. + */ +function parseDuration(duration: string | undefined): number { + if (!duration || !duration.endsWith('s')) { + return 0; + } + return Number(duration.slice(0, -1)); // slice removes the trailing 's'. +} diff --git a/packages/ai/src/types/responses.ts b/packages/ai/src/types/responses.ts index 6a8636e4c6..8b64045c83 100644 --- a/packages/ai/src/types/responses.ts +++ b/packages/ai/src/types/responses.ts @@ -616,6 +616,19 @@ export interface LiveServerToolCallCancellation { functionIds: string[]; } +/** + * Notification that the server will not be able to service the client soon. + * + * @beta + */ +export interface LiveServerGoingAwayNotice { + type: 'goingAwayNotice'; + /** + * The remaining time (in seconds) before the connection will be terminated. + */ + timeLeft: number; +} + /** * The types of responses that can be returned by {@link LiveSession.receive}. * @@ -624,7 +637,8 @@ export interface LiveServerToolCallCancellation { export const LiveResponseType = { SERVER_CONTENT: 'serverContent', TOOL_CALL: 'toolCall', - TOOL_CALL_CANCELLATION: 'toolCallCancellation' + TOOL_CALL_CANCELLATION: 'toolCallCancellation', + GOING_AWAY_NOTICE: 'goingAwayNotice' }; /** From f9254b6d28cc086a763d7fed42a59d6d2199aae8 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Fri, 30 Jan 2026 09:59:13 -0800 Subject: [PATCH 051/174] feat(ai): Remove preview tags from code execution and URL context features (#9475) --- .changeset/pink-brooms-compare.md | 6 +++ common/api-review/ai.api.md | 29 ++++++--------- docs-devsite/ai.codeexecutionresult.md | 13 +------ docs-devsite/ai.codeexecutionresultpart.md | 43 ++++------------------ docs-devsite/ai.executablecode.md | 13 +------ docs-devsite/ai.executablecodepart.md | 43 ++++------------------ docs-devsite/ai.md | 42 ++++++--------------- docs-devsite/ai.urlcontextmetadata.md | 8 +--- docs-devsite/ai.urlmetadata.md | 13 +------ packages/ai/src/types/content.ts | 8 ++-- packages/ai/src/types/enums.ts | 8 ++-- packages/ai/src/types/responses.ts | 8 ++-- 12 files changed, 65 insertions(+), 169 deletions(-) create mode 100644 .changeset/pink-brooms-compare.md diff --git a/.changeset/pink-brooms-compare.md b/.changeset/pink-brooms-compare.md new file mode 100644 index 0000000000..2ad388cd44 --- /dev/null +++ b/.changeset/pink-brooms-compare.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +Remove "preview" tags from code execution and URL context documentation. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 61db3e04dd..843bedc885 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -185,13 +185,13 @@ export interface CitationMetadata { citations: Citation[]; } -// @beta +// @public export interface CodeExecutionResult { outcome?: Outcome; output?: string; } -// @beta +// @public export interface CodeExecutionResultPart { // (undocumented) codeExecutionResult?: CodeExecutionResult; @@ -283,13 +283,13 @@ export interface ErrorDetails { reason?: string; } -// @beta +// @public export interface ExecutableCode { code?: string; language?: Language; } -// @beta +// @public export interface ExecutableCodePart { // (undocumented) codeExecutionResult?: never; @@ -461,8 +461,6 @@ export interface GenerateContentCandidate { index: number; // (undocumented) safetyRatings?: SafetyRating[]; - // Warning: (ae-incompatible-release-tags) The symbol "urlContextMetadata" is marked as @public, but its signature references "URLContextMetadata" which is marked as @beta - // // (undocumented) urlContextMetadata?: URLContextMetadata; } @@ -873,13 +871,13 @@ export class IntegerSchema extends Schema { constructor(schemaParams?: SchemaParams); } -// @beta +// @public export const Language: { UNSPECIFIED: string; PYTHON: string; }; -// @beta +// @public export type Language = (typeof Language)[keyof typeof Language]; // @beta @@ -1113,7 +1111,7 @@ export interface OnDeviceParams { promptOptions?: LanguageModelPromptOptions; } -// @beta +// @public export const Outcome: { UNSPECIFIED: string; OK: string; @@ -1121,12 +1119,9 @@ export const Outcome: { DEADLINE_EXCEEDED: string; }; -// @beta +// @public export type Outcome = (typeof Outcome)[keyof typeof Outcome]; -// Warning: (ae-incompatible-release-tags) The symbol "Part" is marked as @public, but its signature references "ExecutableCodePart" which is marked as @beta -// Warning: (ae-incompatible-release-tags) The symbol "Part" is marked as @public, but its signature references "CodeExecutionResultPart" which is marked as @beta -// // @public export type Part = TextPart | InlineDataPart | FunctionCallPart | FunctionResponsePart | FileDataPart | ExecutableCodePart | CodeExecutionResultPart; @@ -1422,7 +1417,7 @@ export type TypedSchema = IntegerSchema | NumberSchema | StringSchema | BooleanS export interface URLContext { } -// @beta +// @public export interface URLContextMetadata { urlMetadata: URLMetadata[]; } @@ -1432,13 +1427,13 @@ export interface URLContextTool { urlContext: URLContext; } -// @beta +// @public export interface URLMetadata { retrievedUrl?: string; urlRetrievalStatus?: URLRetrievalStatus; } -// @beta +// @public export const URLRetrievalStatus: { URL_RETRIEVAL_STATUS_UNSPECIFIED: string; URL_RETRIEVAL_STATUS_SUCCESS: string; @@ -1447,7 +1442,7 @@ export const URLRetrievalStatus: { URL_RETRIEVAL_STATUS_UNSAFE: string; }; -// @beta +// @public export type URLRetrievalStatus = (typeof URLRetrievalStatus)[keyof typeof URLRetrievalStatus]; // @public diff --git a/docs-devsite/ai.codeexecutionresult.md b/docs-devsite/ai.codeexecutionresult.md index d9d937ecad..d0be155c4e 100644 --- a/docs-devsite/ai.codeexecutionresult.md +++ b/docs-devsite/ai.codeexecutionresult.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # CodeExecutionResult interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The results of code execution run by the model. Signature: @@ -25,14 +22,11 @@ export interface CodeExecutionResult | Property | Type | Description | | --- | --- | --- | -| [outcome](./ai.codeexecutionresult.md#codeexecutionresultoutcome) | [Outcome](./ai.md#outcome) | (Public Preview) The result of the code execution. | -| [output](./ai.codeexecutionresult.md#codeexecutionresultoutput) | string | (Public Preview) The output from the code execution, or an error message if it failed. | +| [outcome](./ai.codeexecutionresult.md#codeexecutionresultoutcome) | [Outcome](./ai.md#outcome) | The result of the code execution. | +| [output](./ai.codeexecutionresult.md#codeexecutionresultoutput) | string | The output from the code execution, or an error message if it failed. | ## CodeExecutionResult.outcome -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The result of the code execution. Signature: @@ -43,9 +37,6 @@ outcome?: Outcome; ## CodeExecutionResult.output -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The output from the code execution, or an error message if it failed. Signature: diff --git a/docs-devsite/ai.codeexecutionresultpart.md b/docs-devsite/ai.codeexecutionresultpart.md index 19364c5a7b..6142a3ec79 100644 --- a/docs-devsite/ai.codeexecutionresultpart.md +++ b/docs-devsite/ai.codeexecutionresultpart.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # CodeExecutionResultPart interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents the code execution result from the model. Signature: @@ -25,20 +22,17 @@ export interface CodeExecutionResultPart | Property | Type | Description | | --- | --- | --- | -| [codeExecutionResult](./ai.codeexecutionresultpart.md#codeexecutionresultpartcodeexecutionresult) | [CodeExecutionResult](./ai.codeexecutionresult.md#codeexecutionresult_interface) | (Public Preview) | -| [executableCode](./ai.codeexecutionresultpart.md#codeexecutionresultpartexecutablecode) | never | (Public Preview) | -| [fileData](./ai.codeexecutionresultpart.md#codeexecutionresultpartfiledata) | never | (Public Preview) | -| [functionCall](./ai.codeexecutionresultpart.md#codeexecutionresultpartfunctioncall) | never | (Public Preview) | -| [functionResponse](./ai.codeexecutionresultpart.md#codeexecutionresultpartfunctionresponse) | never | (Public Preview) | -| [inlineData](./ai.codeexecutionresultpart.md#codeexecutionresultpartinlinedata) | never | (Public Preview) | -| [text](./ai.codeexecutionresultpart.md#codeexecutionresultparttext) | never | (Public Preview) | -| [thought](./ai.codeexecutionresultpart.md#codeexecutionresultpartthought) | never | (Public Preview) | +| [codeExecutionResult](./ai.codeexecutionresultpart.md#codeexecutionresultpartcodeexecutionresult) | [CodeExecutionResult](./ai.codeexecutionresult.md#codeexecutionresult_interface) | | +| [executableCode](./ai.codeexecutionresultpart.md#codeexecutionresultpartexecutablecode) | never | | +| [fileData](./ai.codeexecutionresultpart.md#codeexecutionresultpartfiledata) | never | | +| [functionCall](./ai.codeexecutionresultpart.md#codeexecutionresultpartfunctioncall) | never | | +| [functionResponse](./ai.codeexecutionresultpart.md#codeexecutionresultpartfunctionresponse) | never | | +| [inlineData](./ai.codeexecutionresultpart.md#codeexecutionresultpartinlinedata) | never | | +| [text](./ai.codeexecutionresultpart.md#codeexecutionresultparttext) | never | | +| [thought](./ai.codeexecutionresultpart.md#codeexecutionresultpartthought) | never | | ## CodeExecutionResultPart.codeExecutionResult -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -47,9 +41,6 @@ codeExecutionResult?: CodeExecutionResult; ## CodeExecutionResultPart.executableCode -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -58,9 +49,6 @@ executableCode?: never; ## CodeExecutionResultPart.fileData -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -69,9 +57,6 @@ fileData: never; ## CodeExecutionResultPart.functionCall -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -80,9 +65,6 @@ functionCall?: never; ## CodeExecutionResultPart.functionResponse -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -91,9 +73,6 @@ functionResponse?: never; ## CodeExecutionResultPart.inlineData -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -102,9 +81,6 @@ inlineData?: never; ## CodeExecutionResultPart.text -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -113,9 +89,6 @@ text?: never; ## CodeExecutionResultPart.thought -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/ai.executablecode.md b/docs-devsite/ai.executablecode.md index c2dfa09cd7..bab79bacc5 100644 --- a/docs-devsite/ai.executablecode.md +++ b/docs-devsite/ai.executablecode.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # ExecutableCode interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An interface for executable code returned by the model. Signature: @@ -25,14 +22,11 @@ export interface ExecutableCode | Property | Type | Description | | --- | --- | --- | -| [code](./ai.executablecode.md#executablecodecode) | string | (Public Preview) The source code to be executed. | -| [language](./ai.executablecode.md#executablecodelanguage) | [Language](./ai.md#language) | (Public Preview) The programming language of the code. | +| [code](./ai.executablecode.md#executablecodecode) | string | The source code to be executed. | +| [language](./ai.executablecode.md#executablecodelanguage) | [Language](./ai.md#language) | The programming language of the code. | ## ExecutableCode.code -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The source code to be executed. Signature: @@ -43,9 +37,6 @@ code?: string; ## ExecutableCode.language -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The programming language of the code. Signature: diff --git a/docs-devsite/ai.executablecodepart.md b/docs-devsite/ai.executablecodepart.md index cac32c132e..99c6bf0598 100644 --- a/docs-devsite/ai.executablecodepart.md +++ b/docs-devsite/ai.executablecodepart.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # ExecutableCodePart interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents the code that is executed by the model. Signature: @@ -25,20 +22,17 @@ export interface ExecutableCodePart | Property | Type | Description | | --- | --- | --- | -| [codeExecutionResult](./ai.executablecodepart.md#executablecodepartcodeexecutionresult) | never | (Public Preview) | -| [executableCode](./ai.executablecodepart.md#executablecodepartexecutablecode) | [ExecutableCode](./ai.executablecode.md#executablecode_interface) | (Public Preview) | -| [fileData](./ai.executablecodepart.md#executablecodepartfiledata) | never | (Public Preview) | -| [functionCall](./ai.executablecodepart.md#executablecodepartfunctioncall) | never | (Public Preview) | -| [functionResponse](./ai.executablecodepart.md#executablecodepartfunctionresponse) | never | (Public Preview) | -| [inlineData](./ai.executablecodepart.md#executablecodepartinlinedata) | never | (Public Preview) | -| [text](./ai.executablecodepart.md#executablecodeparttext) | never | (Public Preview) | -| [thought](./ai.executablecodepart.md#executablecodepartthought) | never | (Public Preview) | +| [codeExecutionResult](./ai.executablecodepart.md#executablecodepartcodeexecutionresult) | never | | +| [executableCode](./ai.executablecodepart.md#executablecodepartexecutablecode) | [ExecutableCode](./ai.executablecode.md#executablecode_interface) | | +| [fileData](./ai.executablecodepart.md#executablecodepartfiledata) | never | | +| [functionCall](./ai.executablecodepart.md#executablecodepartfunctioncall) | never | | +| [functionResponse](./ai.executablecodepart.md#executablecodepartfunctionresponse) | never | | +| [inlineData](./ai.executablecodepart.md#executablecodepartinlinedata) | never | | +| [text](./ai.executablecodepart.md#executablecodeparttext) | never | | +| [thought](./ai.executablecodepart.md#executablecodepartthought) | never | | ## ExecutableCodePart.codeExecutionResult -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -47,9 +41,6 @@ codeExecutionResult?: never; ## ExecutableCodePart.executableCode -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -58,9 +49,6 @@ executableCode?: ExecutableCode; ## ExecutableCodePart.fileData -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -69,9 +57,6 @@ fileData: never; ## ExecutableCodePart.functionCall -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -80,9 +65,6 @@ functionCall?: never; ## ExecutableCodePart.functionResponse -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -91,9 +73,6 @@ functionResponse?: never; ## ExecutableCodePart.inlineData -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -102,9 +81,6 @@ inlineData?: never; ## ExecutableCodePart.text -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -113,9 +89,6 @@ text?: never; ## ExecutableCodePart.thought -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index 52198890be..ea796aab13 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -65,8 +65,8 @@ The Firebase AI Web SDK. | [ChromeAdapter](./ai.chromeadapter.md#chromeadapter_interface) | (Public Preview) Defines an inference "backend" that uses Chrome's on-device model, and encapsulates logic for detecting when on-device inference is possible.These methods should not be called directly by the user. | | [Citation](./ai.citation.md#citation_interface) | A single citation. | | [CitationMetadata](./ai.citationmetadata.md#citationmetadata_interface) | Citation metadata that may be found on a [GenerateContentCandidate](./ai.generatecontentcandidate.md#generatecontentcandidate_interface). | -| [CodeExecutionResult](./ai.codeexecutionresult.md#codeexecutionresult_interface) | (Public Preview) The results of code execution run by the model. | -| [CodeExecutionResultPart](./ai.codeexecutionresultpart.md#codeexecutionresultpart_interface) | (Public Preview) Represents the code execution result from the model. | +| [CodeExecutionResult](./ai.codeexecutionresult.md#codeexecutionresult_interface) | The results of code execution run by the model. | +| [CodeExecutionResultPart](./ai.codeexecutionresultpart.md#codeexecutionresultpart_interface) | Represents the code execution result from the model. | | [CodeExecutionTool](./ai.codeexecutiontool.md#codeexecutiontool_interface) | (Public Preview) A tool that enables the model to use code execution. | | [Content](./ai.content.md#content_interface) | Content type for both prompts and response candidates. | | [CountTokensRequest](./ai.counttokensrequest.md#counttokensrequest_interface) | Params for calling [GenerativeModel.countTokens()](./ai.generativemodel.md#generativemodelcounttokens) | @@ -75,8 +75,8 @@ The Firebase AI Web SDK. | [Date\_2](./ai.date_2.md#date_2_interface) | Protobuf google.type.Date | | [EnhancedGenerateContentResponse](./ai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponse_interface) | Response object wrapped with helper methods. | | [ErrorDetails](./ai.errordetails.md#errordetails_interface) | Details object that may be included in an error response. | -| [ExecutableCode](./ai.executablecode.md#executablecode_interface) | (Public Preview) An interface for executable code returned by the model. | -| [ExecutableCodePart](./ai.executablecodepart.md#executablecodepart_interface) | (Public Preview) Represents the code that is executed by the model. | +| [ExecutableCode](./ai.executablecode.md#executablecode_interface) | An interface for executable code returned by the model. | +| [ExecutableCodePart](./ai.executablecodepart.md#executablecodepart_interface) | Represents the code that is executed by the model. | | [FileData](./ai.filedata.md#filedata_interface) | Data pointing to a file uploaded on Google Cloud Storage. | | [FileDataPart](./ai.filedatapart.md#filedatapart_interface) | Content part interface if the part represents [FileData](./ai.filedata.md#filedata_interface) | | [FunctionCall](./ai.functioncall.md#functioncall_interface) | A predicted [FunctionCall](./ai.functioncall.md#functioncall_interface) returned from the model that contains a string representing the [FunctionDeclaration.name](./ai.functiondeclaration.md#functiondeclarationname) and a structured JSON object containing the parameters and their values. | @@ -143,9 +143,9 @@ The Firebase AI Web SDK. | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. | | [Transcription](./ai.transcription.md#transcription_interface) | (Public Preview) Transcription of audio. This can be returned from a [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) if transcription is enabled with the inputAudioTranscription or outputAudioTranscription properties on the [LiveGenerationConfig](./ai.livegenerationconfig.md#livegenerationconfig_interface). | | [URLContext](./ai.urlcontext.md#urlcontext_interface) | (Public Preview) Specifies the URL Context configuration. | -| [URLContextMetadata](./ai.urlcontextmetadata.md#urlcontextmetadata_interface) | (Public Preview) Metadata related to [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface). | +| [URLContextMetadata](./ai.urlcontextmetadata.md#urlcontextmetadata_interface) | Metadata related to [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface). | | [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface) | (Public Preview) A tool that allows you to provide additional context to the models in the form of public web URLs. By including URLs in your request, the Gemini model will access the content from those pages to inform and enhance its response. | -| [URLMetadata](./ai.urlmetadata.md#urlmetadata_interface) | (Public Preview) Metadata for a single URL retrieved by the [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface) tool. | +| [URLMetadata](./ai.urlmetadata.md#urlmetadata_interface) | Metadata for a single URL retrieved by the [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface) tool. | | [UsageMetadata](./ai.usagemetadata.md#usagemetadata_interface) | Usage metadata about a [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | | [VideoMetadata](./ai.videometadata.md#videometadata_interface) | Describes the input video content. | | [VoiceConfig](./ai.voiceconfig.md#voiceconfig_interface) | (Public Preview) Configuration for the voice to used in speech synthesis. | @@ -171,15 +171,15 @@ The Firebase AI Web SDK. | [ImagenSafetyFilterLevel](./ai.md#imagensafetyfilterlevel) | A filter level controlling how aggressively to filter sensitive content.Text prompts provided as inputs and images (generated or uploaded) through Imagen on Vertex AI are assessed against a list of safety filters, which include 'harmful categories' (for example, violence, sexual, derogatory, and toxic). This filter level controls how aggressively to filter out potentially harmful content from responses. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) and the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters) for more details. | | [InferenceMode](./ai.md#inferencemode) | (Public Preview) Determines whether inference happens on-device or in-cloud. | | [InferenceSource](./ai.md#inferencesource) | (Public Preview) Indicates whether inference happened on-device or in-cloud. | -| [Language](./ai.md#language) | (Public Preview) The programming language of the code. | +| [Language](./ai.md#language) | The programming language of the code. | | [LiveResponseType](./ai.md#liveresponsetype) | (Public Preview) The types of responses that can be returned by [LiveSession.receive()](./ai.livesession.md#livesessionreceive). | | [Modality](./ai.md#modality) | Content part modality. | -| [Outcome](./ai.md#outcome) | (Public Preview) Represents the result of the code execution. | +| [Outcome](./ai.md#outcome) | Represents the result of the code execution. | | [POSSIBLE\_ROLES](./ai.md#possible_roles) | Possible roles. | | [ResponseModality](./ai.md#responsemodality) | (Public Preview) Generation modalities to be returned in generation responses. | | [SchemaType](./ai.md#schematype) | Contains the list of OpenAPI data types as defined by the [OpenAPI specification](https://swagger.io/docs/specification/data-models/data-types/) | | [ThinkingLevel](./ai.md#thinkinglevel) | A preset that controls the model's "thinking" process. Use ThinkingLevel.LOW for faster responses on less complex tasks, and ThinkingLevel.HIGH for better reasoning on more complex tasks. | -| [URLRetrievalStatus](./ai.md#urlretrievalstatus) | (Public Preview) The status of a URL retrieval. | +| [URLRetrievalStatus](./ai.md#urlretrievalstatus) | The status of a URL retrieval. | ## Type Aliases @@ -200,13 +200,13 @@ The Firebase AI Web SDK. | [ImagenSafetyFilterLevel](./ai.md#imagensafetyfilterlevel) | A filter level controlling how aggressively to filter sensitive content.Text prompts provided as inputs and images (generated or uploaded) through Imagen on Vertex AI are assessed against a list of safety filters, which include 'harmful categories' (for example, violence, sexual, derogatory, and toxic). This filter level controls how aggressively to filter out potentially harmful content from responses. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) and the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters) for more details. | | [InferenceMode](./ai.md#inferencemode) | (Public Preview) Determines whether inference happens on-device or in-cloud. | | [InferenceSource](./ai.md#inferencesource) | (Public Preview) Indicates whether inference happened on-device or in-cloud. | -| [Language](./ai.md#language) | (Public Preview) The programming language of the code. | +| [Language](./ai.md#language) | The programming language of the code. | | [LanguageModelMessageContentValue](./ai.md#languagemodelmessagecontentvalue) | (Public Preview) Content formats that can be provided as on-device message content. | | [LanguageModelMessageRole](./ai.md#languagemodelmessagerole) | (Public Preview) Allowable roles for on-device language model usage. | | [LanguageModelMessageType](./ai.md#languagemodelmessagetype) | (Public Preview) Allowable types for on-device language model messages. | | [LiveResponseType](./ai.md#liveresponsetype) | (Public Preview) The types of responses that can be returned by [LiveSession.receive()](./ai.livesession.md#livesessionreceive). This is a property on all messages that can be used for type narrowing. This property is not returned by the server, it is assigned to a server message object once it's parsed. | | [Modality](./ai.md#modality) | Content part modality. | -| [Outcome](./ai.md#outcome) | (Public Preview) Represents the result of the code execution. | +| [Outcome](./ai.md#outcome) | Represents the result of the code execution. | | [Part](./ai.md#part) | Content part - includes text, image/video, or function call/response part types. | | [ResponseModality](./ai.md#responsemodality) | (Public Preview) Generation modalities to be returned in generation responses. | | [Role](./ai.md#role) | Role is the producer of the content. | @@ -214,7 +214,7 @@ The Firebase AI Web SDK. | [ThinkingLevel](./ai.md#thinkinglevel) | A preset that controls the model's "thinking" process. Use ThinkingLevel.LOW for faster responses on less complex tasks, and ThinkingLevel.HIGH for better reasoning on more complex tasks. | | [Tool](./ai.md#tool) | Defines a tool that model can call to access external knowledge. | | [TypedSchema](./ai.md#typedschema) | A type that includes all specific Schema types. | -| [URLRetrievalStatus](./ai.md#urlretrievalstatus) | (Public Preview) The status of a URL retrieval. | +| [URLRetrievalStatus](./ai.md#urlretrievalstatus) | The status of a URL retrieval. | ## function(app, ...) @@ -721,9 +721,6 @@ InferenceSource: { ## Language -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The programming language of the code. Signature: @@ -772,9 +769,6 @@ Modality: { ## Outcome -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents the result of the code execution. Signature: @@ -849,9 +843,6 @@ ThinkingLevel: { ## URLRetrievalStatus -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The status of a URL retrieval. URL\_RETRIEVAL\_STATUS\_UNSPECIFIED: Unspecified retrieval status.
    URL\_RETRIEVAL\_STATUS\_SUCCESS: The URL retrieval was successful.
    URL\_RETRIEVAL\_STATUS\_ERROR: The URL retrieval failed.
    URL\_RETRIEVAL\_STATUS\_PAYWALL: The URL retrieval failed because the content is behind a paywall.
    URL\_RETRIEVAL\_STATUS\_UNSAFE: The URL retrieval failed because the content is unsafe.
    @@ -1033,9 +1024,6 @@ export type InferenceSource = (typeof InferenceSource)[keyof typeof InferenceSou ## Language -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The programming language of the code. Signature: @@ -1108,9 +1096,6 @@ export type Modality = (typeof Modality)[keyof typeof Modality]; ## Outcome -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents the result of the code execution. Signature: @@ -1194,9 +1179,6 @@ export type TypedSchema = IntegerSchema | NumberSchema | StringSchema | BooleanS ## URLRetrievalStatus -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The status of a URL retrieval. URL\_RETRIEVAL\_STATUS\_UNSPECIFIED: Unspecified retrieval status.
    URL\_RETRIEVAL\_STATUS\_SUCCESS: The URL retrieval was successful.
    URL\_RETRIEVAL\_STATUS\_ERROR: The URL retrieval failed.
    URL\_RETRIEVAL\_STATUS\_PAYWALL: The URL retrieval failed because the content is behind a paywall.
    URL\_RETRIEVAL\_STATUS\_UNSAFE: The URL retrieval failed because the content is unsafe.
    diff --git a/docs-devsite/ai.urlcontextmetadata.md b/docs-devsite/ai.urlcontextmetadata.md index bc260b997a..dcbf34103e 100644 --- a/docs-devsite/ai.urlcontextmetadata.md +++ b/docs-devsite/ai.urlcontextmetadata.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # URLContextMetadata interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Metadata related to [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface). Signature: @@ -25,13 +22,10 @@ export interface URLContextMetadata | Property | Type | Description | | --- | --- | --- | -| [urlMetadata](./ai.urlcontextmetadata.md#urlcontextmetadataurlmetadata) | [URLMetadata](./ai.urlmetadata.md#urlmetadata_interface)\[\] | (Public Preview) List of URL metadata used to provide context to the Gemini model. | +| [urlMetadata](./ai.urlcontextmetadata.md#urlcontextmetadataurlmetadata) | [URLMetadata](./ai.urlmetadata.md#urlmetadata_interface)\[\] | List of URL metadata used to provide context to the Gemini model. | ## URLContextMetadata.urlMetadata -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - List of URL metadata used to provide context to the Gemini model. Signature: diff --git a/docs-devsite/ai.urlmetadata.md b/docs-devsite/ai.urlmetadata.md index 3cbd27632d..c60a32db83 100644 --- a/docs-devsite/ai.urlmetadata.md +++ b/docs-devsite/ai.urlmetadata.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # URLMetadata interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Metadata for a single URL retrieved by the [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface) tool. Signature: @@ -25,14 +22,11 @@ export interface URLMetadata | Property | Type | Description | | --- | --- | --- | -| [retrievedUrl](./ai.urlmetadata.md#urlmetadataretrievedurl) | string | (Public Preview) The retrieved URL. | -| [urlRetrievalStatus](./ai.urlmetadata.md#urlmetadataurlretrievalstatus) | [URLRetrievalStatus](./ai.md#urlretrievalstatus) | (Public Preview) The status of the URL retrieval. | +| [retrievedUrl](./ai.urlmetadata.md#urlmetadataretrievedurl) | string | The retrieved URL. | +| [urlRetrievalStatus](./ai.urlmetadata.md#urlmetadataurlretrievalstatus) | [URLRetrievalStatus](./ai.md#urlretrievalstatus) | The status of the URL retrieval. | ## URLMetadata.retrievedUrl -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The retrieved URL. Signature: @@ -43,9 +37,6 @@ retrievedUrl?: string; ## URLMetadata.urlRetrievalStatus -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The status of the URL retrieval. Signature: diff --git a/packages/ai/src/types/content.ts b/packages/ai/src/types/content.ts index 401a8cfb1a..b51dcd9c69 100644 --- a/packages/ai/src/types/content.ts +++ b/packages/ai/src/types/content.ts @@ -155,7 +155,7 @@ export interface FileDataPart { /** * Represents the code that is executed by the model. * - * @beta + * @public */ export interface ExecutableCodePart { text?: never; @@ -175,7 +175,7 @@ export interface ExecutableCodePart { /** * Represents the code execution result from the model. * - * @beta + * @public */ export interface CodeExecutionResultPart { text?: never; @@ -195,7 +195,7 @@ export interface CodeExecutionResultPart { /** * An interface for executable code returned by the model. * - * @beta + * @public */ export interface ExecutableCode { /** @@ -211,7 +211,7 @@ export interface ExecutableCode { /** * The results of code execution run by the model. * - * @beta + * @public */ export interface CodeExecutionResult { /** diff --git a/packages/ai/src/types/enums.ts b/packages/ai/src/types/enums.ts index 4e4a45805d..30b10138af 100644 --- a/packages/ai/src/types/enums.ts +++ b/packages/ai/src/types/enums.ts @@ -400,7 +400,7 @@ export type InferenceSource = /** * Represents the result of the code execution. * - * @beta + * @public */ export const Outcome = { UNSPECIFIED: 'OUTCOME_UNSPECIFIED', @@ -412,14 +412,14 @@ export const Outcome = { /** * Represents the result of the code execution. * - * @beta + * @public */ export type Outcome = (typeof Outcome)[keyof typeof Outcome]; /** * The programming language of the code. * - * @beta + * @public */ export const Language = { UNSPECIFIED: 'LANGUAGE_UNSPECIFIED', @@ -429,7 +429,7 @@ export const Language = { /** * The programming language of the code. * - * @beta + * @public */ export type Language = (typeof Language)[keyof typeof Language]; diff --git a/packages/ai/src/types/responses.ts b/packages/ai/src/types/responses.ts index 8b64045c83..0f9a86e103 100644 --- a/packages/ai/src/types/responses.ts +++ b/packages/ai/src/types/responses.ts @@ -380,7 +380,7 @@ export interface Segment { /** * Metadata related to {@link URLContextTool}. * - * @beta + * @public */ export interface URLContextMetadata { /** @@ -392,7 +392,7 @@ export interface URLContextMetadata { /** * Metadata for a single URL retrieved by the {@link URLContextTool} tool. * - * @beta + * @public */ export interface URLMetadata { /** @@ -420,7 +420,7 @@ export interface URLMetadata { * URL_RETRIEVAL_STATUS_UNSAFE: The URL retrieval failed because the content is unsafe. *
    * - * @beta + * @public */ export const URLRetrievalStatus = { /** @@ -460,7 +460,7 @@ export const URLRetrievalStatus = { * URL_RETRIEVAL_STATUS_UNSAFE: The URL retrieval failed because the content is unsafe. *
    * - * @beta + * @public */ export type URLRetrievalStatus = (typeof URLRetrievalStatus)[keyof typeof URLRetrievalStatus]; From b10a296fa1316cd8c82e33b38e1fb66d7bdcbbc6 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 3 Feb 2026 13:42:41 -0500 Subject: [PATCH 052/174] chore: update browserslist DB version (#9478) There's a warning that is being logged because this is over 6 months out of date. Updating the version makes the log go away :) See: https://github.com/browserslist/update-db?tab=readme-ov-file#readme --- package.json | 2 +- yarn.lock | 37 ++++++------------------------------- 2 files changed, 7 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index 49fe50d236..6f6010356e 100644 --- a/package.json +++ b/package.json @@ -141,8 +141,8 @@ "playwright": "1.51.1", "postinstall-postinstall": "2.1.0", "prettier": "2.8.8", - "protractor": "5.4.2", "protobufjs-cli": "^1.1.3", + "protractor": "5.4.2", "request": "2.88.2", "semver": "7.7.1", "simple-git": "3.27.0", diff --git a/yarn.lock b/yarn.lock index caa33e3d21..be3f532cdc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5071,9 +5071,9 @@ camelcase@^6.0.0, camelcase@^6.2.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001688: - version "1.0.30001731" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz" - integrity sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg== + version "1.0.30001766" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz" + integrity sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA== caseless@~0.12.0: version "0.12.0" @@ -15351,7 +15351,7 @@ string-argv@~0.3.1: resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -15369,15 +15369,6 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -15441,7 +15432,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -15462,13 +15453,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -17153,7 +17137,7 @@ workerpool@6.2.0: resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -17187,15 +17171,6 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 6f540dd720217a920fdae6e9b8e592f1c6e267e1 Mon Sep 17 00:00:00 2001 From: Google Open Source Bot Date: Thu, 5 Feb 2026 06:11:41 -0800 Subject: [PATCH 053/174] Version Packages (#9481) Release v12.9.0 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/long-monkeys-prove.md | 7 ------- .changeset/nasty-squids-push.md | 5 ----- .changeset/pink-brooms-compare.md | 6 ------ .changeset/serious-files-argue.md | 5 ----- .changeset/tender-items-pretend.md | 6 ------ .changeset/violet-kangaroos-talk.md | 6 ------ integration/compat-interop/package.json | 4 ++-- integration/firestore/package.json | 4 ++-- integration/messaging/package.json | 2 +- packages/ai/CHANGELOG.md | 15 +++++++++++++++ packages/ai/package.json | 4 ++-- packages/analytics-compat/package.json | 2 +- packages/analytics/package.json | 2 +- packages/app-check-compat/package.json | 2 +- packages/app-check/package.json | 2 +- packages/app-compat/CHANGELOG.md | 7 +++++++ packages/app-compat/package.json | 4 ++-- packages/app/CHANGELOG.md | 6 ++++++ packages/app/package.json | 2 +- packages/auth-compat/package.json | 2 +- packages/auth/package.json | 2 +- packages/data-connect/package.json | 2 +- packages/database-compat/package.json | 2 +- packages/database/package.json | 2 +- packages/firebase/CHANGELOG.md | 22 ++++++++++++++++++++++ packages/firebase/package.json | 12 ++++++------ packages/firestore-compat/CHANGELOG.md | 7 +++++++ packages/firestore-compat/package.json | 6 +++--- packages/firestore/CHANGELOG.md | 10 ++++++++++ packages/firestore/package.json | 6 +++--- packages/functions-compat/package.json | 2 +- packages/functions/package.json | 2 +- packages/installations-compat/package.json | 2 +- packages/installations/package.json | 2 +- packages/messaging-compat/package.json | 2 +- packages/messaging/package.json | 2 +- packages/performance-compat/package.json | 2 +- packages/performance/package.json | 2 +- packages/remote-config-compat/package.json | 2 +- packages/remote-config/package.json | 2 +- packages/storage-compat/package.json | 2 +- packages/storage/package.json | 2 +- packages/template/package.json | 2 +- repo-scripts/size-analysis/package.json | 2 +- 44 files changed, 112 insertions(+), 80 deletions(-) delete mode 100644 .changeset/long-monkeys-prove.md delete mode 100644 .changeset/nasty-squids-push.md delete mode 100644 .changeset/pink-brooms-compare.md delete mode 100644 .changeset/serious-files-argue.md delete mode 100644 .changeset/tender-items-pretend.md delete mode 100644 .changeset/violet-kangaroos-talk.md diff --git a/.changeset/long-monkeys-prove.md b/.changeset/long-monkeys-prove.md deleted file mode 100644 index 03ee821351..0000000000 --- a/.changeset/long-monkeys-prove.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -AI Logic: Extend the `LiveSession.receive()` return types to include a `LiveServiceGoingAwayNotice` -which signifies that the service will soon close the session. diff --git a/.changeset/nasty-squids-push.md b/.changeset/nasty-squids-push.md deleted file mode 100644 index c613008d8d..0000000000 --- a/.changeset/nasty-squids-push.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/ai': patch ---- - -Internal: Add tag to log requests made to cloud while in hybrid mode. diff --git a/.changeset/pink-brooms-compare.md b/.changeset/pink-brooms-compare.md deleted file mode 100644 index 2ad388cd44..0000000000 --- a/.changeset/pink-brooms-compare.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -Remove "preview" tags from code execution and URL context documentation. diff --git a/.changeset/serious-files-argue.md b/.changeset/serious-files-argue.md deleted file mode 100644 index 64d63c683b..0000000000 --- a/.changeset/serious-files-argue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/firestore': patch ---- - -Log a warning when `databaseId` is not found. diff --git a/.changeset/tender-items-pretend.md b/.changeset/tender-items-pretend.md deleted file mode 100644 index 8eb25ba9ad..0000000000 --- a/.changeset/tender-items-pretend.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -Add params on `UsageMetadata` that provide cache-related usage data when the implicit caching feature is used. diff --git a/.changeset/violet-kangaroos-talk.md b/.changeset/violet-kangaroos-talk.md deleted file mode 100644 index d76e0288f7..0000000000 --- a/.changeset/violet-kangaroos-talk.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/firestore': minor ---- - -Add support for `regexFind` and `regexFindAll` Pipeline expressions. diff --git a/integration/compat-interop/package.json b/integration/compat-interop/package.json index 70530c4216..ec184dc36b 100644 --- a/integration/compat-interop/package.json +++ b/integration/compat-interop/package.json @@ -8,8 +8,8 @@ "test:debug": "karma start --browsers Chrome --auto-watch" }, "dependencies": { - "@firebase/app": "0.14.7", - "@firebase/app-compat": "0.5.7", + "@firebase/app": "0.14.8", + "@firebase/app-compat": "0.5.8", "@firebase/analytics": "0.10.19", "@firebase/analytics-compat": "0.2.25", "@firebase/auth": "1.12.0", diff --git a/integration/firestore/package.json b/integration/firestore/package.json index a524cb0fed..12a872f550 100644 --- a/integration/firestore/package.json +++ b/integration/firestore/package.json @@ -15,8 +15,8 @@ "test:memory:debug": "yarn build:memory; karma start --auto-watch --browsers Chrome" }, "dependencies": { - "@firebase/app": "0.14.7", - "@firebase/firestore": "4.10.0" + "@firebase/app": "0.14.8", + "@firebase/firestore": "4.11.0" }, "devDependencies": { "@types/mocha": "9.1.1", diff --git a/integration/messaging/package.json b/integration/messaging/package.json index ff608365f3..0ad87e6cff 100644 --- a/integration/messaging/package.json +++ b/integration/messaging/package.json @@ -9,7 +9,7 @@ "test:manual": "mocha --exit" }, "devDependencies": { - "firebase": "12.8.0", + "firebase": "12.9.0", "chai": "4.5.0", "chromedriver": "119.0.1", "express": "4.21.2", diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index f908524101..6482ee77f9 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,5 +1,20 @@ # @firebase/ai +## 2.8.0 + +### Minor Changes + +- [`8123231`](https://github.com/firebase/firebase-js-sdk/commit/8123231a1e7030400ac362e13d4cafb8d40f5d4c) [#9461](https://github.com/firebase/firebase-js-sdk/pull/9461) - AI Logic: Extend the `LiveSession.receive()` return types to include a `LiveServiceGoingAwayNotice` + which signifies that the service will soon close the session. + +- [`f9254b6`](https://github.com/firebase/firebase-js-sdk/commit/f9254b6d28cc086a763d7fed42a59d6d2199aae8) [#9475](https://github.com/firebase/firebase-js-sdk/pull/9475) - Remove "preview" tags from code execution and URL context documentation. + +- [`2e74329`](https://github.com/firebase/firebase-js-sdk/commit/2e74329868f90e92ac8a32d131aa9dd9226ccb59) [#9462](https://github.com/firebase/firebase-js-sdk/pull/9462) - Add params on `UsageMetadata` that provide cache-related usage data when the implicit caching feature is used. + +### Patch Changes + +- [`691a506`](https://github.com/firebase/firebase-js-sdk/commit/691a506ecaa10ac3f0354313f5de5a47f4c85199) [#9469](https://github.com/firebase/firebase-js-sdk/pull/9469) - Internal: Add tag to log requests made to cloud while in hybrid mode. + ## 2.7.0 ### Minor Changes diff --git a/packages/ai/package.json b/packages/ai/package.json index 7cf1d2bbf8..31be2be09b 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/ai", - "version": "2.7.0", + "version": "2.8.0", "description": "The Firebase AI SDK", "author": "Firebase (https://firebase.google.com/)", "engines": { @@ -60,7 +60,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/analytics-compat/package.json b/packages/analytics-compat/package.json index bf44c4299e..e06390a870 100644 --- a/packages/analytics-compat/package.json +++ b/packages/analytics-compat/package.json @@ -22,7 +22,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.7", + "@firebase/app-compat": "0.5.8", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/analytics/package.json b/packages/analytics/package.json index 50519a7150..c5edcf52d3 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -47,7 +47,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "@rollup/plugin-commonjs": "21.1.0", diff --git a/packages/app-check-compat/package.json b/packages/app-check-compat/package.json index 0769902e86..29da9f0595 100644 --- a/packages/app-check-compat/package.json +++ b/packages/app-check-compat/package.json @@ -43,7 +43,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.7", + "@firebase/app-compat": "0.5.8", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-check/package.json b/packages/app-check/package.json index a38a1935ab..25132c41e1 100644 --- a/packages/app-check/package.json +++ b/packages/app-check/package.json @@ -44,7 +44,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-compat/CHANGELOG.md b/packages/app-compat/CHANGELOG.md index ce994ed1e8..82e03235ca 100644 --- a/packages/app-compat/CHANGELOG.md +++ b/packages/app-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/app-compat +## 0.5.8 + +### Patch Changes + +- Updated dependencies []: + - @firebase/app@0.14.8 + ## 0.5.7 ### Patch Changes diff --git a/packages/app-compat/package.json b/packages/app-compat/package.json index 47520a763f..36e8139e02 100644 --- a/packages/app-compat/package.json +++ b/packages/app-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-compat", - "version": "0.5.7", + "version": "0.5.8", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,7 +37,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "@firebase/util": "1.13.0", "@firebase/logger": "0.5.0", "@firebase/component": "0.7.0", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 444f25f479..5d69707fb3 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/app +## 0.14.8 + +### Patch Changes + +- Update SDK_VERSION. + ## 0.14.7 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 7b9392f306..265ac8d873 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app", - "version": "0.14.7", + "version": "0.14.8", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index c085e94b98..ebd93672de 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -57,7 +57,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.7", + "@firebase/app-compat": "0.5.8", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/auth/package.json b/packages/auth/package.json index 209ea283ed..2fefbc687f 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -131,7 +131,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-strip": "2.1.0", "@types/express": "4.17.21", diff --git a/packages/data-connect/package.json b/packages/data-connect/package.json index 7280975814..104e4d7f83 100644 --- a/packages/data-connect/package.json +++ b/packages/data-connect/package.json @@ -55,7 +55,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/database-compat/package.json b/packages/database-compat/package.json index 422763546f..c2cd0ae9ea 100644 --- a/packages/database-compat/package.json +++ b/packages/database-compat/package.json @@ -57,7 +57,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.7", + "@firebase/app-compat": "0.5.8", "typescript": "5.5.4" }, "repository": { diff --git a/packages/database/package.json b/packages/database/package.json index 20f17a1bbf..642ddff7d1 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -57,7 +57,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/firebase/CHANGELOG.md b/packages/firebase/CHANGELOG.md index 40f6ae9266..ef42dca4d0 100644 --- a/packages/firebase/CHANGELOG.md +++ b/packages/firebase/CHANGELOG.md @@ -1,5 +1,27 @@ # firebase +## 12.9.0 + +### Minor Changes + +- [`8123231`](https://github.com/firebase/firebase-js-sdk/commit/8123231a1e7030400ac362e13d4cafb8d40f5d4c) [#9461](https://github.com/firebase/firebase-js-sdk/pull/9461) - AI Logic: Extend the `LiveSession.receive()` return types to include a `LiveServiceGoingAwayNotice` + which signifies that the service will soon close the session. + +- [`f9254b6`](https://github.com/firebase/firebase-js-sdk/commit/f9254b6d28cc086a763d7fed42a59d6d2199aae8) [#9475](https://github.com/firebase/firebase-js-sdk/pull/9475) - Remove "preview" tags from code execution and URL context documentation. + +- [`2e74329`](https://github.com/firebase/firebase-js-sdk/commit/2e74329868f90e92ac8a32d131aa9dd9226ccb59) [#9462](https://github.com/firebase/firebase-js-sdk/pull/9462) - Add params on `UsageMetadata` that provide cache-related usage data when the implicit caching feature is used. + +- [`08e3acd`](https://github.com/firebase/firebase-js-sdk/commit/08e3acdf098dc5499081c610bcbe428f376f9ded) [#9459](https://github.com/firebase/firebase-js-sdk/pull/9459) - Add support for `regexFind` and `regexFindAll` Pipeline expressions. + +### Patch Changes + +- Updated dependencies [[`8123231`](https://github.com/firebase/firebase-js-sdk/commit/8123231a1e7030400ac362e13d4cafb8d40f5d4c), [`691a506`](https://github.com/firebase/firebase-js-sdk/commit/691a506ecaa10ac3f0354313f5de5a47f4c85199), [`f9254b6`](https://github.com/firebase/firebase-js-sdk/commit/f9254b6d28cc086a763d7fed42a59d6d2199aae8), [`65a553b`](https://github.com/firebase/firebase-js-sdk/commit/65a553baf435be2463477ef9ddb114f26a2845ce), [`2e74329`](https://github.com/firebase/firebase-js-sdk/commit/2e74329868f90e92ac8a32d131aa9dd9226ccb59), [`08e3acd`](https://github.com/firebase/firebase-js-sdk/commit/08e3acdf098dc5499081c610bcbe428f376f9ded)]: + - @firebase/app@0.14.8 + - @firebase/ai@2.8.0 + - @firebase/firestore@4.11.0 + - @firebase/app-compat@0.5.8 + - @firebase/firestore-compat@0.4.5 + ## 12.8.0 ### Minor Changes diff --git a/packages/firebase/package.json b/packages/firebase/package.json index 479bd3c338..592c9937df 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -1,6 +1,6 @@ { "name": "firebase", - "version": "12.8.0", + "version": "12.9.0", "description": "Firebase JavaScript library for web and Node.js", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -423,17 +423,17 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/ai": "2.7.0", - "@firebase/app": "0.14.7", - "@firebase/app-compat": "0.5.7", + "@firebase/ai": "2.8.0", + "@firebase/app": "0.14.8", + "@firebase/app-compat": "0.5.8", "@firebase/app-types": "0.9.3", "@firebase/auth": "1.12.0", "@firebase/auth-compat": "0.6.2", "@firebase/data-connect": "0.3.12", "@firebase/database": "1.1.0", "@firebase/database-compat": "2.1.0", - "@firebase/firestore": "4.10.0", - "@firebase/firestore-compat": "0.4.4", + "@firebase/firestore": "4.11.0", + "@firebase/firestore-compat": "0.4.5", "@firebase/functions": "0.13.1", "@firebase/functions-compat": "0.4.1", "@firebase/installations": "0.6.19", diff --git a/packages/firestore-compat/CHANGELOG.md b/packages/firestore-compat/CHANGELOG.md index 0214c7ebab..3fdb7f3d79 100644 --- a/packages/firestore-compat/CHANGELOG.md +++ b/packages/firestore-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/firestore-compat +## 0.4.5 + +### Patch Changes + +- Updated dependencies [[`65a553b`](https://github.com/firebase/firebase-js-sdk/commit/65a553baf435be2463477ef9ddb114f26a2845ce), [`08e3acd`](https://github.com/firebase/firebase-js-sdk/commit/08e3acdf098dc5499081c610bcbe428f376f9ded)]: + - @firebase/firestore@4.11.0 + ## 0.4.4 ### Patch Changes diff --git a/packages/firestore-compat/package.json b/packages/firestore-compat/package.json index e4f62da141..262ee0d1cb 100644 --- a/packages/firestore-compat/package.json +++ b/packages/firestore-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore-compat", - "version": "0.4.4", + "version": "0.4.5", "description": "The Cloud Firestore component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -47,13 +47,13 @@ }, "dependencies": { "@firebase/component": "0.7.0", - "@firebase/firestore": "4.10.0", + "@firebase/firestore": "4.11.0", "@firebase/util": "1.13.0", "@firebase/firestore-types": "3.0.3", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.7", + "@firebase/app-compat": "0.5.8", "@types/eslint": "7.29.0", "rollup": "2.79.2", "rollup-plugin-sourcemaps": "0.6.3", diff --git a/packages/firestore/CHANGELOG.md b/packages/firestore/CHANGELOG.md index 59dc24ec7d..e798dbdd04 100644 --- a/packages/firestore/CHANGELOG.md +++ b/packages/firestore/CHANGELOG.md @@ -1,5 +1,15 @@ # @firebase/firestore +## 4.11.0 + +### Minor Changes + +- [`08e3acd`](https://github.com/firebase/firebase-js-sdk/commit/08e3acdf098dc5499081c610bcbe428f376f9ded) [#9459](https://github.com/firebase/firebase-js-sdk/pull/9459) - Add support for `regexFind` and `regexFindAll` Pipeline expressions. + +### Patch Changes + +- [`65a553b`](https://github.com/firebase/firebase-js-sdk/commit/65a553baf435be2463477ef9ddb114f26a2845ce) [#9472](https://github.com/firebase/firebase-js-sdk/pull/9472) - Log a warning when `databaseId` is not found. + ## 4.10.0 ### Minor Changes diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 76cc2b3e32..e595b55e14 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore", - "version": "4.10.0", + "version": "4.11.0", "engines": { "node": ">=20.0.0" }, @@ -145,8 +145,8 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.7", - "@firebase/app-compat": "0.5.7", + "@firebase/app": "0.14.8", + "@firebase/app-compat": "0.5.8", "@firebase/auth": "1.12.0", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", diff --git a/packages/functions-compat/package.json b/packages/functions-compat/package.json index df4dd9ab26..6bdb22e507 100644 --- a/packages/functions-compat/package.json +++ b/packages/functions-compat/package.json @@ -29,7 +29,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.7", + "@firebase/app-compat": "0.5.8", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/functions/package.json b/packages/functions/package.json index 3234e0ddb4..fc9b48ff62 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -49,7 +49,7 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/installations-compat/package.json b/packages/installations-compat/package.json index 85abab437b..962a420d21 100644 --- a/packages/installations-compat/package.json +++ b/packages/installations-compat/package.json @@ -44,7 +44,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app-compat": "0.5.7", + "@firebase/app-compat": "0.5.8", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/installations/package.json b/packages/installations/package.json index fc12ac8a92..84bd448f40 100644 --- a/packages/installations/package.json +++ b/packages/installations/package.json @@ -49,7 +49,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/messaging-compat/package.json b/packages/messaging-compat/package.json index 64cb0ed782..6281f9da5f 100644 --- a/packages/messaging-compat/package.json +++ b/packages/messaging-compat/package.json @@ -44,7 +44,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.7", + "@firebase/app-compat": "0.5.8", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", "ts-essentials": "9.4.2", diff --git a/packages/messaging/package.json b/packages/messaging/package.json index 3f4e7e8941..a74df15bcf 100644 --- a/packages/messaging/package.json +++ b/packages/messaging/package.json @@ -60,7 +60,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/performance-compat/package.json b/packages/performance-compat/package.json index 4e250140ec..ab2b4e884f 100644 --- a/packages/performance-compat/package.json +++ b/packages/performance-compat/package.json @@ -51,7 +51,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.7" + "@firebase/app-compat": "0.5.8" }, "repository": { "directory": "packages/performance-compat", diff --git a/packages/performance/package.json b/packages/performance/package.json index 80ffab1f8c..c70b1ed6a0 100644 --- a/packages/performance/package.json +++ b/packages/performance/package.json @@ -47,7 +47,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/remote-config-compat/package.json b/packages/remote-config-compat/package.json index 501f3c1a9d..0ff334df69 100644 --- a/packages/remote-config-compat/package.json +++ b/packages/remote-config-compat/package.json @@ -50,7 +50,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.7" + "@firebase/app-compat": "0.5.8" }, "repository": { "directory": "packages/remote-config-compat", diff --git a/packages/remote-config/package.json b/packages/remote-config/package.json index 5d8c953f62..2d700d885a 100644 --- a/packages/remote-config/package.json +++ b/packages/remote-config/package.json @@ -48,7 +48,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/storage-compat/package.json b/packages/storage-compat/package.json index 7003c451bc..32d2d2d116 100644 --- a/packages/storage-compat/package.json +++ b/packages/storage-compat/package.json @@ -44,7 +44,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.7", + "@firebase/app-compat": "0.5.8", "@firebase/auth-compat": "0.6.2", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", diff --git a/packages/storage/package.json b/packages/storage/package.json index ca4af33efa..c09be0c392 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -54,7 +54,7 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "@firebase/auth": "1.12.0", "rollup": "2.79.2", "@rollup/plugin-alias": "5.1.1", diff --git a/packages/template/package.json b/packages/template/package.json index 543eda528c..240b6bcf45 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -48,7 +48,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index 4c8caee603..da72e290ea 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -40,7 +40,7 @@ "yargs": "17.7.2" }, "devDependencies": { - "@firebase/app": "0.14.7", + "@firebase/app": "0.14.8", "@firebase/logger": "0.5.0", "@types/webpack": "5.28.5" }, From 2bd48a604d4ab4df4a9dec9a78a880a9b18891c7 Mon Sep 17 00:00:00 2001 From: Google Admin Date: Wed, 18 Feb 2026 12:11:49 -0500 Subject: [PATCH 054/174] Refactor Github Action per b/485167538 (#9555) Co-authored-by: Ben Knutson --- .github/workflows/check-changeset.yml | 8 +++++-- .github/workflows/e2e-test.yml | 9 +++++--- .../workflows/prerelease-manual-deploy.yml | 6 +++-- .github/workflows/release-prod.yml | 8 +++++-- .github/workflows/release-staging.yml | 23 +++++++++++++------ 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/.github/workflows/check-changeset.yml b/.github/workflows/check-changeset.yml index 26eb962887..741c47da67 100644 --- a/.github/workflows/check-changeset.yml +++ b/.github/workflows/check-changeset.yml @@ -52,10 +52,14 @@ jobs: - name: Print changeset checker output run: | cat << 'eof_delimiter_that_will_never_occur_in_CHANGESET_ERROR_MESSAGE' - ${{steps.check-changeset.outputs.CHANGESET_ERROR_MESSAGE}} + ${STEPS_CHECK_CHANGESET_OUTPUTS_CHANGESET_ERROR_MESSAGE} eof_delimiter_that_will_never_occur_in_CHANGESET_ERROR_MESSAGE + env: + STEPS_CHECK_CHANGESET_OUTPUTS_CHANGESET_ERROR_MESSAGE: ${{steps.check-changeset.outputs.CHANGESET_ERROR_MESSAGE}} - name: Print blocking failure status - run: echo "${{steps.check-changeset.outputs.BLOCKING_FAILURE}}" + run: echo "${STEPS_CHECK_CHANGESET_OUTPUTS_BLOCKING_FAILURE}" + env: + STEPS_CHECK_CHANGESET_OUTPUTS_BLOCKING_FAILURE: ${{steps.check-changeset.outputs.BLOCKING_FAILURE}} - name: Find Comment # This commit represents v3.1.0 uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 89ea939dce..7f7c245f79 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -52,17 +52,20 @@ jobs: echo "export const config = $PROJECT_CONFIG; export const testAccount = $TEST_ACCOUNT" > firebase-config.js - name: Poll npm until version to test is available for install run: | - echo "Polling npm for firebase@${{ github.event.client_payload.versionOrTag }}" + echo "Polling npm for firebase@${GITHUB_EVENT_CLIENT_PAYLOAD_VERSIONORTAG}" node ./scripts/release/poll-npm-publish.js # run in root working-directory: '.' env: VERSION: ${{ github.event.client_payload.versionOrTag }} + GITHUB_EVENT_CLIENT_PAYLOAD_VERSIONORTAG: ${{ github.event.client_payload.versionOrTag }} - name: Yarn install run: | - echo "Installing firebase@${{ github.event.client_payload.versionOrTag }}" - yarn add firebase@${{ github.event.client_payload.versionOrTag }} + echo "Installing firebase@${GITHUB_EVENT_CLIENT_PAYLOAD_VERSIONORTAG}" + yarn add firebase@${GITHUB_EVENT_CLIENT_PAYLOAD_VERSIONORTAG} yarn + env: + GITHUB_EVENT_CLIENT_PAYLOAD_VERSIONORTAG: ${{ github.event.client_payload.versionOrTag }} - name: Deploy "callTest" cloud function run: | pushd functions diff --git a/.github/workflows/prerelease-manual-deploy.yml b/.github/workflows/prerelease-manual-deploy.yml index cf85836d99..9d3e517dd5 100644 --- a/.github/workflows/prerelease-manual-deploy.yml +++ b/.github/workflows/prerelease-manual-deploy.yml @@ -41,7 +41,7 @@ jobs: - name: Yarn install run: yarn - name: Deploy prerelease - run: yarn release custom -p ${{ github.event.inputs.prereleaseName }} -t ${{ github.event.inputs.npmTag }} + run: yarn release custom -p ${GITHUB_EVENT_INPUTS_PRERELEASENAME} -t ${GITHUB_EVENT_INPUTS_NPMTAG} env: NPM_TOKEN_ANALYTICS: ${{secrets.NPM_TOKEN_ANALYTICS}} NPM_TOKEN_ANALYTICS_INTEROP_TYPES: ${{secrets.NPM_TOKEN_ANALYTICS_INTEROP_TYPES}} @@ -93,4 +93,6 @@ jobs: NPM_TOKEN_APP_CHECK_COMPAT: ${{ secrets.NPM_TOKEN_APP_CHECK_COMPAT }} NPM_TOKEN_API_DOCUMENTER: ${{ secrets.NPM_TOKEN_API_DOCUMENTER }} CI: true - \ No newline at end of file + GITHUB_EVENT_INPUTS_PRERELEASENAME: ${{ github.event.inputs.prereleaseName }} + GITHUB_EVENT_INPUTS_NPMTAG: ${{ github.event.inputs.npmTag }} + diff --git a/.github/workflows/release-prod.yml b/.github/workflows/release-prod.yml index 253ae95120..9c887e2940 100644 --- a/.github/workflows/release-prod.yml +++ b/.github/workflows/release-prod.yml @@ -112,16 +112,20 @@ jobs: echo "BASE_VERSION=$VERSION" >> $GITHUB_OUTPUT - name: Echo version in shell run: | - echo "Base version: ${{ steps.get-version.outputs.BASE_VERSION }}" + echo "Base version: ${STEPS_GET_VERSION_OUTPUTS_BASE_VERSION}" + env: + STEPS_GET_VERSION_OUTPUTS_BASE_VERSION: ${{ steps.get-version.outputs.BASE_VERSION }} - name: Log to release tracker # Sends release information to cloud functions endpoint of release tracker. run: | DATE=$(date +'%m/%d/%Y') - BASE_VERSION=${{ steps.get-version.outputs.BASE_VERSION }} + BASE_VERSION=${STEPS_GET_VERSION_OUTPUTS_BASE_VERSION} RELEASE_TRACKER_URL=${{ secrets.RELEASE_TRACKER_URL }} curl -X POST -H "Content-Type:application/json" \ -d "{\"version\":\"$BASE_VERSION\",\"date\":\"$DATE\"}" \ $RELEASE_TRACKER_URL/logProduction + env: + STEPS_GET_VERSION_OUTPUTS_BASE_VERSION: ${{ steps.get-version.outputs.BASE_VERSION }} - name: Create GitHub release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-staging.yml b/.github/workflows/release-staging.yml index 52aafa9273..4f061fa423 100644 --- a/.github/workflows/release-staging.yml +++ b/.github/workflows/release-staging.yml @@ -143,19 +143,24 @@ jobs: echo "BASE_VERSION=$BASE_VERSION" >> $GITHUB_OUTPUT - name: Echo versions in shell run: | - echo "Staging release ${{ steps.get-version.outputs.STAGING_VERSION }}" - echo "Base version: ${{ steps.get-version.outputs.BASE_VERSION }}" + echo "Staging release ${STEPS_GET_VERSION_OUTPUTS_STAGING_VERSION}" + echo "Base version: ${STEPS_GET_VERSION_OUTPUTS_BASE_VERSION}" + env: + STEPS_GET_VERSION_OUTPUTS_STAGING_VERSION: ${{ steps.get-version.outputs.STAGING_VERSION }} + STEPS_GET_VERSION_OUTPUTS_BASE_VERSION: ${{ steps.get-version.outputs.BASE_VERSION }} - name: Launch E2E tests workflow # Trigger e2e-test.yml run: | OSS_BOT_GITHUB_TOKEN=${{ secrets.OSS_BOT_GITHUB_TOKEN }} - VERSION_OR_TAG=${{ steps.get-version.outputs.STAGING_VERSION }} + VERSION_OR_TAG=${STEPS_GET_VERSION_OUTPUTS_STAGING_VERSION} curl -X POST \ -H "Content-Type:application/json" \ -H "Accept:application/vnd.github.v3+json" \ -H "Authorization:Bearer $OSS_BOT_GITHUB_TOKEN" \ -d "{\"event_type\":\"staging-tests\", \"client_payload\":{\"versionOrTag\":\"$VERSION_OR_TAG\"}}" \ https://api.github.com/repos/firebase/firebase-js-sdk/dispatches + env: + STEPS_GET_VERSION_OUTPUTS_STAGING_VERSION: ${{ steps.get-version.outputs.STAGING_VERSION }} - name: Check for changes requiring a reference doc publish id: docs-check # If a diff is found (length of DIFF_CONTENTS > 0) it will write DOCS_NEEDED=true @@ -173,11 +178,15 @@ jobs: if: ${{ always() }} run: | DATE=$(date +'%m/%d/%Y') - BASE_VERSION=${{ steps.get-version.outputs.BASE_VERSION }} - STAGING_VERSION=${{ steps.get-version.outputs.STAGING_VERSION }} - OPERATOR=${{ github.actor }} + BASE_VERSION=${STEPS_GET_VERSION_OUTPUTS_BASE_VERSION} + STAGING_VERSION=${STEPS_GET_VERSION_OUTPUTS_STAGING_VERSION} + OPERATOR=${GITHUB_ACTOR} RELEASE_TRACKER_URL=${{ secrets.RELEASE_TRACKER_URL }} - DOCS_NEEDED=${{ steps.docs-check.outputs.DOCS_NEEDED }} + DOCS_NEEDED=${STEPS_DOCS_CHECK_OUTPUTS_DOCS_NEEDED} curl -X POST -H "Content-Type:application/json" \ -d "{\"version\":\"$BASE_VERSION\",\"tag\":\"$STAGING_VERSION\",\"date\":\"$DATE\",\"operator\":\"$OPERATOR\",\"docs_needed\":\"$DOCS_NEEDED\"}" \ $RELEASE_TRACKER_URL/logStaging + env: + STEPS_GET_VERSION_OUTPUTS_BASE_VERSION: ${{ steps.get-version.outputs.BASE_VERSION }} + STEPS_GET_VERSION_OUTPUTS_STAGING_VERSION: ${{ steps.get-version.outputs.STAGING_VERSION }} + STEPS_DOCS_CHECK_OUTPUTS_DOCS_NEEDED: ${{ steps.docs-check.outputs.DOCS_NEEDED }} From 35b284af4789f9081addce73ad5d85ab34e984f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 10:10:00 -0800 Subject: [PATCH 055/174] build(deps): bump lodash in /packages/auth-compat/demo/functions (#9482) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.21 to 4.17.23. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.21...4.17.23) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.17.23 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/auth-compat/demo/functions/yarn.lock | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/auth-compat/demo/functions/yarn.lock b/packages/auth-compat/demo/functions/yarn.lock index 08302e6e6c..a8eb80b657 100644 --- a/packages/auth-compat/demo/functions/yarn.lock +++ b/packages/auth-compat/demo/functions/yarn.lock @@ -78,7 +78,7 @@ dependencies: tslib "^2.1.0" -"@google-cloud/firestore@^6.6.0": +"@google-cloud/firestore@^6.8.0": version "6.8.0" resolved "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-6.8.0.tgz#d8c852844c381afaf62592796606c10e178400b5" integrity sha512-JRpk06SmZXLGz0pNx1x7yU3YhkUXheKgH5hbDZ4kMsdhtfV5qPLJLRI4wv69K0cZorIk+zTMOwptue7hizo0eA== @@ -789,10 +789,10 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -firebase-admin@11.10.1: - version "11.10.1" - resolved "https://registry.npmjs.org/firebase-admin/-/firebase-admin-11.10.1.tgz#5f0f83a44627e89938d350c5e4bbac76596c963e" - integrity sha512-atv1E6GbuvcvWaD3eHwrjeP5dAVs+EaHEJhu9CThMzPY6In8QYDiUR6tq5SwGl4SdA/GcAU0nhwWc/FSJsAzfQ== +firebase-admin@11.11.1: + version "11.11.1" + resolved "https://registry.npmjs.org/firebase-admin/-/firebase-admin-11.11.1.tgz#6712923de70d218c9f514d73005d976d03339605" + integrity sha512-UyEbq+3u6jWzCYbUntv/HuJiTixwh36G1R9j0v71mSvGAx/YZEWEW7uSGLYxBYE6ckVRQoKMr40PYUEzrm/4dg== dependencies: "@fastify/busboy" "^1.2.1" "@firebase/database-compat" "^0.3.4" @@ -803,7 +803,7 @@ firebase-admin@11.10.1: node-forge "^1.3.1" uuid "^9.0.0" optionalDependencies: - "@google-cloud/firestore" "^6.6.0" + "@google-cloud/firestore" "^6.8.0" "@google-cloud/storage" "^6.9.5" firebase-functions@3.24.1: @@ -1198,9 +1198,9 @@ lodash.once@^4.0.0: integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + version "4.17.23" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" + integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== long@^5.0.0: version "5.2.3" @@ -1849,4 +1849,4 @@ yargs@^17.7.2: yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== \ No newline at end of file + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 93eeffcb3463b035f32b36cf26853b88aba5b22d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 10:10:52 -0800 Subject: [PATCH 056/174] build(deps): bump lodash in /packages/auth-compat/demo (#9464) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.21 to 4.17.23. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.21...4.17.23) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.17.23 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/auth-compat/demo/yarn.lock | 107 +++++++++++++++++----------- 1 file changed, 67 insertions(+), 40 deletions(-) diff --git a/packages/auth-compat/demo/yarn.lock b/packages/auth-compat/demo/yarn.lock index 02d205be7c..dc56599d4f 100644 --- a/packages/auth-compat/demo/yarn.lock +++ b/packages/auth-compat/demo/yarn.lock @@ -930,17 +930,16 @@ dependencies: "@rollup/pluginutils" "^3.0.8" -"@rollup/plugin-node-resolve@13.3.0": - version "13.3.0" - resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz#da1c5c5ce8316cef96a2f823d111c1e4e498801c" - integrity sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw== +"@rollup/plugin-node-resolve@16.0.0": + version "16.0.0" + resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.0.tgz#b1a0594661f40d7b061d82136e847354ff85f211" + integrity sha512-0FPvAeVUT/zdWoO0jnb/V5BlBsUSNfkIOtFHzMO4H9MOklrmQFY6FduVHKucNb/aTFxvnGhj4MNj/T1oNdDfNg== dependencies: - "@rollup/pluginutils" "^3.1.0" - "@types/resolve" "1.17.1" + "@rollup/pluginutils" "^5.0.1" + "@types/resolve" "1.20.2" deepmerge "^4.2.2" - is-builtin-module "^3.1.0" is-module "^1.0.0" - resolve "^1.19.0" + resolve "^1.22.1" "@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.0.9", "@rollup/pluginutils@^3.1.0": version "3.1.0" @@ -959,6 +958,15 @@ estree-walker "^2.0.1" picomatch "^2.2.2" +"@rollup/pluginutils@^5.0.1": + version "5.3.0" + resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz#57ba1b0cbda8e7a3c597a4853c807b156e21a7b4" + integrity sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^4.0.2" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -974,6 +982,11 @@ resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/estree@^1.0.0": + version "1.0.8" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + "@types/minimatch@^3.0.3": version "3.0.5" resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" @@ -984,11 +997,6 @@ resolved "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== -"@types/node@*": - version "16.9.6" - resolved "https://registry.npmjs.org/@types/node/-/node-16.9.6.tgz#040a64d7faf9e5d9e940357125f0963012e66f04" - integrity sha512-YHUZhBOMTM3mjFkXVcK+WwAcYmyhe1wL4lfqNtzI0b3qAy7yuSetnM7QJazgE5PFmgVTNGiLOgRFfJMqW7XpSQ== - "@types/normalize-package-data@^2.4.0": version "2.4.1" resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" @@ -999,12 +1007,10 @@ resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== -"@types/resolve@1.17.1": - version "1.17.1" - resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" - integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== - dependencies: - "@types/node" "*" +"@types/resolve@1.20.2": + version "1.20.2" + resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" + integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== "@yarn-tool/resolve-package@^1.0.40": version "1.0.46" @@ -1225,11 +1231,6 @@ buffer-from@^1.0.0: resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -builtin-modules@^3.0.0: - version "3.2.0" - resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" - integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA== - builtins@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" @@ -1812,7 +1813,7 @@ estree-walker@^1.0.1: resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== -estree-walker@^2.0.1: +estree-walker@^2.0.1, estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== @@ -2002,6 +2003,11 @@ function-bind@^1.1.1: resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + gauge@~2.7.3: version "2.7.4" resolved "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -2219,6 +2225,13 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -2415,13 +2428,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-builtin-module@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.1.0.tgz#6fdb24313b1c03b75f8b9711c0feb8c30b903b00" - integrity sha512-OV7JjAgOTfAFJmHZLvpSTb4qi0nIILDV1gWPYDnDJUTNFM5aGlRAhk4QcT8i7TuAleeEV5Fdkqn3t4mS+Q11fg== - dependencies: - builtin-modules "^3.0.0" - is-callable@^1.1.4, is-callable@^1.2.4: version "1.2.4" resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" @@ -2434,6 +2440,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-core-module@^2.16.1: + version "2.16.1" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + is-core-module@^2.2.0, is-core-module@^2.5.0: version "2.6.0" resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" @@ -2801,9 +2814,9 @@ lodash.templatesettings@^4.0.0: lodash._reinterpolate "^3.0.0" lodash@^4.17.15, lodash@^4.17.19, lodash@^4.7.0: - version "4.17.21" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + version "4.17.23" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" + integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== lru-cache@^6.0.0: version "6.0.0" @@ -3597,6 +3610,11 @@ picomatch@^2.2.2, picomatch@^2.2.3: resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== +picomatch@^4.0.2: + version "4.0.3" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + pify@^2.3.0: version "2.3.0" resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -3896,7 +3914,7 @@ resolve-from@^5.0.0: resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve@^1.10.0, resolve@^1.17.0, resolve@^1.19.0: +resolve@^1.10.0, resolve@^1.17.0: version "1.20.0" resolved "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -3913,6 +3931,15 @@ resolve@^1.20.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@^1.22.1: + version "1.22.11" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" + integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ== + dependencies: + is-core-module "^2.16.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -4539,10 +4566,10 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@4.7.4: - version "4.7.4" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" - integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== +typescript@5.5.4: + version "5.5.4" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" + integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== uglify-js@^3.1.4, uglify-js@^3.4.9: version "3.14.2" From d7c311a4bb2d23bb5a88b31f981f1da4bc058a41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 10:12:56 -0800 Subject: [PATCH 057/174] build(deps): bump lodash in /packages/rules-unit-testing/functions (#9463) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.21 to 4.17.23. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.21...4.17.23) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.17.23 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/rules-unit-testing/functions/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rules-unit-testing/functions/yarn.lock b/packages/rules-unit-testing/functions/yarn.lock index 8a777c0ba1..fa4168e298 100644 --- a/packages/rules-unit-testing/functions/yarn.lock +++ b/packages/rules-unit-testing/functions/yarn.lock @@ -1239,9 +1239,9 @@ lodash.once@^4.0.0: integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + version "4.17.23" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" + integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== long@^4.0.0: version "4.0.0" From 9ced4281d342ff523aca0a8dd397fec251d25954 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 10:14:50 -0800 Subject: [PATCH 058/174] build(deps): bump lodash in /packages/auth/demo/functions (#9466) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.21 to 4.17.23. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.21...4.17.23) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.17.23 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/auth/demo/functions/yarn.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/auth/demo/functions/yarn.lock b/packages/auth/demo/functions/yarn.lock index db07d180da..a8eb80b657 100644 --- a/packages/auth/demo/functions/yarn.lock +++ b/packages/auth/demo/functions/yarn.lock @@ -78,7 +78,7 @@ dependencies: tslib "^2.1.0" -"@google-cloud/firestore@^6.6.0": +"@google-cloud/firestore@^6.8.0": version "6.8.0" resolved "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-6.8.0.tgz#d8c852844c381afaf62592796606c10e178400b5" integrity sha512-JRpk06SmZXLGz0pNx1x7yU3YhkUXheKgH5hbDZ4kMsdhtfV5qPLJLRI4wv69K0cZorIk+zTMOwptue7hizo0eA== @@ -789,10 +789,10 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -firebase-admin@11.10.1: - version "11.10.1" - resolved "https://registry.npmjs.org/firebase-admin/-/firebase-admin-11.10.1.tgz#5f0f83a44627e89938d350c5e4bbac76596c963e" - integrity sha512-atv1E6GbuvcvWaD3eHwrjeP5dAVs+EaHEJhu9CThMzPY6In8QYDiUR6tq5SwGl4SdA/GcAU0nhwWc/FSJsAzfQ== +firebase-admin@11.11.1: + version "11.11.1" + resolved "https://registry.npmjs.org/firebase-admin/-/firebase-admin-11.11.1.tgz#6712923de70d218c9f514d73005d976d03339605" + integrity sha512-UyEbq+3u6jWzCYbUntv/HuJiTixwh36G1R9j0v71mSvGAx/YZEWEW7uSGLYxBYE6ckVRQoKMr40PYUEzrm/4dg== dependencies: "@fastify/busboy" "^1.2.1" "@firebase/database-compat" "^0.3.4" @@ -803,7 +803,7 @@ firebase-admin@11.10.1: node-forge "^1.3.1" uuid "^9.0.0" optionalDependencies: - "@google-cloud/firestore" "^6.6.0" + "@google-cloud/firestore" "^6.8.0" "@google-cloud/storage" "^6.9.5" firebase-functions@3.24.1: @@ -1198,9 +1198,9 @@ lodash.once@^4.0.0: integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + version "4.17.23" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" + integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== long@^5.0.0: version "5.2.3" From c48b47674186e950985ece6ce4d70ccbec86a430 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 10:15:38 -0800 Subject: [PATCH 059/174] chore(deps): update dependency webpack-dev-server to v5.2.1 [security] (#9078) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- e2e/smoke-tests/package.json | 2 +- e2e/smoke-tests/yarn.lock | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/e2e/smoke-tests/package.json b/e2e/smoke-tests/package.json index 2fca5aacd8..2ddf668490 100644 --- a/e2e/smoke-tests/package.json +++ b/e2e/smoke-tests/package.json @@ -32,7 +32,7 @@ "typescript": "5.5.4", "webpack": "5.98.0", "webpack-cli": "5.1.4", - "webpack-dev-server": "5.2.0" + "webpack-dev-server": "5.2.1" }, "engines": { "node": ">=20.0.0" diff --git a/e2e/smoke-tests/yarn.lock b/e2e/smoke-tests/yarn.lock index 63a037e750..636c64fb01 100644 --- a/e2e/smoke-tests/yarn.lock +++ b/e2e/smoke-tests/yarn.lock @@ -2303,6 +2303,16 @@ "@types/range-parser" "*" "@types/send" "*" +"@types/express-serve-static-core@^4.17.21": + version "4.19.8" + resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz#99b960322a4d576b239a640ab52ef191989b036f" + integrity sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + "@types/express-serve-static-core@^4.17.33": version "4.19.6" resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz" @@ -6057,14 +6067,15 @@ webpack-dev-middleware@^7.4.2: range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-dev-server@5.2.0: - version "5.2.0" - resolved "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.0.tgz" - integrity sha512-90SqqYXA2SK36KcT6o1bvwvZfJFcmoamqeJY7+boioffX9g9C0wjjJRGUrQIuh43pb0ttX7+ssavmj/WN2RHtA== +webpack-dev-server@5.2.1: + version "5.2.1" + resolved "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.1.tgz#049072d6e19cbda8cf600b9e364e6662d61218ba" + integrity sha512-ml/0HIj9NLpVKOMq+SuBPLHcmbG+TGIjXRHsYfZwocUBIqEvws8NnS/V9AFQ5FKP+tgn5adwVwRrTEpGL33QFQ== dependencies: "@types/bonjour" "^3.5.13" "@types/connect-history-api-fallback" "^1.5.4" "@types/express" "^4.17.21" + "@types/express-serve-static-core" "^4.17.21" "@types/serve-index" "^1.9.4" "@types/serve-static" "^1.15.5" "@types/sockjs" "^0.3.36" From 4d2ab8507efe95ccd7ffd8e77adfe11c1c041140 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 10:17:24 -0800 Subject: [PATCH 060/174] chore(deps): update google-github-actions/auth digest to fc21748 (#8879) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/health-metrics-pull-request.yml | 4 ++-- .github/workflows/health-metrics-release.yml | 2 +- .github/workflows/test-changed-firestore-integration.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/health-metrics-pull-request.yml b/.github/workflows/health-metrics-pull-request.yml index bc28a0841c..a9a29b2db7 100644 --- a/.github/workflows/health-metrics-pull-request.yml +++ b/.github/workflows/health-metrics-pull-request.yml @@ -43,7 +43,7 @@ jobs: with: node-version: 22.10.0 # This commit represents v0.8.3 - - uses: 'google-github-actions/auth@c4799db9111fba4461e9f9da8732e5057b394f72' + - uses: 'google-github-actions/auth@fc2174804b84f912b1f6d334e9463f484f1c552d' with: credentials_json: '${{ secrets.GCP_SA_KEY }}' # This commit represents v2.1.4 @@ -62,7 +62,7 @@ jobs: with: node-version: 22.10.0 # This commit represents v0.8.3 - - uses: 'google-github-actions/auth@c4799db9111fba4461e9f9da8732e5057b394f72' + - uses: 'google-github-actions/auth@fc2174804b84f912b1f6d334e9463f484f1c552d' with: credentials_json: '${{ secrets.GCP_SA_KEY }}' # This commit represents v2.1.4 diff --git a/.github/workflows/health-metrics-release.yml b/.github/workflows/health-metrics-release.yml index 79aef4b3da..0c26afb037 100644 --- a/.github/workflows/health-metrics-release.yml +++ b/.github/workflows/health-metrics-release.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: # This commit represents v0.8.3 - - uses: 'google-github-actions/auth@c4799db9111fba4461e9f9da8732e5057b394f72' + - uses: 'google-github-actions/auth@fc2174804b84f912b1f6d334e9463f484f1c552d' with: credentials_json: '${{ secrets.GCP_SA_KEY }}' # This commit represents v2.1.4 diff --git a/.github/workflows/test-changed-firestore-integration.yml b/.github/workflows/test-changed-firestore-integration.yml index b894e70e1e..2f4c104fc2 100644 --- a/.github/workflows/test-changed-firestore-integration.yml +++ b/.github/workflows/test-changed-firestore-integration.yml @@ -34,7 +34,7 @@ jobs: # This makes Actions fetch all Git history so run-changed script can diff properly. fetch-depth: 0 # This commit represents v0.8.3 - - uses: 'google-github-actions/auth@c4799db9111fba4461e9f9da8732e5057b394f72' + - uses: 'google-github-actions/auth@fc2174804b84f912b1f6d334e9463f484f1c552d' if: ${{ fromJSON(env.run_terraform_steps) }} with: credentials_json: '${{ secrets.JSSDK_ACTIONS_SA_KEY }}' From d4b22a872cd42c23cc23e5be093741bd5a5d0bd4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 10:20:14 -0800 Subject: [PATCH 061/174] build(deps-dev): bump lodash from 4.17.21 to 4.17.23 (#9465) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.21 to 4.17.23. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.21...4.17.23) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.17.23 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 6f6010356e..9d79c73560 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "lcov-result-merger": "3.3.0", "lerna": "4.0.0", "listr": "0.14.3", - "lodash": "4.17.21", + "lodash": "4.17.23", "long": "3.2.0", "merge2": "1.4.1", "mkdirp": "1.0.4", diff --git a/yarn.lock b/yarn.lock index be3f532cdc..907accd333 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10958,10 +10958,10 @@ lodash.templatesettings@^4.0.0: dependencies: lodash._reinterpolate "^3.0.0" -lodash@4.17.21, lodash@^4.16.6, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.7.0, lodash@~4.17.15, lodash@~4.17.21: - version "4.17.21" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +lodash@4.17.23, lodash@^4.16.6, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.7.0, lodash@~4.17.15, lodash@~4.17.21: + version "4.17.23" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" + integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== log-driver@^1.2.7: version "1.2.7" From 7b1e6ec79e81c0014d581ee335aacf0950908863 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 18 Feb 2026 11:38:12 -0800 Subject: [PATCH 062/174] Remove health metrics workflows (#9571) --- .../workflows/health-metrics-pull-request.yml | 74 ------------------- .github/workflows/health-metrics-release.yml | 37 ---------- 2 files changed, 111 deletions(-) delete mode 100644 .github/workflows/health-metrics-pull-request.yml delete mode 100644 .github/workflows/health-metrics-release.yml diff --git a/.github/workflows/health-metrics-pull-request.yml b/.github/workflows/health-metrics-pull-request.yml deleted file mode 100644 index a9a29b2db7..0000000000 --- a/.github/workflows/health-metrics-pull-request.yml +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright 2023 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. - -name: Health Metrics - -on: - push: - branches: ['**'] - pull_request: - -env: - GITHUB_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - # TODO(yifany): parse from git commit history directly - # Reason: actions/checkout@v2 does not always honor ${{ github.event.pull_request.base.sha }}, - # therefore "base.sha" sometimes is not the commit that actually gets merged with the - # pull request head commit for CI test. - # See: - # - https://github.com/actions/checkout/issues/27 - # - https://github.com/actions/checkout/issues/237 - GITHUB_PULL_REQUEST_BASE_SHA: ${{ github.event.pull_request.base.sha }} - # Bump Node memory limit - NODE_OPTIONS: "--max-old-space-size=4096" - -jobs: - binary-size: - name: Binary Size - if: (github.event_name == 'push' || !(github.event.pull_request.head.repo.fork)) && (github.actor != 'dependabot[bot]') - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 22.10.0 - # This commit represents v0.8.3 - - uses: 'google-github-actions/auth@fc2174804b84f912b1f6d334e9463f484f1c552d' - with: - credentials_json: '${{ secrets.GCP_SA_KEY }}' - # This commit represents v2.1.4 - - uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a - - run: yarn install - - run: yarn build - - name: Run health-metrics/binary-size test - run: yarn size-report - modular-export-size: - name: Binary Size For Modular Exports - if: (github.event_name == 'push' || !(github.event.pull_request.head.repo.fork)) && (github.actor != 'dependabot[bot]') - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 22.10.0 - # This commit represents v0.8.3 - - uses: 'google-github-actions/auth@fc2174804b84f912b1f6d334e9463f484f1c552d' - with: - credentials_json: '${{ secrets.GCP_SA_KEY }}' - # This commit represents v2.1.4 - - uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a - - run: yarn install - - run: yarn build - - name: Run health-metrics/modular-exports-binary-size test - run: yarn modular-export-size-report - # TODO(yifany): Enable startup times testing on CI. diff --git a/.github/workflows/health-metrics-release.yml b/.github/workflows/health-metrics-release.yml deleted file mode 100644 index 0c26afb037..0000000000 --- a/.github/workflows/health-metrics-release.yml +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2023 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. - -name: Health Metrics - -on: - push: - tags: ['**'] - -jobs: - release-diffing: - name: Release Diffing - runs-on: ubuntu-latest - steps: - # This commit represents v0.8.3 - - uses: 'google-github-actions/auth@fc2174804b84f912b1f6d334e9463f484f1c552d' - with: - credentials_json: '${{ secrets.GCP_SA_KEY }}' - # This commit represents v2.1.4 - - uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a - # This commit represents v1.4 - - uses: FirebaseExtended/github-actions/health-metrics/release-diffing@41c787c37157e4c5932b951e531c041efa5bb7a4 - with: - repo: ${{ github.repository }} - ref: ${{ github.ref }} - commit: ${{ github.sha }} From 47f85219d570f05c196e0085f2892d1297308fed Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 18 Feb 2026 11:38:38 -0800 Subject: [PATCH 063/174] feat(ai): Automatic function calling (#9489) --- .changeset/cool-bulldogs-impress.md | 6 + common/api-review/ai.api.md | 10 + docs-devsite/ai.functiondeclaration.md | 11 + docs-devsite/ai.functionresponse.md | 9 + docs-devsite/ai.requestoptions.md | 13 + packages/ai/src/methods/chat-session.test.ts | 749 +++++++++++++++++- packages/ai/src/methods/chat-session.ts | 354 +++++++-- packages/ai/src/methods/generate-content.ts | 4 +- .../ai/src/models/generative-model.test.ts | 7 +- packages/ai/src/models/generative-model.ts | 3 +- packages/ai/src/requests/response-helpers.ts | 5 +- .../ai/src/requests/stream-reader.test.ts | 73 +- packages/ai/src/requests/stream-reader.ts | 51 +- packages/ai/src/types/content.ts | 1 + packages/ai/src/types/requests.ts | 15 + 15 files changed, 1224 insertions(+), 87 deletions(-) create mode 100644 .changeset/cool-bulldogs-impress.md diff --git a/.changeset/cool-bulldogs-impress.md b/.changeset/cool-bulldogs-impress.md new file mode 100644 index 0000000000..f75fe44e9e --- /dev/null +++ b/.changeset/cool-bulldogs-impress.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +Added automatic function calling capability when using `ChatSession`. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 843bedc885..8f6ee39ed0 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -143,6 +143,12 @@ export class BooleanSchema extends Schema { export class ChatSession { // Warning: (ae-incompatible-release-tags) The symbol "__constructor" is marked as @public, but its signature references "ChromeAdapter" which is marked as @beta constructor(apiSettings: ApiSettings, model: string, chromeAdapter?: ChromeAdapter | undefined, params?: StartChatParams | undefined, requestOptions?: RequestOptions | undefined); + // @internal + _callFunctionsAsNeeded(functionCalls: FunctionCall[]): Promise; + // @internal + _formatRequest(incomingContent: Content, tempHistory: Content[]): GenerateContentRequest; + // @internal + _getCallableFunctionCalls(response?: GenerateContentResponse): FunctionCall[] | undefined; getHistory(): Promise; // (undocumented) model: string; @@ -407,6 +413,7 @@ export interface FunctionCallPart { // @public export interface FunctionDeclaration { description: string; + functionReference?: Function; name: string; parameters?: ObjectSchema | ObjectSchemaRequest; } @@ -422,6 +429,8 @@ export interface FunctionResponse { // (undocumented) name: string; // (undocumented) + parts?: Part[]; + // (undocumented) response: object; } @@ -1145,6 +1154,7 @@ export interface PromptFeedback { // @public export interface RequestOptions { baseUrl?: string; + maxSequentalFunctionCalls?: number; timeout?: number; } diff --git a/docs-devsite/ai.functiondeclaration.md b/docs-devsite/ai.functiondeclaration.md index 460c979265..d6d672b3e0 100644 --- a/docs-devsite/ai.functiondeclaration.md +++ b/docs-devsite/ai.functiondeclaration.md @@ -23,6 +23,7 @@ export interface FunctionDeclaration | Property | Type | Description | | --- | --- | --- | | [description](./ai.functiondeclaration.md#functiondeclarationdescription) | string | Description and purpose of the function. Model uses it to decide how and whether to call the function. | +| [functionReference](./ai.functiondeclaration.md#functiondeclarationfunctionreference) | Function | Reference to an actual function to call. Specifying this will cause the function to be called automatically when requested by the model. | | [name](./ai.functiondeclaration.md#functiondeclarationname) | string | The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a max length of 64. | | [parameters](./ai.functiondeclaration.md#functiondeclarationparameters) | [ObjectSchema](./ai.objectschema.md#objectschema_class) \| [ObjectSchemaRequest](./ai.objectschemarequest.md#objectschemarequest_interface) | Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. Parameter names are case-sensitive. For a function with no parameters, this can be left unset. | @@ -36,6 +37,16 @@ Description and purpose of the function. Model uses it to decide how and whether description: string; ``` +## FunctionDeclaration.functionReference + +Reference to an actual function to call. Specifying this will cause the function to be called automatically when requested by the model. + +Signature: + +```typescript +functionReference?: Function; +``` + ## FunctionDeclaration.name The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a max length of 64. diff --git a/docs-devsite/ai.functionresponse.md b/docs-devsite/ai.functionresponse.md index 980d964f70..2a214d3dfe 100644 --- a/docs-devsite/ai.functionresponse.md +++ b/docs-devsite/ai.functionresponse.md @@ -24,6 +24,7 @@ export interface FunctionResponse | --- | --- | --- | | [id](./ai.functionresponse.md#functionresponseid) | string | The id of the [FunctionCall](./ai.functioncall.md#functioncall_interface). | | [name](./ai.functionresponse.md#functionresponsename) | string | | +| [parts](./ai.functionresponse.md#functionresponseparts) | [Part](./ai.md#part)\[\] | | | [response](./ai.functionresponse.md#functionresponseresponse) | object | | ## FunctionResponse.id @@ -46,6 +47,14 @@ id?: string; name: string; ``` +## FunctionResponse.parts + +Signature: + +```typescript +parts?: Part[]; +``` + ## FunctionResponse.response Signature: diff --git a/docs-devsite/ai.requestoptions.md b/docs-devsite/ai.requestoptions.md index c04230fcd6..e7e8aeb828 100644 --- a/docs-devsite/ai.requestoptions.md +++ b/docs-devsite/ai.requestoptions.md @@ -23,6 +23,7 @@ export interface RequestOptions | Property | Type | Description | | --- | --- | --- | | [baseUrl](./ai.requestoptions.md#requestoptionsbaseurl) | string | Base url for endpoint. Defaults to https://firebasevertexai.googleapis.com, which is the [Firebase AI Logic API](https://console.cloud.google.com/apis/library/firebasevertexai.googleapis.com?project=_) (used regardless of your chosen Gemini API provider). | +| [maxSequentalFunctionCalls](./ai.requestoptions.md#requestoptionsmaxsequentalfunctioncalls) | number | Limits amount of sequential function calls the SDK can make during automatic function calling, in order to prevent infinite loops. If not specified, this value defaults to 10.When it reaches this limit, it will return the last response received from the model, whether it is a text response or further function calls. | | [timeout](./ai.requestoptions.md#requestoptionstimeout) | number | Request timeout in milliseconds. Defaults to 180 seconds (180000ms). | ## RequestOptions.baseUrl @@ -35,6 +36,18 @@ Base url for endpoint. Defaults to https://firebasevertexai.googleapis.com, whic baseUrl?: string; ``` +## RequestOptions.maxSequentalFunctionCalls + +Limits amount of sequential function calls the SDK can make during automatic function calling, in order to prevent infinite loops. If not specified, this value defaults to 10. + +When it reaches this limit, it will return the last response received from the model, whether it is a text response or further function calls. + +Signature: + +```typescript +maxSequentalFunctionCalls?: number; +``` + ## RequestOptions.timeout Request timeout in milliseconds. Defaults to 180 seconds (180000ms). diff --git a/packages/ai/src/methods/chat-session.test.ts b/packages/ai/src/methods/chat-session.test.ts index 1f084d0b1e..3ebf0edae8 100644 --- a/packages/ai/src/methods/chat-session.test.ts +++ b/packages/ai/src/methods/chat-session.test.ts @@ -16,16 +16,21 @@ */ import { expect, use } from 'chai'; -import { match, restore, stub, useFakeTimers } from 'sinon'; +import { match, restore, SinonSpy, spy, stub, useFakeTimers } from 'sinon'; import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; import * as generateContentMethods from './generate-content'; -import { Content, GenerateContentStreamResult } from '../types'; +import { + Content, + FunctionDeclaration, + GenerateContentStreamResult +} from '../types'; import { ChatSession } from './chat-session'; import { ApiSettings } from '../types/internal'; import { VertexAIBackend } from '../backend'; import { fakeChromeAdapter } from '../../test-utils/get-fake-firebase-services'; import { logger } from '../logger'; +import { Schema } from '../api'; use(sinonChai); use(chaiAsPromised); @@ -38,6 +43,18 @@ const fakeApiSettings: ApiSettings = { backend: new VertexAIBackend() }; +function getGreeting({ + username +}: Record): Record { + return { greeting: `Hi, ${username}` }; +} + +function getFarewell({ + username +}: Record): Record { + return { farewell: `Bye, ${username}` }; +} + describe('ChatSession', () => { afterEach(() => { restore(); @@ -378,4 +395,732 @@ describe('ChatSession', () => { ); }); }); + describe('Automatic function calling', () => { + const finalResponse = { + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [ + { + text: 'final response' + } + ] + } + } + ] + }; + const getFunctionDeclarationGreeting = ( + greetingSpy: SinonSpy + ): FunctionDeclaration => ({ + name: 'getGreeting', + functionReference: greetingSpy, + description: `Given the user's name, give a custom greeting`, + parameters: Schema.object({ + properties: { + username: Schema.string({ + description: "The user's name" + }) + } + }) + }); + const getFunctionDeclarationFarewell = ( + farewellSpy: SinonSpy + ): FunctionDeclaration => ({ + name: 'getFarewell', + functionReference: farewellSpy, + description: `Given the user's name, give a custom farewell`, + parameters: Schema.object({ + properties: { + username: Schema.string({ + description: "The user's name" + }) + } + }) + }); + const functionCallPartGreeting = { + functionCall: { + name: 'getGreeting', + args: { username: 'Bob' } + } + }; + const functionCallPartFarewell = { + functionCall: { + name: 'getFarewell', + args: { username: 'Bob' } + } + }; + describe('sendMessage()', () => { + it('calls one function automatically', async () => { + const greetingSpy = spy(getGreeting); + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + // @ts-ignore + ).callsFake(async (apiSettings, model, params) => { + const parts = params.contents[params.contents.length - 1].parts; + if (parts[0].text?.includes('Bob')) { + return { + response: { + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [functionCallPartGreeting] + } + } + ] + } + }; + } else if (parts[0].functionResponse) { + return { + response: finalResponse + }; + } + }); + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + { + tools: [ + { + functionDeclarations: [ + getFunctionDeclarationGreeting(greetingSpy) + ] + } + ] + } + ); + const result = await chatSession.sendMessage('My name is Bob'); + expect( + result.response.candidates?.[0].content.parts[0].text + ).to.include('final response'); + expect(generateContentStub).to.be.calledTwice; + const functionResponseContents = + generateContentStub.secondCall.args[2].contents; + expect( + functionResponseContents[functionResponseContents.length - 1].parts + .length + ).to.equal(1); + expect( + functionResponseContents[functionResponseContents.length - 1].parts[0] + .functionResponse + ).to.deep.equal({ + name: 'getGreeting', + response: { greeting: 'Hi, Bob' } + }); + expect(greetingSpy).to.be.calledWith({ username: 'Bob' }); + }); + it('calls two functions automatically', async () => { + const greetingSpy = spy(getGreeting); + const farewellSpy = spy(getFarewell); + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + // @ts-ignore + ).callsFake(async (apiSettings, model, params) => { + const parts = params.contents[params.contents.length - 1].parts; + if (parts[0].text?.includes('Bob')) { + return { + response: { + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [ + functionCallPartGreeting, + functionCallPartFarewell + ] + } + } + ] + } + }; + } else if (parts[0].functionResponse) { + return { + response: finalResponse + }; + } + }); + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + { + tools: [ + { + functionDeclarations: [ + getFunctionDeclarationGreeting(greetingSpy), + getFunctionDeclarationFarewell(farewellSpy) + ] + } + ] + } + ); + const result = await chatSession.sendMessage('My name is Bob'); + expect( + result.response.candidates?.[0].content.parts[0].text + ).to.include('final response'); + expect(generateContentStub).to.be.calledTwice; + const functionResponseContents = + generateContentStub.secondCall.args[2].contents; + expect( + functionResponseContents[functionResponseContents.length - 1].parts + .length + ).to.equal(2); + expect( + functionResponseContents[functionResponseContents.length - 1].parts[0] + .functionResponse + ).to.deep.equal({ + name: 'getGreeting', + response: { greeting: 'Hi, Bob' } + }); + expect( + functionResponseContents[functionResponseContents.length - 1].parts[1] + .functionResponse + ).to.deep.equal({ + name: 'getFarewell', + response: { farewell: 'Bye, Bob' } + }); + expect(greetingSpy).to.be.calledWith({ username: 'Bob' }); + expect(farewellSpy).to.be.calledWith({ username: 'Bob' }); + }); + it('does not call any functions if sequential limit is set to 0', async () => { + const greetingSpy = spy(getGreeting); + const warnStub = stub(logger, 'warn'); + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + // @ts-ignore + ).callsFake(async (apiSettings, model, params) => { + const parts = params.contents[params.contents.length - 1].parts; + if (parts[0].text?.includes('Bob')) { + return { + response: { + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [functionCallPartGreeting] + } + } + ] + } + }; + } else if (parts[0].functionResponse) { + return { + response: finalResponse + }; + } + }); + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + { + tools: [ + { + functionDeclarations: [ + getFunctionDeclarationGreeting(greetingSpy) + ] + } + ] + }, + { + maxSequentalFunctionCalls: 0 + } + ); + const result = await chatSession.sendMessage('My name is Bob'); + expect( + result.response.candidates?.[0].content.parts[0].functionCall?.name + ).to.equal('getGreeting'); + expect(generateContentStub).to.be.calledOnce; + expect(warnStub).calledWithMatch('exceeded the limit'); + expect(greetingSpy).to.not.be.called; + }); + }); + describe('sendMessageStream()', () => { + it('calls one function automatically', async () => { + const greetingSpy = spy(getGreeting); + const generateContentStreamStub = stub( + generateContentMethods, + 'generateContentStream' + // @ts-ignore + ).callsFake(async (apiSettings, model, params) => { + const parts = params.contents[params.contents.length - 1].parts; + if (parts[0].text?.includes('Bob')) { + return { + firstValue: { + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [functionCallPartGreeting] + } + } + ] + } + }; + } else if (parts[0].functionResponse) { + return { + firstValue: finalResponse, + response: finalResponse + }; + } + }); + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + { + tools: [ + { + functionDeclarations: [ + getFunctionDeclarationGreeting(greetingSpy) + ] + } + ] + } + ); + const result = await chatSession.sendMessageStream('My name is Bob'); + // No sense testing the stream fully, it's just stubbed data. + await result.response; + expect(generateContentStreamStub).to.be.calledTwice; + const functionResponseContents = + generateContentStreamStub.secondCall.args[2].contents; + expect( + functionResponseContents[functionResponseContents.length - 1].parts + .length + ).to.equal(1); + expect( + functionResponseContents[functionResponseContents.length - 1].parts[0] + .functionResponse + ).to.deep.equal({ + name: 'getGreeting', + response: { greeting: 'Hi, Bob' } + }); + expect(greetingSpy).to.be.calledWith({ username: 'Bob' }); + }); + it('calls two functions automatically', async () => { + const greetingSpy = spy(getGreeting); + const farewellSpy = spy(getFarewell); + const generateContentStreamStub = stub( + generateContentMethods, + 'generateContentStream' + // @ts-ignore + ).callsFake(async (apiSettings, model, params) => { + const parts = params.contents[params.contents.length - 1].parts; + if (parts[0].text?.includes('Bob')) { + return { + firstValue: { + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [ + functionCallPartGreeting, + functionCallPartFarewell + ] + } + } + ] + } + }; + } else if (parts[0].functionResponse) { + return { + firstValue: finalResponse, + response: finalResponse + }; + } + }); + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + { + tools: [ + { + functionDeclarations: [ + getFunctionDeclarationGreeting(greetingSpy), + getFunctionDeclarationFarewell(farewellSpy) + ] + } + ] + } + ); + const result = await chatSession.sendMessageStream('My name is Bob'); + await result.response; + expect(generateContentStreamStub).to.be.calledTwice; + const functionResponseContents = + generateContentStreamStub.secondCall.args[2].contents; + expect( + functionResponseContents[functionResponseContents.length - 1].parts + .length + ).to.equal(2); + expect( + functionResponseContents[functionResponseContents.length - 1].parts[0] + .functionResponse + ).to.deep.equal({ + name: 'getGreeting', + response: { greeting: 'Hi, Bob' } + }); + expect( + functionResponseContents[functionResponseContents.length - 1].parts[1] + .functionResponse + ).to.deep.equal({ + name: 'getFarewell', + response: { farewell: 'Bye, Bob' } + }); + expect(greetingSpy).to.be.calledWith({ username: 'Bob' }); + expect(farewellSpy).to.be.calledWith({ username: 'Bob' }); + }); + it('does not call any functions if sequential limit is set to 0', async () => { + const greetingSpy = spy(getGreeting); + const warnStub = stub(logger, 'warn'); + const functionCallResponse = { + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [functionCallPartGreeting] + } + } + ] + }; + const generateContentStreamStub = stub( + generateContentMethods, + 'generateContentStream' + // @ts-ignore + ).callsFake(async (apiSettings, model, params) => { + const parts = params.contents[params.contents.length - 1].parts; + if (parts[0].text?.includes('Bob')) { + return { + firstValue: functionCallResponse, + response: functionCallResponse + }; + } else if (parts[0].functionResponse) { + return { + firstValue: finalResponse, + response: finalResponse + }; + } + }); + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + { + tools: [ + { + functionDeclarations: [ + getFunctionDeclarationGreeting(greetingSpy) + ] + } + ] + }, + { + maxSequentalFunctionCalls: 0 + } + ); + const result = await chatSession.sendMessageStream('My name is Bob'); + // No sense testing the stream fully, it's just stubbed data. + const response = await result.response; + expect( + response.candidates?.[0].content.parts[0].functionCall?.name + ).to.equal('getGreeting'); + expect(generateContentStreamStub).to.be.calledOnce; + expect(warnStub).calledWithMatch('exceeded the limit'); + expect(greetingSpy).to.not.be.called; + }); + }); + }); + describe('_getCallableFunctionCalls()', () => { + it('returns all functions if they have references', async () => { + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + fakeChromeAdapter, + { + tools: [ + { + functionDeclarations: [ + { + name: 'myFunction1', + functionReference: () => {}, + description: 'a function', + parameters: Schema.object({ + properties: { + someParam: Schema.string({ + description: 'some param' + }) + } + }) + }, + { + name: 'myFunction2', + functionReference: () => {}, + description: 'another function', + parameters: Schema.object({ + properties: { + someParam: Schema.string({ + description: 'some param' + }) + } + }) + } + ] + } + ] + } + ); + const query1 = chatSession._getCallableFunctionCalls({ + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [{ functionCall: { name: 'myFunction1', args: {} } }] + } + } + ] + }); + expect(query1?.length).to.equal(1); + const query2 = chatSession._getCallableFunctionCalls({ + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [ + { functionCall: { name: 'myFunction1', args: {} } }, + { functionCall: { name: 'myFunction2', args: {} } } + ] + } + } + ] + }); + expect(query2?.length).to.equal(2); + }); + it('returns undefined if any called function does not have a reference', async () => { + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + fakeChromeAdapter, + { + tools: [ + { + functionDeclarations: [ + { + name: 'myFunction1', + functionReference: () => {}, + description: 'a function', + parameters: Schema.object({ + properties: { + someParam: Schema.string({ + description: 'some param' + }) + } + }) + }, + { + name: 'myFunction2', + description: 'another function', + parameters: Schema.object({ + properties: { + someParam: Schema.string({ + description: 'some param' + }) + } + }) + } + ] + } + ] + } + ); + const query1 = chatSession._getCallableFunctionCalls({ + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [{ functionCall: { name: 'myFunction1', args: {} } }] + } + } + ] + }); + expect(query1?.length).to.equal(1); + const query2 = chatSession._getCallableFunctionCalls({ + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [ + { functionCall: { name: 'myFunction1', args: {} } }, + { functionCall: { name: 'myFunction2', args: {} } } + ] + } + } + ] + }); + expect(query2).to.be.undefined; + }); + }); + describe('_callFunctionsAsNeeded()', () => { + it('calls functions and formats responses', async () => { + const myFunction1 = spy(() => ({ replyParam: 'hi' })); + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + fakeChromeAdapter, + { + tools: [ + { + functionDeclarations: [ + { + name: 'myFunction1', + functionReference: myFunction1, + description: 'a function', + parameters: Schema.object({ + properties: { + someParam: Schema.string({ + description: 'some param' + }) + } + }) + } + ] + } + ] + } + ); + const responseParts = await chatSession._callFunctionsAsNeeded([ + { name: 'myFunction1', args: { someParam: 'a' } } + ]); + expect(myFunction1).to.be.calledWith({ someParam: 'a' }); + expect(responseParts[0].functionResponse).to.deep.equal({ + name: 'myFunction1', + response: { replyParam: 'hi' } + }); + }); + it('calls functions and formats responses (2 functions)', async () => { + const myFunction1 = spy(() => ({ replyParam: 'hi' })); + const myFunction2 = spy(() => ({ replyParam: 'yo' })); + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + fakeChromeAdapter, + { + tools: [ + { + functionDeclarations: [ + { + name: 'myFunction1', + functionReference: myFunction1, + description: 'a function', + parameters: Schema.object({ + properties: { + someParam: Schema.string({ + description: 'some param' + }) + } + }) + }, + { + name: 'myFunction2', + functionReference: myFunction2, + description: 'another function', + parameters: Schema.object({ + properties: { + someParam: Schema.string({ + description: 'some param' + }) + } + }) + } + ] + } + ] + } + ); + const responseParts = await chatSession._callFunctionsAsNeeded([ + { name: 'myFunction1', args: { someParam: 'a' } }, + { name: 'myFunction2', args: { someParam: 'b' } } + ]); + expect(myFunction1).to.be.calledWith({ someParam: 'a' }); + expect(myFunction2).to.be.calledWith({ someParam: 'b' }); + expect(responseParts[0].functionResponse).to.deep.equal({ + name: 'myFunction1', + response: { replyParam: 'hi' } + }); + expect(responseParts[1].functionResponse).to.deep.equal({ + name: 'myFunction2', + response: { replyParam: 'yo' } + }); + }); + it('calls functions and formats responses (one function async)', async () => { + const myFunction1 = spy(() => ({ replyParam: 'hi' })); + const myFunction2 = spy(() => Promise.resolve({ replyParam: 'yo' })); + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + fakeChromeAdapter, + { + tools: [ + { + functionDeclarations: [ + { + name: 'myFunction1', + functionReference: myFunction1, + description: 'a function', + parameters: Schema.object({ + properties: { + someParam: Schema.string({ + description: 'some param' + }) + } + }) + }, + { + name: 'myFunction2', + functionReference: myFunction2, + description: 'another function', + parameters: Schema.object({ + properties: { + someParam: Schema.string({ + description: 'some param' + }) + } + }) + } + ] + } + ] + } + ); + const responseParts = await chatSession._callFunctionsAsNeeded([ + { name: 'myFunction1', args: { someParam: 'a' } }, + { name: 'myFunction2', args: { someParam: 'b' } } + ]); + expect(myFunction1).to.be.calledWith({ someParam: 'a' }); + expect(myFunction2).to.be.calledWith({ someParam: 'b' }); + expect(responseParts[0].functionResponse).to.deep.equal({ + name: 'myFunction1', + response: { replyParam: 'hi' } + }); + expect(responseParts[1].functionResponse).to.deep.equal({ + name: 'myFunction2', + response: { replyParam: 'yo' } + }); + }); + }); }); diff --git a/packages/ai/src/methods/chat-session.ts b/packages/ai/src/methods/chat-session.ts index f4015607f8..63e34e54c1 100644 --- a/packages/ai/src/methods/chat-session.ts +++ b/packages/ai/src/methods/chat-session.ts @@ -16,8 +16,13 @@ */ import { + AIErrorCode, Content, + FunctionCall, + FunctionDeclarationsTool, + FunctionResponsePart, GenerateContentRequest, + GenerateContentResponse, GenerateContentResult, GenerateContentStreamResult, Part, @@ -26,12 +31,16 @@ import { StartChatParams } from '../types'; import { formatNewContent } from '../requests/request-helpers'; -import { formatBlockErrorMessage } from '../requests/response-helpers'; +import { + formatBlockErrorMessage, + getFunctionCalls +} from '../requests/response-helpers'; import { validateChatHistory } from './chat-session-helpers'; import { generateContent, generateContentStream } from './generate-content'; import { ApiSettings } from '../types/internal'; import { logger } from '../logger'; import { ChromeAdapter } from '../types/chrome-adapter'; +import { AIError } from '../errors'; /** * Used to break the internal promise chain when an error is already handled @@ -39,6 +48,12 @@ import { ChromeAdapter } from '../types/chrome-adapter'; */ const SILENT_ERROR = 'SILENT_ERROR'; +/** + * Prevent infinite loop if the model continues to request sequential + * function calls during automatic function calling. + */ +const DEFAULT_MAX_SEQUENTIAL_FUNCTION_CALLS = 10; + /** * ChatSession class that enables sending chat messages and stores * history of sent and received messages so far. @@ -80,63 +95,118 @@ export class ChatSession { } /** - * Sends a chat message and receives a non-streaming - * {@link GenerateContentResult} + * Format Content into a request for generateContent or + * generateContentStream. + * @internal */ - async sendMessage( - request: string | Array, - singleRequestOptions?: SingleRequestOptions - ): Promise { - await this._sendPromise; - const newContent = formatNewContent(request); - const generateContentRequest: GenerateContentRequest = { + _formatRequest( + incomingContent: Content, + tempHistory: Content[] + ): GenerateContentRequest { + return { safetySettings: this.params?.safetySettings, generationConfig: this.params?.generationConfig, tools: this.params?.tools, toolConfig: this.params?.toolConfig, systemInstruction: this.params?.systemInstruction, - contents: [...this._history, newContent] + contents: [...this._history, ...tempHistory, incomingContent] }; + } + + /** + * Sends a chat message and receives a non-streaming + * {@link GenerateContentResult} + */ + async sendMessage( + request: string | Array, + singleRequestOptions?: SingleRequestOptions + ): Promise { let finalResult = {} as GenerateContentResult; + await this._sendPromise; + /** + * Temporarily store multiple turns for cases like automatic function + * calling, only writing them to official history when the entire + * sequence has completed successfully. + */ + const tempHistory: Content[] = []; - this._sendPromise = this._sendPromise - .then(() => - generateContent( + this._sendPromise = this._sendPromise.then(async () => { + let functionCalls: FunctionCall[] | undefined; + let functionCallTurnCount = 0; + const functionCallMaxTurns = + this.requestOptions?.maxSequentalFunctionCalls ?? + DEFAULT_MAX_SEQUENTIAL_FUNCTION_CALLS; + + // Repeats until model returns a response with no function calls + // or until `functionCallMaxTurns` is met or exceeded. + do { + let formattedContent; + + if (functionCalls) { + functionCallTurnCount++; + const functionResponseParts = await this._callFunctionsAsNeeded( + functionCalls + ); + formattedContent = formatNewContent(functionResponseParts); + } else { + formattedContent = formatNewContent(request); + } + const formattedRequest = this._formatRequest( + formattedContent, + tempHistory + ); + + tempHistory.push(formattedContent); + + const result = await generateContent( this._apiSettings, this.model, - generateContentRequest, + formattedRequest, this.chromeAdapter, { ...this.requestOptions, ...singleRequestOptions } - ) - ) - .then(result => { - // TODO: Make this update atomic. If creating `responseContent` throws, - // history will contain the user message but not the response, causing - // validation errors on the next request. - if ( - result.response.candidates && - result.response.candidates.length > 0 - ) { - this._history.push(newContent); - const responseContent: Content = { - parts: result.response.candidates?.[0].content.parts || [], - role: result.response.candidates?.[0].content.role || 'model' - }; - this._history.push(responseContent); - } else { - const blockErrorMessage = formatBlockErrorMessage(result.response); - if (blockErrorMessage) { - logger.warn( - `sendMessage() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.` - ); + ); + if (result) { + finalResult = result; + functionCalls = this._getCallableFunctionCalls(result.response); + if ( + result.response.candidates && + result.response.candidates.length > 0 + ) { + // TODO: Make this update atomic. If creating `responseContent` throws, + // history will contain the user message but not the response, causing + // validation errors on the next request. + const responseContent: Content = { + parts: result.response.candidates?.[0].content.parts || [], + // Response seems to come back without a role set. + role: result.response.candidates?.[0].content.role || 'model' + }; + tempHistory.push(responseContent); + } else { + const blockErrorMessage = formatBlockErrorMessage(result.response); + if (blockErrorMessage) { + logger.warn( + `sendMessage() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.` + ); + } } + } else { + functionCalls = undefined; } - finalResult = result; - }); + } while (functionCalls && functionCallTurnCount < functionCallMaxTurns); + + if (functionCalls && functionCallTurnCount >= functionCallMaxTurns) { + logger.warn( + `Automatic function calling exceeded the limit of` + + ` ${functionCallMaxTurns} function calls. Returning last model response.` + ); + } + }); + await this._sendPromise; + this._history = this._history.concat(tempHistory); return finalResult; } @@ -150,30 +220,90 @@ export class ChatSession { singleRequestOptions?: SingleRequestOptions ): Promise { await this._sendPromise; - const newContent = formatNewContent(request); - const generateContentRequest: GenerateContentRequest = { - safetySettings: this.params?.safetySettings, - generationConfig: this.params?.generationConfig, - tools: this.params?.tools, - toolConfig: this.params?.toolConfig, - systemInstruction: this.params?.systemInstruction, - contents: [...this._history, newContent] - }; - const streamPromise = generateContentStream( - this._apiSettings, - this.model, - generateContentRequest, - this.chromeAdapter, - { - ...this.requestOptions, - ...singleRequestOptions - } - ); + /** + * Temporarily store multiple turns for cases like automatic function + * calling, only writing them to official history when the entire + * sequence has completed successfully. + */ + const tempHistory: Content[] = []; + + const callGenerateContentStream = + async (): Promise => { + let functionCalls: FunctionCall[] | undefined; + let functionCallTurnCount = 0; + const functionCallMaxTurns = + this.requestOptions?.maxSequentalFunctionCalls ?? + DEFAULT_MAX_SEQUENTIAL_FUNCTION_CALLS; + let result: GenerateContentStreamResult & { + firstValue?: GenerateContentResponse; + }; + + // Repeats until model returns a response with no function calls + // or until `functionCallMaxTurns` is met or exceeded. + do { + let formattedContent; + + if (functionCalls) { + functionCallTurnCount++; + const functionResponseParts = await this._callFunctionsAsNeeded( + functionCalls + ); + formattedContent = formatNewContent(functionResponseParts); + } else { + formattedContent = formatNewContent(request); + } + + tempHistory.push(formattedContent); + const formattedRequest = this._formatRequest( + formattedContent, + tempHistory + ); + + result = await generateContentStream( + this._apiSettings, + this.model, + formattedRequest, + this.chromeAdapter, + { + ...this.requestOptions, + ...singleRequestOptions + } + ); + + functionCalls = this._getCallableFunctionCalls(result.firstValue); + + if ( + functionCalls && + result.firstValue && + result.firstValue.candidates && + result.firstValue.candidates.length > 0 + ) { + const responseContent = { + ...result.firstValue.candidates[0].content + }; + if (!responseContent.role) { + responseContent.role = 'model'; + } + tempHistory.push(responseContent); + } + } while (functionCalls && functionCallTurnCount < functionCallMaxTurns); + + if (functionCalls && functionCallTurnCount >= functionCallMaxTurns) { + logger.warn( + `Automatic function calling exceeded the limit of` + + ` ${functionCallMaxTurns} function calls. Returning last model response.` + ); + } + return { stream: result.stream, response: result.response }; + }; - // We hook into the chain to update history, but we don't block the - // return of `streamPromise` to the user. + const streamPromise = callGenerateContentStream(); + + // Add onto the chain. this._sendPromise = this._sendPromise - .then(() => streamPromise) + .then(async () => streamPromise) + // This must be handled to avoid unhandled rejection, but jump + // to the final catch block with a label to not log this error. .catch(_ignored => { // If the initial fetch fails, the user's `streamPromise` rejects. // We swallow the error here to prevent double logging in the final catch. @@ -186,7 +316,7 @@ export class ChatSession { // TODO: Move response validation logic upstream to `stream-reader` so // errors propagate to the user's `result.response` promise. if (response.candidates && response.candidates.length > 0) { - this._history.push(newContent); + this._history = this._history.concat(tempHistory); // TODO: Validate that `response.candidates[0].content` is not null. const responseContent = { ...response.candidates[0].content }; if (!responseContent.role) { @@ -210,4 +340,104 @@ export class ChatSession { }); return streamPromise; } + + /** + * Get function calls that the SDK has references to actually call. + * This is all-or-nothing. If the model is requesting multiple + * function calls, all of them must have references in order for + * automatic function calling to work. + * + * @internal + */ + _getCallableFunctionCalls( + response?: GenerateContentResponse + ): FunctionCall[] | undefined { + const functionDeclarationsTool = this.params?.tools?.find( + tool => (tool as FunctionDeclarationsTool).functionDeclarations + ) as FunctionDeclarationsTool; + if (!functionDeclarationsTool?.functionDeclarations) { + return; + } + const functionCalls = getFunctionCalls(response); + if (!functionCalls) { + return; + } + for (const functionCall of functionCalls) { + const hasFunctionReference = + functionDeclarationsTool.functionDeclarations?.some( + declaration => + declaration.name === functionCall.name && + typeof declaration.functionReference === 'function' + ); + if (!hasFunctionReference) { + return; + } + } + return functionCalls; + } + + /** + * Call user-defined functions if requested by the model, and return + * the response that should be sent to the model. + * @internal + */ + async _callFunctionsAsNeeded( + functionCalls: FunctionCall[] + ): Promise { + const activeCallList = new Map< + string, + { id?: string; results: Promise> } + >(); + const promiseList = []; + const functionDeclarationsTool = this.params?.tools?.find( + tool => (tool as FunctionDeclarationsTool).functionDeclarations + ) as FunctionDeclarationsTool; + if ( + functionDeclarationsTool && + functionDeclarationsTool.functionDeclarations + ) { + for (const functionCall of functionCalls) { + const functionDeclaration = + functionDeclarationsTool.functionDeclarations.find( + declaration => declaration.name === functionCall.name + ); + if (functionDeclaration?.functionReference) { + const results = Promise.resolve( + functionDeclaration.functionReference!(functionCall.args) + ).catch(e => { + const wrappedError = new AIError( + AIErrorCode.ERROR, + `Error in user-defined function "${functionDeclaration.name}": ${ + (e as Error).message + }` + ); + wrappedError.stack = (e as Error).stack; + throw wrappedError; + }); + activeCallList.set(functionCall.name, { + id: functionCall.id, + results + }); + promiseList.push(results); + } + } + // Wait for promises to finish. + await Promise.all(promiseList); + const functionResponseParts = []; + for (const [name, callData] of activeCallList) { + functionResponseParts.push({ + functionResponse: { + name, + response: await callData.results + } + }); + } + return functionResponseParts; + } else { + throw new AIError( + AIErrorCode.REQUEST_ERROR, + `No function declarations were provided in "tools".` + ); + } + } } diff --git a/packages/ai/src/methods/generate-content.ts b/packages/ai/src/methods/generate-content.ts index b3065a4917..8b7efc3ef1 100644 --- a/packages/ai/src/methods/generate-content.ts +++ b/packages/ai/src/methods/generate-content.ts @@ -62,7 +62,9 @@ export async function generateContentStream( params: GenerateContentRequest, chromeAdapter?: ChromeAdapter, singleRequestOptions?: SingleRequestOptions -): Promise { +): Promise< + GenerateContentStreamResult & { firstValue?: GenerateContentResponse } +> { const callResult = await callCloudOrDevice( params, chromeAdapter, diff --git a/packages/ai/src/models/generative-model.test.ts b/packages/ai/src/models/generative-model.test.ts index a7d8eb3ff1..fb90e1fbf0 100644 --- a/packages/ai/src/models/generative-model.test.ts +++ b/packages/ai/src/models/generative-model.test.ts @@ -667,7 +667,7 @@ describe('GenerativeModel dispatch logic', () => { makeRequestStub = stub(request, 'makeRequest').resolves( getMockResponseStreaming( 'vertexAI', - 'unary-success-basic-reply-short.json' + 'streaming-success-basic-reply-short.txt' ) as Response ); } else { @@ -686,7 +686,10 @@ describe('GenerativeModel dispatch logic', () => { isAvailable: stub(), generateContent: stub().resolves(new Response(JSON.stringify({}))), generateContentStream: stub().resolves( - new Response(new ReadableStream()) + getMockResponseStreaming( + 'vertexAI', + 'streaming-success-basic-reply-short.txt' + ) as Response ), countTokens: stub().resolves(new Response(JSON.stringify({}))), mode: InferenceMode.PREFER_ON_DEVICE diff --git a/packages/ai/src/models/generative-model.ts b/packages/ai/src/models/generative-model.ts index 6f04046cf1..20922f0004 100644 --- a/packages/ai/src/models/generative-model.ts +++ b/packages/ai/src/models/generative-model.ts @@ -117,7 +117,7 @@ export class GenerativeModel extends AIModel { singleRequestOptions?: SingleRequestOptions ): Promise { const formattedParams = formatGenerateContentInput(request); - return generateContentStream( + const { stream, response } = await generateContentStream( this._apiSettings, this.model, { @@ -135,6 +135,7 @@ export class GenerativeModel extends AIModel { ...singleRequestOptions } ); + return { stream, response }; } /** diff --git a/packages/ai/src/requests/response-helpers.ts b/packages/ai/src/requests/response-helpers.ts index bb3748f6bc..34d2013007 100644 --- a/packages/ai/src/requests/response-helpers.ts +++ b/packages/ai/src/requests/response-helpers.ts @@ -184,8 +184,11 @@ export function getText( * Returns every {@link FunctionCall} associated with first candidate. */ export function getFunctionCalls( - response: GenerateContentResponse + response?: GenerateContentResponse ): FunctionCall[] | undefined { + if (!response) { + return undefined; + } const functionCalls: FunctionCall[] = []; if (response.candidates?.[0].content?.parts) { for (const part of response.candidates?.[0].content?.parts) { diff --git a/packages/ai/src/requests/stream-reader.test.ts b/packages/ai/src/requests/stream-reader.test.ts index ca3c2cdcfe..96ac4c9f24 100644 --- a/packages/ai/src/requests/stream-reader.test.ts +++ b/packages/ai/src/requests/stream-reader.test.ts @@ -87,11 +87,17 @@ describe('processStream', () => { 'vertexAI', 'streaming-success-basic-reply-short.txt' ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); for await (const response of result.stream) { expect(response.text()).to.not.be.empty; expect(response.inferenceSource).to.equal(InferenceSource.IN_CLOUD); } + expect(result.firstValue?.candidates?.[0].content.parts[0].text).to.equal( + 'Cheyenne' + ); const aggregatedResponse = await result.response; expect(aggregatedResponse.text()).to.include('Cheyenne'); expect(aggregatedResponse.inferenceSource).to.equal( @@ -103,7 +109,7 @@ describe('processStream', () => { 'vertexAI', 'streaming-success-basic-reply-short.txt' ); - const result = processStream( + const result = await processStream( fakeResponse as Response, fakeApiSettings, InferenceSource.ON_DEVICE @@ -123,7 +129,13 @@ describe('processStream', () => { 'vertexAI', 'streaming-success-basic-reply-long.txt' ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); + expect(result.firstValue?.candidates?.[0].content.parts[0].text).to.equal( + 'Okay' + ); for await (const response of result.stream) { expect(response.text()).to.not.be.empty; } @@ -137,7 +149,10 @@ describe('processStream', () => { 'streaming-success-basic-reply-long.txt', 1e6 ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); for await (const response of result.stream) { expect(response.text()).to.not.be.empty; } @@ -150,7 +165,10 @@ describe('processStream', () => { 'vertexAI', 'streaming-success-utf8.txt' ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); for await (const response of result.stream) { expect(response.text()).to.not.be.empty; } @@ -163,7 +181,10 @@ describe('processStream', () => { 'vertexAI', 'streaming-success-function-call-short.txt' ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); for await (const response of result.stream) { expect(response.text()).to.be.empty; expect(response.functionCalls()).to.be.deep.equal([ @@ -187,7 +208,10 @@ describe('processStream', () => { 'vertexAI', 'streaming-failure-finish-reason-safety.txt' ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); const aggregatedResponse = await result.response; expect(aggregatedResponse.candidates?.[0].finishReason).to.equal('SAFETY'); expect(aggregatedResponse.text).to.throw('SAFETY'); @@ -200,7 +224,10 @@ describe('processStream', () => { 'vertexAI', 'streaming-failure-prompt-blocked-safety.txt' ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); const aggregatedResponse = await result.response; expect(aggregatedResponse.text).to.throw('SAFETY'); expect(aggregatedResponse.promptFeedback?.blockReason).to.equal('SAFETY'); @@ -213,7 +240,10 @@ describe('processStream', () => { 'vertexAI', 'streaming-failure-empty-content.txt' ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); const aggregatedResponse = await result.response; expect(aggregatedResponse.text()).to.equal(''); for await (const response of result.stream) { @@ -226,7 +256,10 @@ describe('processStream', () => { 'streaming-success-empty-parts.txt' ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); for await (const response of result.stream) { expect(response.candidates?.[0].content.parts.length).to.be.at.least(1); } @@ -239,7 +272,10 @@ describe('processStream', () => { 'vertexAI', 'streaming-success-unknown-safety-enum.txt' ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); const aggregatedResponse = await result.response; expect(aggregatedResponse.text()).to.include('Cats'); for await (const response of result.stream) { @@ -251,7 +287,10 @@ describe('processStream', () => { 'vertexAI', 'streaming-failure-recitation-no-content.txt' ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); const aggregatedResponse = await result.response; expect(aggregatedResponse.text).to.throw('RECITATION'); expect(aggregatedResponse.candidates?.[0].content.parts[0].text).to.include( @@ -270,7 +309,10 @@ describe('processStream', () => { 'vertexAI', 'streaming-success-citations.txt' ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); const aggregatedResponse = await result.response; expect(aggregatedResponse.text()).to.include('Quantum mechanics is'); expect( @@ -290,7 +332,10 @@ describe('processStream', () => { 'vertexAI', 'streaming-success-empty-text-part.txt' ); - const result = processStream(fakeResponse as Response, fakeApiSettings); + const result = await processStream( + fakeResponse as Response, + fakeApiSettings + ); const aggregatedResponse = await result.response; expect(aggregatedResponse.text()).to.equal('1'); expect(aggregatedResponse.candidates?.length).to.equal(1); diff --git a/packages/ai/src/requests/stream-reader.ts b/packages/ai/src/requests/stream-reader.ts index 7af4d857bc..bc94f10ff0 100644 --- a/packages/ai/src/requests/stream-reader.ts +++ b/packages/ai/src/requests/stream-reader.ts @@ -44,11 +44,13 @@ const responseLineRE = /^data\: (.*)(?:\n\n|\r\r|\r\n\r\n)/; * * @param response - Response from a fetch call */ -export function processStream( +export async function processStream( response: Response, apiSettings: ApiSettings, inferenceSource?: InferenceSource -): GenerateContentStreamResult { +): Promise< + GenerateContentStreamResult & { firstValue?: GenerateContentResponse } +> { const inputStream = response.body!.pipeThrough( new TextDecoderStream('utf8', { fatal: true }) ); @@ -59,10 +61,51 @@ export function processStream( // We split the stream so the user can iterate over partial results (stream1) // while we aggregate the full result for history/final response (stream2). const [stream1, stream2] = responseStream.tee(); - + const { response: internalResponse, firstValue } = + await processStreamInternal(stream2, apiSettings, inferenceSource); return { stream: generateResponseSequence(stream1, apiSettings, inferenceSource), - response: getResponsePromise(stream2, apiSettings, inferenceSource) + response: internalResponse, + firstValue + }; +} + +/** + * Consumes streams teed from the input stream for internal needs. + * The streams need to be teed because each stream can only be consumed + * by one reader. + * + * "streamForPeek" + * This tee is used to peek at the first value for relevant information + * that we need to evaluate before returning the stream handle to the + * client. For example, we need to check if the response is a function + * call that may need to be handled by automatic function calling before + * returning a response to the client. + * + * "streamForAggregation" + * We iterate through this tee independently from the user and aggregate + * it into a single response when the stream is complete. We need this + * aggregate object to add to chat history when using ChatSession. It's + * also provided to the user if they want it. + */ +async function processStreamInternal( + stream: ReadableStream, + apiSettings: ApiSettings, + inferenceSource?: InferenceSource +): Promise<{ + firstValue?: GenerateContentResponse; + response: Promise; +}> { + const [streamForPeek, streamForAggregation] = stream.tee(); + const reader = streamForPeek.getReader(); + const { value } = await reader.read(); + return { + firstValue: value, + response: getResponsePromise( + streamForAggregation, + apiSettings, + inferenceSource + ) }; } diff --git a/packages/ai/src/types/content.ts b/packages/ai/src/types/content.ts index b51dcd9c69..cd5ce878a1 100644 --- a/packages/ai/src/types/content.ts +++ b/packages/ai/src/types/content.ts @@ -265,6 +265,7 @@ export interface FunctionResponse { id?: string; name: string; response: object; + parts?: Part[]; } /** diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index 0692a9cc1d..c4d7b24d2c 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -252,6 +252,15 @@ export interface RequestOptions { * (used regardless of your chosen Gemini API provider). */ baseUrl?: string; + /** + * Limits amount of sequential function calls the SDK can make during automatic + * function calling, in order to prevent infinite loops. If not specified, + * this value defaults to 10. + * + * When it reaches this limit, it will return the last response received + * from the model, whether it is a text response or further function calls. + */ + maxSequentalFunctionCalls?: number; } /** @@ -332,6 +341,12 @@ export interface FunctionDeclaration { * case-sensitive. For a function with no parameters, this can be left unset. */ parameters?: ObjectSchema | ObjectSchemaRequest; + /** + * Reference to an actual function to call. Specifying this will cause the + * function to be called automatically when requested by the model. + */ + // eslint-disable-next-line @typescript-eslint/ban-types + functionReference?: Function; } /** From f0b0398eb8fad06161c8133143eba515a4501c6e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Feb 2026 11:45:35 -0800 Subject: [PATCH 064/174] chore(deps): update dependency @rollup/plugin-strip to v3 (#8745) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- packages/auth/package.json | 2 +- yarn.lock | 45 +++++++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/packages/auth/package.json b/packages/auth/package.json index 2fefbc687f..c9deabf6d3 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -133,7 +133,7 @@ "devDependencies": { "@firebase/app": "0.14.8", "@rollup/plugin-json": "6.1.0", - "@rollup/plugin-strip": "2.1.0", + "@rollup/plugin-strip": "3.0.4", "@types/express": "4.17.21", "chromedriver": "119.0.1", "cookie-store": "4.0.0-next.4", diff --git a/yarn.lock b/yarn.lock index 907accd333..01fa806c07 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2673,14 +2673,14 @@ "@rollup/pluginutils" "^5.0.1" magic-string "^0.30.3" -"@rollup/plugin-strip@2.1.0": - version "2.1.0" - resolved "https://registry.npmjs.org/@rollup/plugin-strip/-/plugin-strip-2.1.0.tgz#04c2d2ccfb2c6b192bb70447fbf26e336379a333" - integrity sha512-OKlIlXMFlH4nVxq0beNSIKVw0LkpNUpVjjvfzH5OAOAR5dhLZgLZBzwYX4ifIAs18YDrreMcZH4xnKmW9fI2AQ== +"@rollup/plugin-strip@3.0.4": + version "3.0.4" + resolved "https://registry.npmjs.org/@rollup/plugin-strip/-/plugin-strip-3.0.4.tgz#ad623cc18cf305b484f8bf38fde4ae855c1229e4" + integrity sha512-LDRV49ZaavxUo2YoKKMQjCxzCxugu1rCPQa0lDYBOWLj6vtzBMr8DcoJjsmg+s450RbKbe3qI9ZLaSO+O1oNbg== dependencies: - "@rollup/pluginutils" "^3.1.0" - estree-walker "^2.0.1" - magic-string "^0.25.7" + "@rollup/pluginutils" "^5.0.1" + estree-walker "^2.0.2" + magic-string "^0.30.3" "@rollup/plugin-terser@0.4.4": version "0.4.4" @@ -15351,7 +15351,7 @@ string-argv@~0.3.1: resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -15369,6 +15369,15 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -15432,7 +15441,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -15453,6 +15462,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -17137,7 +17153,7 @@ workerpool@6.2.0: resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -17171,6 +17187,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 46fa57f9e6df52aff114c74b011a0b54c5a8db7c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Feb 2026 11:46:31 -0800 Subject: [PATCH 065/174] fix(deps): update dependency @rollup/plugin-virtual to v3 (#8771) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- repo-scripts/size-analysis/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index da72e290ea..62b47514e8 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -30,7 +30,7 @@ "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-node-resolve": "16.0.0", - "@rollup/plugin-virtual": "2.1.0", + "@rollup/plugin-virtual": "3.0.2", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/yarn.lock b/yarn.lock index 01fa806c07..946f8af55b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2691,10 +2691,10 @@ smob "^1.0.0" terser "^5.17.4" -"@rollup/plugin-virtual@2.1.0": - version "2.1.0" - resolved "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-2.1.0.tgz#a77bfd0dff74f0203401c75287ff4d1a1cfbc816" - integrity sha512-CPPAtlKT53HFqC8jFHb/V5WErpU8Hrq2TyCR0A7kPQMlF2wNUf0o1xuAc+Qxj8NCZM0Z3Yvl+FbUXfJjVWqDwA== +"@rollup/plugin-virtual@3.0.2": + version "3.0.2" + resolved "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz#17e17eeecb4c9fa1c0a6e72c9e5f66382fddbb82" + integrity sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A== "@rollup/pluginutils@^3.0.9", "@rollup/pluginutils@^3.1.0": version "3.1.0" From 920624ade0431ae2fd9998a179fbe7111b723a8b Mon Sep 17 00:00:00 2001 From: Morgan Chen Date: Fri, 20 Feb 2026 07:33:05 -0800 Subject: [PATCH 066/174] Use environment for wdr tokens (#9578) * use environment for wdr tokens * missed a file --- .github/workflows/canary-deploy.yml | 1 + .github/workflows/prerelease-manual-deploy.yml | 1 + .github/workflows/release-pr.yml | 1 + .github/workflows/release-prod.yml | 1 + .github/workflows/release-staging.yml | 1 + 5 files changed, 5 insertions(+) diff --git a/.github/workflows/canary-deploy.yml b/.github/workflows/canary-deploy.yml index 0d93ceefad..043a9f9f06 100644 --- a/.github/workflows/canary-deploy.yml +++ b/.github/workflows/canary-deploy.yml @@ -22,6 +22,7 @@ on: jobs: deploy: + environment: release name: Canary Deploy runs-on: ubuntu-latest diff --git a/.github/workflows/prerelease-manual-deploy.yml b/.github/workflows/prerelease-manual-deploy.yml index 9d3e517dd5..7b44fce4d4 100644 --- a/.github/workflows/prerelease-manual-deploy.yml +++ b/.github/workflows/prerelease-manual-deploy.yml @@ -25,6 +25,7 @@ on: required: true jobs: deploy: + environment: release name: Prerelease Deploy runs-on: ubuntu-latest diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml index a999258a88..249e2ea042 100644 --- a/.github/workflows/release-pr.yml +++ b/.github/workflows/release-pr.yml @@ -22,6 +22,7 @@ on: jobs: release: + environment: release name: Create Release PR runs-on: ubuntu-latest permissions: diff --git a/.github/workflows/release-prod.yml b/.github/workflows/release-prod.yml index 9c887e2940..b04595bdfc 100644 --- a/.github/workflows/release-prod.yml +++ b/.github/workflows/release-prod.yml @@ -25,6 +25,7 @@ on: jobs: deploy: + environment: release name: Production Release runs-on: ubuntu-latest # Allow GITHUB_TOKEN to have write permissions diff --git a/.github/workflows/release-staging.yml b/.github/workflows/release-staging.yml index 4f061fa423..1feb8734a5 100644 --- a/.github/workflows/release-staging.yml +++ b/.github/workflows/release-staging.yml @@ -42,6 +42,7 @@ env: jobs: deploy: + environment: release name: Staging Release runs-on: ubuntu-latest # Block this workflow if run on a non-release branch. From f12668659e499ab5d90676a07ab692c75569fea1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:19:47 -0800 Subject: [PATCH 067/174] fix(deps): update dependency @rushstack/node-core-library to v5 (#8816) * fix(deps): update dependency @rushstack/node-core-library to v5 * Fix method name --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Christina Holland --- repo-scripts/api-documenter/package.json | 2 +- .../api-documenter/src/cli/BaseAction.ts | 2 +- yarn.lock | 50 ++++++++----------- 3 files changed, 24 insertions(+), 30 deletions(-) diff --git a/repo-scripts/api-documenter/package.json b/repo-scripts/api-documenter/package.json index 6305cbf937..39573bdd6f 100644 --- a/repo-scripts/api-documenter/package.json +++ b/repo-scripts/api-documenter/package.json @@ -23,7 +23,7 @@ "dependencies": { "api-extractor-model-me": "0.1.1", "@microsoft/tsdoc": "0.12.24", - "@rushstack/node-core-library": "3.66.1", + "@rushstack/node-core-library": "5.19.1", "@rushstack/ts-command-line": "4.23.3", "colors": "~1.4.0", "resolve": "~1.22.0", diff --git a/repo-scripts/api-documenter/src/cli/BaseAction.ts b/repo-scripts/api-documenter/src/cli/BaseAction.ts index 9d33c9c490..4d4050401c 100644 --- a/repo-scripts/api-documenter/src/cli/BaseAction.ts +++ b/repo-scripts/api-documenter/src/cli/BaseAction.ts @@ -105,7 +105,7 @@ export abstract class BaseAction extends CommandLineAction { const addFileNameSuffix: boolean = this._fileNameSuffixParameter.value; - for (const filename of FileSystem.readFolder(inputFolder)) { + for (const filename of FileSystem.readFolderItemNames(inputFolder)) { if (filename.match(/\.api\.json$/i)) { console.log(`Reading ${filename}`); const filenamePath: string = path.join(inputFolder, filename); diff --git a/yarn.lock b/yarn.lock index 946f8af55b..6a6ca5c3cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2742,28 +2742,29 @@ timsort "~0.3.0" z-schema "~3.18.3" -"@rushstack/node-core-library@3.66.1": - version "3.66.1" - resolved "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.66.1.tgz#a1c61a47ab626d5bd435fea33fe938f47007a8de" - integrity sha512-ker69cVKAoar7MMtDFZC4CzcDxjwqIhFzqEnYI5NRN/8M3om6saWCVx/A7vL2t/jFCJsnzQplRDqA7c78pytng== +"@rushstack/node-core-library@5.10.2": + version "5.10.2" + resolved "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.10.2.tgz#8d12bc5bd9244ea57f441877246efb0a1b7b7df6" + integrity sha512-xOF/2gVJZTfjTxbo4BDj9RtQq/HFnrrKdtem4JkyRLnwsRz2UDTg8gA1/et10fBx5RxmZD9bYVGST69W8ME5OQ== dependencies: - colors "~1.2.1" + ajv "~8.13.0" + ajv-draft-04 "~1.0.0" + ajv-formats "~3.0.1" fs-extra "~7.0.1" import-lazy "~4.0.0" jju "~1.4.0" resolve "~1.22.1" semver "~7.5.4" - z-schema "~5.0.2" -"@rushstack/node-core-library@5.10.2": - version "5.10.2" - resolved "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.10.2.tgz#8d12bc5bd9244ea57f441877246efb0a1b7b7df6" - integrity sha512-xOF/2gVJZTfjTxbo4BDj9RtQq/HFnrrKdtem4JkyRLnwsRz2UDTg8gA1/et10fBx5RxmZD9bYVGST69W8ME5OQ== +"@rushstack/node-core-library@5.19.1": + version "5.19.1" + resolved "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.19.1.tgz#2bafbb81cdd886798db2adc44ad41506fa80195a" + integrity sha512-ESpb2Tajlatgbmzzukg6zyAhH+sICqJR2CNXNhXcEbz6UGCQfrKCtkxOpJTftWc8RGouroHG0Nud1SJAszvpmA== dependencies: ajv "~8.13.0" ajv-draft-04 "~1.0.0" ajv-formats "~3.0.1" - fs-extra "~7.0.1" + fs-extra "~11.3.0" import-lazy "~4.0.0" jju "~1.4.0" resolve "~1.22.1" @@ -7914,6 +7915,15 @@ fs-extra@^9.0.0, fs-extra@^9.1.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs-extra@~11.3.0: + version "11.3.3" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz#a27da23b72524e81ac6c3815cc0179b8c74c59ee" + integrity sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-minipass@^1.2.7: version "1.2.7" resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -10876,7 +10886,7 @@ lodash.isboolean@^3.0.3: resolved "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== -lodash.isequal@^4.0.0, lodash.isequal@^4.5.0: +lodash.isequal@^4.0.0: version "4.5.0" resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== @@ -16685,11 +16695,6 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" -validator@^13.7.0: - version "13.12.0" - resolved "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz#7d78e76ba85504da3fee4fd1922b385914d4b35f" - integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg== - validator@^8.0.0: version "8.2.0" resolved "https://registry.npmjs.org/validator/-/validator-8.2.0.tgz#3c1237290e37092355344fef78c231249dab77b9" @@ -17494,17 +17499,6 @@ z-schema@~3.18.3: optionalDependencies: commander "^2.7.1" -z-schema@~5.0.2: - version "5.0.6" - resolved "https://registry.npmjs.org/z-schema/-/z-schema-5.0.6.tgz#46d6a687b15e4a4369e18d6cb1c7b8618fc256c5" - integrity sha512-+XR1GhnWklYdfr8YaZv/iu+vY+ux7V5DS5zH1DQf6bO5ufrt/5cgNhVO5qyhsjFXvsqQb/f08DWE9b6uPscyAg== - dependencies: - lodash.get "^4.4.2" - lodash.isequal "^4.5.0" - validator "^13.7.0" - optionalDependencies: - commander "^10.0.0" - zip-stream@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz#e141b930ed60ccaf5d7fa9c8260e0d1748a2bbfb" From f8996c4cec849db4d6f9dad1df728a49cc063b96 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Fri, 20 Feb 2026 19:26:08 -0500 Subject: [PATCH 068/174] feat(firestore): add string pipeline expressions (#9479) --- .changeset/eighty-ghosts-pull.md | 6 + .../firestore-lite-pipelines.api.md | 48 ++ common/api-review/firestore-pipelines.api.md | 48 ++ .../firestore_lite_pipelines.expression.md | 218 +++++++++ docs-devsite/firestore_lite_pipelines.md | 448 ++++++++++++++++++ .../firestore_pipelines.expression.md | 218 +++++++++ docs-devsite/firestore_pipelines.md | 448 ++++++++++++++++++ .../firestore/lite/pipelines/pipelines.ts | 6 + packages/firestore/src/api_pipelines.ts | 6 + .../firestore/src/lite-api/expressions.ts | 432 +++++++++++++++++ .../test/integration/api/pipeline.test.ts | 215 ++++++++- packages/firestore/test/lite/pipeline.test.ts | 193 +++++++- 12 files changed, 2273 insertions(+), 13 deletions(-) create mode 100644 .changeset/eighty-ghosts-pull.md diff --git a/.changeset/eighty-ghosts-pull.md b/.changeset/eighty-ghosts-pull.md new file mode 100644 index 0000000000..e7425c2f0d --- /dev/null +++ b/.changeset/eighty-ghosts-pull.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/firestore': minor +--- + +Support added for the following string Pipeline expressions: `stringRepeat`, `stringReplaceOne`, `stringReplaceAll`, `stringIndexOf`, `ltrim`, `rtrim`. diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index 5495e6c3a8..0d7da1ee24 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -510,6 +510,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ logicalMinimum(second: Expression | unknown, ...others: Array): FunctionExpression; /* Excluded from this release type: _readUserData */ + ltrim(valueToTrim?: string | Expression | Bytes): FunctionExpression; + /* Excluded from this release type: _readUserData */ mapGet(subfield: string): FunctionExpression; /* Excluded from this release type: _readUserData */ mapMerge(secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; @@ -564,6 +566,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ round(decimalPlaces: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ + rtrim(valueToTrim?: string | Expression | Bytes): FunctionExpression; + /* Excluded from this release type: _readUserData */ split(delimiter: string): FunctionExpression; /* Excluded from this release type: _readUserData */ split(delimiter: Expression): FunctionExpression; @@ -580,6 +584,14 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ stringContains(expr: Expression): BooleanExpression; /* Excluded from this release type: _readUserData */ + stringIndexOf(search: string | Expression | Bytes): FunctionExpression; + /* Excluded from this release type: _readUserData */ + stringRepeat(repetitions: number | Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + stringReplaceAll(find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; + /* Excluded from this release type: _readUserData */ + stringReplaceOne(find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; + /* Excluded from this release type: _readUserData */ stringReverse(): FunctionExpression; /* Excluded from this release type: _readUserData */ substring(position: number, length?: number): FunctionExpression; @@ -824,6 +836,12 @@ export function logicalMinimum(first: Expression, second: Expression | unknown, // @beta export function logicalMinimum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +// @beta +export function ltrim(fieldName: string, valueToTrim?: string | Expression | Bytes): FunctionExpression; + +// @beta +export function ltrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; + // @beta export function map(elements: Record): FunctionExpression; @@ -1093,6 +1111,12 @@ export function round(fieldName: string, decimalPlaces: number | Expression): Fu // @beta export function round(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; +// @beta +export function rtrim(fieldName: string, valueToTrim?: string | Expression | Bytes): FunctionExpression; + +// @beta +export function rtrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; + // @beta export type SampleStageOptions = StageOptions & OneOf<{ percentage: number; @@ -1170,6 +1194,30 @@ export function stringContains(stringExpression: Expression, substring: string): // @beta export function stringContains(stringExpression: Expression, substring: Expression): BooleanExpression; +// @beta +export function stringIndexOf(fieldName: string, search: string | Expression | Bytes): FunctionExpression; + +// @beta +export function stringIndexOf(expression: Expression, search: string | Expression | Bytes): FunctionExpression; + +// @beta +export function stringRepeat(fieldName: string, repetitions: number | Expression): FunctionExpression; + +// @beta +export function stringRepeat(expression: Expression, repetitions: number | Expression): FunctionExpression; + +// @beta +export function stringReplaceAll(fieldName: string, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; + +// @beta +export function stringReplaceAll(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; + +// @beta +export function stringReplaceOne(fieldName: string, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; + +// @beta +export function stringReplaceOne(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; + // @beta export function stringReverse(stringExpression: Expression): FunctionExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 366ef7914e..6ebe182f5d 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -513,6 +513,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ logicalMinimum(second: Expression | unknown, ...others: Array): FunctionExpression; /* Excluded from this release type: _readUserData */ + ltrim(valueToTrim?: string | Expression | Bytes): FunctionExpression; + /* Excluded from this release type: _readUserData */ mapGet(subfield: string): FunctionExpression; /* Excluded from this release type: _readUserData */ mapMerge(secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; @@ -567,6 +569,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ round(decimalPlaces: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ + rtrim(valueToTrim?: string | Expression | Bytes): FunctionExpression; + /* Excluded from this release type: _readUserData */ split(delimiter: string): FunctionExpression; /* Excluded from this release type: _readUserData */ split(delimiter: Expression): FunctionExpression; @@ -583,6 +587,14 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ stringContains(expr: Expression): BooleanExpression; /* Excluded from this release type: _readUserData */ + stringIndexOf(search: string | Expression | Bytes): FunctionExpression; + /* Excluded from this release type: _readUserData */ + stringRepeat(repetitions: number | Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + stringReplaceAll(find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; + /* Excluded from this release type: _readUserData */ + stringReplaceOne(find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; + /* Excluded from this release type: _readUserData */ stringReverse(): FunctionExpression; /* Excluded from this release type: _readUserData */ substring(position: number, length?: number): FunctionExpression; @@ -827,6 +839,12 @@ export function logicalMinimum(first: Expression, second: Expression | unknown, // @beta export function logicalMinimum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; +// @beta +export function ltrim(fieldName: string, valueToTrim?: string | Expression | Bytes): FunctionExpression; + +// @beta +export function ltrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; + // @beta export function map(elements: Record): FunctionExpression; @@ -1130,6 +1148,12 @@ export function round(fieldName: string, decimalPlaces: number | Expression): Fu // @beta export function round(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; +// @beta +export function rtrim(fieldName: string, valueToTrim?: string | Expression | Bytes): FunctionExpression; + +// @beta +export function rtrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; + // @beta export type SampleStageOptions = StageOptions & OneOf<{ percentage: number; @@ -1207,6 +1231,30 @@ export function stringContains(stringExpression: Expression, substring: string): // @beta export function stringContains(stringExpression: Expression, substring: Expression): BooleanExpression; +// @beta +export function stringIndexOf(fieldName: string, search: string | Expression | Bytes): FunctionExpression; + +// @beta +export function stringIndexOf(expression: Expression, search: string | Expression | Bytes): FunctionExpression; + +// @beta +export function stringRepeat(fieldName: string, repetitions: number | Expression): FunctionExpression; + +// @beta +export function stringRepeat(expression: Expression, repetitions: number | Expression): FunctionExpression; + +// @beta +export function stringReplaceAll(fieldName: string, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; + +// @beta +export function stringReplaceAll(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; + +// @beta +export function stringReplaceOne(fieldName: string, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; + +// @beta +export function stringReplaceOne(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; + // @beta export function stringReverse(stringExpression: Expression): FunctionExpression; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index 42d7215392..0a16f00814 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -111,6 +111,7 @@ field("optional_field").ifAbsent(field('default_field')) | [log10()](./firestore_lite_pipelines.expression.md#expressionlog10) | | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | | [logicalMaximum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalmaximum) | | (Public Preview) Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. | | [logicalMinimum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalminimum) | | (Public Preview) Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. | +| [ltrim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressionltrim) | | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | | [mapGet(subfield)](./firestore_lite_pipelines.expression.md#expressionmapget) | | (Public Preview) Accesses a value from a map (object) field using the provided key. | | [mapMerge(secondMap, otherMaps)](./firestore_lite_pipelines.expression.md#expressionmapmerge) | | (Public Preview) Creates an expression that merges multiple map values. | | [mapRemove(key)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | @@ -138,6 +139,7 @@ field("optional_field").ifAbsent(field('default_field')) | [round()](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | | [round(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | | [round(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [rtrim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressionrtrim) | | (Public Preview) Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | | [split(delimiter)](./firestore_lite_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | | [split(delimiter)](./firestore_lite_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | | [sqrt()](./firestore_lite_pipelines.expression.md#expressionsqrt) | | (Public Preview) Creates an expression that computes the square root of a numeric value. | @@ -146,6 +148,10 @@ field("optional_field").ifAbsent(field('default_field')) | [stringConcat(secondString, otherStrings)](./firestore_lite_pipelines.expression.md#expressionstringconcat) | | (Public Preview) Creates an expression that concatenates string expressions together. | | [stringContains(substring)](./firestore_lite_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified substring. | | [stringContains(expr)](./firestore_lite_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains the string represented by another expression. | +| [stringIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionstringindexof) | | (Public Preview) Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | +| [stringRepeat(repetitions)](./firestore_lite_pipelines.expression.md#expressionstringrepeat) | | (Public Preview) Creates an expression that repeats a string or byte array a specified number of times. | +| [stringReplaceAll(find, replacement)](./firestore_lite_pipelines.expression.md#expressionstringreplaceall) | | (Public Preview) Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | +| [stringReplaceOne(find, replacement)](./firestore_lite_pipelines.expression.md#expressionstringreplaceone) | | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | | [stringReverse()](./firestore_lite_pipelines.expression.md#expressionstringreverse) | | (Public Preview) Creates an expression that reverses a string. | | [substring(position, length)](./firestore_lite_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | | [substring(position, length)](./firestore_lite_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | @@ -2305,6 +2311,43 @@ field("timestamp").logicalMinimum(Function.currentTimestamp()); ``` +## Expression.ltrim() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. + +Signature: + +```typescript +ltrim(valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the trimmed string. + +### 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('"'); + +``` + ## Expression.mapGet() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3206,6 +3249,43 @@ field("price").round(constant(2)); ``` +## Expression.rtrim() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. + +Signature: + +```typescript +rtrim(valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the trimmed 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('"'); + +``` + ## Expression.split() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3472,6 +3552,144 @@ field("description").stringContains(field("keyword")); ``` +## Expression.stringIndexOf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that finds the index of the first occurrence of a substring or byte sequence. + +Signature: + +```typescript +stringIndexOf(search: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the index of the first occurrence. + +### Example + + +```typescript +// Find the index of "foo" in the 'text' field +field("text").stringIndexOf("foo"); + +``` + +## Expression.stringRepeat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that repeats a string or byte array a specified number of times. + +Signature: + +```typescript +stringRepeat(repetitions: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| repetitions | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The number of times to repeat the string or byte array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the repeated string or byte array. + +### Example + + +```typescript +// Repeat the 'label' field 3 times +field("label").stringRepeat(3); + +``` + +## Expression.stringReplaceAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. + +Signature: + +```typescript +stringReplaceAll(find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| find | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The replacement string or byte sequence. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the string or byte array with replacements. + +### Example + + +```typescript +// Replace all occurrences of "foo" with "bar" in the 'text' field +field("text").stringReplaceAll("foo", "bar"); + +``` + +## Expression.stringReplaceOne() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. + +Signature: + +```typescript +stringReplaceOne(find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| find | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The replacement string or byte sequence. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the string or byte array with the replacement. + +### Example + + +```typescript +// Replace the first occurrence of "foo" with "bar" in the 'text' field +field("text").stringReplaceOne("foo", "bar"); + +``` + ## Expression.stringReverse() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 763c38a5fc..8d1db97e93 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -90,15 +90,21 @@ https://github.com/firebase/firebase-js-sdk | [log(expression, base)](./firestore_lite_pipelines.md#log_ac183e2) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. | | [log(expression, base)](./firestore_lite_pipelines.md#log_1894737) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. | | [log10(expression)](./firestore_lite_pipelines.md#log10_1138a27) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | +| [ltrim(expression, valueToTrim)](./firestore_lite_pipelines.md#ltrim_775e2f2) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | | [maximum(expression)](./firestore_lite_pipelines.md#maximum_1138a27) | (Public Preview) Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. | | [minimum(expression)](./firestore_lite_pipelines.md#minimum_1138a27) | (Public Preview) Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. | | [mod(expression, value)](./firestore_lite_pipelines.md#mod_01df3cf) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. | | [notEqual(expression, value)](./firestore_lite_pipelines.md#notequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is not equal to a constant value. | | [round(expression)](./firestore_lite_pipelines.md#round_1138a27) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | | [round(expression, decimalPlaces)](./firestore_lite_pipelines.md#round_a3a92d0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [rtrim(expression, valueToTrim)](./firestore_lite_pipelines.md#rtrim_775e2f2) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | | [split(expression, delimiter)](./firestore_lite_pipelines.md#split_5b5612b) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | | [split(expression, delimiter)](./firestore_lite_pipelines.md#split_5a171ed) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | | [sqrt(expression)](./firestore_lite_pipelines.md#sqrt_1138a27) | (Public Preview) Creates an expression that computes the square root of a numeric value. | +| [stringIndexOf(expression, search)](./firestore_lite_pipelines.md#stringindexof_6dfca5f) | (Public Preview) Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | +| [stringRepeat(expression, repetitions)](./firestore_lite_pipelines.md#stringrepeat_a55ba16) | (Public Preview) Creates an expression that repeats a string or byte array a specified number of times. | +| [stringReplaceAll(expression, find, replacement)](./firestore_lite_pipelines.md#stringreplaceall_197ecbe) | (Public Preview) Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | +| [stringReplaceOne(expression, find, replacement)](./firestore_lite_pipelines.md#stringreplaceone_197ecbe) | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | | [subtract(expression, value)](./firestore_lite_pipelines.md#subtract_01df3cf) | (Public Preview) Creates an expression that subtracts a constant value from an expression. | | [sum(expression)](./firestore_lite_pipelines.md#sum_1138a27) | (Public Preview) Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. | | [type(expression)](./firestore_lite_pipelines.md#type_1138a27) | (Public Preview) Creates an expression that returns the data type of an expression's result. | @@ -162,6 +168,7 @@ https://github.com/firebase/firebase-js-sdk | [log10(fieldName)](./firestore_lite_pipelines.md#log10_e5b0480) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | | [logicalMaximum(fieldName, second, others)](./firestore_lite_pipelines.md#logicalmaximum_828272e) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | | [logicalMinimum(fieldName, second, others)](./firestore_lite_pipelines.md#logicalminimum_828272e) | (Public Preview) Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. | +| [ltrim(fieldName, valueToTrim)](./firestore_lite_pipelines.md#ltrim_c0e3211) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | | [mapGet(fieldName, subField)](./firestore_lite_pipelines.md#mapget_06663cf) | (Public Preview) Accesses a value from a map (object) field using the provided key. | | [maximum(fieldName)](./firestore_lite_pipelines.md#maximum_e5b0480) | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | | [minimum(fieldName)](./firestore_lite_pipelines.md#minimum_e5b0480) | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | @@ -182,6 +189,7 @@ https://github.com/firebase/firebase-js-sdk | [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_cb1318d) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | | [round(fieldName)](./firestore_lite_pipelines.md#round_e5b0480) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | | [round(fieldName, decimalPlaces)](./firestore_lite_pipelines.md#round_07d0cf0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [rtrim(fieldName, valueToTrim)](./firestore_lite_pipelines.md#rtrim_c0e3211) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | | [split(fieldName, delimiter)](./firestore_lite_pipelines.md#split_2cfdd37) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | | [split(fieldName, delimiter)](./firestore_lite_pipelines.md#split_f4fe06a) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | | [sqrt(fieldName)](./firestore_lite_pipelines.md#sqrt_e5b0480) | (Public Preview) Creates an expression that computes the square root of a numeric value. | @@ -190,6 +198,10 @@ https://github.com/firebase/firebase-js-sdk | [stringConcat(fieldName, secondString, otherStrings)](./firestore_lite_pipelines.md#stringconcat_d80077e) | (Public Preview) Creates an expression that concatenates string functions, fields or constants together. | | [stringContains(fieldName, substring)](./firestore_lite_pipelines.md#stringcontains_5b94cfe) | (Public Preview) Creates an expression that checks if a string field contains a specified substring. | | [stringContains(fieldName, substring)](./firestore_lite_pipelines.md#stringcontains_ac3ba47) | (Public Preview) Creates an expression that checks if a string field contains a substring specified by an expression. | +| [stringIndexOf(fieldName, search)](./firestore_lite_pipelines.md#stringindexof_6c4650e) | (Public Preview) Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | +| [stringRepeat(fieldName, repetitions)](./firestore_lite_pipelines.md#stringrepeat_e144a59) | (Public Preview) Creates an expression that repeats a string or byte array a specified number of times. | +| [stringReplaceAll(fieldName, find, replacement)](./firestore_lite_pipelines.md#stringreplaceall_b0db15f) | (Public Preview) Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | +| [stringReplaceOne(fieldName, find, replacement)](./firestore_lite_pipelines.md#stringreplaceone_b0db15f) | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | | [subtract(fieldName, expression)](./firestore_lite_pipelines.md#subtract_1e91657) | (Public Preview) Creates an expression that subtracts an expression from a field's value. | | [subtract(fieldName, value)](./firestore_lite_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. | | [sum(fieldName)](./firestore_lite_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. | @@ -2486,6 +2498,44 @@ log10(field("value")); ``` +### ltrim(expression, valueToTrim) {:#ltrim_775e2f2} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. + +Signature: + +```typescript +export declare function ltrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. + +### Example + + +```typescript +// Trim whitespace from the beginning of the 'userInput' field +ltrim(field("userInput")); + +// Trim quotes from the beginning of the 'userInput' field +ltrim(field("userInput"), '"'); + +``` + ### maximum(expression) {:#maximum_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2693,6 +2743,44 @@ round(field("price"), constant(2)); ``` +### rtrim(expression, valueToTrim) {:#rtrim_775e2f2} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. + +Signature: + +```typescript +export declare function rtrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. + +### Example + + +```typescript +// Trim whitespace from the end of the 'userInput' field +rtrim(field("userInput")); + +// Trim quotes from the end of the 'userInput' field +rtrim(field("userInput"), '"'); + +``` + ### split(expression, delimiter) {:#split_5b5612b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2797,6 +2885,148 @@ sqrt(field("value")); ``` +### stringIndexOf(expression, search) {:#stringindexof_6dfca5f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that finds the index of the first occurrence of a substring or byte sequence. + +Signature: + +```typescript +export declare function stringIndexOf(expression: Expression, search: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| search | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index of the first occurrence. + +### Example + + +```typescript +// Find the index of "foo" in the 'text' field +stringIndexOf(field("text"), "foo"); + +``` + +### stringRepeat(expression, repetitions) {:#stringrepeat_a55ba16} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that repeats a string or byte array a specified number of times. + +Signature: + +```typescript +export declare function stringRepeat(expression: Expression, repetitions: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| repetitions | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The number of times to repeat the string or byte array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the repeated string or byte array. + +### Example + + +```typescript +// Repeat the 'label' field 3 times +stringRepeat(field("label"), 3); + +``` + +### stringReplaceAll(expression, find, replacement) {:#stringreplaceall_197ecbe} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. + +Signature: + +```typescript +export declare function stringReplaceAll(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| find | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The replacement string or byte sequence. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with replacements. + +### Example + + +```typescript +// Replace all occurrences of "foo" with "bar" in the 'text' field +stringReplaceAll(field("text"), "foo", "bar"); + +``` + +### stringReplaceOne(expression, find, replacement) {:#stringreplaceone_197ecbe} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. + +Signature: + +```typescript +export declare function stringReplaceOne(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| find | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The replacement string or byte sequence. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with the replacement. + +### Example + + +```typescript +// Replace the first occurrence of "foo" with "bar" in the 'text' field +stringReplaceOne(field("text"), "foo", "bar"); + +``` + ### subtract(expression, value) {:#subtract_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4888,6 +5118,44 @@ logicalMinimum("field1", field("field2"), 1000); ``` +### ltrim(fieldName, valueToTrim) {:#ltrim_c0e3211} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. + +Signature: + +```typescript +export declare function ltrim(fieldName: string, valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. + +### Example + + +```typescript +// Trim whitespace from the beginning of the 'userInput' field +ltrim(field("userInput")); + +// Trim quotes from the beginning of the 'userInput' field +ltrim(field("userInput"), '"'); + +``` + ### mapGet(fieldName, subField) {:#mapget_06663cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -5593,6 +5861,44 @@ round("price", 2); ``` +### rtrim(fieldName, valueToTrim) {:#rtrim_c0e3211} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. + +Signature: + +```typescript +export declare function rtrim(fieldName: string, valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. + +### Example + + +```typescript +// Trim whitespace from the end of the 'userInput' field +rtrim(field("userInput")); + +// Trim quotes from the end of the 'userInput' field +rtrim(field("userInput"), '"'); + +``` + ### split(fieldName, delimiter) {:#split_2cfdd37} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -5873,6 +6179,148 @@ stringContains("description", field("keyword")); ``` +### stringIndexOf(fieldName, search) {:#stringindexof_6c4650e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that finds the index of the first occurrence of a substring or byte sequence. + +Signature: + +```typescript +export declare function stringIndexOf(fieldName: string, search: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| search | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index of the first occurrence. + +### Example + + +```typescript +// Find the index of "foo" in the 'text' field +stringIndexOf("text", "foo"); + +``` + +### stringRepeat(fieldName, repetitions) {:#stringrepeat_e144a59} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that repeats a string or byte array a specified number of times. + +Signature: + +```typescript +export declare function stringRepeat(fieldName: string, repetitions: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| repetitions | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The number of times to repeat the string or byte array. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the repeated string or byte array. + +### Example + + +```typescript +// Repeat the 'label' field 3 times +stringRepeat("label", 3); + +``` + +### stringReplaceAll(fieldName, find, replacement) {:#stringreplaceall_b0db15f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. + +Signature: + +```typescript +export declare function stringReplaceAll(fieldName: string, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| find | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The replacement string or byte sequence. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with replacements. + +### Example + + +```typescript +// Replace all occurrences of "foo" with "bar" in the 'text' field +stringReplaceAll("text", "foo", "bar"); + +``` + +### stringReplaceOne(fieldName, find, replacement) {:#stringreplaceone_b0db15f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. + +Signature: + +```typescript +export declare function stringReplaceOne(fieldName: string, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| find | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The replacement string or byte sequence. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with the replacement. + +### Example + + +```typescript +// Replace the first occurrence of "foo" with "bar" in the 'text' field +stringReplaceOne("text", "foo", "bar"); + +``` + ### subtract(fieldName, expression) {:#subtract_1e91657} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index b09e0727a5..355dc83232 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -111,6 +111,7 @@ field("optional_field").ifAbsent(field('default_field')) | [log10()](./firestore_pipelines.expression.md#expressionlog10) | | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | | [logicalMaximum(second, others)](./firestore_pipelines.expression.md#expressionlogicalmaximum) | | (Public Preview) Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. | | [logicalMinimum(second, others)](./firestore_pipelines.expression.md#expressionlogicalminimum) | | (Public Preview) Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. | +| [ltrim(valueToTrim)](./firestore_pipelines.expression.md#expressionltrim) | | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | | [mapGet(subfield)](./firestore_pipelines.expression.md#expressionmapget) | | (Public Preview) Accesses a value from a map (object) field using the provided key. | | [mapMerge(secondMap, otherMaps)](./firestore_pipelines.expression.md#expressionmapmerge) | | (Public Preview) Creates an expression that merges multiple map values. | | [mapRemove(key)](./firestore_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | @@ -138,6 +139,7 @@ field("optional_field").ifAbsent(field('default_field')) | [round()](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | | [round(decimalPlaces)](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | | [round(decimalPlaces)](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [rtrim(valueToTrim)](./firestore_pipelines.expression.md#expressionrtrim) | | (Public Preview) Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | | [split(delimiter)](./firestore_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | | [split(delimiter)](./firestore_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | | [sqrt()](./firestore_pipelines.expression.md#expressionsqrt) | | (Public Preview) Creates an expression that computes the square root of a numeric value. | @@ -146,6 +148,10 @@ field("optional_field").ifAbsent(field('default_field')) | [stringConcat(secondString, otherStrings)](./firestore_pipelines.expression.md#expressionstringconcat) | | (Public Preview) Creates an expression that concatenates string expressions together. | | [stringContains(substring)](./firestore_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified substring. | | [stringContains(expr)](./firestore_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains the string represented by another expression. | +| [stringIndexOf(search)](./firestore_pipelines.expression.md#expressionstringindexof) | | (Public Preview) Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | +| [stringRepeat(repetitions)](./firestore_pipelines.expression.md#expressionstringrepeat) | | (Public Preview) Creates an expression that repeats a string or byte array a specified number of times. | +| [stringReplaceAll(find, replacement)](./firestore_pipelines.expression.md#expressionstringreplaceall) | | (Public Preview) Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | +| [stringReplaceOne(find, replacement)](./firestore_pipelines.expression.md#expressionstringreplaceone) | | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | | [stringReverse()](./firestore_pipelines.expression.md#expressionstringreverse) | | (Public Preview) Creates an expression that reverses a string. | | [substring(position, length)](./firestore_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | | [substring(position, length)](./firestore_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | @@ -2305,6 +2311,43 @@ field("timestamp").logicalMinimum(Function.currentTimestamp()); ``` +## Expression.ltrim() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. + +Signature: + +```typescript +ltrim(valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the trimmed string. + +### 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('"'); + +``` + ## Expression.mapGet() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3206,6 +3249,43 @@ field("price").round(constant(2)); ``` +## Expression.rtrim() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. + +Signature: + +```typescript +rtrim(valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the trimmed 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('"'); + +``` + ## Expression.split() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3472,6 +3552,144 @@ field("description").stringContains(field("keyword")); ``` +## Expression.stringIndexOf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that finds the index of the first occurrence of a substring or byte sequence. + +Signature: + +```typescript +stringIndexOf(search: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the index of the first occurrence. + +### Example + + +```typescript +// Find the index of "foo" in the 'text' field +field("text").stringIndexOf("foo"); + +``` + +## Expression.stringRepeat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that repeats a string or byte array a specified number of times. + +Signature: + +```typescript +stringRepeat(repetitions: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| repetitions | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | The number of times to repeat the string or byte array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the repeated string or byte array. + +### Example + + +```typescript +// Repeat the 'label' field 3 times +field("label").stringRepeat(3); + +``` + +## Expression.stringReplaceAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. + +Signature: + +```typescript +stringReplaceAll(find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| find | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The replacement string or byte sequence. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the string or byte array with replacements. + +### Example + + +```typescript +// Replace all occurrences of "foo" with "bar" in the 'text' field +field("text").stringReplaceAll("foo", "bar"); + +``` + +## Expression.stringReplaceOne() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. + +Signature: + +```typescript +stringReplaceOne(find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| find | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The replacement string or byte sequence. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the string or byte array with the replacement. + +### Example + + +```typescript +// Replace the first occurrence of "foo" with "bar" in the 'text' field +field("text").stringReplaceOne("foo", "bar"); + +``` + ## Expression.stringReverse() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index d61d357ce3..63e5790ee7 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -90,15 +90,21 @@ https://github.com/firebase/firebase-js-sdk | [log(expression, base)](./firestore_pipelines.md#log_ac183e2) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. | | [log(expression, base)](./firestore_pipelines.md#log_1894737) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. | | [log10(expression)](./firestore_pipelines.md#log10_1138a27) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | +| [ltrim(expression, valueToTrim)](./firestore_pipelines.md#ltrim_775e2f2) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | | [maximum(expression)](./firestore_pipelines.md#maximum_1138a27) | (Public Preview) Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. | | [minimum(expression)](./firestore_pipelines.md#minimum_1138a27) | (Public Preview) Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. | | [mod(expression, value)](./firestore_pipelines.md#mod_01df3cf) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. | | [notEqual(expression, value)](./firestore_pipelines.md#notequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is not equal to a constant value. | | [round(expression)](./firestore_pipelines.md#round_1138a27) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | | [round(expression, decimalPlaces)](./firestore_pipelines.md#round_a3a92d0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [rtrim(expression, valueToTrim)](./firestore_pipelines.md#rtrim_775e2f2) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | | [split(expression, delimiter)](./firestore_pipelines.md#split_5b5612b) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | | [split(expression, delimiter)](./firestore_pipelines.md#split_5a171ed) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | | [sqrt(expression)](./firestore_pipelines.md#sqrt_1138a27) | (Public Preview) Creates an expression that computes the square root of a numeric value. | +| [stringIndexOf(expression, search)](./firestore_pipelines.md#stringindexof_6dfca5f) | (Public Preview) Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | +| [stringRepeat(expression, repetitions)](./firestore_pipelines.md#stringrepeat_a55ba16) | (Public Preview) Creates an expression that repeats a string or byte array a specified number of times. | +| [stringReplaceAll(expression, find, replacement)](./firestore_pipelines.md#stringreplaceall_197ecbe) | (Public Preview) Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | +| [stringReplaceOne(expression, find, replacement)](./firestore_pipelines.md#stringreplaceone_197ecbe) | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | | [subtract(expression, value)](./firestore_pipelines.md#subtract_01df3cf) | (Public Preview) Creates an expression that subtracts a constant value from an expression. | | [sum(expression)](./firestore_pipelines.md#sum_1138a27) | (Public Preview) Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. | | [type(expression)](./firestore_pipelines.md#type_1138a27) | (Public Preview) Creates an expression that returns the data type of an expression's result. | @@ -162,6 +168,7 @@ https://github.com/firebase/firebase-js-sdk | [log10(fieldName)](./firestore_pipelines.md#log10_e5b0480) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | | [logicalMaximum(fieldName, second, others)](./firestore_pipelines.md#logicalmaximum_828272e) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | | [logicalMinimum(fieldName, second, others)](./firestore_pipelines.md#logicalminimum_828272e) | (Public Preview) Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. | +| [ltrim(fieldName, valueToTrim)](./firestore_pipelines.md#ltrim_c0e3211) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | | [mapGet(fieldName, subField)](./firestore_pipelines.md#mapget_06663cf) | (Public Preview) Accesses a value from a map (object) field using the provided key. | | [maximum(fieldName)](./firestore_pipelines.md#maximum_e5b0480) | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | | [minimum(fieldName)](./firestore_pipelines.md#minimum_e5b0480) | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | @@ -182,6 +189,7 @@ https://github.com/firebase/firebase-js-sdk | [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_cb1318d) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | | [round(fieldName)](./firestore_pipelines.md#round_e5b0480) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | | [round(fieldName, decimalPlaces)](./firestore_pipelines.md#round_07d0cf0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [rtrim(fieldName, valueToTrim)](./firestore_pipelines.md#rtrim_c0e3211) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | | [split(fieldName, delimiter)](./firestore_pipelines.md#split_2cfdd37) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | | [split(fieldName, delimiter)](./firestore_pipelines.md#split_f4fe06a) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | | [sqrt(fieldName)](./firestore_pipelines.md#sqrt_e5b0480) | (Public Preview) Creates an expression that computes the square root of a numeric value. | @@ -190,6 +198,10 @@ https://github.com/firebase/firebase-js-sdk | [stringConcat(fieldName, secondString, otherStrings)](./firestore_pipelines.md#stringconcat_d80077e) | (Public Preview) Creates an expression that concatenates string functions, fields or constants together. | | [stringContains(fieldName, substring)](./firestore_pipelines.md#stringcontains_5b94cfe) | (Public Preview) Creates an expression that checks if a string field contains a specified substring. | | [stringContains(fieldName, substring)](./firestore_pipelines.md#stringcontains_ac3ba47) | (Public Preview) Creates an expression that checks if a string field contains a substring specified by an expression. | +| [stringIndexOf(fieldName, search)](./firestore_pipelines.md#stringindexof_6c4650e) | (Public Preview) Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | +| [stringRepeat(fieldName, repetitions)](./firestore_pipelines.md#stringrepeat_e144a59) | (Public Preview) Creates an expression that repeats a string or byte array a specified number of times. | +| [stringReplaceAll(fieldName, find, replacement)](./firestore_pipelines.md#stringreplaceall_b0db15f) | (Public Preview) Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | +| [stringReplaceOne(fieldName, find, replacement)](./firestore_pipelines.md#stringreplaceone_b0db15f) | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | | [subtract(fieldName, expression)](./firestore_pipelines.md#subtract_1e91657) | (Public Preview) Creates an expression that subtracts an expression from a field's value. | | [subtract(fieldName, value)](./firestore_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. | | [sum(fieldName)](./firestore_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. | @@ -2492,6 +2504,44 @@ log10(field("value")); ``` +### ltrim(expression, valueToTrim) {:#ltrim_775e2f2} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. + +Signature: + +```typescript +export declare function ltrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. + +### Example + + +```typescript +// Trim whitespace from the beginning of the 'userInput' field +ltrim(field("userInput")); + +// Trim quotes from the beginning of the 'userInput' field +ltrim(field("userInput"), '"'); + +``` + ### maximum(expression) {:#maximum_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2699,6 +2749,44 @@ round(field("price"), constant(2)); ``` +### rtrim(expression, valueToTrim) {:#rtrim_775e2f2} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. + +Signature: + +```typescript +export declare function rtrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. + +### Example + + +```typescript +// Trim whitespace from the end of the 'userInput' field +rtrim(field("userInput")); + +// Trim quotes from the end of the 'userInput' field +rtrim(field("userInput"), '"'); + +``` + ### split(expression, delimiter) {:#split_5b5612b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2803,6 +2891,148 @@ sqrt(field("value")); ``` +### stringIndexOf(expression, search) {:#stringindexof_6dfca5f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that finds the index of the first occurrence of a substring or byte sequence. + +Signature: + +```typescript +export declare function stringIndexOf(expression: Expression, search: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| search | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index of the first occurrence. + +### Example + + +```typescript +// Find the index of "foo" in the 'text' field +stringIndexOf(field("text"), "foo"); + +``` + +### stringRepeat(expression, repetitions) {:#stringrepeat_a55ba16} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that repeats a string or byte array a specified number of times. + +Signature: + +```typescript +export declare function stringRepeat(expression: Expression, repetitions: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| repetitions | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | The number of times to repeat the string or byte array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the repeated string or byte array. + +### Example + + +```typescript +// Repeat the 'label' field 3 times +stringRepeat(field("label"), 3); + +``` + +### stringReplaceAll(expression, find, replacement) {:#stringreplaceall_197ecbe} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. + +Signature: + +```typescript +export declare function stringReplaceAll(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| find | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The replacement string or byte sequence. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with replacements. + +### Example + + +```typescript +// Replace all occurrences of "foo" with "bar" in the 'text' field +stringReplaceAll(field("text"), "foo", "bar"); + +``` + +### stringReplaceOne(expression, find, replacement) {:#stringreplaceone_197ecbe} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. + +Signature: + +```typescript +export declare function stringReplaceOne(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| find | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The replacement string or byte sequence. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with the replacement. + +### Example + + +```typescript +// Replace the first occurrence of "foo" with "bar" in the 'text' field +stringReplaceOne(field("text"), "foo", "bar"); + +``` + ### subtract(expression, value) {:#subtract_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4894,6 +5124,44 @@ logicalMinimum("field1", field("field2"), 1000); ``` +### ltrim(fieldName, valueToTrim) {:#ltrim_c0e3211} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. + +Signature: + +```typescript +export declare function ltrim(fieldName: string, valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. + +### Example + + +```typescript +// Trim whitespace from the beginning of the 'userInput' field +ltrim(field("userInput")); + +// Trim quotes from the beginning of the 'userInput' field +ltrim(field("userInput"), '"'); + +``` + ### mapGet(fieldName, subField) {:#mapget_06663cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -5599,6 +5867,44 @@ round("price", 2); ``` +### rtrim(fieldName, valueToTrim) {:#rtrim_c0e3211} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. + +Signature: + +```typescript +export declare function rtrim(fieldName: string, valueToTrim?: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. + +### Example + + +```typescript +// Trim whitespace from the end of the 'userInput' field +rtrim(field("userInput")); + +// Trim quotes from the end of the 'userInput' field +rtrim(field("userInput"), '"'); + +``` + ### split(fieldName, delimiter) {:#split_2cfdd37} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -5879,6 +6185,148 @@ stringContains("description", field("keyword")); ``` +### stringIndexOf(fieldName, search) {:#stringindexof_6c4650e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that finds the index of the first occurrence of a substring or byte sequence. + +Signature: + +```typescript +export declare function stringIndexOf(fieldName: string, search: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| search | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index of the first occurrence. + +### Example + + +```typescript +// Find the index of "foo" in the 'text' field +stringIndexOf("text", "foo"); + +``` + +### stringRepeat(fieldName, repetitions) {:#stringrepeat_e144a59} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that repeats a string or byte array a specified number of times. + +Signature: + +```typescript +export declare function stringRepeat(fieldName: string, repetitions: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| repetitions | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | The number of times to repeat the string or byte array. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the repeated string or byte array. + +### Example + + +```typescript +// Repeat the 'label' field 3 times +stringRepeat("label", 3); + +``` + +### stringReplaceAll(fieldName, find, replacement) {:#stringreplaceall_b0db15f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. + +Signature: + +```typescript +export declare function stringReplaceAll(fieldName: string, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| find | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The replacement string or byte sequence. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with replacements. + +### Example + + +```typescript +// Replace all occurrences of "foo" with "bar" in the 'text' field +stringReplaceAll("text", "foo", "bar"); + +``` + +### stringReplaceOne(fieldName, find, replacement) {:#stringreplaceone_b0db15f} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. + +Signature: + +```typescript +export declare function stringReplaceOne(fieldName: string, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the string or byte array. | +| find | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The replacement string or byte sequence. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with the replacement. + +### Example + + +```typescript +// Replace the first occurrence of "foo" with "bar" in the 'text' field +stringReplaceOne("text", "foo", "bar"); + +``` + ### subtract(fieldName, expression) {:#subtract_1e91657} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index 5f6faabb54..df003e3697 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -139,7 +139,13 @@ export { toLower, toUpper, trim, + ltrim, + rtrim, stringConcat, + stringIndexOf, + stringRepeat, + stringReplaceAll, + stringReplaceOne, mapGet, countAll, minimum, diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index accefdad83..a08d0e08be 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -94,7 +94,13 @@ export { toLower, toUpper, trim, + ltrim, + rtrim, stringConcat, + stringIndexOf, + stringRepeat, + stringReplaceAll, + stringReplaceOne, mapGet, countAll, count, diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index 33617ddf06..5d4692333c 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -1216,6 +1216,56 @@ export abstract class Expression implements ProtoValueSerializable, UserData { 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?: string | Expression | Bytes): FunctionExpression { + const args: Expression[] = [this]; + if (valueToTrim) { + args.push(valueToDefaultExpr(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?: string | Expression | Bytes): FunctionExpression { + const args: Expression[] = [this]; + if (valueToTrim) { + args.push(valueToDefaultExpr(valueToTrim)); + } + return new FunctionExpression('rtrim', args, 'rtrim'); + } + /** * @beta * Creates an expression that concatenates string expressions together. @@ -1243,6 +1293,98 @@ export abstract class Expression implements ProtoValueSerializable, UserData { ); } + /** + * @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: string | Expression | Bytes): FunctionExpression { + return new FunctionExpression( + 'string_index_of', + [this, valueToDefaultExpr(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: number | Expression): FunctionExpression { + return new FunctionExpression( + 'string_repeat', + [this, valueToDefaultExpr(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: string | Expression | Bytes, + replacement: string | Expression | Bytes + ): FunctionExpression { + return new FunctionExpression( + 'string_replace_all', + [this, valueToDefaultExpr(find), valueToDefaultExpr(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: string | Expression | Bytes, + replacement: string | Expression | Bytes + ): FunctionExpression { + return new FunctionExpression( + 'string_replace_one', + [this, valueToDefaultExpr(find), valueToDefaultExpr(replacement)], + 'stringReplaceOne' + ); + } + /** * @beta * Creates an expression that concatenates expression results together. @@ -6677,6 +6819,110 @@ export function trim( return fieldOrExpression(expr).trim(valueToTrim); } +/** + * @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 + * ltrim(field("userInput")); + * + * // Trim quotes from the beginning of the 'userInput' field + * ltrim(field("userInput"), '"'); + * ``` + * + * @param fieldName - The name of the field containing the string or byte array. + * @param valueToTrim - Optional. A string or byte array containing the characters/bytes to trim. + * If not specified, whitespace will be trimmed. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the trimmed string or byte array. + */ +export function ltrim( + fieldName: string, + valueToTrim?: string | Expression | Bytes +): FunctionExpression; + +/** + * @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 + * ltrim(field("userInput")); + * + * // Trim quotes from the beginning of the 'userInput' field + * ltrim(field("userInput"), '"'); + * ``` + * + * @param expression - The expression representing the string or byte array. + * @param valueToTrim - Optional. A string or byte array containing the characters/bytes to trim. + * If not specified, whitespace will be trimmed. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the trimmed string or byte array. + */ +export function ltrim( + expression: Expression, + valueToTrim?: string | Expression | Bytes +): FunctionExpression; +export function ltrim( + expr: Expression | string, + valueToTrim?: string | Expression | Bytes +): FunctionExpression { + return fieldOrExpression(expr).ltrim(valueToTrim); +} + +/** + * @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 + * rtrim(field("userInput")); + * + * // Trim quotes from the end of the 'userInput' field + * rtrim(field("userInput"), '"'); + * ``` + * + * @param fieldName - The name of the field containing the string or byte array. + * @param valueToTrim - Optional. A string or byte array containing the characters/bytes to trim. + * If not specified, whitespace will be trimmed. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the trimmed string or byte array. + */ +export function rtrim( + fieldName: string, + valueToTrim?: string | Expression | Bytes +): FunctionExpression; + +/** + * @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 + * rtrim(field("userInput")); + * + * // Trim quotes from the end of the 'userInput' field + * rtrim(field("userInput"), '"'); + * ``` + * + * @param expression - The expression representing the string or byte array. + * @param valueToTrim - Optional. A string or byte array containing the characters/bytes to trim. + * If not specified, whitespace will be trimmed. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the trimmed string or byte array. + */ +export function rtrim( + expression: Expression, + valueToTrim?: string | Expression | Bytes +): FunctionExpression; +export function rtrim( + expr: Expression | string, + valueToTrim?: string | Expression | Bytes +): FunctionExpression { + return fieldOrExpression(expr).rtrim(valueToTrim); +} + /** * @beta * @@ -6730,6 +6976,192 @@ export function 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 + * stringIndexOf("text", "foo"); + * ``` + * + * @param fieldName - The name of the field containing the string or byte array. + * @param search - The substring or byte sequence to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the index of the first occurrence. + */ +export function stringIndexOf( + fieldName: string, + search: string | Expression | Bytes +): FunctionExpression; + +/** + * @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 + * stringIndexOf(field("text"), "foo"); + * ``` + * + * @param expression - The expression representing the string or byte array. + * @param search - The substring or byte sequence to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the index of the first occurrence. + */ +export function stringIndexOf( + expression: Expression, + search: string | Expression | Bytes +): FunctionExpression; +export function stringIndexOf( + expr: Expression | string, + search: string | Expression | Bytes +): FunctionExpression { + return fieldOrExpression(expr).stringIndexOf(search); +} + +/** + * @beta + * Creates an expression that repeats a string or byte array a specified number of times. + * + * @example + * ```typescript + * // Repeat the 'label' field 3 times + * stringRepeat("label", 3); + * ``` + * + * @param fieldName - The name of the field containing the string or byte array. + * @param repetitions - The number of times to repeat the string or byte array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the repeated string or byte array. + */ +export function stringRepeat( + fieldName: string, + repetitions: number | Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that repeats a string or byte array a specified number of times. + * + * @example + * ```typescript + * // Repeat the 'label' field 3 times + * stringRepeat(field("label"), 3); + * ``` + * + * @param expression - The expression representing the string or byte array. + * @param repetitions - The number of times to repeat the string or byte array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the repeated string or byte array. + */ +export function stringRepeat( + expression: Expression, + repetitions: number | Expression +): FunctionExpression; +export function stringRepeat( + expr: Expression | string, + repetitions: number | Expression +): FunctionExpression { + return fieldOrExpression(expr).stringRepeat(repetitions); +} + +/** + * @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 + * stringReplaceAll("text", "foo", "bar"); + * ``` + * + * @param fieldName - The name of the field containing the string or byte array. + * @param find - The substring or byte sequence to search for. + * @param replacement - The replacement string or byte sequence. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the string or byte array with replacements. + */ +export function stringReplaceAll( + fieldName: string, + find: string | Expression | Bytes, + replacement: string | Expression | Bytes +): FunctionExpression; + +/** + * @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 + * stringReplaceAll(field("text"), "foo", "bar"); + * ``` + * + * @param expression - The expression representing the string or byte array. + * @param find - The substring or byte sequence to search for. + * @param replacement - The replacement string or byte sequence. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the string or byte array with replacements. + */ +export function stringReplaceAll( + expression: Expression, + find: string | Expression | Bytes, + replacement: string | Expression | Bytes +): FunctionExpression; +export function stringReplaceAll( + expr: Expression | string, + find: string | Expression | Bytes, + replacement: string | Expression | Bytes +): FunctionExpression { + return fieldOrExpression(expr).stringReplaceAll(find, replacement); +} + +/** + * @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 + * stringReplaceOne("text", "foo", "bar"); + * ``` + * + * @param fieldName - The name of the field containing the string or byte array. + * @param find - The substring or byte sequence to search for. + * @param replacement - The replacement string or byte sequence. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the string or byte array with the replacement. + */ +export function stringReplaceOne( + fieldName: string, + find: string | Expression | Bytes, + replacement: string | Expression | Bytes +): FunctionExpression; + +/** + * @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 + * stringReplaceOne(field("text"), "foo", "bar"); + * ``` + * + * @param expression - The expression representing the string or byte array. + * @param find - The substring or byte sequence to search for. + * @param replacement - The replacement string or byte sequence. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the string or byte array with the replacement. + */ +export function stringReplaceOne( + expression: Expression, + find: string | Expression | Bytes, + replacement: string | Expression | Bytes +): FunctionExpression; +export function stringReplaceOne( + expr: Expression | string, + find: string | Expression | Bytes, + replacement: string | Expression | Bytes +): FunctionExpression { + return fieldOrExpression(expr).stringReplaceOne(find, replacement); +} + /** * @beta * diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 1015c746a9..5825d5980c 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -65,6 +65,7 @@ import { equal, reverse, toUpper, + trim, euclideanDistance, greaterThan, like, @@ -81,28 +82,32 @@ import { regexFindAll, regexMatch, startsWith, - stringConcat, - subtract, + charLength, conditional, - equalAny, - logicalMaximum, - notEqualAny, - multiply, countIf, + equalAny, exists, - charLength, - minimum, - maximum, - isError, ifError, - trim, + isError, + logicalMaximum, + logicalMinimum, + ltrim, + maximum, + minimum, + multiply, + notEqualAny, + stringConcat, + stringIndexOf, + stringRepeat, + stringReplaceAll, + stringReplaceOne, + subtract, isAbsent, timestampSubtract, mapRemove, mapMerge, documentId, substring, - logicalMinimum, xor, field, constant, @@ -126,6 +131,7 @@ import { exp, pow, round, + rtrim, collectionId, ln, log, @@ -3855,6 +3861,191 @@ apiDescribe.skipClassic('Pipelines', persistence => { }); }); + it('testLTrim', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + spacedTitle: " The Hitchhiker's Guide to the Galaxy ", + userNameWithQuotes: '"alice"', + bytes: Bytes.fromUint8Array( + Uint8Array.from([0x00, 0x01, 0x02, 0x00, 0x00]) + ) + }) + ) + .select( + ltrim('spacedTitle').as('ltrimmedTitle'), + field('userNameWithQuotes').ltrim('"').as('userName'), + field('bytes') + .ltrim(Bytes.fromUint8Array(Uint8Array.from([0x00]))) + .as('bytes') + ) + .limit(1) + ); + expectResults(snapshot, { + ltrimmedTitle: "The Hitchhiker's Guide to the Galaxy ", + userName: 'alice"', + bytes: Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02, 0x00, 0x00])) + }); + }); + + it('testRTrim', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + spacedTitle: " The Hitchhiker's Guide to the Galaxy ", + userNameWithQuotes: '"alice"', + bytes: Bytes.fromUint8Array( + Uint8Array.from([0x00, 0x01, 0x02, 0x00, 0x00]) + ) + }) + ) + .select( + rtrim('spacedTitle').as('rtrimmedTitle'), + field('userNameWithQuotes').rtrim('"').as('userName'), + field('bytes') + .rtrim(Bytes.fromUint8Array(Uint8Array.from([0x00]))) + .as('bytes') + ) + .limit(1) + ); + expectResults(snapshot, { + rtrimmedTitle: " The Hitchhiker's Guide to the Galaxy", + userName: '"alice', + bytes: Bytes.fromUint8Array(Uint8Array.from([0x00, 0x01, 0x02])) + }); + }); + + it('testStringRepeat', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + title: "The Hitchhiker's Guide to the Galaxy", + bytes: Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02, 0x03])) + }) + ) + .select( + stringRepeat(field('title'), 2).as('repeatedTitle'), + stringRepeat(field('bytes'), 2).as('repeatedBytes') + ) + .limit(1) + ); + + expectResults(snapshot, { + repeatedTitle: + "The Hitchhiker's Guide to the GalaxyThe Hitchhiker's Guide to the Galaxy", + repeatedBytes: Bytes.fromUint8Array( + Uint8Array.from([0x01, 0x02, 0x03, 0x01, 0x02, 0x03]) + ) + }); + }); + + it('testStringReplaceAll', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + title: "The Hitchhiker's Guide to the Galaxy", + bytes: Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02, 0x02])) + }) + ) + .select( + stringReplaceAll(field('title'), 'the', 'a').as('replacedAll'), + stringReplaceAll(toLower('title'), 'the', 'a').as( + 'replacedAllLower' + ), + stringReplaceAll( + field('bytes'), + Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02, 0x02])), + Bytes.fromUint8Array(Uint8Array.from([0x03, 0x03, 0x03])) + ).as('replacedEntireByteArray'), + stringReplaceAll( + field('bytes'), + Bytes.fromUint8Array(Uint8Array.from([0x02])), + Bytes.fromUint8Array(Uint8Array.from([0x03])) + ).as('replacedMultipleBytes') + ) + .limit(1) + ); + + expectResults(snapshot, { + replacedAll: "The Hitchhiker's Guide to a Galaxy", + replacedAllLower: "a hitchhiker's guide to a galaxy", + replacedEntireByteArray: Bytes.fromUint8Array( + Uint8Array.from([0x03, 0x03, 0x03]) + ), + replacedMultipleBytes: Bytes.fromUint8Array( + Uint8Array.from([0x01, 0x03, 0x03]) + ) + }); + }); + + it('testStringReplaceOne', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + title: "The Hitchhiker's Guide to the Galaxy", + bytes: Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02, 0x02])) + }) + ) + .select( + stringReplaceOne(field('title'), 'e', 'X').as('replacedOne'), + stringReplaceOne( + field('bytes'), + Bytes.fromUint8Array(Uint8Array.from([0x02])), + Bytes.fromUint8Array(Uint8Array.from([0x03])) + ).as('replacedOneByte') + ) + .limit(1) + ); + expectResults(snapshot, { + replacedOne: "ThX Hitchhiker's Guide to the Galaxy", + replacedOneByte: Bytes.fromUint8Array( + Uint8Array.from([0x01, 0x03, 0x02]) + ) + }); + }); + + it('testStringIndexOf', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + title: "The Hitchhiker's Guide to the Galaxy", + bytes: Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02, 0x03])) + }) + ) + .select( + stringIndexOf(field('title'), 'Guide').as('indexOfGuide'), + stringIndexOf( + field('bytes'), + constant(Bytes.fromUint8Array(Uint8Array.from([0x02]))) + ).as('indexOfByte') + ) + .limit(1) + ); + + expectResults(snapshot, { + indexOfGuide: 17, + indexOfByte: 1 + }); + }); + it('test reverse', async () => { const snapshot = await execute( firestore diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 8d363c00af..a81050490e 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -85,6 +85,7 @@ import { conditional, logicalMaximum, logicalMinimum, + ltrim, exists, reverse, like, @@ -115,12 +116,17 @@ import { descending, FunctionExpression, AggregateFunction, - stringConcat, arrayContainsAll, arrayLength, charLength, divide, not, + rtrim, + stringConcat, + stringIndexOf, + stringRepeat, + stringReplaceAll, + stringReplaceOne, toLower, toUpper, trim, @@ -3812,6 +3818,191 @@ describe.skipClassic('Firestore Pipelines', () => { }); }); + it('testLTrim', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + spacedTitle: " The Hitchhiker's Guide to the Galaxy ", + userNameWithQuotes: '"alice"', + bytes: Bytes.fromUint8Array( + Uint8Array.from([0x00, 0x01, 0x02, 0x00, 0x00]) + ) + }) + ) + .select( + ltrim('spacedTitle').as('ltrimmedTitle'), + field('userNameWithQuotes').ltrim('"').as('userName'), + field('bytes') + .ltrim(Bytes.fromUint8Array(Uint8Array.from([0x00]))) + .as('bytes') + ) + .limit(1) + ); + expectResults(snapshot, { + ltrimmedTitle: "The Hitchhiker's Guide to the Galaxy ", + userName: 'alice"', + bytes: Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02, 0x00, 0x00])) + }); + }); + + it('testRTrim', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + spacedTitle: " The Hitchhiker's Guide to the Galaxy ", + userNameWithQuotes: '"alice"', + bytes: Bytes.fromUint8Array( + Uint8Array.from([0x00, 0x01, 0x02, 0x00, 0x00]) + ) + }) + ) + .select( + rtrim('spacedTitle').as('rtrimmedTitle'), + field('userNameWithQuotes').rtrim('"').as('userName'), + field('bytes') + .rtrim(Bytes.fromUint8Array(Uint8Array.from([0x00]))) + .as('bytes') + ) + .limit(1) + ); + expectResults(snapshot, { + rtrimmedTitle: " The Hitchhiker's Guide to the Galaxy", + userName: '"alice', + bytes: Bytes.fromUint8Array(Uint8Array.from([0x00, 0x01, 0x02])) + }); + }); + + it('testStringRepeat', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + title: "The Hitchhiker's Guide to the Galaxy", + bytes: Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02, 0x03])) + }) + ) + .select( + stringRepeat(field('title'), 2).as('repeatedTitle'), + stringRepeat(field('bytes'), 2).as('repeatedBytes') + ) + .limit(1) + ); + + expectResults(snapshot, { + repeatedTitle: + "The Hitchhiker's Guide to the GalaxyThe Hitchhiker's Guide to the Galaxy", + repeatedBytes: Bytes.fromUint8Array( + Uint8Array.from([0x01, 0x02, 0x03, 0x01, 0x02, 0x03]) + ) + }); + }); + + it('testStringReplaceAll', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + title: "The Hitchhiker's Guide to the Galaxy", + bytes: Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02, 0x02])) + }) + ) + .select( + stringReplaceAll(field('title'), 'the', 'a').as('replacedAll'), + stringReplaceAll(toLower('title'), 'the', 'a').as( + 'replacedAllLower' + ), + stringReplaceAll( + field('bytes'), + Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02, 0x02])), + Bytes.fromUint8Array(Uint8Array.from([0x03, 0x03, 0x03])) + ).as('replacedEntireByteArray'), + stringReplaceAll( + field('bytes'), + Bytes.fromUint8Array(Uint8Array.from([0x02])), + Bytes.fromUint8Array(Uint8Array.from([0x03])) + ).as('replacedMultipleBytes') + ) + .limit(1) + ); + + expectResults(snapshot, { + replacedAll: "The Hitchhiker's Guide to a Galaxy", + replacedAllLower: "a hitchhiker's guide to a galaxy", + replacedEntireByteArray: Bytes.fromUint8Array( + Uint8Array.from([0x03, 0x03, 0x03]) + ), + replacedMultipleBytes: Bytes.fromUint8Array( + Uint8Array.from([0x01, 0x03, 0x03]) + ) + }); + }); + + it('testStringReplaceOne', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + title: "The Hitchhiker's Guide to the Galaxy", + bytes: Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02, 0x02])) + }) + ) + .select( + stringReplaceOne(field('title'), 'e', 'X').as('replacedOne'), + stringReplaceOne( + field('bytes'), + Bytes.fromUint8Array(Uint8Array.from([0x02])), + Bytes.fromUint8Array(Uint8Array.from([0x03])) + ).as('replacedOneByte') + ) + .limit(1) + ); + expectResults(snapshot, { + replacedOne: "ThX Hitchhiker's Guide to the Galaxy", + replacedOneByte: Bytes.fromUint8Array( + Uint8Array.from([0x01, 0x03, 0x02]) + ) + }); + }); + + it('testStringIndexOf', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + title: "The Hitchhiker's Guide to the Galaxy", + bytes: Bytes.fromUint8Array(Uint8Array.from([0x01, 0x02, 0x03])) + }) + ) + .select( + stringIndexOf(field('title'), 'Guide').as('indexOfGuide'), + stringIndexOf( + field('bytes'), + constant(Bytes.fromUint8Array(Uint8Array.from([0x02]))) + ).as('indexOfByte') + ) + .limit(1) + ); + + expectResults(snapshot, { + indexOfGuide: 17, + indexOfByte: 1 + }); + }); + it('test reverse', async () => { const snapshot = await execute( firestore From 852162bc94935a826b548e71ac124749ab3e799f Mon Sep 17 00:00:00 2001 From: Yvonne Pan <103622026+yvonnep165@users.noreply.github.com> Date: Mon, 23 Feb 2026 10:57:04 -0500 Subject: [PATCH 069/174] feat(firestore): add rand and trunc expressions (#9498) * add rand and trunc expressions and tests * Update packages/firestore/src/lite-api/expressions.ts Co-authored-by: Daniel La Rocque * Update packages/firestore/src/lite-api/expressions.ts Co-authored-by: Daniel La Rocque * Update packages/firestore/src/lite-api/expressions.ts Co-authored-by: Daniel La Rocque --------- Co-authored-by: Daniel La Rocque --- .changeset/orange-bags-jog.md | 6 + .../firestore-lite-pipelines.api.md | 21 +++ common/api-review/firestore-pipelines.api.md | 21 +++ .../firestore_lite_pipelines.expression.md | 98 ++++++++++ docs-devsite/firestore_lite_pipelines.md | 170 ++++++++++++++++++ .../firestore_pipelines.expression.md | 98 ++++++++++ docs-devsite/firestore_pipelines.md | 170 ++++++++++++++++++ .../firestore/lite/pipelines/pipelines.ts | 2 + packages/firestore/src/api_pipelines.ts | 2 + .../firestore/src/lite-api/expressions.ts | 150 ++++++++++++++++ .../test/integration/api/pipeline.test.ts | 71 ++++++++ packages/firestore/test/lite/pipeline.test.ts | 71 ++++++++ 12 files changed, 880 insertions(+) create mode 100644 .changeset/orange-bags-jog.md diff --git a/.changeset/orange-bags-jog.md b/.changeset/orange-bags-jog.md new file mode 100644 index 0000000000..812cae7aae --- /dev/null +++ b/.changeset/orange-bags-jog.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/firestore': minor +--- + +Add support for rand and trunc pipeline expressions diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index 0d7da1ee24..0f222b4930 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -628,6 +628,12 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ trim(valueToTrim?: string | Expression | Bytes): FunctionExpression; /* Excluded from this release type: _readUserData */ + trunc(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + trunc(decimalPlaces: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + trunc(decimalPlaces: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ type(): FunctionExpression; /* Excluded from this release type: _readUserData */ unixMicrosToTimestamp(): FunctionExpression; @@ -1035,6 +1041,9 @@ export function pow(base: string, exponent: Expression): FunctionExpression; // @beta export function pow(base: string, exponent: number): FunctionExpression; +// @beta +export function rand(): FunctionExpression; + // @beta export function regexContains(fieldName: string, pattern: string): BooleanExpression; @@ -1323,6 +1332,18 @@ export function trim(fieldName: string, valueToTrim?: string | Expression): Func // @beta export function trim(stringExpression: Expression, valueToTrim?: string | Expression): FunctionExpression; +// @beta +export function trunc(fieldName: string): FunctionExpression; + +// @beta +export function trunc(expression: Expression): FunctionExpression; + +// @beta +export function trunc(fieldName: string, decimalPlaces: number | Expression): FunctionExpression; + +// @beta +export function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; + // @beta export function type(fieldName: string): FunctionExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 6ebe182f5d..289707510c 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -631,6 +631,12 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ trim(valueToTrim?: string | Expression | Bytes): FunctionExpression; /* Excluded from this release type: _readUserData */ + trunc(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + trunc(decimalPlaces: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + trunc(decimalPlaces: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ type(): FunctionExpression; /* Excluded from this release type: _readUserData */ unixMicrosToTimestamp(): FunctionExpression; @@ -1072,6 +1078,9 @@ export function pow(base: string, exponent: Expression): FunctionExpression; // @beta export function pow(base: string, exponent: number): FunctionExpression; +// @beta +export function rand(): FunctionExpression; + // @beta export function regexContains(fieldName: string, pattern: string): BooleanExpression; @@ -1360,6 +1369,18 @@ export function trim(fieldName: string, valueToTrim?: string | Expression): Func // @beta export function trim(stringExpression: Expression, valueToTrim?: string | Expression): FunctionExpression; +// @beta +export function trunc(fieldName: string): FunctionExpression; + +// @beta +export function trunc(expression: Expression): FunctionExpression; + +// @beta +export function trunc(fieldName: string, decimalPlaces: number | Expression): FunctionExpression; + +// @beta +export function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; + // @beta export function type(fieldName: string): FunctionExpression; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index 0a16f00814..a8c3b793ea 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -170,6 +170,9 @@ field("optional_field").ifAbsent(field('default_field')) | [toLower()](./firestore_lite_pipelines.expression.md#expressiontolower) | | (Public Preview) Creates an expression that converts a string to lowercase. | | [toUpper()](./firestore_lite_pipelines.expression.md#expressiontoupper) | | (Public Preview) Creates an expression that converts a string to uppercase. | | [trim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressiontrim) | | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array. | +| [trunc()](./firestore_lite_pipelines.expression.md#expressiontrunc) | | (Public Preview) Creates an expression that truncates the numeric value to an integer. | +| [trunc(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressiontrunc) | | (Public Preview) Creates an expression that truncates a numeric value to the specified number of decimal places. | +| [trunc(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressiontrunc) | | (Public Preview) Creates an expression that truncates a numeric value to the specified number of decimal places. | | [type()](./firestore_lite_pipelines.expression.md#expressiontype) | | (Public Preview) Creates an expression that returns the data type of this expression's result, as a string. | | [unixMicrosToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixmicrostotimestamp) | | (Public Preview) 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. | | [unixMillisToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixmillistotimestamp) | | (Public Preview) 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. | @@ -4242,6 +4245,101 @@ field("userInput").trim('"'); ``` +## Expression.trunc() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates the numeric value to an integer. + +Signature: + +```typescript +trunc(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the 'rating' field +field("rating").trunc(); + +``` + +## Expression.trunc() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a numeric value to the specified number of decimal places. + +Signature: + +```typescript +trunc(decimalPlaces: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| decimalPlaces | number | A constant specifying the truncation precision in decimal places. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the value of the 'rating' field to two decimal places. +field("rating").trunc(2); + +``` + +## Expression.trunc() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a numeric value to the specified number of decimal places. + +Signature: + +```typescript +trunc(decimalPlaces: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| decimalPlaces | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression specifying the truncation precision in decimal places. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the value of the 'rating' field to two decimal places. +field("rating").trunc(constant(2)); + +``` + ## Expression.type() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 8d1db97e93..ec86287893 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -18,6 +18,7 @@ https://github.com/firebase/firebase-js-sdk | function() | | [countAll()](./firestore_lite_pipelines.md#countall) | (Public Preview) Creates an aggregation that counts the total number of stage inputs. | | [currentTimestamp()](./firestore_lite_pipelines.md#currenttimestamp) | (Public Preview) Creates an expression that evaluates to the current server timestamp. | +| [rand()](./firestore_lite_pipelines.md#rand) | (Public Preview) Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. | | function(array, ...) | | [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_a00ea48) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. | | [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_7328608) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. | @@ -107,6 +108,8 @@ https://github.com/firebase/firebase-js-sdk | [stringReplaceOne(expression, find, replacement)](./firestore_lite_pipelines.md#stringreplaceone_197ecbe) | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | | [subtract(expression, value)](./firestore_lite_pipelines.md#subtract_01df3cf) | (Public Preview) Creates an expression that subtracts a constant value from an expression. | | [sum(expression)](./firestore_lite_pipelines.md#sum_1138a27) | (Public Preview) Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. | +| [trunc(expression)](./firestore_lite_pipelines.md#trunc_1138a27) | (Public Preview) Creates an expression that truncates the numeric value of an expression to an integer. | +| [trunc(expression, decimalPlaces)](./firestore_lite_pipelines.md#trunc_a3a92d0) | (Public Preview) Creates an expression that truncates a numeric value to the specified number of decimal places. | | [type(expression)](./firestore_lite_pipelines.md#type_1138a27) | (Public Preview) Creates an expression that returns the data type of an expression's result. | | function(field, ...) | | [isAbsent(field)](./firestore_lite_pipelines.md#isabsent_0fb8cd4) | (Public Preview) Creates an expression that returns true if a field is absent. Otherwise, returns false even if the field value is null. | @@ -215,6 +218,8 @@ https://github.com/firebase/firebase-js-sdk | [toLower(fieldName)](./firestore_lite_pipelines.md#tolower_e5b0480) | (Public Preview) Creates an expression that converts a string field to lowercase. | | [toUpper(fieldName)](./firestore_lite_pipelines.md#toupper_e5b0480) | (Public Preview) Creates an expression that converts a string field to uppercase. | | [trim(fieldName, valueToTrim)](./firestore_lite_pipelines.md#trim_c9f90ee) | (Public Preview) Creates an expression that removes leading and trailing whitespace from a string or byte array. | +| [trunc(fieldName)](./firestore_lite_pipelines.md#trunc_e5b0480) | (Public Preview) Creates an expression that truncates the numeric value of a field to an integer. | +| [trunc(fieldName, decimalPlaces)](./firestore_lite_pipelines.md#trunc_07d0cf0) | (Public Preview) Creates an expression that truncates a numeric expression to the specified number of decimal places. | | [type(fieldName)](./firestore_lite_pipelines.md#type_e5b0480) | (Public Preview) Creates an expression that returns the data type of the data in the specified field. | | [unixMicrosToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixmicrostotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | | [unixMillisToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixmillistotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | @@ -453,6 +458,33 @@ currentTimestamp() ``` +### rand() {:#rand} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. + +Signature: + +```typescript +export declare function rand(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the rand operation. + +### Example + + +```typescript +// Generate a random number between 0.0 and 1.0. +rand(); + +``` + ## function(array, ...) ### arrayContains(array, element) {:#arraycontains_a00ea48} @@ -3096,6 +3128,75 @@ sum(field("orderAmount")).as("totalRevenue"); ``` +### trunc(expression) {:#trunc_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates the numeric value of an expression to an integer. + +Signature: + +```typescript +export declare function trunc(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be truncated. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the value of the 'rating' field. +trunc(field("rating")); + +``` + +### trunc(expression, decimalPlaces) {:#trunc_a3a92d0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a numeric value to the specified number of decimal places. + +Signature: + +```typescript +export declare function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be truncated. | +| decimalPlaces | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A constant or expression specifying the truncation precision in decimal places. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the value of the 'rating' field to two decimal places. +trunc(field("rating"), constant(2)); + +``` + ### type(expression) {:#type_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -6777,6 +6878,75 @@ trim("userInput", '"'); ``` +### trunc(fieldName) {:#trunc_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates the numeric value of a field to an integer. + +Signature: + +```typescript +export declare function trunc(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the number to truncate. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the value of the 'rating' field +trunc("rating"); + +``` + +### trunc(fieldName, decimalPlaces) {:#trunc_07d0cf0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a numeric expression to the specified number of decimal places. + +Signature: + +```typescript +export declare function trunc(fieldName: string, decimalPlaces: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to truncate. | +| decimalPlaces | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A constant or expression specifying the truncation precision in decimal places. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the value of the 'rating' field to two decimal places. +trunc("rating", 2); + +``` + ### type(fieldName) {:#type_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 355dc83232..deafd1eb48 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -170,6 +170,9 @@ field("optional_field").ifAbsent(field('default_field')) | [toLower()](./firestore_pipelines.expression.md#expressiontolower) | | (Public Preview) Creates an expression that converts a string to lowercase. | | [toUpper()](./firestore_pipelines.expression.md#expressiontoupper) | | (Public Preview) Creates an expression that converts a string to uppercase. | | [trim(valueToTrim)](./firestore_pipelines.expression.md#expressiontrim) | | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array. | +| [trunc()](./firestore_pipelines.expression.md#expressiontrunc) | | (Public Preview) Creates an expression that truncates the numeric value to an integer. | +| [trunc(decimalPlaces)](./firestore_pipelines.expression.md#expressiontrunc) | | (Public Preview) Creates an expression that truncates a numeric value to the specified number of decimal places. | +| [trunc(decimalPlaces)](./firestore_pipelines.expression.md#expressiontrunc) | | (Public Preview) Creates an expression that truncates a numeric value to the specified number of decimal places. | | [type()](./firestore_pipelines.expression.md#expressiontype) | | (Public Preview) Creates an expression that returns the data type of this expression's result, as a string. | | [unixMicrosToTimestamp()](./firestore_pipelines.expression.md#expressionunixmicrostotimestamp) | | (Public Preview) 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. | | [unixMillisToTimestamp()](./firestore_pipelines.expression.md#expressionunixmillistotimestamp) | | (Public Preview) 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. | @@ -4242,6 +4245,101 @@ field("userInput").trim('"'); ``` +## Expression.trunc() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates the numeric value to an integer. + +Signature: + +```typescript +trunc(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the 'rating' field +field("rating").trunc(); + +``` + +## Expression.trunc() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a numeric value to the specified number of decimal places. + +Signature: + +```typescript +trunc(decimalPlaces: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| decimalPlaces | number | A constant specifying the truncation precision in decimal places. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the value of the 'rating' field to two decimal places. +field("rating").trunc(2); + +``` + +## Expression.trunc() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a numeric value to the specified number of decimal places. + +Signature: + +```typescript +trunc(decimalPlaces: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| decimalPlaces | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression specifying the truncation precision in decimal places. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the value of the 'rating' field to two decimal places. +field("rating").trunc(constant(2)); + +``` + ## Expression.type() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 63e5790ee7..9ce0a7898b 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -18,6 +18,7 @@ https://github.com/firebase/firebase-js-sdk | function() | | [countAll()](./firestore_pipelines.md#countall) | (Public Preview) Creates an aggregation that counts the total number of stage inputs. | | [currentTimestamp()](./firestore_pipelines.md#currenttimestamp) | (Public Preview) Creates an expression that evaluates to the current server timestamp. | +| [rand()](./firestore_pipelines.md#rand) | (Public Preview) Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. | | function(array, ...) | | [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_a00ea48) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. | | [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_7328608) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. | @@ -107,6 +108,8 @@ https://github.com/firebase/firebase-js-sdk | [stringReplaceOne(expression, find, replacement)](./firestore_pipelines.md#stringreplaceone_197ecbe) | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | | [subtract(expression, value)](./firestore_pipelines.md#subtract_01df3cf) | (Public Preview) Creates an expression that subtracts a constant value from an expression. | | [sum(expression)](./firestore_pipelines.md#sum_1138a27) | (Public Preview) Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. | +| [trunc(expression)](./firestore_pipelines.md#trunc_1138a27) | (Public Preview) Creates an expression that truncates the numeric value of an expression to an integer. | +| [trunc(expression, decimalPlaces)](./firestore_pipelines.md#trunc_a3a92d0) | (Public Preview) Creates an expression that truncates a numeric value to the specified number of decimal places. | | [type(expression)](./firestore_pipelines.md#type_1138a27) | (Public Preview) Creates an expression that returns the data type of an expression's result. | | function(field, ...) | | [isAbsent(field)](./firestore_pipelines.md#isabsent_0fb8cd4) | (Public Preview) Creates an expression that returns true if a field is absent. Otherwise, returns false even if the field value is null. | @@ -215,6 +218,8 @@ https://github.com/firebase/firebase-js-sdk | [toLower(fieldName)](./firestore_pipelines.md#tolower_e5b0480) | (Public Preview) Creates an expression that converts a string field to lowercase. | | [toUpper(fieldName)](./firestore_pipelines.md#toupper_e5b0480) | (Public Preview) Creates an expression that converts a string field to uppercase. | | [trim(fieldName, valueToTrim)](./firestore_pipelines.md#trim_c9f90ee) | (Public Preview) Creates an expression that removes leading and trailing whitespace from a string or byte array. | +| [trunc(fieldName)](./firestore_pipelines.md#trunc_e5b0480) | (Public Preview) Creates an expression that truncates the numeric value of a field to an integer. | +| [trunc(fieldName, decimalPlaces)](./firestore_pipelines.md#trunc_07d0cf0) | (Public Preview) Creates an expression that truncates a numeric expression to the specified number of decimal places. | | [type(fieldName)](./firestore_pipelines.md#type_e5b0480) | (Public Preview) Creates an expression that returns the data type of the data in the specified field. | | [unixMicrosToTimestamp(fieldName)](./firestore_pipelines.md#unixmicrostotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | | [unixMillisToTimestamp(fieldName)](./firestore_pipelines.md#unixmillistotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | @@ -459,6 +464,33 @@ currentTimestamp() ``` +### rand() {:#rand} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. + +Signature: + +```typescript +export declare function rand(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the rand operation. + +### Example + + +```typescript +// Generate a random number between 0.0 and 1.0. +rand(); + +``` + ## function(array, ...) ### arrayContains(array, element) {:#arraycontains_a00ea48} @@ -3102,6 +3134,75 @@ sum(field("orderAmount")).as("totalRevenue"); ``` +### trunc(expression) {:#trunc_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates the numeric value of an expression to an integer. + +Signature: + +```typescript +export declare function trunc(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be truncated. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the value of the 'rating' field. +trunc(field("rating")); + +``` + +### trunc(expression, decimalPlaces) {:#trunc_a3a92d0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a numeric value to the specified number of decimal places. + +Signature: + +```typescript +export declare function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be truncated. | +| decimalPlaces | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | A constant or expression specifying the truncation precision in decimal places. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the value of the 'rating' field to two decimal places. +trunc(field("rating"), constant(2)); + +``` + ### type(expression) {:#type_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -6783,6 +6884,75 @@ trim("userInput", '"'); ``` +### trunc(fieldName) {:#trunc_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates the numeric value of a field to an integer. + +Signature: + +```typescript +export declare function trunc(fieldName: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the number to truncate. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the value of the 'rating' field +trunc("rating"); + +``` + +### trunc(fieldName, decimalPlaces) {:#trunc_07d0cf0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that truncates a numeric expression to the specified number of decimal places. + +Signature: + +```typescript +export declare function trunc(fieldName: string, decimalPlaces: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to truncate. | +| decimalPlaces | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | A constant or expression specifying the truncation precision in decimal places. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the truncated value. + +### Example + + +```typescript +// Truncate the value of the 'rating' field to two decimal places. +trunc("rating", 2); + +``` + ### type(fieldName) {:#type_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index df003e3697..cdc172eb57 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -172,11 +172,13 @@ export { floor, exp, pow, + rand, round, collectionId, ln, log, sqrt, + trunc, stringReverse, log10, concat, diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index a08d0e08be..b551f9667f 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -140,11 +140,13 @@ export { floor, exp, pow, + rand, round, collectionId, ln, log, sqrt, + trunc, stringReverse, length, abs, diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index 5d4692333c..bf5a054fec 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -2321,6 +2321,61 @@ export abstract class Expression implements ProtoValueSerializable, UserData { return new FunctionExpression('pow', [this, valueToDefaultExpr(exponent)]); } + /** + * @beta + * Creates an expression that truncates the numeric value to an integer. + * + * @example + * ```typescript + * // Truncate the 'rating' field + * field("rating").trunc(); + * ``` + * + * @returns A new `Expression` representing the truncated value. + */ + trunc(): FunctionExpression; + + /** + * @beta + * Creates an expression that truncates a numeric value to the specified number of decimal places. + * + * @example + * ```typescript + * // Truncate the value of the 'rating' field to two decimal places. + * field("rating").trunc(2); + * ``` + * + * @param decimalPlaces - A constant specifying the truncation precision in decimal places. + * @returns A new `Expression` representing the truncated value. + */ + trunc(decimalPlaces: number): FunctionExpression; + + /** + * @beta + * Creates an expression that truncates a numeric value to the specified number of decimal places. + * + * @example + * ```typescript + * // Truncate the value of the 'rating' field to two decimal places. + * field("rating").trunc(constant(2)); + * ``` + * + * @param decimalPlaces - An expression specifying the truncation precision in decimal places. + * @returns A new `Expression` representing the truncated value. + */ + trunc(decimalPlaces: Expression): FunctionExpression; + trunc(decimalPlaces?: number | Expression): FunctionExpression { + if (decimalPlaces === undefined) { + return new FunctionExpression('trunc', [this]); + } else { + return new FunctionExpression( + 'trunc', + [this, valueToDefaultExpr(decimalPlaces)], + 'trunc' + ); + } + } + /** * @beta * Creates an expression that rounds a numeric value to the nearest whole number. @@ -8249,6 +8304,23 @@ export function pow( return fieldOrExpression(base).pow(exponent as number); } +/** + * @beta + * + * Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. + * + * @example + * ```typescript + * // Generate a random number between 0.0 and 1.0. + * rand(); + * ``` + * + * @returns A new `Expression` representing the rand operation. + */ +export function rand(): FunctionExpression { + return new FunctionExpression('rand', [], 'rand'); +} + /** * @beta * Creates an expression that rounds a numeric value to the nearest whole number. @@ -8327,6 +8399,84 @@ export function round( } } +/** + * @beta + * Creates an expression that truncates the numeric value of a field to an integer. + * + * @example + * ```typescript + * // Truncate the value of the 'rating' field + * trunc("rating"); + * ``` + * + * @param fieldName - The name of the field containing the number to truncate. + * @returns A new `Expression` representing the truncated value. + */ +export function trunc(fieldName: string): FunctionExpression; + +/** + * @beta + * Creates an expression that truncates the numeric value of an expression to an integer. + * + * @example + * ```typescript + * // Truncate the value of the 'rating' field. + * trunc(field("rating")); + * ``` + * + * @param expression - An expression evaluating to a numeric value, which will be truncated. + * @returns A new `Expression` representing the truncated value. + */ +export function trunc(expression: Expression): FunctionExpression; + +/** + * @beta + * Creates an expression that truncates a numeric expression to the specified number of decimal places. + * + * @example + * ```typescript + * // Truncate the value of the 'rating' field to two decimal places. + * trunc("rating", 2); + * ``` + * + * @param fieldName - The name of the field to truncate. + * @param decimalPlaces - A constant or expression specifying the truncation precision in decimal places. + * @returns A new `Expression` representing the truncated value. + */ +export function trunc( + fieldName: string, + decimalPlaces: number | Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that truncates a numeric value to the specified number of decimal places. + * + * @example + * ```typescript + * // Truncate the value of the 'rating' field to two decimal places. + * trunc(field("rating"), constant(2)); + * ``` + * + * @param expression - An expression evaluating to a numeric value, which will be truncated. + * @param decimalPlaces - A constant or expression specifying the truncation precision in decimal places. + * @returns A new `Expression` representing the truncated value. + */ +export function trunc( + expression: Expression, + decimalPlaces: number | Expression +): FunctionExpression; +export function trunc( + expr: Expression | string, + decimalPlaces?: number | Expression +): FunctionExpression { + if (decimalPlaces === undefined) { + return fieldOrExpression(expr).trunc(); + } else { + return fieldOrExpression(expr).trunc(valueToDefaultExpr(decimalPlaces)); + } +} + /** * @beta * Creates an expression that returns the collection ID from a path. diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 5825d5980c..d90a31c080 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -130,12 +130,14 @@ import { floor, exp, pow, + rand, round, rtrim, collectionId, ln, log, sqrt, + trunc, stringReverse, length, abs, @@ -3366,6 +3368,21 @@ apiDescribe.skipClassic('Pipelines', persistence => { ); }); + it('testRand', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(rand().as('randomNumber')) + .limit(1) + ); + expect(snapshot.results.length).to.equal(1); + const randomNumber = snapshot.results[0].data()['randomNumber'] as number; + expect(randomNumber).to.be.a('number'); + expect(randomNumber).to.be.gte(0); + expect(randomNumber).to.be.lt(1); + }); + it('can round a numeric value', async () => { const snapshot = await execute( firestore @@ -3450,6 +3467,60 @@ apiDescribe.skipClassic('Pipelines', persistence => { }); }); + it('can truncate a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('Pride and Prejudice')) + .limit(1) + .select(field('rating').trunc().as('truncatedRating')) + ); + expectResults(snapshot, { + truncatedRating: 4 + }); + }); + + it('can truncate a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('Pride and Prejudice')) + .limit(1) + .select(trunc('rating').as('truncatedRating')) + ); + expectResults(snapshot, { + truncatedRating: 4 + }); + }); + + it('can truncate a numeric value to specified precision', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + foo: 4.123456 + }) + ) + .select( + field('foo').trunc(0).as('0'), + trunc('foo', 1).as('1'), + trunc('foo', constant(2)).as('2'), + trunc(field('foo'), 4).as('4') + ) + ); + expectResults(snapshot, { + '0': 4, + '1': 4.1, + '2': 4.12, + '4': 4.1234 + }); + }); + it('can get the collectionId from a path', async () => { const snapshot = await execute( firestore diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index a81050490e..066cca7f21 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -139,11 +139,13 @@ import { floor, exp, pow, + rand, round, collectionId, ln, log, sqrt, + trunc, stringReverse, log10, concat, @@ -3338,6 +3340,21 @@ describe.skipClassic('Firestore Pipelines', () => { ); }); + it('testRand', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(rand().as('randomNumber')) + .limit(1) + ); + expect(snapshot.results.length).to.equal(1); + const randomNumber = snapshot.results[0].data()['randomNumber'] as number; + expect(randomNumber).to.be.a('number'); + expect(randomNumber).to.be.gte(0); + expect(randomNumber).to.be.lt(1); + }); + it('can round a numeric value', async () => { const snapshot = await execute( firestore @@ -3422,6 +3439,60 @@ describe.skipClassic('Firestore Pipelines', () => { }); }); + it('can truncate a numeric value', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('Pride and Prejudice')) + .limit(1) + .select(field('rating').trunc().as('truncatedRating')) + ); + expectResults(snapshot, { + truncatedRating: 4 + }); + }); + + it('can truncate a numeric value with the top-level function', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(field('title').equal('Pride and Prejudice')) + .limit(1) + .select(trunc('rating').as('truncatedRating')) + ); + expectResults(snapshot, { + truncatedRating: 4 + }); + }); + + it('can truncate a numeric value to specified precision', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + foo: 4.123456 + }) + ) + .select( + field('foo').trunc(0).as('0'), + trunc('foo', 1).as('1'), + trunc('foo', constant(2)).as('2'), + trunc(field('foo'), 4).as('4') + ) + ); + expectResults(snapshot, { + '0': 4, + '1': 4.1, + '2': 4.12, + '4': 4.1234 + }); + }); + it('can get the collectionId from a path', async () => { const snapshot = await execute( firestore From 659d9bb7987c1fb7bc9f3d772fe1c467f7e4f80f Mon Sep 17 00:00:00 2001 From: Yvonne Pan <103622026+yvonnep165@users.noreply.github.com> Date: Mon, 23 Feb 2026 11:44:14 -0500 Subject: [PATCH 070/174] feat(firestore): add accumulators expressions (#9576) * add first and last aggregation expressions * add array_agg aggregation expression * add array_agg_distinct aggregation expression * Add changeset and documentation * fix formatting * add remark documentation for array_agg and array_agg_distinct --- .changeset/few-dodos-ring.md | 6 + .../firestore-lite-pipelines.api.md | 32 ++ common/api-review/firestore-pipelines.api.md | 32 ++ .../firestore_lite_pipelines.expression.md | 116 +++++++ docs-devsite/firestore_lite_pipelines.md | 288 ++++++++++++++++++ .../firestore_pipelines.expression.md | 116 +++++++ docs-devsite/firestore_pipelines.md | 288 ++++++++++++++++++ .../firestore/lite/pipelines/pipelines.ts | 4 + packages/firestore/src/api_pipelines.ts | 4 + .../firestore/src/lite-api/expressions.ts | 234 ++++++++++++++ .../test/integration/api/pipeline.test.ts | 52 ++++ packages/firestore/test/lite/pipeline.test.ts | 52 ++++ 12 files changed, 1224 insertions(+) create mode 100644 .changeset/few-dodos-ring.md diff --git a/.changeset/few-dodos-ring.md b/.changeset/few-dodos-ring.md new file mode 100644 index 0000000000..f4182c1f4d --- /dev/null +++ b/.changeset/few-dodos-ring.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/firestore': minor +--- + +Add support for first, last, array_agg and array_agg_distinct expressions diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index 0f222b4930..5c465728e1 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -65,6 +65,18 @@ export function and(first: BooleanExpression, second: BooleanExpression, ...more // @beta export function array(elements: unknown[]): FunctionExpression; +// @beta +export function arrayAgg(expression: Expression): AggregateFunction; + +// @beta +export function arrayAgg(fieldName: string): AggregateFunction; + +// @beta +export function arrayAggDistinct(expression: Expression): AggregateFunction; + +// @beta +export function arrayAggDistinct(fieldName: string): AggregateFunction; + // @beta export function arrayConcat(firstArray: Expression, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; @@ -377,6 +389,10 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ add(second: Expression | unknown): FunctionExpression; /* Excluded from this release type: _readUserData */ + arrayAgg(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + arrayAggDistinct(): AggregateFunction; + /* Excluded from this release type: _readUserData */ arrayConcat(secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; /* Excluded from this release type: _readUserData */ arrayContains(expression: Expression): BooleanExpression; @@ -462,6 +478,8 @@ export abstract class Expression { // (undocumented) abstract readonly expressionType: ExpressionType; /* Excluded from this release type: _readUserData */ + first(): AggregateFunction; + /* Excluded from this release type: _readUserData */ floor(): FunctionExpression; /* Excluded from this release type: _readUserData */ greaterThan(expression: Expression): BooleanExpression; @@ -488,6 +506,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ join(delimiter: string): Expression; /* Excluded from this release type: _readUserData */ + last(): AggregateFunction; + /* Excluded from this release type: _readUserData */ length(): FunctionExpression; /* Excluded from this release type: _readUserData */ lessThan(experession: Expression): BooleanExpression; @@ -677,6 +697,12 @@ export type FindNearestStageOptions = StageOptions & { distanceField?: string; }; +// @beta +export function first(expression: Expression): AggregateFunction; + +// @beta +export function first(fieldName: string): AggregateFunction; + // @beta export function floor(expr: Expression): FunctionExpression; @@ -757,6 +783,12 @@ export function join(arrayExpression: Expression, delimiter: string): Expression // @beta export function join(arrayFieldName: string, delimiterExpression: Expression): Expression; +// @beta +export function last(expression: Expression): AggregateFunction; + +// @beta +export function last(fieldName: string): AggregateFunction; + // @beta function length_2(fieldName: string): FunctionExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 289707510c..04fa1df808 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -65,6 +65,18 @@ export function and(first: BooleanExpression, second: BooleanExpression, ...more // @beta export function array(elements: unknown[]): FunctionExpression; +// @beta +export function arrayAgg(expression: Expression): AggregateFunction; + +// @beta +export function arrayAgg(fieldName: string): AggregateFunction; + +// @beta +export function arrayAggDistinct(expression: Expression): AggregateFunction; + +// @beta +export function arrayAggDistinct(fieldName: string): AggregateFunction; + // @beta export function arrayConcat(firstArray: Expression, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; @@ -380,6 +392,10 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ add(second: Expression | unknown): FunctionExpression; /* Excluded from this release type: _readUserData */ + arrayAgg(): AggregateFunction; + /* Excluded from this release type: _readUserData */ + arrayAggDistinct(): AggregateFunction; + /* Excluded from this release type: _readUserData */ arrayConcat(secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; /* Excluded from this release type: _readUserData */ arrayContains(expression: Expression): BooleanExpression; @@ -465,6 +481,8 @@ export abstract class Expression { // (undocumented) abstract readonly expressionType: ExpressionType; /* Excluded from this release type: _readUserData */ + first(): AggregateFunction; + /* Excluded from this release type: _readUserData */ floor(): FunctionExpression; /* Excluded from this release type: _readUserData */ greaterThan(expression: Expression): BooleanExpression; @@ -491,6 +509,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ join(delimiter: string): Expression; /* Excluded from this release type: _readUserData */ + last(): AggregateFunction; + /* Excluded from this release type: _readUserData */ length(): FunctionExpression; /* Excluded from this release type: _readUserData */ lessThan(experession: Expression): BooleanExpression; @@ -680,6 +700,12 @@ export type FindNearestStageOptions = StageOptions & { distanceField?: string; }; +// @beta +export function first(expression: Expression): AggregateFunction; + +// @beta +export function first(fieldName: string): AggregateFunction; + // @beta export function floor(expr: Expression): FunctionExpression; @@ -760,6 +786,12 @@ export function join(arrayExpression: Expression, delimiter: string): Expression // @beta export function join(arrayFieldName: string, delimiterExpression: Expression): Expression; +// @beta +export function last(expression: Expression): AggregateFunction; + +// @beta +export function last(fieldName: string): AggregateFunction; + // @beta function length_2(fieldName: string): FunctionExpression; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index a8c3b793ea..8c0f4fa78e 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -39,6 +39,8 @@ export declare abstract class Expression | --- | --- | --- | | [abs()](./firestore_lite_pipelines.expression.md#expressionabs) | | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | | [add(second)](./firestore_lite_pipelines.expression.md#expressionadd) | | (Public Preview) Creates an expression that adds this expression to another expression. | +| [arrayAgg()](./firestore_lite_pipelines.expression.md#expressionarrayagg) | | (Public Preview) Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. | +| [arrayAggDistinct()](./firestore_lite_pipelines.expression.md#expressionarrayaggdistinct) | | (Public Preview) Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. | | [arrayConcat(secondArray, otherArrays)](./firestore_lite_pipelines.expression.md#expressionarrayconcat) | | (Public Preview) Creates an expression that concatenates an array expression with one or more other arrays. | | [arrayContains(expression)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific element. | | [arrayContains(value)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific value. | @@ -80,6 +82,7 @@ export declare abstract class Expression | [euclideanDistance(vector)](./firestore_lite_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. | | [exists()](./firestore_lite_pipelines.expression.md#expressionexists) | | (Public Preview) Creates an expression that checks if a field exists in the document. | | [exp()](./firestore_lite_pipelines.expression.md#expressionexp) | | (Public Preview) Creates an expression that computes e to the power of this expression. | +| [first()](./firestore_lite_pipelines.expression.md#expressionfirst) | | (Public Preview) Creates an aggregation that finds the first value of an expression across multiple stage inputs. | | [floor()](./firestore_lite_pipelines.expression.md#expressionfloor) | | (Public Preview) Creates an expression that computes the floor of a numeric value. | | [greaterThan(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than another expression. | | [greaterThan(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than a constant value. | @@ -100,6 +103,7 @@ field("optional_field").ifAbsent(field('default_field')) | [isError()](./firestore_lite_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. | | [join(delimiterExpression)](./firestore_lite_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array into a string. | | [join(delimiter)](./firestore_lite_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array field into a string. | +| [last()](./firestore_lite_pipelines.expression.md#expressionlast) | | (Public Preview) Creates an aggregation that finds the last value of an expression across multiple stage inputs. | | [length()](./firestore_lite_pipelines.expression.md#expressionlength) | | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(experession)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than another expression. | | [lessThan(value)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than a constant value. | @@ -251,6 +255,64 @@ field("quantity").add(field("reserve")); ``` +## Expression.arrayAgg() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +arrayAgg(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'array\_agg' aggregation. + +### Example + + +```typescript +// Collect all tags from books into an array +field("tags").arrayAgg().as("allTags"); + +``` + +## Expression.arrayAggDistinct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +arrayAggDistinct(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'array\_agg\_distinct' aggregation. + +### Example + + +```typescript +// Collect all distinct tags from books into an array +field("tags").arrayAggDistinct().as("allDistinctTags"); + +``` + ## Expression.arrayConcat() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1533,6 +1595,33 @@ field("value").exp(); ``` +## Expression.first() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the first value of an expression across multiple stage inputs. + +Signature: + +```typescript +first(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'first' aggregation. + +### Example + + +```typescript +// Find the first value of the 'rating' field +field("rating").first().as("firstRating"); + +``` + ## Expression.floor() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1956,6 +2045,33 @@ field("tags").join(", ") ``` +## Expression.last() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the last value of an expression across multiple stage inputs. + +Signature: + +```typescript +last(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'last' aggregation. + +### Example + + +```typescript +// Find the last value of the 'rating' field +field("rating").last().as("lastRating"); + +``` + ## Expression.length() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index ec86287893..ecb7a91740 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -72,6 +72,8 @@ https://github.com/firebase/firebase-js-sdk | [unixMillisToTimestamp(expr)](./firestore_lite_pipelines.md#unixmillistotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | | [unixSecondsToTimestamp(expr)](./firestore_lite_pipelines.md#unixsecondstotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | | function(expression, ...) | +| [arrayAgg(expression)](./firestore_lite_pipelines.md#arrayagg_1138a27) | (Public Preview) Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. | +| [arrayAggDistinct(expression)](./firestore_lite_pipelines.md#arrayaggdistinct_1138a27) | (Public Preview) Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. | | [arraySum(expression)](./firestore_lite_pipelines.md#arraysum_1138a27) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | | [average(expression)](./firestore_lite_pipelines.md#average_1138a27) | (Public Preview) Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. | | [ceil(expression)](./firestore_lite_pipelines.md#ceil_1138a27) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | @@ -82,8 +84,10 @@ https://github.com/firebase/firebase-js-sdk | [equalAny(expression, values)](./firestore_lite_pipelines.md#equalany_7e759b5) | (Public Preview) Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. | | [equalAny(expression, arrayExpression)](./firestore_lite_pipelines.md#equalany_214ce68) | (Public Preview) Creates an expression that checks if an expression is equal to any of the provided values. | | [exp(expression)](./firestore_lite_pipelines.md#exp_1138a27) | (Public Preview) Creates an expression that computes e to the power of the expression's result. | +| [first(expression)](./firestore_lite_pipelines.md#first_1138a27) | (Public Preview) Creates an aggregation that finds the first value of an expression across multiple stage inputs. | | [greaterThan(expression, value)](./firestore_lite_pipelines.md#greaterthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than a constant value. | | [greaterThanOrEqual(expression, value)](./firestore_lite_pipelines.md#greaterthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than or equal to a constant value. | +| [last(expression)](./firestore_lite_pipelines.md#last_1138a27) | (Public Preview) Creates an aggregation that finds the last value of an expression across multiple stage inputs. | | [length\_2(expression)](./firestore_lite_pipelines.md#length_2_1138a27) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(expression, value)](./firestore_lite_pipelines.md#lessthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than a constant value. | | [lessThanOrEqual(expression, value)](./firestore_lite_pipelines.md#lessthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than or equal to a constant value. | @@ -120,6 +124,8 @@ https://github.com/firebase/firebase-js-sdk | function(fieldName, ...) | | [abs(fieldName)](./firestore_lite_pipelines.md#abs_e5b0480) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | | [add(fieldName, second)](./firestore_lite_pipelines.md#add_b75bb8b) | (Public Preview) Creates an expression that adds a field's value to an expression. | +| [arrayAgg(fieldName)](./firestore_lite_pipelines.md#arrayagg_e5b0480) | (Public Preview) Creates an aggregation that collects all values of a field across multiple stage inputs into an array. | +| [arrayAggDistinct(fieldName)](./firestore_lite_pipelines.md#arrayaggdistinct_e5b0480) | (Public Preview) Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. | | [arrayContains(fieldName, element)](./firestore_lite_pipelines.md#arraycontains_aaace4a) | (Public Preview) Creates an expression that checks if a field's array value contains a specific element. | | [arrayContains(fieldName, element)](./firestore_lite_pipelines.md#arraycontains_999590f) | (Public Preview) Creates an expression that checks if a field's array value contains a specific value. | | [arrayContainsAll(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsall_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. | @@ -153,11 +159,13 @@ https://github.com/firebase/firebase-js-sdk | [euclideanDistance(fieldName, vectorExpression)](./firestore_lite_pipelines.md#euclideandistance_ed766a1) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a vector expression. | | [exists(fieldName)](./firestore_lite_pipelines.md#exists_e5b0480) | (Public Preview) Creates an expression that checks if a field exists. | | [exp(fieldName)](./firestore_lite_pipelines.md#exp_e5b0480) | (Public Preview) Creates an expression that computes e to the power of the expression's result. | +| [first(fieldName)](./firestore_lite_pipelines.md#first_e5b0480) | (Public Preview) Creates an aggregation that finds the first value of a field across multiple stage inputs. | | [floor(fieldName)](./firestore_lite_pipelines.md#floor_e5b0480) | (Public Preview) Creates an expression that computes the floor of a numeric value. | | [greaterThan(fieldName, expression)](./firestore_lite_pipelines.md#greaterthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is greater than an expression. | | [greaterThan(fieldName, value)](./firestore_lite_pipelines.md#greaterthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than a constant value. | | [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_2e16acb) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to an expression. | | [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to a constant value. | +| [last(fieldName)](./firestore_lite_pipelines.md#last_e5b0480) | (Public Preview) Creates an aggregation that finds the last value of a field across multiple stage inputs. | | [length\_2(fieldName)](./firestore_lite_pipelines.md#length_2_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(fieldName, expression)](./firestore_lite_pipelines.md#lessthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than an expression. | | [lessThan(fieldName, value)](./firestore_lite_pipelines.md#lessthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than a constant value. | @@ -1871,6 +1879,78 @@ unixSecondsToTimestamp(field("seconds")); ## function(expression, ...) +### arrayAgg(expression) {:#arrayagg_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +export declare function arrayAgg(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to collect values from. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg' aggregation. + +### Example + + +```typescript +// Collect all tags from books into an array +arrayAgg(field("tags")).as("allTags"); + +``` + +### arrayAggDistinct(expression) {:#arrayaggdistinct_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +export declare function arrayAggDistinct(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to collect values from. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg\_distinct' aggregation. + +### Example + + +```typescript +// Collect all distinct tags from books into an array +arrayAggDistinct(field("tags")).as("allDistinctTags"); + +``` + ### arraySum(expression) {:#arraysum_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2215,6 +2295,40 @@ exp(constant(2)); ``` +### first(expression) {:#first_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the first value of an expression across multiple stage inputs. + +Signature: + +```typescript +export declare function first(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the first value of. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'first' aggregation. + +### Example + + +```typescript +// Find the first value of the 'rating' field +first(field("rating")).as("firstRating"); + +``` + ### greaterThan(expression, value) {:#greaterthan_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2285,6 +2399,40 @@ greaterThanOrEqual(field("quantity"), 10); ``` +### last(expression) {:#last_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the last value of an expression across multiple stage inputs. + +Signature: + +```typescript +export declare function last(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the last value of. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'last' aggregation. + +### Example + + +```typescript +// Find the last value of the 'rating' field +last(field("rating")).as("lastRating"); + +``` + ### length\_2(expression) {:#length_2_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3447,6 +3595,78 @@ add("quantity", field("reserve")); ``` +### arrayAgg(fieldName) {:#arrayagg_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all values of a field across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +export declare function arrayAgg(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to collect values from. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg' aggregation. + +### Example + + +```typescript +// Collect all tags from books into an array +arrayAgg("tags").as("allTags"); + +``` + +### arrayAggDistinct(fieldName) {:#arrayaggdistinct_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +export declare function arrayAggDistinct(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to collect values from. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg\_distinct' aggregation. + +### Example + + +```typescript +// Collect all distinct tags from books into an array +arrayAggDistinct("tags").as("allDistinctTags"); + +``` + ### arrayContains(fieldName, element) {:#arraycontains_aaace4a} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4595,6 +4815,40 @@ exp('value'); ``` +### first(fieldName) {:#first_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the first value of a field across multiple stage inputs. + +Signature: + +```typescript +export declare function first(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to find the first value of. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'first' aggregation. + +### Example + + +```typescript +// Find the first value of the 'rating' field +first("rating").as("firstRating"); + +``` + ### floor(fieldName) {:#floor_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4760,6 +5014,40 @@ greaterThanOrEqual("score", 80); ``` +### last(fieldName) {:#last_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the last value of a field across multiple stage inputs. + +Signature: + +```typescript +export declare function last(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to find the last value of. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'last' aggregation. + +### Example + + +```typescript +// Find the last value of the 'rating' field +last("rating").as("lastRating"); + +``` + ### length\_2(fieldName) {:#length_2_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index deafd1eb48..870ad214f2 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -39,6 +39,8 @@ export declare abstract class Expression | --- | --- | --- | | [abs()](./firestore_pipelines.expression.md#expressionabs) | | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | | [add(second)](./firestore_pipelines.expression.md#expressionadd) | | (Public Preview) Creates an expression that adds this expression to another expression. | +| [arrayAgg()](./firestore_pipelines.expression.md#expressionarrayagg) | | (Public Preview) Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. | +| [arrayAggDistinct()](./firestore_pipelines.expression.md#expressionarrayaggdistinct) | | (Public Preview) Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. | | [arrayConcat(secondArray, otherArrays)](./firestore_pipelines.expression.md#expressionarrayconcat) | | (Public Preview) Creates an expression that concatenates an array expression with one or more other arrays. | | [arrayContains(expression)](./firestore_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific element. | | [arrayContains(value)](./firestore_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific value. | @@ -80,6 +82,7 @@ export declare abstract class Expression | [euclideanDistance(vector)](./firestore_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. | | [exists()](./firestore_pipelines.expression.md#expressionexists) | | (Public Preview) Creates an expression that checks if a field exists in the document. | | [exp()](./firestore_pipelines.expression.md#expressionexp) | | (Public Preview) Creates an expression that computes e to the power of this expression. | +| [first()](./firestore_pipelines.expression.md#expressionfirst) | | (Public Preview) Creates an aggregation that finds the first value of an expression across multiple stage inputs. | | [floor()](./firestore_pipelines.expression.md#expressionfloor) | | (Public Preview) Creates an expression that computes the floor of a numeric value. | | [greaterThan(expression)](./firestore_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than another expression. | | [greaterThan(value)](./firestore_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than a constant value. | @@ -100,6 +103,7 @@ field("optional_field").ifAbsent(field('default_field')) | [isError()](./firestore_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. | | [join(delimiterExpression)](./firestore_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array into a string. | | [join(delimiter)](./firestore_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array field into a string. | +| [last()](./firestore_pipelines.expression.md#expressionlast) | | (Public Preview) Creates an aggregation that finds the last value of an expression across multiple stage inputs. | | [length()](./firestore_pipelines.expression.md#expressionlength) | | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(experession)](./firestore_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than another expression. | | [lessThan(value)](./firestore_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than a constant value. | @@ -251,6 +255,64 @@ field("quantity").add(field("reserve")); ``` +## Expression.arrayAgg() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +arrayAgg(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'array\_agg' aggregation. + +### Example + + +```typescript +// Collect all tags from books into an array +field("tags").arrayAgg().as("allTags"); + +``` + +## Expression.arrayAggDistinct() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +arrayAggDistinct(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'array\_agg\_distinct' aggregation. + +### Example + + +```typescript +// Collect all distinct tags from books into an array +field("tags").arrayAggDistinct().as("allDistinctTags"); + +``` + ## Expression.arrayConcat() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1533,6 +1595,33 @@ field("value").exp(); ``` +## Expression.first() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the first value of an expression across multiple stage inputs. + +Signature: + +```typescript +first(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'first' aggregation. + +### Example + + +```typescript +// Find the first value of the 'rating' field +field("rating").first().as("firstRating"); + +``` + ## Expression.floor() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -1956,6 +2045,33 @@ field("tags").join(", ") ``` +## Expression.last() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the last value of an expression across multiple stage inputs. + +Signature: + +```typescript +last(): AggregateFunction; +``` +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'last' aggregation. + +### Example + + +```typescript +// Find the last value of the 'rating' field +field("rating").last().as("lastRating"); + +``` + ## Expression.length() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 9ce0a7898b..eaec9beeb5 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -72,6 +72,8 @@ https://github.com/firebase/firebase-js-sdk | [unixMillisToTimestamp(expr)](./firestore_pipelines.md#unixmillistotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | | [unixSecondsToTimestamp(expr)](./firestore_pipelines.md#unixsecondstotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | | function(expression, ...) | +| [arrayAgg(expression)](./firestore_pipelines.md#arrayagg_1138a27) | (Public Preview) Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. | +| [arrayAggDistinct(expression)](./firestore_pipelines.md#arrayaggdistinct_1138a27) | (Public Preview) Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. | | [arraySum(expression)](./firestore_pipelines.md#arraysum_1138a27) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | | [average(expression)](./firestore_pipelines.md#average_1138a27) | (Public Preview) Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. | | [ceil(expression)](./firestore_pipelines.md#ceil_1138a27) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | @@ -82,8 +84,10 @@ https://github.com/firebase/firebase-js-sdk | [equalAny(expression, values)](./firestore_pipelines.md#equalany_7e759b5) | (Public Preview) Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. | | [equalAny(expression, arrayExpression)](./firestore_pipelines.md#equalany_214ce68) | (Public Preview) Creates an expression that checks if an expression is equal to any of the provided values. | | [exp(expression)](./firestore_pipelines.md#exp_1138a27) | (Public Preview) Creates an expression that computes e to the power of the expression's result. | +| [first(expression)](./firestore_pipelines.md#first_1138a27) | (Public Preview) Creates an aggregation that finds the first value of an expression across multiple stage inputs. | | [greaterThan(expression, value)](./firestore_pipelines.md#greaterthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than a constant value. | | [greaterThanOrEqual(expression, value)](./firestore_pipelines.md#greaterthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than or equal to a constant value. | +| [last(expression)](./firestore_pipelines.md#last_1138a27) | (Public Preview) Creates an aggregation that finds the last value of an expression across multiple stage inputs. | | [length\_2(expression)](./firestore_pipelines.md#length_2_1138a27) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(expression, value)](./firestore_pipelines.md#lessthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than a constant value. | | [lessThanOrEqual(expression, value)](./firestore_pipelines.md#lessthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than or equal to a constant value. | @@ -120,6 +124,8 @@ https://github.com/firebase/firebase-js-sdk | function(fieldName, ...) | | [abs(fieldName)](./firestore_pipelines.md#abs_e5b0480) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | | [add(fieldName, second)](./firestore_pipelines.md#add_b75bb8b) | (Public Preview) Creates an expression that adds a field's value to an expression. | +| [arrayAgg(fieldName)](./firestore_pipelines.md#arrayagg_e5b0480) | (Public Preview) Creates an aggregation that collects all values of a field across multiple stage inputs into an array. | +| [arrayAggDistinct(fieldName)](./firestore_pipelines.md#arrayaggdistinct_e5b0480) | (Public Preview) Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. | | [arrayContains(fieldName, element)](./firestore_pipelines.md#arraycontains_aaace4a) | (Public Preview) Creates an expression that checks if a field's array value contains a specific element. | | [arrayContains(fieldName, element)](./firestore_pipelines.md#arraycontains_999590f) | (Public Preview) Creates an expression that checks if a field's array value contains a specific value. | | [arrayContainsAll(fieldName, values)](./firestore_pipelines.md#arraycontainsall_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. | @@ -153,11 +159,13 @@ https://github.com/firebase/firebase-js-sdk | [euclideanDistance(fieldName, vectorExpression)](./firestore_pipelines.md#euclideandistance_ed766a1) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a vector expression. | | [exists(fieldName)](./firestore_pipelines.md#exists_e5b0480) | (Public Preview) Creates an expression that checks if a field exists. | | [exp(fieldName)](./firestore_pipelines.md#exp_e5b0480) | (Public Preview) Creates an expression that computes e to the power of the expression's result. | +| [first(fieldName)](./firestore_pipelines.md#first_e5b0480) | (Public Preview) Creates an aggregation that finds the first value of a field across multiple stage inputs. | | [floor(fieldName)](./firestore_pipelines.md#floor_e5b0480) | (Public Preview) Creates an expression that computes the floor of a numeric value. | | [greaterThan(fieldName, expression)](./firestore_pipelines.md#greaterthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is greater than an expression. | | [greaterThan(fieldName, value)](./firestore_pipelines.md#greaterthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than a constant value. | | [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_2e16acb) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to an expression. | | [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to a constant value. | +| [last(fieldName)](./firestore_pipelines.md#last_e5b0480) | (Public Preview) Creates an aggregation that finds the last value of a field across multiple stage inputs. | | [length\_2(fieldName)](./firestore_pipelines.md#length_2_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(fieldName, expression)](./firestore_pipelines.md#lessthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than an expression. | | [lessThan(fieldName, value)](./firestore_pipelines.md#lessthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than a constant value. | @@ -1877,6 +1885,78 @@ unixSecondsToTimestamp(field("seconds")); ## function(expression, ...) +### arrayAgg(expression) {:#arrayagg_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +export declare function arrayAgg(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to collect values from. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg' aggregation. + +### Example + + +```typescript +// Collect all tags from books into an array +arrayAgg(field("tags")).as("allTags"); + +``` + +### arrayAggDistinct(expression) {:#arrayaggdistinct_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +export declare function arrayAggDistinct(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to collect values from. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg\_distinct' aggregation. + +### Example + + +```typescript +// Collect all distinct tags from books into an array +arrayAggDistinct(field("tags")).as("allDistinctTags"); + +``` + ### arraySum(expression) {:#arraysum_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2221,6 +2301,40 @@ exp(constant(2)); ``` +### first(expression) {:#first_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the first value of an expression across multiple stage inputs. + +Signature: + +```typescript +export declare function first(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the first value of. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'first' aggregation. + +### Example + + +```typescript +// Find the first value of the 'rating' field +first(field("rating")).as("firstRating"); + +``` + ### greaterThan(expression, value) {:#greaterthan_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2291,6 +2405,40 @@ greaterThanOrEqual(field("quantity"), 10); ``` +### last(expression) {:#last_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the last value of an expression across multiple stage inputs. + +Signature: + +```typescript +export declare function last(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the last value of. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'last' aggregation. + +### Example + + +```typescript +// Find the last value of the 'rating' field +last(field("rating")).as("lastRating"); + +``` + ### length\_2(expression) {:#length_2_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -3453,6 +3601,78 @@ add("quantity", field("reserve")); ``` +### arrayAgg(fieldName) {:#arrayagg_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all values of a field across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +export declare function arrayAgg(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to collect values from. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg' aggregation. + +### Example + + +```typescript +// Collect all tags from books into an array +arrayAgg("tags").as("allTags"); + +``` + +### arrayAggDistinct(fieldName) {:#arrayaggdistinct_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +export declare function arrayAggDistinct(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to collect values from. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg\_distinct' aggregation. + +### Example + + +```typescript +// Collect all distinct tags from books into an array +arrayAggDistinct("tags").as("allDistinctTags"); + +``` + ### arrayContains(fieldName, element) {:#arraycontains_aaace4a} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4601,6 +4821,40 @@ exp('value'); ``` +### first(fieldName) {:#first_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the first value of a field across multiple stage inputs. + +Signature: + +```typescript +export declare function first(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to find the first value of. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'first' aggregation. + +### Example + + +```typescript +// Find the first value of the 'rating' field +first("rating").as("firstRating"); + +``` + ### floor(fieldName) {:#floor_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4766,6 +5020,40 @@ greaterThanOrEqual("score", 80); ``` +### last(fieldName) {:#last_e5b0480} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that finds the last value of a field across multiple stage inputs. + +Signature: + +```typescript +export declare function last(fieldName: string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to find the last value of. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'last' aggregation. + +### Example + + +```typescript +// Find the last value of the 'rating' field +last("rating").as("lastRating"); + +``` + ### length\_2(fieldName) {:#length_2_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index cdc172eb57..61c484dd16 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -150,6 +150,10 @@ export { countAll, minimum, maximum, + first, + last, + arrayAgg, + arrayAggDistinct, cosineDistance, dotProduct, euclideanDistance, diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index b551f9667f..0002526380 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -110,6 +110,10 @@ export { or, minimum, maximum, + first, + last, + arrayAgg, + arrayAggDistinct, cosineDistance, dotProduct, euclideanDistance, diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index bf5a054fec..c6b13038bf 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -1607,6 +1607,84 @@ export abstract class Expression implements ProtoValueSerializable, UserData { 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(): AggregateFunction { + 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(): AggregateFunction { + 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(): AggregateFunction { + 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(): AggregateFunction { + return AggregateFunction._create( + 'array_agg_distinct', + [this], + 'arrayAggDistinct' + ); + } + /** * @beta * Creates an aggregation that counts the number of distinct values of the expression or field. @@ -7458,6 +7536,162 @@ export function maximum(value: Expression | string): AggregateFunction { return fieldOrExpression(value).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 + * first(field("rating")).as("firstRating"); + * ``` + * + * @param expression - The expression to find the first value of. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'first' aggregation. + */ +export function first(expression: Expression): AggregateFunction; + +/** + * @beta + * Creates an aggregation that finds the first value of a field across multiple stage inputs. + * + * @example + * ```typescript + * // Find the first value of the 'rating' field + * first("rating").as("firstRating"); + * ``` + * + * @param fieldName - The name of the field to find the first value of. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'first' aggregation. + */ +export function first(fieldName: string): AggregateFunction; +export function first(value: Expression | string): AggregateFunction { + return fieldOrExpression(value).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 + * last(field("rating")).as("lastRating"); + * ``` + * + * @param expression - The expression to find the last value of. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'last' aggregation. + */ +export function last(expression: Expression): AggregateFunction; + +/** + * @beta + * Creates an aggregation that finds the last value of a field across multiple stage inputs. + * + * @example + * ```typescript + * // Find the last value of the 'rating' field + * last("rating").as("lastRating"); + * ``` + * + * @param fieldName - The name of the field to find the last value of. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'last' aggregation. + */ +export function last(fieldName: string): AggregateFunction; +export function last(value: Expression | string): AggregateFunction { + return fieldOrExpression(value).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 + * arrayAgg(field("tags")).as("allTags"); + * ``` + * + * @param expression - The expression to collect values from. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'array_agg' aggregation. + */ +export function arrayAgg(expression: Expression): AggregateFunction; + +/** + * @beta + * Creates an aggregation that collects all values of a field 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 + * arrayAgg("tags").as("allTags"); + * ``` + * + * @param fieldName - The name of the field to collect values from. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'array_agg' aggregation. + */ +export function arrayAgg(fieldName: string): AggregateFunction; +export function arrayAgg(value: Expression | string): AggregateFunction { + return fieldOrExpression(value).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 + * arrayAggDistinct(field("tags")).as("allDistinctTags"); + * ``` + * + * @param expression - The expression to collect values from. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'array_agg_distinct' aggregation. + */ +export function arrayAggDistinct(expression: Expression): AggregateFunction; + +/** + * @beta + * Creates an aggregation that collects all distinct values of a field 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 + * arrayAggDistinct("tags").as("allDistinctTags"); + * ``` + * + * @param fieldName - The name of the field to collect values from. + * @returns A new {@link @firebase/firestore/pipelines#AggregateFunction} representing the 'array_agg_distinct' aggregation. + */ +export function arrayAggDistinct(fieldName: string): AggregateFunction; +export function arrayAggDistinct( + value: Expression | string +): AggregateFunction { + return fieldOrExpression(value).arrayAggDistinct(); +} + /** * @beta * diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index d90a31c080..9854e96f26 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -87,6 +87,10 @@ import { countIf, equalAny, exists, + first, + last, + arrayAgg, + arrayAggDistinct, ifError, isError, logicalMaximum, @@ -970,6 +974,54 @@ apiDescribe.skipClassic('Pipelines', persistence => { }); }); + it('returns first and last accumulations', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('published').ascending()) + .aggregate( + first('rating').as('firstBookRating'), + first('title').as('firstBookTitle'), + last('rating').as('lastBookRating'), + last('title').as('lastBookTitle') + ) + ); + expectResults(snapshot, { + firstBookRating: 4.5, + firstBookTitle: 'Pride and Prejudice', + lastBookRating: 4.1, + lastBookTitle: "The Handmaid's Tale" + }); + }); + + it('returns arrayAgg accumulations', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('published').ascending()) + .aggregate(arrayAgg('rating').as('allRatings')) + ); + expectResults(snapshot, { + allRatings: [4.5, 4.3, 4.0, 4.2, 4.7, 4.2, 4.6, 4.3, 4.2, 4.1] + }); + }); + + it('returns arrayAggDistinct accumulations', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate(arrayAggDistinct('rating').as('allDistinctRatings')) + ); + const data = snapshot.results[0].data(); + data['allDistinctRatings'].sort((a: number, b: number) => a - b); + expect(data).to.deep.equal({ + allDistinctRatings: [4.0, 4.1, 4.2, 4.3, 4.5, 4.6, 4.7] + }); + }); + it('returns countif accumulation', async () => { let snapshot = await execute( firestore diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 066cca7f21..d6334f89d7 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -100,6 +100,10 @@ import { countAll, minimum, maximum, + first, + last, + arrayAgg, + arrayAggDistinct, cosineDistance, dotProduct, euclideanDistance, @@ -958,6 +962,54 @@ describe.skipClassic('Firestore Pipelines', () => { }); }); + it('returns first and last accumulations', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('published').ascending()) + .aggregate( + first('rating').as('firstBookRating'), + first('title').as('firstBookTitle'), + last('rating').as('lastBookRating'), + last('title').as('lastBookTitle') + ) + ); + expectResults(snapshot, { + firstBookRating: 4.5, + firstBookTitle: 'Pride and Prejudice', + lastBookRating: 4.1, + lastBookTitle: "The Handmaid's Tale" + }); + }); + + it('returns arrayAgg accumulations', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('published').ascending()) + .aggregate(arrayAgg('rating').as('allRatings')) + ); + expectResults(snapshot, { + allRatings: [4.5, 4.3, 4.0, 4.2, 4.7, 4.2, 4.6, 4.3, 4.2, 4.1] + }); + }); + + it('returns arrayAggDistinct accumulations', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .aggregate(arrayAggDistinct('rating').as('allDistinctRatings')) + ); + const data = snapshot.results[0].data(); + data['allDistinctRatings'].sort((a: number, b: number) => a - b); + expect(data).to.deep.equal({ + allDistinctRatings: [4.0, 4.1, 4.2, 4.3, 4.5, 4.6, 4.7] + }); + }); + it('returns countif accumulation', async () => { let snapshot = await execute( firestore From 60415091e1cb2481255343122a18c9f2845ca505 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Mon, 23 Feb 2026 14:36:00 -0500 Subject: [PATCH 071/174] feat(firestore): add `isType` expression (#9484) --- .changeset/tiny-jokes-compete.md | 6 + .../firestore-lite-pipelines.api.md | 11 + common/api-review/firestore-pipelines.api.md | 11 + .../firestore_lite_pipelines.expression.md | 39 ++++ docs-devsite/firestore_lite_pipelines.md | 94 ++++++++ .../firestore_pipelines.expression.md | 39 ++++ docs-devsite/firestore_pipelines.md | 94 ++++++++ .../firestore/lite/pipelines/pipelines.ts | 6 +- packages/firestore/src/api_pipelines.ts | 6 +- .../firestore/src/lite-api/expressions.ts | 206 ++++++++++++++---- .../test/integration/api/pipeline.test.ts | 72 +++++- packages/firestore/test/lite/pipeline.test.ts | 129 +++++++++++ 12 files changed, 660 insertions(+), 53 deletions(-) create mode 100644 .changeset/tiny-jokes-compete.md diff --git a/.changeset/tiny-jokes-compete.md b/.changeset/tiny-jokes-compete.md new file mode 100644 index 0000000000..65f96cfe06 --- /dev/null +++ b/.changeset/tiny-jokes-compete.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/firestore': minor +--- + +feat(firestore): Support added for the `isType` Pipeline expression. diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index 5c465728e1..a6ddac04af 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -502,6 +502,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ isError(): BooleanExpression; /* Excluded from this release type: _readUserData */ + isType(type: Type): BooleanExpression; + /* Excluded from this release type: _readUserData */ join(delimiterExpression: Expression): Expression; /* Excluded from this release type: _readUserData */ join(delimiter: string): Expression; @@ -771,6 +773,12 @@ export function isAbsent(field: string): BooleanExpression; // @beta export function isError(value: Expression): BooleanExpression; +// @beta +export function isType(fieldName: string, type: Type): BooleanExpression; + +// @beta +export function isType(expression: Expression, type: Type): BooleanExpression; + // @beta export function join(arrayFieldName: string, delimiter: string): Expression; @@ -1376,6 +1384,9 @@ export function trunc(fieldName: string, decimalPlaces: number | Expression): Fu // @beta export function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; +// @beta +export type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp'; + // @beta export function type(fieldName: string): FunctionExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 04fa1df808..a3ade5bd39 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -505,6 +505,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ isError(): BooleanExpression; /* Excluded from this release type: _readUserData */ + isType(type: Type): BooleanExpression; + /* Excluded from this release type: _readUserData */ join(delimiterExpression: Expression): Expression; /* Excluded from this release type: _readUserData */ join(delimiter: string): Expression; @@ -774,6 +776,12 @@ export function isAbsent(field: string): BooleanExpression; // @beta export function isError(value: Expression): BooleanExpression; +// @beta +export function isType(fieldName: string, type: Type): BooleanExpression; + +// @beta +export function isType(expression: Expression, type: Type): BooleanExpression; + // @beta export function join(arrayFieldName: string, delimiter: string): Expression; @@ -1413,6 +1421,9 @@ export function trunc(fieldName: string, decimalPlaces: number | Expression): Fu // @beta export function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; +// @beta +export type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp'; + // @beta export function type(fieldName: string): FunctionExpression; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index 8c0f4fa78e..4f61999d42 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -101,6 +101,7 @@ field("optional_field").ifAbsent(field('default_field')) | [ifError(catchValue)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | | [isAbsent()](./firestore_lite_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. | | [isError()](./firestore_lite_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. | +| [isType(type)](./firestore_lite_pipelines.expression.md#expressionistype) | | (Public Preview) Creates an expression that checks if the result of this expression is of the given type. | | [join(delimiterExpression)](./firestore_lite_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array into a string. | | [join(delimiter)](./firestore_lite_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array field into a string. | | [last()](./firestore_lite_pipelines.expression.md#expressionlast) | | (Public Preview) Creates an aggregation that finds the last value of an expression across multiple stage inputs. | @@ -1977,6 +1978,42 @@ field("title").arrayContains(1).isError(); ``` +## Expression.isType() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the result of this expression is of the given type. + +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. + +Signature: + +```typescript +isType(type: Type): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | [Type](./firestore_lite_pipelines.md#type) | The type to check for. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise. + +### Example + + +```typescript +// Check if the 'price' field is specifically an integer (not just 'number') +field('price').isType('int64'); + +``` + ## Expression.join() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4463,6 +4500,8 @@ field("rating").trunc(constant(2)); Creates an expression that returns the data type of this expression's result, as a string. +This is evaluated on the backend. This means: 1. Generic typed elements (like `array`) 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"`. + Signature: ```typescript diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index ecb7a91740..b2580e7010 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -87,6 +87,7 @@ https://github.com/firebase/firebase-js-sdk | [first(expression)](./firestore_lite_pipelines.md#first_1138a27) | (Public Preview) Creates an aggregation that finds the first value of an expression across multiple stage inputs. | | [greaterThan(expression, value)](./firestore_lite_pipelines.md#greaterthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than a constant value. | | [greaterThanOrEqual(expression, value)](./firestore_lite_pipelines.md#greaterthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than or equal to a constant value. | +| [isType(expression, type)](./firestore_lite_pipelines.md#istype_27398ce) | (Public Preview) Creates an expression that checks if the result of an expression is of the given type. | | [last(expression)](./firestore_lite_pipelines.md#last_1138a27) | (Public Preview) Creates an aggregation that finds the last value of an expression across multiple stage inputs. | | [length\_2(expression)](./firestore_lite_pipelines.md#length_2_1138a27) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(expression, value)](./firestore_lite_pipelines.md#lessthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than a constant value. | @@ -165,6 +166,7 @@ https://github.com/firebase/firebase-js-sdk | [greaterThan(fieldName, value)](./firestore_lite_pipelines.md#greaterthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than a constant value. | | [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_2e16acb) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to an expression. | | [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to a constant value. | +| [isType(fieldName, type)](./firestore_lite_pipelines.md#istype_5da287e) | (Public Preview) Creates an expression that checks if the value in the specified field is of the given type. | | [last(fieldName)](./firestore_lite_pipelines.md#last_e5b0480) | (Public Preview) Creates an aggregation that finds the last value of a field across multiple stage inputs. | | [length\_2(fieldName)](./firestore_lite_pipelines.md#length_2_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(fieldName, expression)](./firestore_lite_pipelines.md#lessthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than an expression. | @@ -405,6 +407,7 @@ https://github.com/firebase/firebase-js-sdk | [SetOptions](./firestore_lite_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | | [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | (Public Preview) Specify time granularity for expressions. | +| [Type](./firestore_lite_pipelines.md#type) | (Public Preview) An enumeration of the different types generated by the Firestore backend.

    • Numerics evaluate directly to backend representation (int64 or float64), not JS number.
    • JavaScript Date and firestore Timestamp objects strictly evaluate to 'timestamp'.
    • Advanced configurations parsing backend types (such as decimal128, max_key or min_key from BSON) are also incorporated in this union string type. Note that decimal128 is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    | | [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | | [UnnestStageOptions](./firestore_lite_pipelines.md#unneststageoptions) | (Public Preview) Represents the specific options available for configuring an UnnestStage within a pipeline. | | [WhereStageOptions](./firestore_lite_pipelines.md#wherestageoptions) | (Public Preview) Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). | @@ -2399,6 +2402,43 @@ greaterThanOrEqual(field("quantity"), 10); ``` +### isType(expression, type) {:#istype_27398ce} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the result of an expression is of the given type. + +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. + +Signature: + +```typescript +export declare function isType(expression: Expression, type: Type): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | +| type | [Type](./firestore_lite_pipelines.md#type) | The type to check for. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise. + +### Example + + +```typescript +// Check if the result of a calculation is a number +isType(add('count', 1), 'number') + +``` + ### last(expression) {:#last_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -5014,6 +5054,43 @@ greaterThanOrEqual("score", 80); ``` +### isType(fieldName, type) {:#istype_5da287e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the value in the specified field is of the given type. + +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. + +Signature: + +```typescript +export declare function isType(fieldName: string, type: Type): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to check. | +| type | [Type](./firestore_lite_pipelines.md#type) | The type to check for. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +A new `BooleanExpression` that evaluates to true if the field's value is of the given type, false otherwise. + +### Example + + +```typescript +// Check if the 'price' field is a floating point number (evaluating to true inside pipeline conditionals) +isType('price', 'float64'); + +``` + ### last(fieldName) {:#last_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -7242,6 +7319,8 @@ trunc("rating", 2); Creates an expression that returns the data type of the data in the specified field. +String inputs passed iteratively to this global function act as `field()` path lookups. If you wish to pass a string literal value, it must be wrapped: `type(constant("my_string"))`. + Signature: ```typescript @@ -10728,6 +10807,21 @@ Specify time granularity for expressions. export declare type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; ``` +## Type + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An enumeration of the different types generated by the Firestore backend. + +
    • Numerics evaluate directly to backend representation (`int64` or `float64`), not JS `number`.
    • JavaScript `Date` and firestore `Timestamp` objects strictly evaluate to `'timestamp'`.
    • Advanced configurations parsing backend types (such as `decimal128`, `max_key` or `min_key` from BSON) are also incorporated in this union string type. Note that `decimal128` is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    + +Signature: + +```typescript +export declare type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp'; +``` + ## UnionStageOptions > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 870ad214f2..76d7aea010 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -101,6 +101,7 @@ field("optional_field").ifAbsent(field('default_field')) | [ifError(catchValue)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | | [isAbsent()](./firestore_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. | | [isError()](./firestore_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. | +| [isType(type)](./firestore_pipelines.expression.md#expressionistype) | | (Public Preview) Creates an expression that checks if the result of this expression is of the given type. | | [join(delimiterExpression)](./firestore_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array into a string. | | [join(delimiter)](./firestore_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array field into a string. | | [last()](./firestore_pipelines.expression.md#expressionlast) | | (Public Preview) Creates an aggregation that finds the last value of an expression across multiple stage inputs. | @@ -1977,6 +1978,42 @@ field("title").arrayContains(1).isError(); ``` +## Expression.isType() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the result of this expression is of the given type. + +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. + +Signature: + +```typescript +isType(type: Type): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | [Type](./firestore_pipelines.md#type) | The type to check for. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise. + +### Example + + +```typescript +// Check if the 'price' field is specifically an integer (not just 'number') +field('price').isType('int64'); + +``` + ## Expression.join() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -4463,6 +4500,8 @@ field("rating").trunc(constant(2)); Creates an expression that returns the data type of this expression's result, as a string. +This is evaluated on the backend. This means: 1. Generic typed elements (like `array`) 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"`. + Signature: ```typescript diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index eaec9beeb5..4e92232c31 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -87,6 +87,7 @@ https://github.com/firebase/firebase-js-sdk | [first(expression)](./firestore_pipelines.md#first_1138a27) | (Public Preview) Creates an aggregation that finds the first value of an expression across multiple stage inputs. | | [greaterThan(expression, value)](./firestore_pipelines.md#greaterthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than a constant value. | | [greaterThanOrEqual(expression, value)](./firestore_pipelines.md#greaterthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than or equal to a constant value. | +| [isType(expression, type)](./firestore_pipelines.md#istype_27398ce) | (Public Preview) Creates an expression that checks if the result of an expression is of the given type. | | [last(expression)](./firestore_pipelines.md#last_1138a27) | (Public Preview) Creates an aggregation that finds the last value of an expression across multiple stage inputs. | | [length\_2(expression)](./firestore_pipelines.md#length_2_1138a27) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(expression, value)](./firestore_pipelines.md#lessthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than a constant value. | @@ -165,6 +166,7 @@ https://github.com/firebase/firebase-js-sdk | [greaterThan(fieldName, value)](./firestore_pipelines.md#greaterthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than a constant value. | | [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_2e16acb) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to an expression. | | [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to a constant value. | +| [isType(fieldName, type)](./firestore_pipelines.md#istype_5da287e) | (Public Preview) Creates an expression that checks if the value in the specified field is of the given type. | | [last(fieldName)](./firestore_pipelines.md#last_e5b0480) | (Public Preview) Creates an aggregation that finds the last value of a field across multiple stage inputs. | | [length\_2(fieldName)](./firestore_pipelines.md#length_2_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(fieldName, expression)](./firestore_pipelines.md#lessthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than an expression. | @@ -411,6 +413,7 @@ https://github.com/firebase/firebase-js-sdk | [SetOptions](./firestore_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | | [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | | [TimeGranularity](./firestore_pipelines.md#timegranularity) | (Public Preview) Specify time granularity for expressions. | +| [Type](./firestore_pipelines.md#type) | (Public Preview) An enumeration of the different types generated by the Firestore backend.
    • Numerics evaluate directly to backend representation (int64 or float64), not JS number.
    • JavaScript Date and firestore Timestamp objects strictly evaluate to 'timestamp'.
    • Advanced configurations parsing backend types (such as decimal128, max_key or min_key from BSON) are also incorporated in this union string type. Note that decimal128 is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    | | [UnionStageOptions](./firestore_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | | [UnnestStageOptions](./firestore_pipelines.md#unneststageoptions) | (Public Preview) Represents the specific options available for configuring an UnnestStage within a pipeline. | | [WhereStageOptions](./firestore_pipelines.md#wherestageoptions) | (Public Preview) Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). | @@ -2405,6 +2408,43 @@ greaterThanOrEqual(field("quantity"), 10); ``` +### isType(expression, type) {:#istype_27398ce} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the result of an expression is of the given type. + +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. + +Signature: + +```typescript +export declare function isType(expression: Expression, type: Type): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | +| type | [Type](./firestore_pipelines.md#type) | The type to check for. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise. + +### Example + + +```typescript +// Check if the result of a calculation is a number +isType(add('count', 1), 'number') + +``` + ### last(expression) {:#last_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -5020,6 +5060,43 @@ greaterThanOrEqual("score", 80); ``` +### isType(fieldName, type) {:#istype_5da287e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if the value in the specified field is of the given type. + +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. + +Signature: + +```typescript +export declare function isType(fieldName: string, type: Type): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field to check. | +| type | [Type](./firestore_pipelines.md#type) | The type to check for. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +A new `BooleanExpression` that evaluates to true if the field's value is of the given type, false otherwise. + +### Example + + +```typescript +// Check if the 'price' field is a floating point number (evaluating to true inside pipeline conditionals) +isType('price', 'float64'); + +``` + ### last(fieldName) {:#last_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -7248,6 +7325,8 @@ trunc("rating", 2); Creates an expression that returns the data type of the data in the specified field. +String inputs passed iteratively to this global function act as `field()` path lookups. If you wish to pass a string literal value, it must be wrapped: `type(constant("my_string"))`. + Signature: ```typescript @@ -10803,6 +10882,21 @@ Specify time granularity for expressions. export declare type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; ``` +## Type + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An enumeration of the different types generated by the Firestore backend. + +
    • Numerics evaluate directly to backend representation (`int64` or `float64`), not JS `number`.
    • JavaScript `Date` and firestore `Timestamp` objects strictly evaluate to `'timestamp'`.
    • Advanced configurations parsing backend types (such as `decimal128`, `max_key` or `min_key` from BSON) are also incorporated in this union string type. Note that `decimal128` is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    + +Signature: + +```typescript +export declare type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp'; +``` + ## UnionStageOptions > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index 61c484dd16..8682d2eb07 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -141,6 +141,8 @@ export { trim, ltrim, rtrim, + type, + isType, stringConcat, stringIndexOf, stringRepeat, @@ -193,7 +195,6 @@ export { arraySum, split, timestampTruncate, - type, AliasedExpression, Field, Constant, @@ -204,5 +205,6 @@ export { Selectable, BooleanExpression, AggregateFunction, - TimeGranularity + TimeGranularity, + Type } from '../../src/lite-api/expressions'; diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index 0002526380..c19e9c859c 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -96,6 +96,8 @@ export { trim, ltrim, rtrim, + type, + isType, stringConcat, stringIndexOf, stringRepeat, @@ -162,7 +164,6 @@ export { arraySum, timestampTruncate, split, - type, Expression, AliasedExpression, Field, @@ -173,7 +174,8 @@ export { ExpressionType, AliasedAggregate, Selectable, - TimeGranularity + TimeGranularity, + Type } from './lite-api/expressions'; export { _internalPipelineToExecutePipelineRequestProto } from './remote/internal_serializer'; diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index c6b13038bf..c5718b3dc4 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -55,6 +55,39 @@ export type ExpressionType = | 'ListOfExpressions' | 'AliasedExpression'; +/** + * @beta + * + * An enumeration of the different types generated by the Firestore backend. + * + *
      + *
    • Numerics evaluate directly to backend representation (`int64` or `float64`), not JS `number`.
    • + *
    • JavaScript `Date` and firestore `Timestamp` objects strictly evaluate to `'timestamp'`.
    • + *
    • Advanced configurations parsing backend types (such as `decimal128`, `max_key` or `min_key` from BSON) are also incorporated in this union string type. Note that `decimal128` is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    • + *
    + */ +export type Type = + | 'null' + | 'array' + | 'boolean' + | 'bytes' + | 'timestamp' + | 'geo_point' + | 'number' + | 'int32' + | 'int64' + | 'float64' + | 'decimal128' + | 'map' + | 'reference' + | 'string' + | 'vector' + | 'max_key' + | 'min_key' + | 'object_id' + | 'regex' + | 'request_timestamp'; + /** * Converts a value to an Expression, Returning either a Constant, MapFunction, * ArrayFunction, or the input itself (if it's already an expression). @@ -1266,6 +1299,53 @@ export abstract class Expression implements ProtoValueSerializable, UserData { 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`) 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(): FunctionExpression { + 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: Type): BooleanExpression { + return new FunctionExpression( + 'is_type', + [this, constant(type)], + 'isType' + ).asBoolean(); + } + /** * @beta * Creates an expression that concatenates string expressions together. @@ -2791,22 +2871,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { 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(): FunctionExpression { - return new FunctionExpression('type', [this]); - } - // TODO(new-expression): Add new expression method definitions above this line /** @@ -7056,6 +7120,84 @@ export function rtrim( return fieldOrExpression(expr).rtrim(valueToTrim); } +/** + * @beta + * Creates an expression that returns the data type of the data in the specified field. + * + * @remarks + * String inputs passed iteratively to this global function act as `field()` path lookups. + * If you wish to pass a string literal value, it must be wrapped: `type(constant("my_string"))`. + * + * @example + * ```typescript + * // Get the data type of the value in field 'title' + * type('title') + * ``` + * + * @returns A new `Expression` representing the data type. + */ +export function type(fieldName: string): FunctionExpression; +/** + * @beta + * Creates an expression that returns the data type of an expression's result. + * + * @example + * ```typescript + * // Get the data type of a conditional expression + * type(conditional(exists('foo'), constant(1), constant(true))) + * ``` + * + * @returns A new `Expression` representing the data type. + */ +export function type(expression: Expression): FunctionExpression; +export function type( + fieldNameOrExpression: string | Expression +): FunctionExpression { + return fieldOrExpression(fieldNameOrExpression).type(); +} + +/** + * @beta + * Creates an expression that checks if the value in the specified field 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 a floating point number (evaluating to true inside pipeline conditionals) + * isType('price', 'float64'); + * ``` + * + * @param fieldName - The name of the field to check. + * @param type - The type to check for. + * @returns A new `BooleanExpression` that evaluates to true if the field's value is of the given type, false otherwise. + */ +export function isType(fieldName: string, type: Type): BooleanExpression; + +/** + * @beta + * Creates an expression that checks if the result of an 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 result of a calculation is a number + * isType(add('count', 1), 'number') + * ``` + * + * @param expression - The expression to check. + * @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. + */ +export function isType(expression: Expression, type: Type): BooleanExpression; +export function isType( + fieldNameOrExpression: string | Expression, + type: Type +): BooleanExpression { + return fieldOrExpression(fieldNameOrExpression).isType(type); +} + /** * @beta * @@ -9446,38 +9588,6 @@ export function timestampTruncate( ); } -/** - * @beta - * Creates an expression that returns the data type of the data in the specified field. - * - * @example - * ```typescript - * // Get the data type of the value in field 'title' - * type('title') - * ``` - * - * @returns A new `Expression` representing the data type. - */ -export function type(fieldName: string): FunctionExpression; -/** - * @beta - * Creates an expression that returns the data type of an expression's result. - * - * @example - * ```typescript - * // Get the data type of a conditional expression - * type(conditional(exists('foo'), constant(1), constant(true))) - * ``` - * - * @returns A new `Expression` representing the data type. - */ -export function type(expression: Expression): FunctionExpression; -export function type( - fieldNameOrExpression: string | Expression -): FunctionExpression { - return fieldOrExpression(fieldNameOrExpression).type(); -} - // TODO(new-expression): Add new top-level expression function definitions above this line /** diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 9854e96f26..5ce4607408 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -154,7 +154,8 @@ import { PipelineSnapshot, timestampTruncate, split, - type + type, + isType } from '../util/pipeline_export'; use(chaiAsPromised); @@ -4507,6 +4508,75 @@ apiDescribe.skipClassic('Pipelines', persistence => { }); }); + it('supports isType', async () => { + const result = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .replaceWith( + map({ + int: constant(1), + float: constant(1.1), + str: constant('a string'), + bool: constant(true), + null: constant(null), + geoPoint: constant(new GeoPoint(0.1, 0.2)), + timestamp: constant(new Timestamp(123456, 0)), + bytes: constant(Bytes.fromUint8Array(new Uint8Array([1, 2, 3]))), + docRef: constant(doc(firestore, randomCol.path, 'bar')), + vector: constant(vector([1, 2, 3])), + map: map({ + numberK: 1, + stringK: 'a string' + }), + array: array([1, '2', true]) + }) + ) + .select( + isType(field('int'), 'int64').as('isInt64'), + isType(field('int'), 'number').as('isInt64IsNumber'), + isType(field('int'), 'decimal128').as('isInt64IsDecimal128'), + field('float').isType('float64').as('isFloat64'), + field('float').isType('number').as('isFloat64IsNumber'), + field('float').isType('decimal128').as('isFloat64IsDecimal128'), + isType('str', 'string').as('isStr'), + isType('int', 'string').as('isNumStr'), + field('bool').isType('boolean').as('isBool'), + isType('null', 'null').as('isNull'), + field('geoPoint').isType('geo_point').as('isGeoPoint'), + isType('timestamp', 'timestamp').as('isTimestamp'), + field('bytes').isType('bytes').as('isBytes'), + isType('docRef', 'reference').as('isDocRef'), + field('vector').isType('vector').as('isVector'), + isType('map', 'map').as('isMap'), + field('array').isType('array').as('isArray'), + field('str').isType('int64').as('isStrNum') + ) + ); + + expectResults(result, { + isInt64: true, + isInt64IsNumber: true, + isInt64IsDecimal128: false, + isFloat64: true, + isFloat64IsNumber: true, + isFloat64IsDecimal128: false, + isStr: true, + isNumStr: false, + isBool: true, + isNull: true, + isGeoPoint: true, + isTimestamp: true, + isBytes: true, + isDocRef: true, + isVector: true, + isMap: true, + isArray: true, + isStrNum: false + }); + }); + // TODO(new-expression): Add new expression tests above this line }); diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index d6334f89d7..01a02cb593 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -66,6 +66,7 @@ import { ifError, isAbsent, isError, + isType, or, map, length, @@ -134,6 +135,7 @@ import { toLower, toUpper, trim, + type, byteLength, arrayGet, abs, @@ -4125,6 +4127,133 @@ describe.skipClassic('Firestore Pipelines', () => { indexOfByte: 1 }); }); + it('testType', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + int: constant(1), + float: constant(1.1), + str: constant('a string'), + bool: constant(true), + null: constant(null), + geoPoint: constant(new GeoPoint(0.1, 0.2)), + timestamp: constant(new Timestamp(123456, 0)), + bytes: constant( + Bytes.fromUint8Array(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 0])) + ), + docRef: constant(doc(firestore, 'foo', 'bar')), + vector: constant(vector([1, 2, 3])), + map: map({ + 'number': 1, + 'string': 'a string' + }), + list: array([1, '2', true]) + }) + ) + .select( + type(field('int')).as('int'), + field('float').type().as('float'), + type('str').as('str'), + field('bool').type().as('bool'), + type('null').as('null'), + field('geoPoint').type().as('geoPoint'), + type('timestamp').as('timestamp'), + field('bytes').type().as('bytes'), + type('docRef').as('docRef'), + field('vector').type().as('vector'), + type('map').as('map'), + field('list').type().as('list') + ) + .limit(1) + ); + + expectResults(snapshot, { + int: 'int64', + float: 'float64', + str: 'string', + bool: 'boolean', + null: 'null', + geoPoint: 'geo_point', + timestamp: 'timestamp', + bytes: 'bytes', + docRef: 'reference', + vector: 'vector', + map: 'map', + list: 'array' + }); + }); + + it('testIsType', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .replaceWith( + map({ + int: constant(1), + float: constant(1.1), + str: constant('a string'), + bool: constant(true), + null: constant(null), + geoPoint: constant(new GeoPoint(0.1, 0.2)), + timestamp: constant(new Timestamp(123456, 0)), + bytes: constant(Bytes.fromUint8Array(new Uint8Array([1, 2, 3]))), + docRef: constant(doc(firestore, randomCol.path, 'bar')), + vector: constant(vector([1, 2, 3])), + map: map({ + numberK: 1, + stringK: 'a string' + }), + array: array([1, '2', true]) + }) + ) + .select( + isType(field('int'), 'int64').as('isInt64'), + isType(field('int'), 'number').as('isInt64IsNumber'), + isType(field('int'), 'decimal128').as('isInt64IsDecimal128'), + field('float').isType('float64').as('isFloat64'), + field('float').isType('number').as('isFloat64IsNumber'), + field('float').isType('decimal128').as('isFloat64IsDecimal128'), + isType('str', 'string').as('isStr'), + isType('int', 'string').as('isNumStr'), + field('bool').isType('boolean').as('isBool'), + isType('null', 'null').as('isNull'), + field('geoPoint').isType('geo_point').as('isGeoPoint'), + isType('timestamp', 'timestamp').as('isTimestamp'), + field('bytes').isType('bytes').as('isBytes'), + isType('docRef', 'reference').as('isDocRef'), + field('vector').isType('vector').as('isVector'), + isType('map', 'map').as('isMap'), + field('array').isType('array').as('isArray'), + field('str').isType('int64').as('isStrNum') + ) + .limit(1) + ); + + expectResults(snapshot, { + isInt64: true, + isInt64IsNumber: true, + isInt64IsDecimal128: false, + isFloat64: true, + isFloat64IsNumber: true, + isFloat64IsDecimal128: false, + isStr: true, + isNumStr: false, + isBool: true, + isNull: true, + isGeoPoint: true, + isTimestamp: true, + isBytes: true, + isDocRef: true, + isVector: true, + isMap: true, + isArray: true, + isStrNum: false + }); + }); it('test reverse', async () => { const snapshot = await execute( From eebba69e912b59e5f097a896e479d139c03d62ca Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 23 Feb 2026 15:30:27 -0800 Subject: [PATCH 072/174] feat(data-connect): Caching for FDC (#9439) --- .changeset/fast-cherries-fold.md | 7 + common/api-review/data-connect.api.md | 92 ++- common/api-review/util.api.md | 3 + .../js/default-connector/.guides/config.json | 9 + .../js/default-connector/.guides/setup.md | 20 + .../js/default-connector/.guides/usage.md | 27 + .../js/default-connector/README.md | 82 ++- .../js/default-connector/esm/index.esm.js | 12 +- .../js/default-connector/index.cjs.js | 10 +- .../js/default-connector/index.d.ts | 39 +- .../js/default-connector/package.json | 4 +- packages/data-connect/.eslintrc.js | 12 +- packages/data-connect/src/api.browser.ts | 94 +-- packages/data-connect/src/api.node.ts | 3 +- packages/data-connect/src/api/DataConnect.ts | 142 ++++- packages/data-connect/src/api/Reference.ts | 3 + packages/data-connect/src/api/index.ts | 20 +- packages/data-connect/src/api/query.ts | 77 ++- packages/data-connect/src/cache/Cache.ts | 146 +++++ .../data-connect/src/cache/CacheProvider.ts | 27 + .../src/cache/EntityDataObject.ts | 68 +++ packages/data-connect/src/cache/EntityNode.ts | 265 ++++++++ .../src/cache/ImpactedQueryRefsAccumulator.ts | 31 + .../src/cache/InMemoryCacheProvider.ts | 47 ++ packages/data-connect/src/cache/ResultTree.ts | 65 ++ .../src/cache/ResultTreeProcessor.ts | 58 ++ packages/data-connect/src/cache/cacheUtils.ts | 63 ++ .../src/core/FirebaseAuthProvider.ts | 4 + .../data-connect/src/core/QueryManager.ts | 245 -------- .../src/core/query/QueryManager.ts | 424 +++++++++++++ .../src/core/query/queryOptions.ts | 33 + .../data-connect/src/core/query/subscribe.ts | 142 +++++ packages/data-connect/src/network/fetch.ts | 98 +-- packages/data-connect/src/network/index.ts | 11 +- .../src/network/transport/index.ts | 48 +- .../src/network/transport/rest.ts | 22 +- packages/data-connect/src/register.ts | 9 +- packages/data-connect/src/util/encoder.ts | 18 +- packages/data-connect/src/util/url.ts | 4 +- packages/data-connect/test/queries.test.ts | 8 +- .../test/unit/QueryManager.test.ts | 6 +- .../data-connect/test/unit/caching.test.ts | 569 ++++++++++++++++++ .../data-connect/test/unit/entitynode.test.ts | 436 ++++++++++++++ packages/data-connect/test/unit/fetch.test.ts | 5 +- packages/data-connect/test/unit/gmpid.test.ts | 1 - .../data-connect/test/unit/maxAge.test.ts | 42 ++ .../test/unit/parseEntityIds.test.ts | 104 ++++ .../data-connect/test/unit/queries.test.ts | 14 +- .../test/unit/transportoptions.test.ts | 11 +- packages/data-connect/test/unit/utils.test.ts | 9 +- packages/data-connect/test/util.ts | 15 +- packages/util/index.node.ts | 1 + packages/util/index.ts | 1 + packages/util/src/sha256.ts | 34 ++ 54 files changed, 3206 insertions(+), 534 deletions(-) create mode 100644 .changeset/fast-cherries-fold.md create mode 100644 e2e/data-connect/dataconnect-generated/js/default-connector/.guides/config.json create mode 100644 e2e/data-connect/dataconnect-generated/js/default-connector/.guides/setup.md create mode 100644 e2e/data-connect/dataconnect-generated/js/default-connector/.guides/usage.md create mode 100644 packages/data-connect/src/cache/Cache.ts create mode 100644 packages/data-connect/src/cache/CacheProvider.ts create mode 100644 packages/data-connect/src/cache/EntityDataObject.ts create mode 100644 packages/data-connect/src/cache/EntityNode.ts create mode 100644 packages/data-connect/src/cache/ImpactedQueryRefsAccumulator.ts create mode 100644 packages/data-connect/src/cache/InMemoryCacheProvider.ts create mode 100644 packages/data-connect/src/cache/ResultTree.ts create mode 100644 packages/data-connect/src/cache/ResultTreeProcessor.ts create mode 100644 packages/data-connect/src/cache/cacheUtils.ts delete mode 100644 packages/data-connect/src/core/QueryManager.ts create mode 100644 packages/data-connect/src/core/query/QueryManager.ts create mode 100644 packages/data-connect/src/core/query/queryOptions.ts create mode 100644 packages/data-connect/src/core/query/subscribe.ts create mode 100644 packages/data-connect/test/unit/caching.test.ts create mode 100644 packages/data-connect/test/unit/entitynode.test.ts create mode 100644 packages/data-connect/test/unit/maxAge.test.ts create mode 100644 packages/data-connect/test/unit/parseEntityIds.test.ts create mode 100644 packages/util/src/sha256.ts diff --git a/.changeset/fast-cherries-fold.md b/.changeset/fast-cherries-fold.md new file mode 100644 index 0000000000..08d360dbf0 --- /dev/null +++ b/.changeset/fast-cherries-fold.md @@ -0,0 +1,7 @@ +--- +"@firebase/data-connect": minor +"@firebase/util": minor +"firebase": minor +--- + +Add Memory-Based caching to Queries in Firebase Data Connect. diff --git a/common/api-review/data-connect.api.md b/common/api-review/data-connect.api.md index 27a9d4af20..c8f4814764 100644 --- a/common/api-review/data-connect.api.md +++ b/common/api-review/data-connect.api.md @@ -11,6 +11,20 @@ import { FirebaseError } from '@firebase/util'; import { LogLevelString } from '@firebase/logger'; import { Provider } from '@firebase/component'; +// @public (undocumented) +export interface CacheProvider { + // (undocumented) + type: T; +} + +// @public (undocumented) +export interface CacheSettings { + // (undocumented) + cacheProvider: CacheProvider; + // (undocumented) + maxAgeSeconds?: number; +} + // @public export type CallerSdkType = 'Base' | 'Generated' | 'TanstackReactCore' | 'GeneratedReact' | 'TanstackAngularCore' | 'GeneratedAngular'; @@ -66,6 +80,12 @@ export class DataConnect { setInitialized(): void; } +// @public (undocumented) +export interface DataConnectEntityArray { + // (undocumented) + entityIds: string[]; +} + // @public export class DataConnectError extends FirebaseError { /* Excluded from this release type: name */ @@ -75,6 +95,11 @@ export class DataConnectError extends FirebaseError { // @public (undocumented) export type DataConnectErrorCode = 'other' | 'already-initialized' | 'not-initialized' | 'not-supported' | 'invalid-argument' | 'partial-error' | 'unauthorized'; +// @public (undocumented) +export type DataConnectExtension = { + path: Array; +} & (DataConnectEntityArray | DataConnectSingleEntity); + // @public export class DataConnectOperationError extends DataConnectError { /* Excluded from this release type: name */ @@ -109,6 +134,28 @@ export interface DataConnectResult extends OpResult { ref: OperationRef; } +// @public (undocumented) +export interface DataConnectSettings { + // (undocumented) + cacheSettings?: CacheSettings; +} + +// @public (undocumented) +export interface DataConnectSingleEntity { + // (undocumented) + entityId: string; +} + +// @public +export interface DataConnectSubscription { + // (undocumented) + errCallback?: (e?: DataConnectError) => void; + // (undocumented) + unsubscribe: () => void; + // (undocumented) + userCallback: OnResultSubscription; +} + // @public (undocumented) export type DataSource = typeof SOURCE_CACHE | typeof SOURCE_SERVER; @@ -116,13 +163,34 @@ export type DataSource = typeof SOURCE_CACHE | typeof SOURCE_SERVER; export function executeMutation(mutationRef: MutationRef): MutationPromise; // @public -export function executeQuery(queryRef: QueryRef): QueryPromise; +export function executeQuery(queryRef: QueryRef, options?: ExecuteQueryOptions): QueryPromise; + +// @public (undocumented) +export interface ExecuteQueryOptions { + // (undocumented) + fetchPolicy: QueryFetchPolicy; +} + +// @public (undocumented) +export interface Extensions { + // (undocumented) + dataConnect?: DataConnectExtension[]; +} // @public +export function getDataConnect(options: ConnectorConfig, settings?: DataConnectSettings): DataConnect; + +// @public (undocumented) export function getDataConnect(options: ConnectorConfig): DataConnect; // @public -export function getDataConnect(app: FirebaseApp, options: ConnectorConfig): DataConnect; +export function getDataConnect(app: FirebaseApp, connectorConfig: ConnectorConfig): DataConnect; + +// @public +export function getDataConnect(app: FirebaseApp, connectorConfig: ConnectorConfig, settings: DataConnectSettings): DataConnect; + +// @public (undocumented) +export function makeMemoryCacheProvider(): CacheProvider<'MEMORY'>; // @public (undocumented) export const MUTATION_STR = "mutation"; @@ -175,6 +243,8 @@ export interface OpResult { // (undocumented) data: Data; // (undocumented) + extensions?: Extensions; + // (undocumented) fetchTime: string; // (undocumented) source: DataSource; @@ -183,6 +253,16 @@ export interface OpResult { // @public (undocumented) export const QUERY_STR = "query"; +// @public +export const QueryFetchPolicy: { + readonly PREFER_CACHE: "PREFER_CACHE"; + readonly CACHE_ONLY: "CACHE_ONLY"; + readonly SERVER_ONLY: "SERVER_ONLY"; +}; + +// @public (undocumented) +export type QueryFetchPolicy = (typeof QueryFetchPolicy)[keyof typeof QueryFetchPolicy]; + // @public export interface QueryPromise extends Promise> { } @@ -238,6 +318,14 @@ export const SOURCE_CACHE = "CACHE"; // @public (undocumented) export const SOURCE_SERVER = "SERVER"; +// @public (undocumented) +export const StorageType: { + readonly MEMORY: "MEMORY"; +}; + +// @public (undocumented) +export type StorageType = (typeof StorageType)[keyof typeof StorageType]; + // @public export function subscribe(queryRefOrSerializedResult: QueryRef | SerializedRef, observer: SubscriptionOptions): QueryUnsubscribe; diff --git a/common/api-review/util.api.md b/common/api-review/util.api.md index 4ac51fda55..349cd392de 100644 --- a/common/api-review/util.api.md +++ b/common/api-review/util.api.md @@ -221,6 +221,9 @@ export class FirebaseError extends Error { // @public export type FirebaseSignInProvider = 'custom' | 'email' | 'password' | 'phone' | 'anonymous' | 'google.com' | 'facebook.com' | 'github.com' | 'twitter.com' | 'microsoft.com' | 'apple.com'; +// @public +export function generateSHA256Hash(input: string): Promise; + // @public export const getDefaultAppConfig: () => Record | undefined; diff --git a/e2e/data-connect/dataconnect-generated/js/default-connector/.guides/config.json b/e2e/data-connect/dataconnect-generated/js/default-connector/.guides/config.json new file mode 100644 index 0000000000..e37ed06f8a --- /dev/null +++ b/e2e/data-connect/dataconnect-generated/js/default-connector/.guides/config.json @@ -0,0 +1,9 @@ +{ + "description": "A set of guides for interacting with the generated firebase dataconnect sdk", + "mcpServers": { + "firebase": { + "command": "npx", + "args": ["-y", "firebase-tools@latest", "experimental:mcp"] + } + } +} diff --git a/e2e/data-connect/dataconnect-generated/js/default-connector/.guides/setup.md b/e2e/data-connect/dataconnect-generated/js/default-connector/.guides/setup.md new file mode 100644 index 0000000000..77a3b2e2ac --- /dev/null +++ b/e2e/data-connect/dataconnect-generated/js/default-connector/.guides/setup.md @@ -0,0 +1,20 @@ +# Setup + +If the user hasn't already installed the SDK, always run the user's node package manager of choice, and install the package in the directory ../package.json. +For more information on where the library is located, look at the connector.yaml file. + +```ts +import { initializeApp } from 'firebase/app'; + +initializeApp({ + // fill in your project config here using the values from your Firebase project or from the `firebase_get_sdk_config` tool from the Firebase MCP server. +}); +``` + +Then, you can run the SDK as needed. +```ts +import { ... } from '@firebasegen/default-connector'; +``` + + + diff --git a/e2e/data-connect/dataconnect-generated/js/default-connector/.guides/usage.md b/e2e/data-connect/dataconnect-generated/js/default-connector/.guides/usage.md new file mode 100644 index 0000000000..8359ffbfed --- /dev/null +++ b/e2e/data-connect/dataconnect-generated/js/default-connector/.guides/usage.md @@ -0,0 +1,27 @@ +# Basic Usage + +Always prioritize using a supported framework over using the generated SDK +directly. Supported frameworks simplify the developer experience and help ensure +best practices are followed. + + + + + +## Advanced Usage +If a user is not using a supported framework, they can use the generated SDK directly. + +Here's an example of how to use it with the first 5 operations: + +```js +import { createMovie, listMovies } from '@firebasegen/default-connector'; + + +// Operation CreateMovie: For variables, look at type CreateMovieVars in ../index.d.ts +const { data } = await CreateMovie(dataConnect, createMovieVars); + +// Operation ListMovies: +const { data } = await ListMovies(dataConnect); + + +``` \ No newline at end of file diff --git a/e2e/data-connect/dataconnect-generated/js/default-connector/README.md b/e2e/data-connect/dataconnect-generated/js/default-connector/README.md index b3f5971d70..e04b813baf 100644 --- a/e2e/data-connect/dataconnect-generated/js/default-connector/README.md +++ b/e2e/data-connect/dataconnect-generated/js/default-connector/README.md @@ -1,5 +1,10 @@ +# Generated TypeScript README +This README will guide you through the process of using the generated JavaScript SDK package for the connector `default`. It will also provide examples on how to use your generated SDK to call your Data Connect queries and mutations. + +***NOTE:** This README is generated alongside the generated SDK. If you make changes to this file, they will be overwritten when the SDK is regenerated.* + # Table of Contents -- [**Overview**](#generated-typescript-readme) +- [**Overview**](#generated-javascript-readme) - [**Accessing the connector**](#accessing-the-connector) - [*Connecting to the local Emulator*](#connecting-to-the-local-emulator) - [**Queries**](#queries) @@ -7,21 +12,14 @@ - [**Mutations**](#mutations) - [*CreateMovie*](#createmovie) -# Generated TypeScript README -This README will guide you through the process of using the generated TypeScript SDK package for the connector `default`. It will also provide examples on how to use your generated SDK to call your Data Connect queries and mutations. - -***NOTE:** This README is generated alongside the generated SDK. If you make changes to this file, they will be overwritten when the SDK is regenerated.* +# Accessing the connector +A connector is a collection of Queries and Mutations. One SDK is generated for each connector - this SDK is generated for the connector `default`. You can find more information about connectors in the [Data Connect documentation](https://firebase.google.com/docs/data-connect#how-does). You can use this generated SDK by importing from the package `@firebasegen/default-connector` as shown below. Both CommonJS and ESM imports are supported. You can also follow the instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#set-client). -# Accessing the connector -A connector is a collection of Queries and Mutations. One SDK is generated for each connector - this SDK is generated for the connector `default`. - -You can find more information about connectors in the [Data Connect documentation](https://firebase.google.com/docs/data-connect#how-does). - -```javascript +```typescript import { getDataConnect } from 'firebase/data-connect'; import { connectorConfig } from '@firebasegen/default-connector'; @@ -34,7 +32,7 @@ By default, the connector will connect to the production service. To connect to the emulator, you can use the following code. You can also follow the emulator instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#instrument-clients). -```javascript +```typescript import { connectDataConnectEmulator, getDataConnect } from 'firebase/data-connect'; import { connectorConfig } from '@firebasegen/default-connector'; @@ -61,16 +59,31 @@ Below are examples of how to use the `default` connector's generated functions t ## ListMovies You can execute the `ListMovies` query using the following action shortcut function, or by calling `executeQuery()` after calling the following `QueryRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): -```javascript +```typescript listMovies(): QueryPromise; -listMoviesRef(): QueryRef; +interface ListMoviesRef { + ... + /* Allow users to create refs without passing in DataConnect */ + (): QueryRef; +} +export const listMoviesRef: ListMoviesRef; ``` You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function. -```javascript +```typescript listMovies(dc: DataConnect): QueryPromise; -listMoviesRef(dc: DataConnect): QueryRef; +interface ListMoviesRef { + ... + (dc: DataConnect): QueryRef; +} +export const listMoviesRef: ListMoviesRef; +``` + +If you need the name of the operation without creating a ref, you can retrieve the operation name by calling the `operationName` property on the listMoviesRef: +```typescript +const name = listMoviesRef.operationName; +console.log(name); ``` ### Variables @@ -79,7 +92,7 @@ The `ListMovies` query has no variables. Recall that executing the `ListMovies` query returns a `QueryPromise` that resolves to an object with a `data` property. The `data` property is an object of type `ListMoviesData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: -```javascript +```typescript export interface ListMoviesData { movies: ({ id: UUIDString; @@ -91,7 +104,7 @@ export interface ListMoviesData { ``` ### Using `ListMovies`'s action shortcut function -```javascript +```typescript import { getDataConnect } from 'firebase/data-connect'; import { connectorConfig, listMovies } from '@firebasegen/default-connector'; @@ -115,7 +128,7 @@ listMovies().then((response) => { ### Using `ListMovies`'s `QueryRef` function -```javascript +```typescript import { getDataConnect, executeQuery } from 'firebase/data-connect'; import { connectorConfig, listMoviesRef } from '@firebasegen/default-connector'; @@ -157,22 +170,37 @@ Below are examples of how to use the `default` connector's generated functions t ## CreateMovie You can execute the `CreateMovie` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): -```javascript +```typescript createMovie(vars: CreateMovieVariables): MutationPromise; -createMovieRef(vars: CreateMovieVariables): MutationRef; +interface CreateMovieRef { + ... + /* Allow users to create refs without passing in DataConnect */ + (vars: CreateMovieVariables): MutationRef; +} +export const createMovieRef: CreateMovieRef; ``` You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. -```javascript +```typescript createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; -createMovieRef(dc: DataConnect, vars: CreateMovieVariables): MutationRef; +interface CreateMovieRef { + ... + (dc: DataConnect, vars: CreateMovieVariables): MutationRef; +} +export const createMovieRef: CreateMovieRef; +``` + +If you need the name of the operation without creating a ref, you can retrieve the operation name by calling the `operationName` property on the createMovieRef: +```typescript +const name = createMovieRef.operationName; +console.log(name); ``` ### Variables The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: -```javascript +```typescript export interface CreateMovieVariables { title: string; genre: string; @@ -183,14 +211,14 @@ export interface CreateMovieVariables { Recall that executing the `CreateMovie` mutation returns a `MutationPromise` that resolves to an object with a `data` property. The `data` property is an object of type `CreateMovieData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: -```javascript +```typescript export interface CreateMovieData { movie_insert: Movie_Key; } ``` ### Using `CreateMovie`'s action shortcut function -```javascript +```typescript import { getDataConnect } from 'firebase/data-connect'; import { connectorConfig, createMovie, CreateMovieVariables } from '@firebasegen/default-connector'; @@ -222,7 +250,7 @@ createMovie(createMovieVars).then((response) => { ### Using `CreateMovie`'s `MutationRef` function -```javascript +```typescript import { getDataConnect, executeMutation } from 'firebase/data-connect'; import { connectorConfig, createMovieRef, CreateMovieVariables } from '@firebasegen/default-connector'; diff --git a/e2e/data-connect/dataconnect-generated/js/default-connector/esm/index.esm.js b/e2e/data-connect/dataconnect-generated/js/default-connector/esm/index.esm.js index e88d2d56d3..5eb3cfc696 100644 --- a/e2e/data-connect/dataconnect-generated/js/default-connector/esm/index.esm.js +++ b/e2e/data-connect/dataconnect-generated/js/default-connector/esm/index.esm.js @@ -1,6 +1,6 @@ /** * @license - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ export const connectorConfig = { location: 'us-central1' }; -export function createMovieRef(dcOrVars, vars) { +export const createMovieRef = (dcOrVars, vars) => { const { dc: dcInstance, vars: inputVars } = validateArgs( connectorConfig, dcOrVars, @@ -38,17 +38,19 @@ export function createMovieRef(dcOrVars, vars) { ); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'CreateMovie', inputVars); -} +}; +createMovieRef.operationName = 'CreateMovie'; export function createMovie(dcOrVars, vars) { return executeMutation(createMovieRef(dcOrVars, vars)); } -export function listMoviesRef(dc) { +export const listMoviesRef = dc => { const { dc: dcInstance } = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return queryRef(dcInstance, 'ListMovies'); -} +}; +listMoviesRef.operationName = 'ListMovies'; export function listMovies(dc) { return executeQuery(listMoviesRef(dc)); diff --git a/e2e/data-connect/dataconnect-generated/js/default-connector/index.cjs.js b/e2e/data-connect/dataconnect-generated/js/default-connector/index.cjs.js index 814406ff09..679720f0ed 100644 --- a/e2e/data-connect/dataconnect-generated/js/default-connector/index.cjs.js +++ b/e2e/data-connect/dataconnect-generated/js/default-connector/index.cjs.js @@ -1,6 +1,6 @@ /** * @license - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ const connectorConfig = { }; exports.connectorConfig = connectorConfig; -exports.createMovieRef = function createMovieRef(dcOrVars, vars) { +const createMovieRef = (dcOrVars, vars) => { const { dc: dcInstance, vars: inputVars } = validateArgs( connectorConfig, dcOrVars, @@ -40,16 +40,20 @@ exports.createMovieRef = function createMovieRef(dcOrVars, vars) { dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'CreateMovie', inputVars); }; +createMovieRef.operationName = 'CreateMovie'; +exports.createMovieRef = createMovieRef; exports.createMovie = function createMovie(dcOrVars, vars) { return executeMutation(createMovieRef(dcOrVars, vars)); }; -exports.listMoviesRef = function listMoviesRef(dc) { +const listMoviesRef = dc => { const { dc: dcInstance } = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return queryRef(dcInstance, 'ListMovies'); }; +listMoviesRef.operationName = 'ListMovies'; +exports.listMoviesRef = listMoviesRef; exports.listMovies = function listMovies(dc) { return executeQuery(listMoviesRef(dc)); diff --git a/e2e/data-connect/dataconnect-generated/js/default-connector/index.d.ts b/e2e/data-connect/dataconnect-generated/js/default-connector/index.d.ts index 474fefd0f4..3d0a1c8b21 100644 --- a/e2e/data-connect/dataconnect-generated/js/default-connector/index.d.ts +++ b/e2e/data-connect/dataconnect-generated/js/default-connector/index.d.ts @@ -1,6 +1,6 @@ /** * @license - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,15 +55,20 @@ export interface Movie_Key { __typename?: 'Movie_Key'; } -/* Allow users to create refs without passing in DataConnect */ -export function createMovieRef( - vars: CreateMovieVariables -): MutationRef; -/* Allow users to pass in custom DataConnect instances */ -export function createMovieRef( - dc: DataConnect, - vars: CreateMovieVariables -): MutationRef; +interface CreateMovieRef { + /* Allow users to create refs without passing in DataConnect */ + (vars: CreateMovieVariables): MutationRef< + CreateMovieData, + CreateMovieVariables + >; + /* Allow users to pass in custom DataConnect instances */ + (dc: DataConnect, vars: CreateMovieVariables): MutationRef< + CreateMovieData, + CreateMovieVariables + >; + operationName: string; +} +export const createMovieRef: CreateMovieRef; export function createMovie( vars: CreateMovieVariables @@ -73,12 +78,14 @@ export function createMovie( vars: CreateMovieVariables ): MutationPromise; -/* Allow users to create refs without passing in DataConnect */ -export function listMoviesRef(): QueryRef; -/* Allow users to pass in custom DataConnect instances */ -export function listMoviesRef( - dc: DataConnect -): QueryRef; +interface ListMoviesRef { + /* Allow users to create refs without passing in DataConnect */ + (): QueryRef; + /* Allow users to pass in custom DataConnect instances */ + (dc: DataConnect): QueryRef; + operationName: string; +} +export const listMoviesRef: ListMoviesRef; export function listMovies(): QueryPromise; export function listMovies( diff --git a/e2e/data-connect/dataconnect-generated/js/default-connector/package.json b/e2e/data-connect/dataconnect-generated/js/default-connector/package.json index e9b57fa0a3..820389543e 100644 --- a/e2e/data-connect/dataconnect-generated/js/default-connector/package.json +++ b/e2e/data-connect/dataconnect-generated/js/default-connector/package.json @@ -5,7 +5,7 @@ "description": "Generated SDK For default", "license": "Apache-2.0", "engines": { - "node": " >=22.0.0" + "node": " >=18.0" }, "typings": "index.d.ts", "module": "esm/index.esm.js", @@ -20,6 +20,6 @@ "./package.json": "./package.json" }, "peerDependencies": { - "firebase": "^10.14.0 || ^11.3.0" + "firebase": "^10.14.0 || ^11.3.0 || ^12.0.0" } } \ No newline at end of file diff --git a/packages/data-connect/.eslintrc.js b/packages/data-connect/.eslintrc.js index faef63a039..b8a23da0be 100644 --- a/packages/data-connect/.eslintrc.js +++ b/packages/data-connect/.eslintrc.js @@ -49,17 +49,7 @@ module.exports = { 'alphabetize': { 'order': 'asc', 'caseInsensitive': true } } ], - 'no-restricted-globals': [ - 'error', - { - 'name': 'window', - 'message': 'Use `PlatformSupport.getPlatform().window` instead.' - }, - { - 'name': 'document', - 'message': 'Use `PlatformSupport.getPlatform().document` instead.' - } - ] + 'no-restricted-globals': ['error'] }, overrides: [ { diff --git a/packages/data-connect/src/api.browser.ts b/packages/data-connect/src/api.browser.ts index d31c325353..486bd6f90c 100644 --- a/packages/data-connect/src/api.browser.ts +++ b/packages/data-connect/src/api.browser.ts @@ -15,95 +15,5 @@ * limitations under the License. */ -import { - OnCompleteSubscription, - OnErrorSubscription, - OnResultSubscription, - QueryRef, - QueryUnsubscribe, - SubscriptionOptions, - toQueryRef -} from './api/query'; -import { OpResult, SerializedRef } from './api/Reference'; -import { DataConnectError, Code } from './core/error'; - -/** - * Subscribe to a `QueryRef` - * @param queryRefOrSerializedResult query ref or serialized result. - * @param observer observer object to use for subscribing. - * @returns `SubscriptionOptions` - */ -export function subscribe( - queryRefOrSerializedResult: - | QueryRef - | SerializedRef, - observer: SubscriptionOptions -): QueryUnsubscribe; -/** - * Subscribe to a `QueryRef` - * @param queryRefOrSerializedResult query ref or serialized result. - * @param onNext Callback to call when result comes back. - * @param onError Callback to call when error gets thrown. - * @param onComplete Called when subscription completes. - * @returns `SubscriptionOptions` - */ -export function subscribe( - queryRefOrSerializedResult: - | QueryRef - | SerializedRef, - onNext: OnResultSubscription, - onError?: OnErrorSubscription, - onComplete?: OnCompleteSubscription -): QueryUnsubscribe; -/** - * Subscribe to a `QueryRef` - * @param queryRefOrSerializedResult query ref or serialized result. - * @param observerOrOnNext observer object or next function. - * @param onError Callback to call when error gets thrown. - * @param onComplete Called when subscription completes. - * @returns `SubscriptionOptions` - */ -export function subscribe( - queryRefOrSerializedResult: - | QueryRef - | SerializedRef, - observerOrOnNext: - | SubscriptionOptions - | OnResultSubscription, - onError?: OnErrorSubscription, - onComplete?: OnCompleteSubscription -): QueryUnsubscribe { - let ref: QueryRef; - let initialCache: OpResult | undefined; - if ('refInfo' in queryRefOrSerializedResult) { - const serializedRef: SerializedRef = - queryRefOrSerializedResult; - const { data, source, fetchTime } = serializedRef; - initialCache = { - data, - source, - fetchTime - }; - ref = toQueryRef(serializedRef); - } else { - ref = queryRefOrSerializedResult; - } - let onResult: OnResultSubscription | undefined = undefined; - if (typeof observerOrOnNext === 'function') { - onResult = observerOrOnNext; - } else { - onResult = observerOrOnNext.onNext; - onError = observerOrOnNext.onErr; - onComplete = observerOrOnNext.onComplete; - } - if (!onResult) { - throw new DataConnectError(Code.INVALID_ARGUMENT, 'Must provide onNext'); - } - return ref.dataConnect._queryManager.addSubscription( - ref, - onResult, - onComplete, - onError, - initialCache - ); -} +export * from './core/query/subscribe'; +export { makeMemoryCacheProvider, CacheProvider } from './api/DataConnect'; diff --git a/packages/data-connect/src/api.node.ts b/packages/data-connect/src/api.node.ts index f8236ebe2d..486bd6f90c 100644 --- a/packages/data-connect/src/api.node.ts +++ b/packages/data-connect/src/api.node.ts @@ -15,4 +15,5 @@ * limitations under the License. */ -export { subscribe } from './api.browser'; +export * from './core/query/subscribe'; +export { makeMemoryCacheProvider, CacheProvider } from './api/DataConnect'; diff --git a/packages/data-connect/src/api/DataConnect.ts b/packages/data-connect/src/api/DataConnect.ts index 15e713ba23..46cfb73f93 100644 --- a/packages/data-connect/src/api/DataConnect.ts +++ b/packages/data-connect/src/api/DataConnect.ts @@ -30,13 +30,15 @@ import { updateEmulatorBanner } from '@firebase/util'; +import { DataConnectCache, MemoryStub } from '../cache/Cache'; +import { InternalCacheProvider } from '../cache/CacheProvider'; import { AppCheckTokenProvider } from '../core/AppCheckTokenProvider'; import { Code, DataConnectError } from '../core/error'; import { AuthTokenProvider, FirebaseAuthProvider } from '../core/FirebaseAuthProvider'; -import { QueryManager } from '../core/QueryManager'; +import { QueryManager } from '../core/query/QueryManager'; import { logDebug, logError } from '../logger'; import { CallerSdkType, @@ -45,6 +47,7 @@ import { TransportClass } from '../network'; import { RESTTransport } from '../network/transport/rest'; +import { PROD_HOST } from '../util/url'; import { MutationManager } from './Mutation'; @@ -104,6 +107,11 @@ export class DataConnect { _isUsingGeneratedSdk: boolean = false; _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base; private _appCheckTokenProvider?: AppCheckTokenProvider; + private _cacheSettings?: CacheSettings; + /** + * @internal + */ + private cache?: DataConnectCache; // @internal constructor( public readonly app: FirebaseApp, @@ -121,6 +129,12 @@ export class DataConnect { } } } + /** + * @internal + */ + getCache(): DataConnectCache | undefined { + return this.cache; + } // @internal _useGeneratedSdk(): void { if (!this._isUsingGeneratedSdk) { @@ -149,6 +163,13 @@ export class DataConnect { return copy; } + /** + * @internal + */ + setCacheSettings(cacheSettings: CacheSettings): void { + this._cacheSettings = cacheSettings; + } + // @internal setInitialized(): void { if (this._initialized) { @@ -159,13 +180,26 @@ export class DataConnect { this._transportClass = RESTTransport; } - if (this._authProvider) { - this._authTokenProvider = new FirebaseAuthProvider( - this.app.name, - this.app.options, - this._authProvider + this._authTokenProvider = new FirebaseAuthProvider( + this.app.name, + this.app.options, + this._authProvider + ); + const connectorConfig: ConnectorConfig = { + connector: this.dataConnectOptions.connector, + service: this.dataConnectOptions.service, + location: this.dataConnectOptions.location + }; + if (this._cacheSettings) { + this.cache = new DataConnectCache( + this._authTokenProvider, + this.app.options.projectId!, + connectorConfig, + this._transportOptions?.host || PROD_HOST, + this._cacheSettings ); } + if (this._appCheckProvider) { this._appCheckTokenProvider = new AppCheckTokenProvider( this.app, @@ -173,7 +207,6 @@ export class DataConnect { ); } - this._initialized = true; this._transport = new this._transportClass( this.dataConnectOptions, this.app.options.apiKey, @@ -191,8 +224,10 @@ export class DataConnect { this._transportOptions.sslEnabled ); } - this._queryManager = new QueryManager(this._transport); + + this._queryManager = new QueryManager(this._transport, this, this.cache); this._mutationManager = new MutationManager(this._transport); + this._initialized = true; } // @internal @@ -251,39 +286,75 @@ export function connectDataConnectEmulator( dc.enableEmulator({ host, port, sslEnabled }); } +export interface DataConnectSettings { + cacheSettings?: CacheSettings; +} + /** * Initialize DataConnect instance * @param options ConnectorConfig */ +export function getDataConnect( + options: ConnectorConfig, + settings?: DataConnectSettings +): DataConnect; export function getDataConnect(options: ConnectorConfig): DataConnect; /** * Initialize DataConnect instance * @param app FirebaseApp to initialize to. - * @param options ConnectorConfig + * @param connectorConfig ConnectorConfig */ export function getDataConnect( app: FirebaseApp, - options: ConnectorConfig + connectorConfig: ConnectorConfig ): DataConnect; + +/** + * Initialize DataConnect instance + * @param app FirebaseApp to initialize to. + * @param connectorConfig ConnectorConfig + */ +export function getDataConnect( + app: FirebaseApp, + connectorConfig: ConnectorConfig, + settings: DataConnectSettings +): DataConnect; + export function getDataConnect( - appOrOptions: FirebaseApp | ConnectorConfig, - optionalOptions?: ConnectorConfig + appOrConnectorConfig: FirebaseApp | ConnectorConfig, + settingsOrConnectorConfig?: ConnectorConfig | DataConnectSettings, + settings?: DataConnectSettings ): DataConnect { let app: FirebaseApp; - let dcOptions: ConnectorConfig; - if ('location' in appOrOptions) { - dcOptions = appOrOptions; + let connectorConfig: ConnectorConfig; + let realSettings: DataConnectSettings; + if ('location' in appOrConnectorConfig) { + connectorConfig = appOrConnectorConfig; app = getApp(); + realSettings = settingsOrConnectorConfig as DataConnectSettings; } else { - dcOptions = optionalOptions!; - app = appOrOptions; + app = appOrConnectorConfig; + connectorConfig = settingsOrConnectorConfig as ConnectorConfig; + realSettings = settings as DataConnectSettings; } if (!app || Object.keys(app).length === 0) { app = getApp(); } + + // Options to store in Firebase Component Provider. + const serializedOptions = { + ...connectorConfig, + projectId: app.options.projectId + }; + + // We should sort the keys before initialization. + const sortedSerialized = Object.fromEntries( + Object.entries(serializedOptions).sort() + ); + const provider = _getProvider(app, 'data-connect'); - const identifier = JSON.stringify(dcOptions); + const identifier = JSON.stringify(sortedSerialized); if (provider.isInitialized(identifier)) { const dcInstance = provider.getImmediate({ identifier }); const options = provider.getOptions(identifier); @@ -293,14 +364,22 @@ export function getDataConnect( return dcInstance; } } - validateDCOptions(dcOptions); + validateDCOptions(connectorConfig); logDebug('Creating new DataConnect instance'); // Initialize with options. - return provider.initialize({ + const dataConnect = provider.initialize({ instanceIdentifier: identifier, - options: dcOptions + options: Object.fromEntries( + Object.entries({ + ...sortedSerialized + }).sort() + ) }); + if (realSettings?.cacheSettings) { + dataConnect.setCacheSettings(realSettings.cacheSettings); + } + return dataConnect; } /** @@ -334,3 +413,24 @@ export function terminate(dataConnect: DataConnect): Promise { return dataConnect._delete(); // TODO(mtewani): Stop pending tasks } +export const StorageType = { + MEMORY: 'MEMORY' +} as const; + +export type StorageType = (typeof StorageType)[keyof typeof StorageType]; + +export interface CacheSettings { + cacheProvider: CacheProvider; + maxAgeSeconds?: number; +} +export interface CacheProvider { + type: T; + /** + * @internal + */ + initialize(cacheId: string): InternalCacheProvider; +} + +export function makeMemoryCacheProvider(): CacheProvider<'MEMORY'> { + return new MemoryStub(); +} diff --git a/packages/data-connect/src/api/Reference.ts b/packages/data-connect/src/api/Reference.ts index f9d7687dd1..18aa5d78df 100644 --- a/packages/data-connect/src/api/Reference.ts +++ b/packages/data-connect/src/api/Reference.ts @@ -15,6 +15,8 @@ * limitations under the License. */ +import { Extensions } from '../network'; + import { DataConnect, DataConnectOptions } from './DataConnect'; export const QUERY_STR = 'query'; export const MUTATION_STR = 'mutation'; @@ -28,6 +30,7 @@ export interface OpResult { data: Data; source: DataSource; fetchTime: string; + extensions?: Extensions; } export interface OperationRef<_Data, Variables> { diff --git a/packages/data-connect/src/api/index.ts b/packages/data-connect/src/api/index.ts index 72ee8b313e..1140e7ed9f 100644 --- a/packages/data-connect/src/api/index.ts +++ b/packages/data-connect/src/api/index.ts @@ -16,7 +16,25 @@ */ export * from '../network'; -export * from './DataConnect'; +export { + ExecuteQueryOptions, + QueryFetchPolicy +} from '../core/query/queryOptions'; +export { + CacheSettings, + validateDCOptions, + ConnectorConfig, + DataConnect, + DataConnectOptions, + DataConnectSettings, + StorageType, + TransportOptions, + areTransportOptionsEqual, + connectDataConnectEmulator, + getDataConnect, + parseOptions, + terminate +} from './DataConnect'; export * from './Reference'; export * from './Mutation'; export * from './query'; diff --git a/packages/data-connect/src/api/query.ts b/packages/data-connect/src/api/query.ts index 43683cafd6..e336de747e 100644 --- a/packages/data-connect/src/api/query.ts +++ b/packages/data-connect/src/api/query.ts @@ -15,7 +15,12 @@ * limitations under the License. */ -import { DataConnectError } from '../core/error'; +import { Code, DataConnectError } from '../core/error'; +import { + ExecuteQueryOptions, + QueryFetchPolicy +} from '../core/query/queryOptions'; +import { DataConnectExtensionWithMaxAge } from '../network/transport'; import { DataConnect, getDataConnect } from './DataConnect'; import { @@ -25,21 +30,6 @@ import { SerializedRef } from './Reference'; -/** - * Signature for `OnResultSubscription` for `subscribe` - */ -export type OnResultSubscription = ( - res: QueryResult -) => void; -/** - * Signature for `OnErrorSubscription` for `subscribe` - */ -export type OnErrorSubscription = (err?: DataConnectError) => void; -/** - * Signature for unsubscribe from `subscribe` - */ -export type QueryUnsubscribe = () => void; - /** * QueryRef object */ @@ -47,6 +37,18 @@ export interface QueryRef extends OperationRef { refType: typeof QUERY_STR; } + +/** @internal */ +export type InternalQueryResult = QueryResult< + Data, + Variables +> & + Omit, 'extensions'> & { + extensions?: { + dataConnect?: DataConnectExtensionWithMaxAge[]; + }; + }; + /** * Result of `executeQuery` */ @@ -69,9 +71,32 @@ export interface QueryPromise * @returns `QueryPromise` */ export function executeQuery( - queryRef: QueryRef + queryRef: QueryRef, + options?: ExecuteQueryOptions ): QueryPromise { - return queryRef.dataConnect._queryManager.executeQuery(queryRef); + if (queryRef.refType !== QUERY_STR) { + return Promise.reject( + new DataConnectError( + Code.INVALID_ARGUMENT, + `ExecuteQuery can only execute query operations` + ) + ); + } + const queryManager = queryRef.dataConnect._queryManager; + const fetchPolicy = options?.fetchPolicy ?? QueryFetchPolicy.PREFER_CACHE; + switch (fetchPolicy) { + case QueryFetchPolicy.SERVER_ONLY: + return queryManager.fetchServerResults(queryRef); + case QueryFetchPolicy.CACHE_ONLY: + return queryManager.fetchCacheResults(queryRef, true); + case QueryFetchPolicy.PREFER_CACHE: + return queryManager.preferCacheResults(queryRef, false); + default: + throw new DataConnectError( + Code.INVALID_ARGUMENT, + `Invalid fetch policy: ${fetchPolicy}` + ); + } } /** @@ -111,7 +136,9 @@ export function queryRef( initialCache?: QueryResult ): QueryRef { dcInstance.setInitialized(); - dcInstance._queryManager.track(queryName, variables, initialCache); + if (initialCache !== undefined) { + dcInstance._queryManager.updateSSR(initialCache); + } return { dataConnect: dcInstance, refType: QUERY_STR, @@ -132,15 +159,3 @@ export function toQueryRef( } = serializedRef; return queryRef(getDataConnect(connectorConfig), name, variables); } -/** - * `OnCompleteSubscription` - */ -export type OnCompleteSubscription = () => void; -/** - * Representation of full observer options in `subscribe` - */ -export interface SubscriptionOptions { - onNext?: OnResultSubscription; - onErr?: OnErrorSubscription; - onComplete?: OnCompleteSubscription; -} diff --git a/packages/data-connect/src/cache/Cache.ts b/packages/data-connect/src/cache/Cache.ts new file mode 100644 index 0000000000..4039427417 --- /dev/null +++ b/packages/data-connect/src/cache/Cache.ts @@ -0,0 +1,146 @@ +/** + * @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. + */ + +import { generateSHA256Hash } from '@firebase/util'; + +import { + CacheProvider, + CacheSettings, + type ConnectorConfig +} from '../api/DataConnect'; +import { Code, DataConnectError } from '../core/error'; +import { type AuthTokenProvider } from '../core/FirebaseAuthProvider'; + +import { InternalCacheProvider } from './CacheProvider'; +import { InMemoryCacheProvider } from './InMemoryCacheProvider'; +import { ResultTree } from './ResultTree'; +import { ResultTreeProcessor } from './ResultTreeProcessor'; + +export const Memory = 'memory'; + +export type DataConnectStorage = typeof Memory; + +/** + * ServerValues + */ +export interface ServerValues extends Record { + maxAge?: number; +} + +export class DataConnectCache { + private cacheProvider: InternalCacheProvider | null = null; + private uid: string | null = null; + constructor( + private authProvider: AuthTokenProvider, + private projectId: string, + private connectorConfig: ConnectorConfig, + private host: string, + public cacheSettings: CacheSettings + ) { + this.authProvider.addTokenChangeListener(async _ => { + const newUid = this.authProvider.getAuth().getUid(); + // We should only close if the token changes and so does the new UID + if (this.uid !== newUid) { + this.cacheProvider?.close(); + this.uid = newUid; + const identifier = await this.getIdentifier(this.uid); + this.cacheProvider = this.initializeNewProviders(identifier); + } + }); + } + + async initialize(): Promise { + if (!this.cacheProvider) { + const identifier = await this.getIdentifier(this.uid); + this.cacheProvider = this.initializeNewProviders(identifier); + } + } + + async getIdentifier(uid: string | null): Promise { + const identifier = `${ + 'memory' // TODO: replace this with indexeddb when persistence is available. + }-${this.projectId}-${this.connectorConfig.service}-${ + this.connectorConfig.connector + }-${this.connectorConfig.location}-${uid}-${this.host}`; + const sha256 = await generateSHA256Hash(identifier); + return sha256; + } + + initializeNewProviders(identifier: string): InternalCacheProvider { + return this.cacheSettings.cacheProvider.initialize(identifier); + } + + async containsResultTree(queryId: string): Promise { + await this.initialize(); + const resultTree = await this.cacheProvider!.getResultTree(queryId); + return resultTree !== undefined; + } + async getResultTree(queryId: string): Promise { + await this.initialize(); + return this.cacheProvider!.getResultTree(queryId); + } + async getResultJSON(queryId: string): Promise> { + await this.initialize(); + const processor = new ResultTreeProcessor(); + const cacheProvider = this.cacheProvider; + const resultTree = await cacheProvider!.getResultTree(queryId); + if (!resultTree) { + throw new DataConnectError( + Code.INVALID_ARGUMENT, + `${queryId} not found in cache. Call "update()" first.` + ); + } + return processor.hydrateResults(resultTree.getRootStub()); + } + async update( + queryId: string, + serverValues: ServerValues, + entityIds: Record + ): Promise { + await this.initialize(); + const processor = new ResultTreeProcessor(); + const cacheProvider = this.cacheProvider; + const { entityNode: stubDataObject, impacted } = + await processor.dehydrateResults( + serverValues, + entityIds, + cacheProvider!, + queryId + ); + const now = new Date(); + await cacheProvider!.setResultTree( + queryId, + new ResultTree( + stubDataObject, + serverValues.maxAge || this.cacheSettings.maxAgeSeconds, + now, + now + ) + ); + return impacted; + } +} + +export class MemoryStub implements CacheProvider<'MEMORY'> { + type: 'MEMORY' = 'MEMORY'; + /** + * @internal + */ + initialize(cacheId: string): InMemoryCacheProvider { + return new InMemoryCacheProvider(cacheId); + } +} diff --git a/packages/data-connect/src/cache/CacheProvider.ts b/packages/data-connect/src/cache/CacheProvider.ts new file mode 100644 index 0000000000..cb08b3d12c --- /dev/null +++ b/packages/data-connect/src/cache/CacheProvider.ts @@ -0,0 +1,27 @@ +/** + * @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. + */ + +import { EntityDataObject } from './EntityDataObject'; +import { ResultTree } from './ResultTree'; + +export interface InternalCacheProvider { + getEntityData(globalId: string): Promise; + updateEntityData(entityData: EntityDataObject): Promise; + getResultTree(queryId: string): Promise; + setResultTree(queryId: string, resultTree: ResultTree): Promise; + close(): void; +} diff --git a/packages/data-connect/src/cache/EntityDataObject.ts b/packages/data-connect/src/cache/EntityDataObject.ts new file mode 100644 index 0000000000..1ae7dbebc5 --- /dev/null +++ b/packages/data-connect/src/cache/EntityDataObject.ts @@ -0,0 +1,68 @@ +/** + * @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. + */ + +export type FDCScalarValue = + | string + | number + | boolean + | undefined + | null + | Record + | FDCScalarValue[]; + +export interface EntityDataObjectJson { + map: { + [key: string]: FDCScalarValue; + }; + referencedFrom: string[]; + globalID: string; +} + +export class EntityDataObject { + getServerValue(key: string): unknown { + return this.serverValues[key]; + } + private serverValues: { [key: string]: FDCScalarValue } = {}; + private referencedFrom = new Set(); + constructor(public readonly globalID: string) {} + getServerValues(): { [key: string]: FDCScalarValue } { + return this.serverValues; + } + toJSON(): EntityDataObjectJson { + return { + globalID: this.globalID, + map: this.serverValues, + referencedFrom: Array.from(this.referencedFrom) + }; + } + static fromJSON(json: EntityDataObjectJson): EntityDataObject { + const edo = new EntityDataObject(json.globalID); + edo.serverValues = json.map; + edo.referencedFrom = new Set(json.referencedFrom); + return edo; + } + + updateServerValue( + key: string, + value: FDCScalarValue, + requestedFrom: string + ): string[] { + this.serverValues[key] = value; + this.referencedFrom.add(requestedFrom); + return Array.from(this.referencedFrom); + } +} diff --git a/packages/data-connect/src/cache/EntityNode.ts b/packages/data-connect/src/cache/EntityNode.ts new file mode 100644 index 0000000000..e3e7b8fdd4 --- /dev/null +++ b/packages/data-connect/src/cache/EntityNode.ts @@ -0,0 +1,265 @@ +/** + * @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. + */ + +import { Code, DataConnectError } from '../core/error'; + +import { InternalCacheProvider } from './CacheProvider'; +import { + EntityDataObject, + EntityDataObjectJson, + FDCScalarValue +} from './EntityDataObject'; +import { ImpactedQueryRefsAccumulator } from './ImpactedQueryRefsAccumulator'; + +export const GLOBAL_ID_KEY = '_id'; +export const OBJECT_LISTS_KEY = '_objectLists'; +export const REFERENCES_KEY = '_references'; +export const SCALARS_KEY = '_scalars'; +export const ENTITY_DATA_KEYS_KEY = '_entity_data_keys'; +export class EntityNode { + entityData?: EntityDataObject; + scalars: Record = {}; + references: { [key: string]: EntityNode } = {}; + objectLists: { + [key: string]: EntityNode[]; + } = {}; + globalId?: string; + entityDataKeys: Set = new Set(); + + async loadData( + queryId: string, + values: FDCScalarValue, + entityIds: Record | undefined, + acc: ImpactedQueryRefsAccumulator, + cacheProvider: InternalCacheProvider + ): Promise { + if (values === undefined) { + return; + } + if (typeof values !== 'object' || Array.isArray(values)) { + throw new DataConnectError( + Code.INVALID_ARGUMENT, + 'EntityNode initialized with non-object value' + ); + } + if (values === null) { + return; + } + + if ( + typeof values === 'object' && + entityIds && + entityIds[GLOBAL_ID_KEY] && + typeof entityIds[GLOBAL_ID_KEY] === 'string' + ) { + this.globalId = entityIds[GLOBAL_ID_KEY]; + this.entityData = await cacheProvider.getEntityData(this.globalId); + } + for (const key in values) { + if (values.hasOwnProperty(key)) { + if (typeof values[key] === 'object') { + if (Array.isArray(values[key])) { + const ids: Record | undefined = + entityIds && (entityIds[key] as Record); + const objArray: EntityNode[] = []; + const scalarArray: Array> = []; + for (const [index, value] of values[key].entries()) { + if (typeof value === 'object') { + if (Array.isArray(value)) { + // Note: we don't support sparse arrays. + } else { + const entityNode = new EntityNode(); + await entityNode.loadData( + queryId, + value, + ids && (ids[index] as Record), + acc, + cacheProvider + ); + objArray.push(entityNode); + } + } else { + scalarArray.push(value); + } + } + if (scalarArray.length > 0 && objArray.length > 0) { + this.scalars[key] = values[key]; + } else if (scalarArray.length > 0) { + if (this.entityData) { + const impactedRefs = this.entityData.updateServerValue( + key, + scalarArray, + queryId + ); + this.entityDataKeys.add(key); + acc.add(impactedRefs); + } else { + this.scalars[key] = scalarArray; + } + } else if (objArray.length > 0) { + this.objectLists[key] = objArray; + } else { + this.scalars[key] = []; + } + } else { + if (values[key] === null) { + this.scalars[key] = null; + continue; + } + const entityNode = new EntityNode(); + // TODO: Load Data might need to be pushed into ResultTreeProcessor instead. + await entityNode.loadData( + queryId, + (values as Record)[key], + entityIds && (entityIds[key] as Record), + acc, + cacheProvider + ); + this.references[key] = entityNode; + } + } else { + if (this.entityData) { + const impactedRefs = this.entityData.updateServerValue( + key, + values[key] as FDCScalarValue, + queryId + ); + this.entityDataKeys.add(key); + acc.add(impactedRefs); + } else { + this.scalars[key] = values[key] as FDCScalarValue; + } + } + } + } + if (this.entityData) { + await cacheProvider.updateEntityData(this.entityData); + } + } + + toJSON(mode: EncodingMode): Record { + const resultObject: Record = {}; + if (mode === EncodingMode.hydrated) { + if (this.entityData) { + for (const key of this.entityDataKeys) { + resultObject[key] = this.entityData.getServerValue(key); + } + } + + if (this.scalars) { + Object.assign(resultObject, this.scalars); + } + if (this.references) { + for (const key in this.references) { + if (this.references.hasOwnProperty(key)) { + resultObject[key] = this.references[key].toJSON(mode); + } + } + } + if (this.objectLists) { + for (const key in this.objectLists) { + if (this.objectLists.hasOwnProperty(key)) { + resultObject[key] = this.objectLists[key].map(obj => + obj.toJSON(mode) + ); + } + } + } + return resultObject; + } else { + // Get JSON representation of dehydrated list + if (this.entityData) { + resultObject[GLOBAL_ID_KEY] = this.entityData.globalID; + } + + resultObject[ENTITY_DATA_KEYS_KEY] = Array.from(this.entityDataKeys); + + if (this.scalars) { + resultObject[SCALARS_KEY] = this.scalars; + } + + if (this.references) { + const references = {} as Record; + for (const key in this.references) { + if (this.references.hasOwnProperty(key)) { + references[key] = this.references[key].toJSON(mode); + } + } + resultObject[REFERENCES_KEY] = references; + } + if (this.objectLists) { + const objectLists = {} as Record; + for (const key in this.objectLists) { + if (this.objectLists.hasOwnProperty(key)) { + objectLists[key] = this.objectLists[key].map(obj => + obj.toJSON(mode) + ); + } + } + resultObject[OBJECT_LISTS_KEY] = objectLists; + } + } + + return resultObject; + } + + static fromJson(obj: DehydratedStubDataObject): EntityNode { + const sdo = new EntityNode(); + if (obj.backingData) { + sdo.entityData = EntityDataObject.fromJSON(obj.backingData); + } + sdo.globalId = obj.globalID; + sdo.scalars = obj.scalars; + if (obj.references) { + const references: Record = {}; + for (const key in obj.references) { + if (obj.references.hasOwnProperty(key)) { + references[key] = EntityNode.fromJson(obj.references[key]); + } + } + sdo.references = references as typeof sdo.references; + } + if (obj.objectLists) { + const objectLists: Record = {}; + for (const key in obj.objectLists) { + if (obj.objectLists.hasOwnProperty(key)) { + objectLists[key] = obj.objectLists[key].map(obj => + EntityNode.fromJson(obj) + ); + } + } + sdo.objectLists = objectLists as typeof sdo.objectLists; + } + return sdo; + } +} + +export interface DehydratedStubDataObject { + backingData?: EntityDataObjectJson; + globalID?: string; + scalars: { [key: string]: FDCScalarValue }; + references: { [key: string]: DehydratedStubDataObject }; + objectLists: { + [key: string]: DehydratedStubDataObject[]; + }; +} + +// Helpful for storing in persistent cache, which is not available yet. +export enum EncodingMode { + hydrated, + dehydrated +} diff --git a/packages/data-connect/src/cache/ImpactedQueryRefsAccumulator.ts b/packages/data-connect/src/cache/ImpactedQueryRefsAccumulator.ts new file mode 100644 index 0000000000..423c4df82b --- /dev/null +++ b/packages/data-connect/src/cache/ImpactedQueryRefsAccumulator.ts @@ -0,0 +1,31 @@ +/** + * @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. + */ + +export class ImpactedQueryRefsAccumulator { + impacted = new Set(); + constructor(private queryId: string) {} + add(impacted: string[]): void { + impacted + .filter(ref => ref !== this.queryId) + .forEach(ref => this.impacted.add(ref)); + } + consumeEvents(): string[] { + const events = Array.from(this.impacted); + this.impacted.clear(); + return events; + } +} diff --git a/packages/data-connect/src/cache/InMemoryCacheProvider.ts b/packages/data-connect/src/cache/InMemoryCacheProvider.ts new file mode 100644 index 0000000000..0a8bb25169 --- /dev/null +++ b/packages/data-connect/src/cache/InMemoryCacheProvider.ts @@ -0,0 +1,47 @@ +/** + * @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. + */ + +import { InternalCacheProvider } from './CacheProvider'; +import { EntityDataObject } from './EntityDataObject'; +import { ResultTree } from './ResultTree'; + +export class InMemoryCacheProvider implements InternalCacheProvider { + private edos = new Map(); + private resultTrees = new Map(); + constructor(private _keyId: string) {} + + async setResultTree(queryId: string, rt: ResultTree): Promise { + this.resultTrees.set(queryId, rt); + } + async getResultTree(queryId: string): Promise { + return this.resultTrees.get(queryId); + } + async updateEntityData(entityData: EntityDataObject): Promise { + this.edos.set(entityData.globalID, entityData); + } + async getEntityData(globalId: string): Promise { + if (!this.edos.has(globalId)) { + this.edos.set(globalId, new EntityDataObject(globalId)); + } + // Because of the above, we can guarantee that there will be an EDO at the globalId. + return this.edos.get(globalId)!; + } + close(): Promise { + // No-op + return Promise.resolve(); + } +} diff --git a/packages/data-connect/src/cache/ResultTree.ts b/packages/data-connect/src/cache/ResultTree.ts new file mode 100644 index 0000000000..50566d48c9 --- /dev/null +++ b/packages/data-connect/src/cache/ResultTree.ts @@ -0,0 +1,65 @@ +/** + * @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. + */ + +import { EntityNode, DehydratedStubDataObject } from './EntityNode'; + +export class ResultTree { + /** + * Create a {@link ResultTree} from a dehydrated JSON object. + * @param value The dehydrated JSON object. + * @returns The {@link ResultTree}. + */ + static fromJson(value: DehydratedResultTreeJson): ResultTree { + return new ResultTree( + EntityNode.fromJson(value.rootStub), + value.maxAge, + value.cachedAt, + value.lastAccessed + ); + } + constructor( + private rootStub: EntityNode, + private maxAge: number = 0, + public readonly cachedAt: Date, + private _lastAccessed: Date + ) {} + isStale(): boolean { + return ( + Date.now() - new Date(this.cachedAt.getTime()).getTime() > + this.maxAge * 1000 + ); + } + updateMaxAge(maxAgeInSeconds: number): void { + this.maxAge = maxAgeInSeconds; + } + updateAccessed(): void { + this._lastAccessed = new Date(); + } + get lastAccessed(): Date { + return this._lastAccessed; + } + getRootStub(): EntityNode { + return this.rootStub; + } +} + +interface DehydratedResultTreeJson { + rootStub: DehydratedStubDataObject; + maxAge: number; + cachedAt: Date; + lastAccessed: Date; +} diff --git a/packages/data-connect/src/cache/ResultTreeProcessor.ts b/packages/data-connect/src/cache/ResultTreeProcessor.ts new file mode 100644 index 0000000000..2a1abbd0df --- /dev/null +++ b/packages/data-connect/src/cache/ResultTreeProcessor.ts @@ -0,0 +1,58 @@ +/** + * @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. + */ + +import { InternalCacheProvider } from './CacheProvider'; +import { EncodingMode, EntityNode } from './EntityNode'; +import { ImpactedQueryRefsAccumulator } from './ImpactedQueryRefsAccumulator'; + +interface DehydratedResults { + entityNode: EntityNode; + impacted: string[]; +} + +export class ResultTreeProcessor { + /** + * Hydrate the EntityNode into a JSON object so that it can be returned to the user. + * @param rootStubObject + * @returns {string} + */ + hydrateResults(rootStubObject: EntityNode): Record { + return rootStubObject.toJSON(EncodingMode.hydrated); + } + /** + * Dehydrate results so that they can be stored in the cache. + * @param json + * @param entityIds + * @param cacheProvider + * @param queryId + * @returns {Promise} + */ + async dehydrateResults( + json: Record, + entityIds: Record, + cacheProvider: InternalCacheProvider, + queryId: string + ): Promise { + const acc = new ImpactedQueryRefsAccumulator(queryId); + const entityNode = new EntityNode(); + await entityNode.loadData(queryId, json, entityIds, acc, cacheProvider); + return { + entityNode, + impacted: acc.consumeEvents() + }; + } +} diff --git a/packages/data-connect/src/cache/cacheUtils.ts b/packages/data-connect/src/cache/cacheUtils.ts new file mode 100644 index 0000000000..1783c85c3c --- /dev/null +++ b/packages/data-connect/src/cache/cacheUtils.ts @@ -0,0 +1,63 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { OpResult } from '../api/Reference'; +import { DataConnectExtension } from '../network'; +export function parseEntityIds( + result: OpResult +): Record { + // Iterate through extensions.dataConnect + const dataConnectExtensions = result.extensions?.dataConnect; + const dataCopy = Object.assign(result); + if (!dataConnectExtensions) { + return dataCopy; + } + const ret: Record = {}; + for (const extension of dataConnectExtensions) { + const { path } = extension; + populatePath(path, ret, extension); + } + return ret; +} + +// mutates the object to update the path +export function populatePath( + path: Array, + toUpdate: Record, + extension: DataConnectExtension +): void { + let curObj: Record = toUpdate; + for (const slice of path) { + if (typeof curObj[slice] !== 'object') { + curObj[slice] = {}; + } + curObj = curObj[slice] as Record; + } + + if ('entityId' in extension && extension.entityId) { + curObj['_id'] = extension.entityId; + } else if ('entityIds' in extension) { + const entityArr = extension.entityIds; + for (let i = 0; i < entityArr.length; i++) { + const entityId = entityArr[i]; + if (typeof curObj[i] === 'undefined') { + curObj[i] = {}; + } + (curObj[i] as Record)._id = entityId; + } + } +} diff --git a/packages/data-connect/src/core/FirebaseAuthProvider.ts b/packages/data-connect/src/core/FirebaseAuthProvider.ts index a19b8a46d6..bb512e9ecf 100644 --- a/packages/data-connect/src/core/FirebaseAuthProvider.ts +++ b/packages/data-connect/src/core/FirebaseAuthProvider.ts @@ -29,6 +29,7 @@ import { logDebug, logError } from '../logger'; export interface AuthTokenProvider { getToken(forceRefresh: boolean): Promise; addTokenChangeListener(listener: AuthTokenListener): void; + getAuth(): FirebaseAuthInternal; } export type AuthTokenListener = (token: string | null) => void; @@ -45,6 +46,9 @@ export class FirebaseAuthProvider implements AuthTokenProvider { _authProvider.onInit(auth => (this._auth = auth)); } } + getAuth(): FirebaseAuthInternal { + return this._auth; + } getToken(forceRefresh: boolean): Promise { if (!this._auth) { return new Promise((resolve, reject) => { diff --git a/packages/data-connect/src/core/QueryManager.ts b/packages/data-connect/src/core/QueryManager.ts deleted file mode 100644 index 109f1d105b..0000000000 --- a/packages/data-connect/src/core/QueryManager.ts +++ /dev/null @@ -1,245 +0,0 @@ -/** - * @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. - */ - -import { - OnCompleteSubscription, - OnErrorSubscription, - OnResultSubscription, - QueryPromise, - QueryRef, - QueryResult -} from '../api/query'; -import { - OperationRef, - QUERY_STR, - OpResult, - SerializedRef, - SOURCE_SERVER, - DataSource, - SOURCE_CACHE -} from '../api/Reference'; -import { logDebug } from '../logger'; -import { DataConnectTransport } from '../network'; -import { encoderImpl } from '../util/encoder'; -import { setIfNotExists } from '../util/map'; - -import { Code, DataConnectError } from './error'; - -/** - * Representation of user provided subscription options. - */ -interface DataConnectSubscription { - userCallback: OnResultSubscription; - errCallback?: (e?: DataConnectError) => void; - onCompleteCallback?: () => void; - unsubscribe: () => void; -} - -interface TrackedQuery { - ref: Omit, 'dataConnect'>; - subscriptions: Array>; - currentCache: OpResult | null; - lastError: DataConnectError | null; -} - -function getRefSerializer( - queryRef: QueryRef, - data: Data, - source: DataSource -) { - return function toJSON(): SerializedRef { - return { - data, - refInfo: { - name: queryRef.name, - variables: queryRef.variables, - connectorConfig: { - projectId: queryRef.dataConnect.app.options.projectId!, - ...queryRef.dataConnect.getSettings() - } - }, - fetchTime: Date.now().toLocaleString(), - source - }; - }; -} - -export class QueryManager { - _queries: Map>; - constructor(private transport: DataConnectTransport) { - this._queries = new Map(); - } - track( - queryName: string, - variables: Variables, - initialCache?: OpResult - ): TrackedQuery { - const ref: TrackedQuery['ref'] = { - name: queryName, - variables, - refType: QUERY_STR - }; - const key = encoderImpl(ref); - const newTrackedQuery: TrackedQuery = { - ref, - subscriptions: [], - currentCache: initialCache || null, - lastError: null - }; - // @ts-ignore - setIfNotExists(this._queries, key, newTrackedQuery); - return this._queries.get(key) as TrackedQuery; - } - addSubscription( - queryRef: OperationRef, - onResultCallback: OnResultSubscription, - onCompleteCallback?: OnCompleteSubscription, - onErrorCallback?: OnErrorSubscription, - initialCache?: OpResult - ): () => void { - const key = encoderImpl({ - name: queryRef.name, - variables: queryRef.variables, - refType: QUERY_STR - }); - const trackedQuery = this._queries.get(key) as TrackedQuery< - Data, - Variables - >; - const subscription = { - userCallback: onResultCallback, - onCompleteCallback, - errCallback: onErrorCallback - }; - const unsubscribe = (): void => { - const trackedQuery = this._queries.get(key)!; - trackedQuery.subscriptions = trackedQuery.subscriptions.filter( - sub => sub !== subscription - ); - onCompleteCallback?.(); - }; - if (initialCache && trackedQuery.currentCache !== initialCache) { - logDebug('Initial cache found. Comparing dates.'); - if ( - !trackedQuery.currentCache || - (trackedQuery.currentCache && - compareDates( - trackedQuery.currentCache.fetchTime, - initialCache.fetchTime - )) - ) { - trackedQuery.currentCache = initialCache; - } - } - if (trackedQuery.currentCache !== null) { - const cachedData = trackedQuery.currentCache.data; - onResultCallback({ - data: cachedData, - source: SOURCE_CACHE, - ref: queryRef as QueryRef, - toJSON: getRefSerializer( - queryRef as QueryRef, - trackedQuery.currentCache.data, - SOURCE_CACHE - ), - fetchTime: trackedQuery.currentCache.fetchTime - }); - if (trackedQuery.lastError !== null && onErrorCallback) { - onErrorCallback(undefined); - } - } - - trackedQuery.subscriptions.push({ - userCallback: onResultCallback, - errCallback: onErrorCallback, - unsubscribe - }); - if (!trackedQuery.currentCache) { - logDebug( - `No cache available for query ${ - queryRef.name - } with variables ${JSON.stringify( - queryRef.variables - )}. Calling executeQuery.` - ); - const promise = this.executeQuery(queryRef as QueryRef); - // We want to ignore the error and let subscriptions handle it - promise.then(undefined, err => {}); - } - return unsubscribe; - } - executeQuery( - queryRef: QueryRef - ): QueryPromise { - if (queryRef.refType !== QUERY_STR) { - throw new DataConnectError( - Code.INVALID_ARGUMENT, - `ExecuteQuery can only execute query operation` - ); - } - const key = encoderImpl({ - name: queryRef.name, - variables: queryRef.variables, - refType: QUERY_STR - }); - const trackedQuery = this._queries.get(key)!; - const result = this.transport.invokeQuery( - queryRef.name, - queryRef.variables - ); - const newR = result.then( - res => { - const fetchTime = new Date().toString(); - const result: QueryResult = { - ...res, - source: SOURCE_SERVER, - ref: queryRef, - toJSON: getRefSerializer(queryRef, res.data, SOURCE_SERVER), - fetchTime - }; - trackedQuery.subscriptions.forEach(subscription => { - subscription.userCallback(result); - }); - trackedQuery.currentCache = { - data: res.data, - source: SOURCE_CACHE, - fetchTime - }; - return result; - }, - err => { - trackedQuery.lastError = err; - trackedQuery.subscriptions.forEach(subscription => { - if (subscription.errCallback) { - subscription.errCallback(err); - } - }); - throw err; - } - ); - - return newR; - } - enableEmulator(host: string, port: number): void { - this.transport.useEmulator(host, port); - } -} -function compareDates(str1: string, str2: string): boolean { - const date1 = new Date(str1); - const date2 = new Date(str2); - return date1.getTime() < date2.getTime(); -} diff --git a/packages/data-connect/src/core/query/QueryManager.ts b/packages/data-connect/src/core/query/QueryManager.ts new file mode 100644 index 0000000000..8e0ab242bd --- /dev/null +++ b/packages/data-connect/src/core/query/QueryManager.ts @@ -0,0 +1,424 @@ +/** + * @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. + */ + +import { type DataConnect } from '../../api/DataConnect'; +import { QueryRef, QueryResult } from '../../api/query'; +import { + QUERY_STR, + SerializedRef, + SOURCE_SERVER, + DataSource, + SOURCE_CACHE +} from '../../api/Reference'; +import { DataConnectSubscription } from '../../api.browser'; +import { DataConnectCache, ServerValues } from '../../cache/Cache'; +import { parseEntityIds } from '../../cache/cacheUtils'; +import { EncodingMode } from '../../cache/EntityNode'; +import { DataConnectTransport, Extensions } from '../../network'; +import { + DataConnectExtensionWithMaxAge, + ExtensionsWithMaxAge +} from '../../network/transport'; +import { decoderImpl, encoderImpl } from '../../util/encoder'; +import { Code, DataConnectError } from '../error'; + +import { + OnCompleteSubscription, + OnErrorSubscription, + OnResultSubscription +} from './subscribe'; + +export function getRefSerializer( + queryRef: QueryRef, + data: Data, + source: DataSource, + fetchTime: string +) { + return function toJSON(): SerializedRef { + return { + data, + refInfo: { + name: queryRef.name, + variables: queryRef.variables, + connectorConfig: { + projectId: queryRef.dataConnect.app.options.projectId!, + ...queryRef.dataConnect.getSettings() + } + }, + fetchTime, + source + }; + }; +} + +export class QueryManager { + async preferCacheResults( + queryRef: QueryRef, + allowStale = false + ): Promise> { + let cacheResult: QueryResult | undefined; + try { + cacheResult = await this.fetchCacheResults(queryRef, allowStale); + } catch (e) { + // Ignore the error and try to fetch from the server. + } + if (cacheResult) { + return cacheResult; + } + return this.fetchServerResults(queryRef); + } + private callbacks = new Map< + string, + Array> + >(); + private subscriptionCache = new Map>(); + constructor( + private transport: DataConnectTransport, + private dc: DataConnect, + private cache?: DataConnectCache + ) {} + private queue: Array> = []; + async waitForQueuedWrites(): Promise { + for (const promise of this.queue) { + await promise; + } + this.queue = []; + } + + updateSSR(updatedData: QueryResult): void { + this.queue.push( + this.updateCache(updatedData).then(async result => + this.publishCacheResultsToSubscribers(result, updatedData.fetchTime) + ) + ); + } + + async updateCache( + result: QueryResult, + extensions?: DataConnectExtensionWithMaxAge[] + ): Promise { + await this.waitForQueuedWrites(); + if (this.cache) { + const entityIds = parseEntityIds(result); + const updatedMaxAge = getMaxAgeFromExtensions(extensions); + if (updatedMaxAge !== undefined) { + this.cache.cacheSettings.maxAgeSeconds = updatedMaxAge; + } + return this.cache.update( + encoderImpl({ + name: result.ref.name, + variables: result.ref.variables, + refType: QUERY_STR + }), + result.data as ServerValues, + entityIds + ); + } else { + const key = encoderImpl({ + name: result.ref.name, + variables: result.ref.variables, + refType: QUERY_STR + }); + this.subscriptionCache.set(key, result); + return [key]; + } + } + + addSubscription( + queryRef: QueryRef, + onResultCallback: OnResultSubscription, + onCompleteCallback?: OnCompleteSubscription, + onErrorCallback?: OnErrorSubscription, + initialCache?: QueryResult + ): () => void { + const key = encoderImpl({ + name: queryRef.name, + variables: queryRef.variables, + refType: QUERY_STR + }); + + const unsubscribe = (): void => { + if (this.callbacks.has(key)) { + const callbackList = this.callbacks.get(key)!; + this.callbacks.set( + key, + callbackList.filter(callback => callback !== subscription) + ); + onCompleteCallback?.(); + } + }; + const subscription: DataConnectSubscription = { + userCallback: onResultCallback, + errCallback: onErrorCallback, + unsubscribe + }; + + if (initialCache) { + this.updateSSR(initialCache); + } + + const promise = this.preferCacheResults(queryRef, /*allowStale=*/ true); + // We want to ignore the error and let subscriptions handle it + promise.then(undefined, err => {}); + + if (!this.callbacks.has(key)) { + this.callbacks.set(key, []); + } + this.callbacks + .get(key)! + .push(subscription as DataConnectSubscription); + + return unsubscribe; + } + + async fetchServerResults( + queryRef: QueryRef + ): Promise> { + await this.waitForQueuedWrites(); + const key = encoderImpl({ + name: queryRef.name, + variables: queryRef.variables, + refType: QUERY_STR + }); + try { + const result = await this.transport.invokeQuery( + queryRef.name, + queryRef.variables + ); + const fetchTime = Date.now().toString(); + const originalExtensions = result.extensions; + const queryResult: QueryResult = { + ...result, + ref: queryRef, + source: SOURCE_SERVER, + fetchTime, + data: result.data, + extensions: getDataConnectExtensionsWithoutMaxAge(originalExtensions), + toJSON: getRefSerializer( + queryRef, + result.data, + SOURCE_SERVER, + fetchTime + ) + }; + let updatedKeys: string[] = []; + updatedKeys = await this.updateCache( + queryResult, + originalExtensions?.dataConnect + ); + this.publishDataToSubscribers(key, queryResult); + if (this.cache) { + await this.publishCacheResultsToSubscribers(updatedKeys, fetchTime); + } else { + this.subscriptionCache.set(key, queryResult); + } + return queryResult; + } catch (e) { + this.publishErrorToSubscribers(key, e); + throw e; + } + } + + async fetchCacheResults( + queryRef: QueryRef, + allowStale = false + ): Promise> { + await this.waitForQueuedWrites(); + let result: QueryResult | undefined | null; + if (!this.cache) { + result = await this.getFromSubscriberCache(queryRef); + } else { + result = await this.getFromResultTreeCache(queryRef, allowStale); + } + if (!result) { + throw new DataConnectError( + Code.OTHER, + 'No cache entry found for query: ' + queryRef.name + ); + } + const fetchTime = Date.now().toString(); + const queryResult: QueryResult = { + ...result, + ref: queryRef, + source: SOURCE_CACHE, + fetchTime, + data: result.data, + extensions: result.extensions, + toJSON: getRefSerializer(queryRef, result.data, SOURCE_CACHE, fetchTime) + }; + if (this.cache) { + const key = encoderImpl({ + name: queryRef.name, + variables: queryRef.variables, + refType: QUERY_STR + }); + await this.publishCacheResultsToSubscribers([key], fetchTime); + } else { + const key = encoderImpl({ + name: queryRef.name, + variables: queryRef.variables, + refType: QUERY_STR + }); + this.subscriptionCache.set(key, queryResult); + this.publishDataToSubscribers(key, queryResult); + } + + return queryResult; + } + + publishErrorToSubscribers(key: string, err: unknown): void { + this.callbacks.get(key)?.forEach(subscription => { + if (subscription.errCallback) { + subscription.errCallback(err as DataConnectError); + } + }); + } + + async getFromResultTreeCache( + queryRef: QueryRef, + allowStale = false + ): Promise | null> { + const key = encoderImpl({ + name: queryRef.name, + variables: queryRef.variables, + refType: QUERY_STR + }); + if (!this.cache || !(await this.cache.containsResultTree(key))) { + return null; + } + const cacheResult: Data = (await this.cache!.getResultJSON(key)) as Data; + const resultTree = await this.cache!.getResultTree(key); + if (!allowStale && resultTree!.isStale()) { + return null; + } + const result: QueryResult = { + source: SOURCE_CACHE, + ref: queryRef, + data: cacheResult, + toJSON: getRefSerializer( + queryRef, + cacheResult, + SOURCE_CACHE, + resultTree!.cachedAt.toString() + ), + fetchTime: resultTree!.cachedAt.toString() + }; + (await this.cache!.getResultTree(key))!.updateAccessed(); + return result; + } + async getFromSubscriberCache( + queryRef: QueryRef + ): Promise | undefined> { + const key = encoderImpl({ + name: queryRef.name, + variables: queryRef.variables, + refType: QUERY_STR + }); + if (!this.subscriptionCache.has(key)) { + return; + } + const result = this.subscriptionCache.get(key); + result!.source = SOURCE_CACHE; + result!.toJSON = getRefSerializer( + result!.ref, + result!.data, + SOURCE_CACHE, + result!.fetchTime + ); + return result as QueryResult; + } + + publishDataToSubscribers( + key: string, + queryResult: QueryResult + ): void { + if (!this.callbacks.has(key)) { + return; + } + const subscribers = this.callbacks.get(key); + subscribers!.forEach(callback => { + callback.userCallback(queryResult); + }); + } + async publishCacheResultsToSubscribers( + impactedQueries: string[], + fetchTime: string + ): Promise { + if (!this.cache) { + return; + } + for (const query of impactedQueries) { + const callbacks = this.callbacks.get(query); + if (!callbacks) { + continue; + } + const newJson = (await this.cache.getResultTree(query))! + .getRootStub() + .toJSON(EncodingMode.hydrated); + const { name, variables } = decoderImpl(query) as unknown as QueryRef< + unknown, + unknown + >; + const queryRef: QueryRef = { + dataConnect: this.dc, + refType: QUERY_STR, + name, + variables + }; + this.publishDataToSubscribers(query, { + data: newJson, + fetchTime, + ref: queryRef, + source: SOURCE_CACHE, + toJSON: getRefSerializer(queryRef, newJson, SOURCE_CACHE, fetchTime) + }); + } + } + enableEmulator(host: string, port: number): void { + this.transport.useEmulator(host, port); + } +} + +export function getMaxAgeFromExtensions( + extensions: DataConnectExtensionWithMaxAge[] | undefined +): number | undefined { + if (!extensions) { + return; + } + for (const extension of extensions) { + if ( + 'maxAge' in extension && + extension.maxAge !== undefined && + extension.maxAge !== null + ) { + if (extension.maxAge.endsWith('s')) { + return Number( + extension.maxAge.substring(0, extension.maxAge.length - 1) + ); + } + } + } +} +function getDataConnectExtensionsWithoutMaxAge( + extensions: ExtensionsWithMaxAge +): Extensions | undefined { + return { + dataConnect: extensions.dataConnect?.filter( + extension => 'entityId' in extension || 'entityIds' in extension + ) + }; +} diff --git a/packages/data-connect/src/core/query/queryOptions.ts b/packages/data-connect/src/core/query/queryOptions.ts new file mode 100644 index 0000000000..6afb1fe94d --- /dev/null +++ b/packages/data-connect/src/core/query/queryOptions.ts @@ -0,0 +1,33 @@ +/** + * @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. + */ + +export const QueryFetchPolicy = { + PREFER_CACHE: 'PREFER_CACHE', + CACHE_ONLY: 'CACHE_ONLY', + SERVER_ONLY: 'SERVER_ONLY' +} as const; + +/* + * Represents policy for how executeQuery fetches data + * + */ +export type QueryFetchPolicy = + (typeof QueryFetchPolicy)[keyof typeof QueryFetchPolicy]; + +export interface ExecuteQueryOptions { + fetchPolicy: QueryFetchPolicy; +} diff --git a/packages/data-connect/src/core/query/subscribe.ts b/packages/data-connect/src/core/query/subscribe.ts new file mode 100644 index 0000000000..5a9f9c73d5 --- /dev/null +++ b/packages/data-connect/src/core/query/subscribe.ts @@ -0,0 +1,142 @@ +/** + * @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. + */ + +import { QueryRef, QueryResult, toQueryRef } from '../../api/query'; +import { SerializedRef } from '../../api/Reference'; +import { DataConnectError, Code } from '../error'; + +import { getRefSerializer } from './QueryManager'; + +/** + * `OnCompleteSubscription` + */ +export type OnCompleteSubscription = () => void; +/** + * Representation of full observer options in `subscribe` + */ +export interface SubscriptionOptions { + onNext?: OnResultSubscription; + onErr?: OnErrorSubscription; + onComplete?: OnCompleteSubscription; +} + +/** + * Signature for `OnResultSubscription` for `subscribe` + */ +export type OnResultSubscription = ( + res: QueryResult +) => void; +/** + * Signature for `OnErrorSubscription` for `subscribe` + */ +export type OnErrorSubscription = (err?: DataConnectError) => void; +/** + * Signature for unsubscribe from `subscribe` + */ +export type QueryUnsubscribe = () => void; +/** + * Representation of user provided subscription options. + */ +export interface DataConnectSubscription { + userCallback: OnResultSubscription; + errCallback?: (e?: DataConnectError) => void; + unsubscribe: () => void; +} + +/** + * Subscribe to a `QueryRef` + * @param queryRefOrSerializedResult query ref or serialized result. + * @param observer observer object to use for subscribing. + * @returns `SubscriptionOptions` + */ +export function subscribe( + queryRefOrSerializedResult: + | QueryRef + | SerializedRef, + observer: SubscriptionOptions +): QueryUnsubscribe; +/** + * Subscribe to a `QueryRef` + * @param queryRefOrSerializedResult query ref or serialized result. + * @param onNext Callback to call when result comes back. + * @param onError Callback to call when error gets thrown. + * @param onComplete Called when subscription completes. + * @returns `SubscriptionOptions` + */ +export function subscribe( + queryRefOrSerializedResult: + | QueryRef + | SerializedRef, + onNext: OnResultSubscription, + onError?: OnErrorSubscription, + onComplete?: OnCompleteSubscription +): QueryUnsubscribe; +/** + * Subscribe to a `QueryRef` + * @param queryRefOrSerializedResult query ref or serialized result. + * @param observerOrOnNext observer object or next function. + * @param onError Callback to call when error gets thrown. + * @param onComplete Called when subscription completes. + * @returns `SubscriptionOptions` + */ +export function subscribe( + queryRefOrSerializedResult: + | QueryRef + | SerializedRef, + observerOrOnNext: + | SubscriptionOptions + | OnResultSubscription, + onError?: OnErrorSubscription, + onComplete?: OnCompleteSubscription +): QueryUnsubscribe { + let ref: QueryRef; + let initialCache: QueryResult | undefined; + if ('refInfo' in queryRefOrSerializedResult) { + const serializedRef: SerializedRef = + queryRefOrSerializedResult; + const { data, source, fetchTime } = serializedRef; + + ref = toQueryRef(serializedRef); + initialCache = { + data, + source, + fetchTime, + ref, + toJSON: getRefSerializer(ref, data, source, fetchTime) + }; + } else { + ref = queryRefOrSerializedResult; + } + let onResult: OnResultSubscription | undefined = undefined; + if (typeof observerOrOnNext === 'function') { + onResult = observerOrOnNext; + } else { + onResult = observerOrOnNext.onNext; + onError = observerOrOnNext.onErr; + onComplete = observerOrOnNext.onComplete; + } + if (!onResult) { + throw new DataConnectError(Code.INVALID_ARGUMENT, 'Must provide onNext'); + } + return ref.dataConnect._queryManager.addSubscription( + ref, + onResult, + onComplete, + onError, + initialCache + ); +} diff --git a/packages/data-connect/src/network/fetch.ts b/packages/data-connect/src/network/fetch.ts index 62cef6fb22..ee9bae4826 100644 --- a/packages/data-connect/src/network/fetch.ts +++ b/packages/data-connect/src/network/fetch.ts @@ -26,7 +26,12 @@ import { import { SDK_VERSION } from '../core/version'; import { logError } from '../logger'; -import { CallerSdkType, CallerSdkTypeEnum } from './transport'; +import { + CallerSdkType, + CallerSdkTypeEnum, + Extensions, + DataConnectResponse +} from './transport'; let connectFetch: typeof fetch | null = globalThis.fetch; export function initializeFetch(fetchImpl: typeof fetch): void { @@ -52,7 +57,7 @@ export interface DataConnectFetchBody { operationName: string; variables: T; } -export function dcFetch( +export async function dcFetch( url: string, body: DataConnectFetchBody, { signal }: AbortController, @@ -62,7 +67,7 @@ export function dcFetch( _isUsingGen: boolean, _callerSdkType: CallerSdkType, _isUsingEmulator: boolean -): Promise<{ data: T; errors: Error[] }> { +): Promise> { if (!connectFetch) { throw new DataConnectError(Code.OTHER, 'No Fetch Implementation detected!'); } @@ -90,51 +95,54 @@ export function dcFetch( fetchOptions.credentials = 'include'; } - return connectFetch(url, fetchOptions) - .catch(err => { - throw new DataConnectError( - Code.OTHER, - 'Failed to fetch: ' + JSON.stringify(err) - ); - }) - .then(async response => { - let jsonResponse = null; - try { - jsonResponse = await response.json(); - } catch (e) { - throw new DataConnectError(Code.OTHER, JSON.stringify(e)); - } - const message = getMessage(jsonResponse); - if (response.status >= 400) { - logError( - 'Error while performing request: ' + JSON.stringify(jsonResponse) - ); - if (response.status === 401) { - throw new DataConnectError(Code.UNAUTHORIZED, message); - } - throw new DataConnectError(Code.OTHER, message); - } - return jsonResponse; - }) - .then(res => { - if (res.errors && res.errors.length) { - const stringified = JSON.stringify(res.errors); - const response: DataConnectOperationFailureResponse = { - errors: res.errors, - data: res.data - }; - throw new DataConnectOperationError( - 'DataConnect error while performing request: ' + stringified, - response - ); - } - return res; - }); + let response: Response; + try { + response = await connectFetch(url, fetchOptions); + } catch (err) { + throw new DataConnectError( + Code.OTHER, + 'Failed to fetch: ' + JSON.stringify(err) + ); + } + let jsonResponse: JsonResponse; + try { + jsonResponse = await response.json(); + } catch (e) { + throw new DataConnectError(Code.OTHER, JSON.stringify(e)); + } + const message = getErrorMessage(jsonResponse); + if (response.status >= 400) { + logError('Error while performing request: ' + JSON.stringify(jsonResponse)); + if (response.status === 401) { + throw new DataConnectError(Code.UNAUTHORIZED, message); + } + throw new DataConnectError(Code.OTHER, message); + } + if (jsonResponse.errors && jsonResponse.errors.length) { + const stringified = JSON.stringify(jsonResponse.errors); + const failureResponse: DataConnectOperationFailureResponse = { + errors: jsonResponse.errors, + data: jsonResponse.data as Record + }; + throw new DataConnectOperationError( + 'DataConnect error while performing request: ' + stringified, + failureResponse + ); + } + if (!jsonResponse.extensions) { + jsonResponse.extensions = { + dataConnect: [] + }; + } + return jsonResponse as DataConnectResponse; } -interface MessageObject { +interface JsonResponse { message?: string; + errors: []; + data: Record | T | null; + extensions?: Extensions; } -function getMessage(obj: MessageObject): string { +function getErrorMessage(obj: JsonResponse): string { if ('message' in obj && obj.message) { return obj.message; } diff --git a/packages/data-connect/src/network/index.ts b/packages/data-connect/src/network/index.ts index 33a2202d57..72dcdb1d0c 100644 --- a/packages/data-connect/src/network/index.ts +++ b/packages/data-connect/src/network/index.ts @@ -15,4 +15,13 @@ * limitations under the License. */ -export * from './transport'; +export { + CallerSdkType, + CallerSdkTypeEnum, + DataConnectTransport, + DataConnectEntityArray, + DataConnectSingleEntity, + DataConnectExtension, + Extensions, + TransportClass +} from './transport'; diff --git a/packages/data-connect/src/network/transport/index.ts b/packages/data-connect/src/network/transport/index.ts index 8b106b4d63..b3856ed30d 100644 --- a/packages/data-connect/src/network/transport/index.ts +++ b/packages/data-connect/src/network/transport/index.ts @@ -39,6 +39,50 @@ export const CallerSdkTypeEnum = { GeneratedAngular: 'GeneratedAngular' // Generated Angular SDK } as const; +export interface DataConnectEntityArray { + entityIds: string[]; +} + +export interface DataConnectSingleEntity { + entityId: string; +} + +export type DataConnectExtension = { + path: Array; +} & (DataConnectEntityArray | DataConnectSingleEntity); + +/** @internal */ +export interface DataConnectMaxAge { + maxAge: string; +} + +/** @internal */ +export type DataConnectExtensionWithMaxAge = { + path: Array; +} & (DataConnectEntityArray | DataConnectSingleEntity | DataConnectMaxAge); + +export interface Extensions { + dataConnect?: DataConnectExtension[]; +} + +/** @internal */ +export interface ExtensionsWithMaxAge { + dataConnect?: DataConnectExtensionWithMaxAge[]; +} + +export interface DataConnectResponse { + data: T; + errors: Error[]; + extensions: Extensions; +} + +/** @internal */ +export interface DataConnectResponseWithMaxAge { + data: T; + errors: Error[]; + extensions: ExtensionsWithMaxAge; +} + /** * @internal */ @@ -46,11 +90,11 @@ export interface DataConnectTransport { invokeQuery( queryName: string, body?: U - ): Promise<{ data: T; errors: Error[] }>; + ): Promise>; invokeMutation( queryName: string, body?: U - ): Promise<{ data: T; errors: Error[] }>; + ): Promise>; useEmulator(host: string, port?: number, sslEnabled?: boolean): void; onTokenChanged: (token: string | null) => void; _setCallerSdkType(callerSdkType: CallerSdkType): void; diff --git a/packages/data-connect/src/network/transport/rest.ts b/packages/data-connect/src/network/transport/rest.ts index 4a3af8ac41..5f5fa320ef 100644 --- a/packages/data-connect/src/network/transport/rest.ts +++ b/packages/data-connect/src/network/transport/rest.ts @@ -23,7 +23,12 @@ import { logDebug } from '../../logger'; import { addToken, urlBuilder } from '../../util/url'; import { dcFetch } from '../fetch'; -import { CallerSdkType, CallerSdkTypeEnum, DataConnectTransport } from '.'; +import { + CallerSdkType, + CallerSdkTypeEnum, + DataConnectResponse, + DataConnectTransport +} from '.'; export class RESTTransport implements DataConnectTransport { private _host = ''; @@ -40,7 +45,7 @@ export class RESTTransport implements DataConnectTransport { constructor( options: DataConnectOptions, private apiKey?: string | undefined, - private appId?: string, + private appId?: string | null, private authProvider?: AuthTokenProvider | undefined, private appCheckProvider?: AppCheckTokenProvider | undefined, transportOptions?: TransportOptions | undefined, @@ -111,7 +116,10 @@ export class RESTTransport implements DataConnectTransport { resolve(this._accessToken) ); if (this.appCheckProvider) { - this._appCheckToken = (await this.appCheckProvider.getToken())?.token; + const appCheckToken = await this.appCheckProvider.getToken(); + if (appCheckToken) { + this._appCheckToken = appCheckToken.token; + } } if (this.authProvider) { starterPromise = this.authProvider @@ -134,9 +142,9 @@ export class RESTTransport implements DataConnectTransport { } withRetry( - promiseFactory: () => Promise<{ data: T; errors: Error[] }>, + promiseFactory: () => Promise>, retry = false - ): Promise<{ data: T; errors: Error[] }> { + ): Promise> { let isNewToken = false; return this.getWithAuth(retry) .then(res => { @@ -164,7 +172,7 @@ export class RESTTransport implements DataConnectTransport { invokeQuery: ( queryName: string, body?: U - ) => Promise<{ data: T; errors: Error[] }> = ( + ) => Promise> = ( queryName: string, body: U ) => { @@ -193,7 +201,7 @@ export class RESTTransport implements DataConnectTransport { invokeMutation: ( queryName: string, body?: U - ) => Promise<{ data: T; errors: Error[] }> = ( + ) => Promise> = ( mutationName: string, body: U ) => { diff --git a/packages/data-connect/src/register.ts b/packages/data-connect/src/register.ts index badebf2a29..5ffe00ea2f 100644 --- a/packages/data-connect/src/register.ts +++ b/packages/data-connect/src/register.ts @@ -33,13 +33,16 @@ export function registerDataConnect(variant?: string): void { _registerComponent( new Component( 'data-connect', - (container, { instanceIdentifier: settings, options }) => { + (container, { instanceIdentifier: connectorConfigStr, options }) => { const app = container.getProvider('app').getImmediate()!; const authProvider = container.getProvider('auth-internal'); const appCheckProvider = container.getProvider('app-check-internal'); let newOpts = options as ConnectorConfig; - if (settings) { - newOpts = JSON.parse(settings); + if (connectorConfigStr) { + newOpts = { + ...JSON.parse(connectorConfigStr), + ...newOpts + }; } if (!app.options.projectId) { throw new DataConnectError( diff --git a/packages/data-connect/src/util/encoder.ts b/packages/data-connect/src/util/encoder.ts index 55aff801d2..373341e656 100644 --- a/packages/data-connect/src/util/encoder.ts +++ b/packages/data-connect/src/util/encoder.ts @@ -15,9 +15,23 @@ * limitations under the License. */ -export type HmacImpl = (obj: unknown) => string; +export type HmacImpl = (obj: Record) => string; export let encoderImpl: HmacImpl; +export type DecodeHmacImpl = (s: string) => Record; +export let decoderImpl: DecodeHmacImpl; export function setEncoder(encoder: HmacImpl): void { encoderImpl = encoder; } -setEncoder(o => JSON.stringify(o)); +export function setDecoder(decoder: DecodeHmacImpl): void { + decoderImpl = decoder; +} +function sortKeysForObj(o: Record): Record { + return Object.keys(o) + .sort() + .reduce((accumulator, currentKey) => { + accumulator[currentKey] = o[currentKey]; + return accumulator; + }, {} as Record); +} +setEncoder((o: Record) => JSON.stringify(sortKeysForObj(o))); +setDecoder(s => sortKeysForObj(JSON.parse(s))); diff --git a/packages/data-connect/src/util/url.ts b/packages/data-connect/src/util/url.ts index 5063058276..16fb28750d 100644 --- a/packages/data-connect/src/util/url.ts +++ b/packages/data-connect/src/util/url.ts @@ -19,6 +19,8 @@ import { DataConnectOptions, TransportOptions } from '../api/DataConnect'; import { Code, DataConnectError } from '../core/error'; import { logError } from '../logger'; +export const PROD_HOST = 'firebasedataconnect.googleapis.com'; + export function urlBuilder( projectConfig: DataConnectOptions, transportOptions: TransportOptions @@ -26,7 +28,7 @@ export function urlBuilder( const { connector, location, projectId: project, service } = projectConfig; const { host, sslEnabled, port } = transportOptions; const protocol = sslEnabled ? 'https' : 'http'; - const realHost = host || `firebasedataconnect.googleapis.com`; + const realHost = host || PROD_HOST; let baseUrl = `${protocol}://${realHost}`; if (typeof port === 'number') { baseUrl += `:${port}`; diff --git a/packages/data-connect/test/queries.test.ts b/packages/data-connect/test/queries.test.ts index 24db1e4508..7c8a48a8c5 100644 --- a/packages/data-connect/test/queries.test.ts +++ b/packages/data-connect/test/queries.test.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { deleteApp, initializeApp, FirebaseApp } from '@firebase/app'; import { expect, use } from 'chai'; import chaiAsPromised from 'chai-as-promised'; @@ -85,13 +86,18 @@ interface PostVariables { } describe('DataConnect Tests', async () => { let dc: DataConnect; + let app: FirebaseApp; const TEST_ID = crypto.randomUUID(); beforeEach(async () => { + app = initializeApp({ + projectId: PROJECT_ID + }); dc = initDatabase(); await seedDatabase(dc, TEST_ID); }); afterEach(async () => { await deleteDatabase(dc); + await deleteApp(app); await terminate(dc); }); function getPostsRef(): QueryRef { @@ -132,7 +138,7 @@ describe('DataConnect Tests', async () => { const taskListQuery = getPostsRef(); const queryResult = await executeQuery(taskListQuery); const result = await waitForFirstEvent(taskListQuery); - expect(result.data).to.eq(queryResult.data); + expect(result.data).to.deep.eq(queryResult.data); expect(result.source).to.eq(SOURCE_CACHE); }); it(`returns the proper JSON when calling .toJSON()`, async () => { diff --git a/packages/data-connect/test/unit/QueryManager.test.ts b/packages/data-connect/test/unit/QueryManager.test.ts index 9acc948d57..b5a4313862 100644 --- a/packages/data-connect/test/unit/QueryManager.test.ts +++ b/packages/data-connect/test/unit/QueryManager.test.ts @@ -55,11 +55,13 @@ describe('Query Manager Tests', () => { const error = new DataConnectError( Code.INVALID_ARGUMENT, - `ExecuteQuery can only execute query operation` + 'ExecuteQuery can only execute query operations' ); // @ts-ignore - expect(() => executeQuery(mutation)).to.throw(error.message); + await expect(executeQuery(mutation)).to.eventually.be.rejectedWith( + error.message + ); expect(() => executeQuery(query)).to.not.throw(error.message); }); }); diff --git a/packages/data-connect/test/unit/caching.test.ts b/packages/data-connect/test/unit/caching.test.ts new file mode 100644 index 0000000000..e8e1b6535d --- /dev/null +++ b/packages/data-connect/test/unit/caching.test.ts @@ -0,0 +1,569 @@ +/** + * @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. + */ + +import { initializeApp, FirebaseApp, deleteApp } from '@firebase/app'; +import { expect } from 'chai'; +import * as sinon from 'sinon'; + +import { + DataConnect, + executeQuery, + getDataConnect, + makeMemoryCacheProvider, + queryRef, + QueryResult, + subscribe, + DataConnectExtension, + OpResult +} from '../../src'; +import { initializeFetch } from '../../src/network/fetch'; + +describe('caching', () => { + let dc: DataConnect; + let app: FirebaseApp; + beforeEach(() => { + const { firebaseApp, dc: newDC } = setup(); + dc = newDC; + app = firebaseApp; + }); + afterEach(async () => { + await deleteApp(app); + }); + it('should resolve from cache with an interdependent query', async () => { + interface Q1Data { + movies: Array<{ + title: string; + }>; + } + interface Q2Data { + movies: Array<{ + title: string; + genre: string; + }>; + } + + const q1MovieData = { + movies: [ + { + title: 'matrix' + } + ] + }; + const q2MovieData = { + movies: [ + { + title: 'matrix', + genre: 'sci-fi' + } + ] + }; + const date = new Date().toISOString(); + const q1 = queryRef(dc, 'q1'); + const matrixEntity = { + path: ['movies', 0], + entityId: 'matrix' + }; + await updateCacheData( + dc, + { + data: q1MovieData, + fetchTime: date, + ref: q1, + source: 'CACHE' + }, + [matrixEntity] + ); + const q2 = queryRef(dc, 'q2'); + await updateCacheData( + dc, + { + data: q2MovieData, + fetchTime: date, + ref: q2, + source: 'CACHE' + }, + [matrixEntity] + ); + + const events: Array< + Pick, 'data' | 'source'> + > = []; + subscribe(q2, event => { + events.push({ + data: event.data, + source: event.source + }); + }); + + const expected = { + data: { + movies: [ + { + title: 'the matrix' + } + ] + }, + extensions: { + dataConnect: [matrixEntity] + } + }; + stubFetch(expected); + const result = await executeQuery(q1, { + fetchPolicy: 'SERVER_ONLY' + }); + expect(result.data.movies).to.deep.eq(expected.data.movies); + // wait for 2 seconds to make sure we don't have too many events coming in. + await waitFor(2000); + + expect(events.length).to.eq(2); + expect(events).to.deep.eq([ + { + data: { + movies: [ + { + genre: 'sci-fi', + title: 'matrix' + } + ] + }, + source: 'CACHE' + } as QueryResult, + { + data: { + movies: [ + { + genre: 'sci-fi', + title: 'the matrix' + } + ] + }, + source: 'CACHE' + } as QueryResult + ]); + const result2 = await executeQuery(q1, { + fetchPolicy: 'CACHE_ONLY' + }); + expect(result2.data.movies).to.deep.eq(expected.data.movies); + const genreResult = await executeQuery(q2, { + fetchPolicy: 'CACHE_ONLY' + }); + expect(genreResult.data.movies).to.deep.eq([ + { + title: 'the matrix', + genre: 'sci-fi' + } + ]); + }); + it('should not resolve from cache when caching is disabled', async () => { + const dcWithoutCache = getDataConnect({ + connector: 'a', + location: 'b', + service: 'c' + }); + interface Q1Data { + movies: Array<{ + title: string; + }>; + } + interface Q2Data { + movies: Array<{ + title: string; + genre: string; + }>; + } + + const q1MovieData = { + movies: [ + { + title: 'matrix' + } + ] + }; + const q2MovieData = { + movies: [ + { + title: 'matrix', + genre: 'sci-fi' + } + ] + }; + const date = new Date().toISOString(); + const q1 = queryRef(dcWithoutCache, 'q1'); + await updateCacheData(dcWithoutCache, { + data: q1MovieData, + fetchTime: date, + ref: q1, + source: 'CACHE' + }); + const q2 = queryRef(dcWithoutCache, 'q2'); + await updateCacheData(dcWithoutCache, { + data: q2MovieData, + fetchTime: date, + ref: q2, + source: 'CACHE' + }); + + const events: Array< + Pick, 'data' | 'source'> + > = []; + subscribe(q2, event => { + events.push({ + data: event.data, + source: event.source + }); + }); + + const expected = { + data: { + movies: [ + { + title: 'matrix' + } + ] + }, + extensions: { + dataConnect: [ + { + path: ['movies', 0], + entityId: 'matrix' + } + ] + } + }; + stubFetch(expected); + const result = await executeQuery(q1, { + fetchPolicy: 'SERVER_ONLY' + }); + expect(result.data.movies).to.deep.eq(expected.data.movies); + // wait for 2 seconds to make sure we don't have too many events coming in. + await waitFor(2000); + + expect(events.length).to.eq(1); + expect(events).to.deep.eq([ + { + data: { + movies: [ + { + genre: 'sci-fi', + title: 'matrix' + } + ] + }, + source: 'CACHE' + } as QueryResult + ]); + }); + it('retrieve entity data when multiple queries have the same entity id', async () => { + interface Q1Data { + movie: { + title: string; + }; + } + const titleResponse: OpResult = { + data: { + movie: { + title: 'matrix' + } + }, + fetchTime: new Date().toISOString(), + source: 'SERVER', + extensions: { + dataConnect: [ + { + path: ['movie'], + entityId: 'matrix' + } + ] + } + }; + + interface Q2Data { + movie: { + genre: string; + }; + } + const genreResponse: OpResult = { + data: { + movie: { + genre: 'sci-fi' + } + }, + fetchTime: new Date().toISOString(), + source: 'SERVER', + extensions: { + dataConnect: [ + { + path: ['movie'], + entityId: 'matrix' + } + ] + } + }; + + const titleQueryId = 'titleQuery'; + await updateCacheData( + dc, + { + data: titleResponse.data, + fetchTime: titleResponse.fetchTime, + ref: queryRef(dc, titleQueryId), + source: titleResponse.source + }, + titleResponse.extensions?.dataConnect + ); + const resultTree = await dc._queryManager.getFromResultTreeCache( + queryRef(dc, titleQueryId) + ); + expect(resultTree?.data).to.deep.eq(titleResponse.data); + const genreQueryId = 'genreQuery'; + await updateCacheData( + dc, + { + data: genreResponse.data, + fetchTime: genreResponse.fetchTime, + ref: queryRef(dc, genreQueryId), + source: genreResponse.source + }, + genreResponse.extensions?.dataConnect + ); + const resultTree2 = await dc._queryManager.getFromResultTreeCache( + queryRef(dc, genreQueryId) + ); + expect(resultTree2?.data).to.deep.eq({ + movie: { + genre: 'sci-fi' + } + }); + const result = await executeQuery(queryRef(dc, genreQueryId), { + fetchPolicy: 'CACHE_ONLY' + }); + expect(result.data).to.deep.eq({ + movie: { + genre: 'sci-fi' + } + }); + }); + it('should retrieve a social media homepage with nested comment arrays and overlapping queries', async () => { + interface Author { + id: string; + name: string; + } + interface PostComment { + content: string; + author: Author; + } + interface Post { + title: string; + author: Author; + comments: PostComment[]; + } + interface HomePageData { + posts: Post[]; + } + const homePageData: HomePageData = { + posts: [ + { + title: 'post1', + author: { id: 'author1', name: 'Alice' }, + comments: [ + { + content: 'comment1', + author: { id: 'author2', name: 'Bob' } + }, + { + content: 'comment2', + author: { id: 'author1', name: 'Alice' } + } + ] + }, + { + title: 'post2', + author: { id: 'author2', name: 'Bob' }, + comments: [] + } + ] + }; + + const getHomePageQueryId = 'getHomePage'; + await updateCacheData( + dc, + { + data: homePageData, + fetchTime: new Date().toISOString(), + ref: queryRef(dc, getHomePageQueryId), + source: 'SERVER' + }, + [ + { + path: ['posts'], + entityIds: ['post1', 'post2'] + }, + { + path: ['posts', 0, 'author'], + entityId: 'author1' + }, + { + path: ['posts', 1, 'author'], + entityId: 'author2' + }, + { + path: ['posts', 0, 'comments'], + entityIds: ['comment1', 'comment2'] + }, + { + path: ['posts', 0, 'comments', 0, 'author'], + entityId: 'author2' + }, + { + path: ['posts', 0, 'comments', 1, 'author'], + entityId: 'author1' + } + ] + ); + + const result = await executeQuery( + queryRef(dc, getHomePageQueryId), + { + fetchPolicy: 'CACHE_ONLY' + } + ); + expect(result.data).to.deep.eq(homePageData); + + interface GetUserCommentsData { + user: { + id: string; + name: string; + comments: PostComment[]; + }; + } + const userCommentsData: GetUserCommentsData = { + user: { + id: 'author1', + name: 'Alice', + comments: [ + { + content: 'comment2', + author: { id: 'author1', name: 'Alice' } + } + ] + } + }; + + const getUserCommentsQueryId = 'getUserComments'; + await updateCacheData( + dc, + { + data: userCommentsData, + fetchTime: new Date().toISOString(), + ref: queryRef(dc, getUserCommentsQueryId), + source: 'SERVER' + }, + [ + { + path: ['user'], + entityId: 'author1' + }, + { + path: ['user', 'comments'], + entityIds: ['comment2'] + }, + { + path: ['user', 'comments', 0, 'author'], + entityId: 'author1' + } + ] + ); + + const result2 = await executeQuery( + queryRef(dc, getUserCommentsQueryId), + { + fetchPolicy: 'CACHE_ONLY' + } + ); + expect(result2.data).to.deep.eq(userCommentsData); + }); +}); + +function stubFetch(response: unknown): void { + const fakeFetchImpl = sinon.stub().returns({ + json: () => { + return Promise.resolve(response); + }, + status: 200 + }); + initializeFetch(fakeFetchImpl); +} + +function setup(): { firebaseApp: FirebaseApp; dc: DataConnect } { + const app = initializeApp({ + projectId: 'p2' + }); + const connectorConfig = { + connector: 'c', + location: 'l', + service: 's' + }; + const dc = getDataConnect(connectorConfig, { + cacheSettings: { + cacheProvider: makeMemoryCacheProvider() + } + }); + return { firebaseApp: app, dc }; +} + +async function waitFor(milliseconds: number): Promise { + return new Promise(resolve => { + setTimeout(() => resolve(), milliseconds); + }); +} +async function updateCacheData( + dc: DataConnect, + { + data, + fetchTime, + ref, + source + }: Omit, 'toJSON'>, + extension?: DataConnectExtension[] +): Promise { + const connectorConfig = dc.getSettings(); + const projectId = dc.app.options.projectId; + return dc._queryManager.updateCache({ + data, + fetchTime, + ref, + source, + extensions: { + dataConnect: extension + }, + toJSON() { + return { + data, + fetchTime, + source, + refInfo: { + connectorConfig: { + ...connectorConfig, + projectId: projectId! + }, + name: ref.name, + variables: ref.variables + } + }; + } + }); +} diff --git a/packages/data-connect/test/unit/entitynode.test.ts b/packages/data-connect/test/unit/entitynode.test.ts new file mode 100644 index 0000000000..7fdc0dec61 --- /dev/null +++ b/packages/data-connect/test/unit/entitynode.test.ts @@ -0,0 +1,436 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai'; + +import { makeMemoryCacheProvider } from '../../src'; +import { + EncodingMode, + EntityNode, + GLOBAL_ID_KEY +} from '../../src/cache/EntityNode'; +import { ImpactedQueryRefsAccumulator } from '../../src/cache/ImpactedQueryRefsAccumulator'; + +describe('entity node', () => { + it('should load data for an array with one entity', async () => { + const node = new EntityNode(); + /** + * { movies: [ { title: 'the matrix' } ] } + * { entityIds: [ { path: ['movies', 0], entityId: 'matrix' } ] } + */ + const exampleData = { + movies: [ + { + title: 'the matrix' + } + ] + }; + const exampleEntityIds = { + movies: [ + { + [GLOBAL_ID_KEY]: 'matrix' + } + ] + }; + const cacheId = 'cacheId'; + const memoryCacheProvider = makeMemoryCacheProvider().initialize(cacheId); + const queryId = 'movies'; + await node.loadData( + queryId, + exampleData, + exampleEntityIds, + new ImpactedQueryRefsAccumulator(queryId), + memoryCacheProvider + ); + expect(node.objectLists).to.have.property('movies'); + expect(node.objectLists.movies[0].entityDataKeys).to.have.lengthOf(1); + expect(node.objectLists.movies[0].entityDataKeys.has('title')).to.be.true; + expect( + node.objectLists.movies[0].toJSON(EncodingMode.hydrated) + ).to.deep.equal(exampleData.movies[0]); + }); + it('should load data for an array with multiple entities', async () => { + /** + * { movies: [ { title: 'the matrix' }, { title: 'the dark knight' } ] } + * { entityIds: [ { path: ['movies'], entityIds: ['matrix', 'the dark knight'] } ] } + */ + const node = new EntityNode(); + const exampleData = { + movies: [ + { + title: 'the matrix' + }, + { + title: 'the dark knight' + } + ] + }; + const exampleEntityIds = { + movies: [ + { + [GLOBAL_ID_KEY]: 'matrix' + }, + { + [GLOBAL_ID_KEY]: 'the dark knight' + } + ] + }; + const cacheId = 'cacheId'; + const memoryCacheProvider = makeMemoryCacheProvider().initialize(cacheId); + const queryId = 'movies'; + await node.loadData( + queryId, + exampleData, + exampleEntityIds, + new ImpactedQueryRefsAccumulator(queryId), + memoryCacheProvider + ); + expect(node.objectLists).to.have.property('movies'); + expect(node.objectLists.movies).to.have.lengthOf(2); + expect(node.objectLists.movies[0].entityDataKeys.has('title')).to.be.true; + expect(node.objectLists.movies[1].entityDataKeys.has('title')).to.be.true; + expect( + node.objectLists.movies.map(movie => movie.toJSON(EncodingMode.hydrated)) + ).to.deep.equal(exampleData.movies); + }); + it('should load data for an object', async () => { + /** + * { movie: { title: 'the matrix' } } + * { entityIds: [ { path: ['movies'], entityId: 'matrix' } ] } + */ + const node = new EntityNode(); + const exampleData = { + movie: { + title: 'the matrix' + } + }; + const exampleEntityIds = { + movie: { + [GLOBAL_ID_KEY]: 'matrix' + } + }; + const cacheId = 'cacheId'; + const memoryCacheProvider = makeMemoryCacheProvider().initialize(cacheId); + const queryId = 'movies'; + await node.loadData( + queryId, + exampleData, + exampleEntityIds, + new ImpactedQueryRefsAccumulator(queryId), + memoryCacheProvider + ); + expect(node.references.movie.entityDataKeys.has('title')).to.be.true; + expect(node.toJSON(EncodingMode.hydrated)).to.deep.equal(exampleData); + }); + it('should keep track of the right fields when two queries have different fields required from entity data objects', async () => { + /** + * { movies: [ { title: 'the matrix' }, { title: 'the dark knight' } ] } + * { entityIds: [ { path: ['movies'], entityIds: ['matrix', 'the dark knight'] } ] } + */ + + const cacheId = 'cacheId'; + const memoryCacheProvider = makeMemoryCacheProvider().initialize(cacheId); + const genreNode = new EntityNode(); + const genreQueryId = 'genre'; + const exampleExtraGenreData = { + movies: [ + { + title: 'the matrix', + genre: 'sci-fi' + }, + { + title: 'the dark knight', + genre: 'action' + } + ] + }; + const exampleExtraGenreEntityIds = { + movies: [ + { + [GLOBAL_ID_KEY]: 'matrix' + }, + { + [GLOBAL_ID_KEY]: 'the dark knight' + } + ] + }; + await genreNode.loadData( + genreQueryId, + exampleExtraGenreData, + exampleExtraGenreEntityIds, + new ImpactedQueryRefsAccumulator(genreQueryId), + memoryCacheProvider + ); + expect( + genreNode.objectLists.movies.map(movie => + movie.toJSON(EncodingMode.hydrated) + ) + ).to.deep.equal(exampleExtraGenreData.movies); + expect(genreNode.objectLists.movies[0].entityDataKeys.has('genre')).to.be + .true; + expect(genreNode.objectLists.movies[1].entityDataKeys.has('genre')).to.be + .true; + const titleNode = new EntityNode(); + const exampleData = { + movies: [ + { + title: 'the matrix' + }, + { + title: 'the dark knight' + } + ] + }; + const exampleEntityIds = { + movies: [ + { + [GLOBAL_ID_KEY]: 'matrix' + }, + { + [GLOBAL_ID_KEY]: 'the dark knight' + } + ] + }; + const queryId = 'movies'; + await titleNode.loadData( + queryId, + exampleData, + exampleEntityIds, + new ImpactedQueryRefsAccumulator(queryId), + memoryCacheProvider + ); + expect( + titleNode.objectLists.movies.map(movie => + movie.toJSON(EncodingMode.hydrated) + ) + ).to.deep.equal(exampleData.movies); + expect(titleNode.objectLists.movies[0].entityDataKeys.has('title')).to.be + .true; + expect(titleNode.objectLists.movies[1].entityDataKeys.has('title')).to.be + .true; + expect(titleNode.objectLists.movies[0].entityDataKeys.has('genre')).to.be + .false; + expect(titleNode.objectLists.movies[1].entityDataKeys.has('genre')).to.be + .false; + expect( + titleNode.objectLists.movies[0].entityData?.getServerValues()?.title + ).to.equal('the matrix'); + expect( + titleNode.objectLists.movies[1].entityData?.getServerValues()?.title + ).to.equal('the dark knight'); + }); + it('should load data for nested entities', async () => { + const exampleEntityIds = { + posts: [ + { + author: { + [GLOBAL_ID_KEY]: 'idForAuthorOfPost1' + } + } + ] + }; + const exampleData = { + posts: [ + { + title: 'Why I love the matrix', + author: { + name: 'Cypher' + } + } + ] + }; + const queryId = 'posts'; + const cacheId = 'cacheId'; + const memoryCacheProvider = makeMemoryCacheProvider().initialize(cacheId); + const node = new EntityNode(); + await node.loadData( + queryId, + exampleData, + exampleEntityIds, + new ImpactedQueryRefsAccumulator(queryId), + memoryCacheProvider + ); + expect( + node.objectLists.posts[0].references['author'].entityDataKeys.has('name') + ).to.be.true; + expect( + node.objectLists.posts[0].references[ + 'author' + ].entityData?.getServerValues()!.name + ).to.equal('Cypher'); + }); + + it('should load data for complex nested lists and objects like a social media feed', async () => { + const exampleEntityIds = { + posts: [ + { + [GLOBAL_ID_KEY]: 'post1', + author: { + [GLOBAL_ID_KEY]: 'author1' + }, + comments: [ + { + [GLOBAL_ID_KEY]: 'comment1', + author: { + [GLOBAL_ID_KEY]: 'author2' + } + }, + { + [GLOBAL_ID_KEY]: 'comment2', + author: { + [GLOBAL_ID_KEY]: 'author1' + } + } + ] + }, + { + [GLOBAL_ID_KEY]: 'post2', + author: { + [GLOBAL_ID_KEY]: 'author2' + }, + comments: [] + } + ] + }; + + const exampleData = { + posts: [ + { + title: 'Hello world', + author: { name: 'Alice', username: '@alice' }, + comments: [ + { + content: 'First!', + author: { name: 'Bob', username: '@bob' } + }, + { + content: 'Nice post', + author: { name: 'Alice', username: '@alice' } + } + ] + }, + { + title: 'Another day', + author: { name: 'Bob', username: '@bob' }, + comments: [] + } + ] + }; + + const queryId = 'homePageQuery'; + const cacheId = 'cacheId'; + const memoryCacheProvider = makeMemoryCacheProvider().initialize(cacheId); + const node = new EntityNode(); + + await node.loadData( + queryId, + exampleData, + exampleEntityIds, + new ImpactedQueryRefsAccumulator(queryId), + memoryCacheProvider + ); + + // Verify root-level entities + expect(node.objectLists).to.have.property('posts'); + expect(node.objectLists.posts).to.have.lengthOf(2); + expect(node.objectLists.posts[0].entityDataKeys.has('title')).to.be.true; + + // Verify nested entities + expect( + node.objectLists.posts[0].references['author'].entityDataKeys.has('name') + ).to.be.true; + expect( + node.objectLists.posts[0].references[ + 'author' + ].entityData?.getServerValues()!.name + ).to.equal('Alice'); + + // Verify deeply nested lists and entities + expect(node.objectLists.posts[0].objectLists['comments']).to.have.lengthOf( + 2 + ); + expect( + node.objectLists.posts[0].objectLists['comments'][0].references[ + 'author' + ].entityData?.getServerValues()!.name + ).to.equal('Bob'); + expect( + node.objectLists.posts[0].objectLists['comments'][1].references[ + 'author' + ].entityData?.getServerValues()!.name + ).to.equal('Alice'); + + // Verify JSON export constructs the merged object fully + expect(node.toJSON(EncodingMode.hydrated)).to.deep.equal(exampleData); + + // Make a second query requesting additional fields for the same entity + const userProfileQueryId = 'userProfileQuery'; + const profileEntityIds = { + profile: { + [GLOBAL_ID_KEY]: 'author1' + } + }; + const profileData = { + profile: { + name: 'Alice', + bio: 'Just another user', + avatarUrl: 'https://example.com/alice.png' + } + }; + const profileNode = new EntityNode(); + + await profileNode.loadData( + userProfileQueryId, + profileData, + profileEntityIds, + new ImpactedQueryRefsAccumulator(userProfileQueryId), + memoryCacheProvider + ); + + // The original node's entity should also have received the new fields + // since both query nodes point to the same global cache manager + const author1Entity = + node.objectLists.posts[0].references['author'].entityData; + expect(author1Entity?.getServerValues()!.name).to.equal('Alice'); + expect(author1Entity?.getServerValues()!.username).to.equal('@alice'); + expect(author1Entity?.getServerValues()!.bio).to.equal('Just another user'); + expect(author1Entity?.getServerValues()!.avatarUrl).to.equal( + 'https://example.com/alice.png' + ); + + // Make sure we kept the original entity keys for this node correct + expect( + node.objectLists.posts[0].references['author'].entityDataKeys.has('name') + ).to.be.true; + expect( + node.objectLists.posts[0].references['author'].entityDataKeys.has( + 'username' + ) + ).to.be.true; + expect( + node.objectLists.posts[0].references['author'].entityDataKeys.has('bio') + ).to.be.false; + + // Verify the profileNode's keys as well + expect(profileNode.references['profile'].entityDataKeys.has('name')).to.be + .true; + expect(profileNode.references['profile'].entityDataKeys.has('bio')).to.be + .true; + expect(profileNode.references['profile'].entityDataKeys.has('username')).to + .be.false; + }); +}); diff --git a/packages/data-connect/test/unit/fetch.test.ts b/packages/data-connect/test/unit/fetch.test.ts index be45695190..43060c90cd 100644 --- a/packages/data-connect/test/unit/fetch.test.ts +++ b/packages/data-connect/test/unit/fetch.test.ts @@ -42,7 +42,10 @@ describe('fetch', () => { mockFetch( { code: 401, - message + message, + extensions: { + dataConnect: [] + } }, true ); diff --git a/packages/data-connect/test/unit/gmpid.test.ts b/packages/data-connect/test/unit/gmpid.test.ts index fa0e1486d8..281a8fe85c 100644 --- a/packages/data-connect/test/unit/gmpid.test.ts +++ b/packages/data-connect/test/unit/gmpid.test.ts @@ -50,7 +50,6 @@ describe('GMPID Tests', () => { await deleteApp(app); }); it('should send a request with the corresponding gmpid if using the app id is specified', async () => { - // @ts-ignore await executeQuery(queryRef(dc, '')).catch(() => {}); expect(fakeFetchImpl).to.be.calledWithMatch( 'https://firebasedataconnect.googleapis.com/v1/projects/p/locations/l/services/s/connectors/c:executeQuery', diff --git a/packages/data-connect/test/unit/maxAge.test.ts b/packages/data-connect/test/unit/maxAge.test.ts new file mode 100644 index 0000000000..5cdc331f89 --- /dev/null +++ b/packages/data-connect/test/unit/maxAge.test.ts @@ -0,0 +1,42 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai'; + +import { getMaxAgeFromExtensions } from '../../src/core/query/QueryManager'; + +describe('maxAge', () => { + it('should update maxAge when server returns a different maxAge', async () => { + const maxAge = getMaxAgeFromExtensions([ + { + path: [], + maxAge: '100s' + } + ]); + expect(maxAge).to.equal(100); + }); + + it('should return undefined when an invalid maxAge is returned', async () => { + const maxAge = getMaxAgeFromExtensions([ + { + path: [], + maxAge: 'abc' + } + ]); + expect(maxAge).to.equal(undefined); + }); +}); diff --git a/packages/data-connect/test/unit/parseEntityIds.test.ts b/packages/data-connect/test/unit/parseEntityIds.test.ts new file mode 100644 index 0000000000..3a53aabf9f --- /dev/null +++ b/packages/data-connect/test/unit/parseEntityIds.test.ts @@ -0,0 +1,104 @@ +/** + * @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. + */ + +/* eslint-disable camelcase */ +import { expect } from 'chai'; + +import { OpResult, SOURCE_SERVER } from '../../src'; +import { parseEntityIds } from '../../src/cache/cacheUtils'; +describe('parseEntityIds', () => { + it('should parse single entity id', () => { + const fetchTime = new Date().toISOString(); + const response: OpResult = { + data: { + posts: [ + { + title: 'Post 1', + author: { + name: 'Alice' + }, + comments_on_post: [ + { + content: 'Great post!' + }, + { + content: 'Insightful' + } + ] + }, + { + title: 'Post 2', + author: { + name: 'Bob' + }, + comments_on_post: [ + { + content: 'Me too' + }, + { + content: 'Congrats!' + } + ] + } + ] + }, + fetchTime, + source: SOURCE_SERVER, + extensions: { + dataConnect: [ + { + path: ['posts'], + entityIds: ['idForPost1GoesHere', 'idForPost2GoesHere'] + }, + { + path: ['posts', 0, 'author'], + entityId: 'idForAuthorOfPost1' + }, + { + path: ['posts', 1, 'author'], + entityId: 'idForAuthorOfPost2' + }, + { + path: ['posts', 0, 'comments_on_post'], + entityIds: ['idForPost1Comment1', 'idForPost1Comment2'] + }, + { + path: ['posts', 1, 'comments_on_post'], + entityIds: ['idForPost2Comment1', 'idForPost2Comment2'] + } + ] + } + }; + const actual = parseEntityIds(response); + // @ts-ignore + expect(actual.posts[0].author._id).to.eq('idForAuthorOfPost1'); + // @ts-ignore + expect(actual.posts[1].author._id).to.eq('idForAuthorOfPost2'); + // @ts-ignore + expect(actual.posts[0]._id).to.eq('idForPost1GoesHere'); + // @ts-ignore + expect(actual.posts[1]._id).to.eq('idForPost2GoesHere'); + // @ts-ignore + expect(actual.posts[0].comments_on_post[0]._id).to.eq('idForPost1Comment1'); + // @ts-ignore + expect(actual.posts[0].comments_on_post[1]._id).to.eq('idForPost1Comment2'); + // @ts-ignore + expect(actual.posts[1].comments_on_post[0]._id).to.eq('idForPost2Comment1'); + // @ts-ignore + expect(actual.posts[1].comments_on_post[1]._id).to.eq('idForPost2Comment2'); + }); +}); diff --git a/packages/data-connect/test/unit/queries.test.ts b/packages/data-connect/test/unit/queries.test.ts index 02d19bf856..51f12c5b21 100644 --- a/packages/data-connect/test/unit/queries.test.ts +++ b/packages/data-connect/test/unit/queries.test.ts @@ -15,7 +15,11 @@ * limitations under the License. */ -import { FirebaseAuthTokenData } from '@firebase/auth-interop-types'; +import { initializeApp } from '@firebase/app'; +import { + FirebaseAuthInternal, + FirebaseAuthTokenData +} from '@firebase/auth-interop-types'; import { expect } from 'chai'; import * as chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; @@ -40,6 +44,9 @@ const options: DataConnectOptions = { }; const INITIAL_TOKEN = 'initial token'; class FakeAuthProvider implements AuthTokenProvider { + getAuth(): FirebaseAuthInternal { + throw new Error('Method not implemented.'); + } private token: string | null = INITIAL_TOKEN; addTokenChangeListener(listener: AuthTokenListener): void {} getToken(forceRefresh: boolean): Promise { @@ -82,6 +89,11 @@ function getPostsRef(): QueryRef { }); } describe('Queries', () => { + beforeEach(() => { + initializeApp({ + projectId: 'p' + }); + }); afterEach(() => { fakeFetchImpl.resetHistory(); }); diff --git a/packages/data-connect/test/unit/transportoptions.test.ts b/packages/data-connect/test/unit/transportoptions.test.ts index a7136b5c40..7a39281910 100644 --- a/packages/data-connect/test/unit/transportoptions.test.ts +++ b/packages/data-connect/test/unit/transportoptions.test.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { deleteApp, initializeApp, FirebaseApp } from '@firebase/app'; import { expect } from 'chai'; import { queryRef } from '../../src'; @@ -24,8 +25,16 @@ import { connectDataConnectEmulator, getDataConnect } from '../../src/api/DataConnect'; -import { app } from '../util'; describe('Transport Options', () => { + let app: FirebaseApp; + beforeEach(() => { + app = initializeApp({ + projectId: 'p' + }); + }); + afterEach(async () => { + await deleteApp(app); + }); it('should return false if transport options are not equal', () => { const transportOptions1: TransportOptions = { host: 'h', diff --git a/packages/data-connect/test/unit/utils.test.ts b/packages/data-connect/test/unit/utils.test.ts index 666ca04ac3..8cb299ef66 100644 --- a/packages/data-connect/test/unit/utils.test.ts +++ b/packages/data-connect/test/unit/utils.test.ts @@ -15,12 +15,19 @@ * limitations under the License. */ +import { deleteApp, initializeApp, FirebaseApp } from '@firebase/app'; import { expect } from 'chai'; import { getDataConnect } from '../../src'; import { validateArgs } from '../../src/util/validateArgs'; -import { app } from '../util'; describe('Utils', () => { + let app: FirebaseApp; + beforeEach(() => { + app = initializeApp({ projectId: 'p' }); + }); + afterEach(async () => { + await deleteApp(app); + }); it('[Vars required: true] should throw if no arguments are provided', () => { const connectorConfig = { connector: 'c', location: 'l', service: 's' }; expect(() => diff --git a/packages/data-connect/test/util.ts b/packages/data-connect/test/util.ts index 625c263c31..329f891c45 100644 --- a/packages/data-connect/test/util.ts +++ b/packages/data-connect/test/util.ts @@ -15,13 +15,12 @@ * limitations under the License. */ -import { initializeApp } from '@firebase/app'; - import { connectDataConnectEmulator, ConnectorConfig, DataConnect, - getDataConnect + getDataConnect, + makeMemoryCacheProvider } from '../src'; export const EMULATOR_PORT = process.env.DC_EMULATOR_PORT; @@ -38,13 +37,13 @@ export function getConnectionConfig(): ConnectorConfig { }; } -export const app = initializeApp({ - projectId: PROJECT_ID -}); - // Seed the database to have the proper fields to query, such as a list of tasks. export function initDatabase(): DataConnect { - const instance = getDataConnect(getConnectionConfig()); + const instance = getDataConnect(getConnectionConfig(), { + cacheSettings: { + cacheProvider: makeMemoryCacheProvider() + } + }); if (USE_EMULATOR) { connectDataConnectEmulator(instance, 'localhost', Number(EMULATOR_PORT)); } diff --git a/packages/util/index.node.ts b/packages/util/index.node.ts index 12fcf8a6de..f77604a4bc 100644 --- a/packages/util/index.node.ts +++ b/packages/util/index.node.ts @@ -43,3 +43,4 @@ export * from './src/formatters'; export * from './src/compat'; export * from './src/global'; export * from './src/url'; +export * from './src/sha256'; diff --git a/packages/util/index.ts b/packages/util/index.ts index 1829c32a42..ecd3557cf8 100644 --- a/packages/util/index.ts +++ b/packages/util/index.ts @@ -38,3 +38,4 @@ export * from './src/formatters'; export * from './src/compat'; export * from './src/global'; export * from './src/url'; +export * from './src/sha256'; diff --git a/packages/util/src/sha256.ts b/packages/util/src/sha256.ts new file mode 100644 index 0000000000..ad069facb0 --- /dev/null +++ b/packages/util/src/sha256.ts @@ -0,0 +1,34 @@ +/** + * @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. + */ + +/** + * @public + * Generates a SHA-256 hash for the given input string. + * + * @param input The string to hash. + * @returns A promise that resolves to the SHA-256 hash as a hex string. + */ +export async function generateSHA256Hash(input: string): Promise { + const textEncoder = new TextEncoder(); + const data = textEncoder.encode(input); + const hashBuffer = await crypto.subtle.digest('SHA-256', data); + + // Convert ArrayBuffer to hex string + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const hexHash = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); + return hexHash; +} From 887fc51fc09e3cbec5b2dcea8d157c3ac5eba8af Mon Sep 17 00:00:00 2001 From: gurusai-voleti Date: Tue, 24 Feb 2026 22:33:40 +0530 Subject: [PATCH 073/174] chore: Migrate gsutil usage instructions to gcloud storage (#9589) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1db82c7960..c3e2d61990 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ order to run the tests, you will need to update your bucket's CORS rules. 1. Install `gsutil` from https://cloud.google.com/storage/docs/gsutil_install 1. You will need to login if this is your first time using `gsutil`. Run `gcloud auth login` and follow the instructions to login. -1. Run `gsutil cors set cors.json gs://` +1. Run `gcloud storage buckets update gs:// --cors-file=cors.json` For more information, visit https://firebase.google.com/docs/storage/web/download-files#cors_configuration From 14d974550c1df023e563c22619dc68b9182946e0 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 24 Feb 2026 12:18:21 -0500 Subject: [PATCH 074/174] feat(firestore): add support for remaining `map` pipeline expressions (#9483) --- .changeset/afraid-pigs-heal.md | 6 + .../firestore-lite-pipelines.api.md | 32 ++ common/api-review/firestore-pipelines.api.md | 32 ++ .../firestore_lite_pipelines.expression.md | 127 ++++++++ docs-devsite/firestore_lite_pipelines.md | 302 ++++++++++++++++++ .../firestore_pipelines.expression.md | 127 ++++++++ docs-devsite/firestore_pipelines.md | 302 ++++++++++++++++++ .../firestore/lite/pipelines/pipelines.ts | 4 + packages/firestore/src/api_pipelines.ts | 4 + .../firestore/src/lite-api/expressions.ts | 284 ++++++++++++++++ .../test/integration/api/pipeline.test.ts | 114 +++++++ packages/firestore/test/lite/pipeline.test.ts | 114 +++++++ 12 files changed, 1448 insertions(+) create mode 100644 .changeset/afraid-pigs-heal.md diff --git a/.changeset/afraid-pigs-heal.md b/.changeset/afraid-pigs-heal.md new file mode 100644 index 0000000000..5f4a4cd5a2 --- /dev/null +++ b/.changeset/afraid-pigs-heal.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/firestore': minor +--- + +Support added for `mapSet`, `mapValues`, `mapEntries`, `mapKeys` Pipelines expressions. diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index a6ddac04af..90ad11225d 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -534,14 +534,22 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ ltrim(valueToTrim?: string | Expression | Bytes): FunctionExpression; /* Excluded from this release type: _readUserData */ + mapEntries(): FunctionExpression; + /* Excluded from this release type: _readUserData */ mapGet(subfield: string): FunctionExpression; /* Excluded from this release type: _readUserData */ + mapKeys(): FunctionExpression; + /* Excluded from this release type: _readUserData */ mapMerge(secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; /* Excluded from this release type: _readUserData */ mapRemove(key: string): FunctionExpression; /* Excluded from this release type: _readUserData */ mapRemove(keyExpr: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ + mapSet(key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; + /* Excluded from this release type: _readUserData */ + mapValues(): FunctionExpression; + /* Excluded from this release type: _readUserData */ maximum(): AggregateFunction; /* Excluded from this release type: _readUserData */ minimum(): AggregateFunction; @@ -891,12 +899,24 @@ export function ltrim(expression: Expression, valueToTrim?: string | Expression // @beta export function map(elements: Record): FunctionExpression; +// @beta +export function mapEntries(mapField: string): FunctionExpression; + +// @beta +export function mapEntries(mapExpression: Expression): FunctionExpression; + // @beta export function mapGet(fieldName: string, subField: string): FunctionExpression; // @beta export function mapGet(mapExpression: Expression, subField: string): FunctionExpression; +// @beta +export function mapKeys(mapField: string): FunctionExpression; + +// @beta +export function mapKeys(mapExpression: Expression): FunctionExpression; + // @beta export function mapMerge(mapField: string, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; @@ -915,6 +935,18 @@ export function mapRemove(mapField: string, keyExpr: Expression): FunctionExpres // @beta export function mapRemove(mapExpr: Expression, keyExpr: Expression): FunctionExpression; +// @beta +export function mapSet(mapField: string, key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; + +// @beta +export function mapSet(mapExpression: Expression, key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; + +// @beta +export function mapValues(mapField: string): FunctionExpression; + +// @beta +export function mapValues(mapExpression: Expression): FunctionExpression; + // @beta export function maximum(expression: Expression): AggregateFunction; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index a3ade5bd39..df058daa1d 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -537,14 +537,22 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ ltrim(valueToTrim?: string | Expression | Bytes): FunctionExpression; /* Excluded from this release type: _readUserData */ + mapEntries(): FunctionExpression; + /* Excluded from this release type: _readUserData */ mapGet(subfield: string): FunctionExpression; /* Excluded from this release type: _readUserData */ + mapKeys(): FunctionExpression; + /* Excluded from this release type: _readUserData */ mapMerge(secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; /* Excluded from this release type: _readUserData */ mapRemove(key: string): FunctionExpression; /* Excluded from this release type: _readUserData */ mapRemove(keyExpr: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ + mapSet(key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; + /* Excluded from this release type: _readUserData */ + mapValues(): FunctionExpression; + /* Excluded from this release type: _readUserData */ maximum(): AggregateFunction; /* Excluded from this release type: _readUserData */ minimum(): AggregateFunction; @@ -894,12 +902,24 @@ export function ltrim(expression: Expression, valueToTrim?: string | Expression // @beta export function map(elements: Record): FunctionExpression; +// @beta +export function mapEntries(mapField: string): FunctionExpression; + +// @beta +export function mapEntries(mapExpression: Expression): FunctionExpression; + // @beta export function mapGet(fieldName: string, subField: string): FunctionExpression; // @beta export function mapGet(mapExpression: Expression, subField: string): FunctionExpression; +// @beta +export function mapKeys(mapField: string): FunctionExpression; + +// @beta +export function mapKeys(mapExpression: Expression): FunctionExpression; + // @beta export function mapMerge(mapField: string, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; @@ -918,6 +938,18 @@ export function mapRemove(mapField: string, keyExpr: Expression): FunctionExpres // @beta export function mapRemove(mapExpr: Expression, keyExpr: Expression): FunctionExpression; +// @beta +export function mapSet(mapField: string, key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; + +// @beta +export function mapSet(mapExpression: Expression, key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; + +// @beta +export function mapValues(mapField: string): FunctionExpression; + +// @beta +export function mapValues(mapExpression: Expression): FunctionExpression; + // @beta export function maximum(expression: Expression): AggregateFunction; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index 4f61999d42..d742954fed 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -117,10 +117,14 @@ field("optional_field").ifAbsent(field('default_field')) | [logicalMaximum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalmaximum) | | (Public Preview) Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. | | [logicalMinimum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalminimum) | | (Public Preview) Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. | | [ltrim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressionltrim) | | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | +| [mapEntries()](./firestore_lite_pipelines.expression.md#expressionmapentries) | | (Public Preview) 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" }, ...]. | | [mapGet(subfield)](./firestore_lite_pipelines.expression.md#expressionmapget) | | (Public Preview) Accesses a value from a map (object) field using the provided key. | +| [mapKeys()](./firestore_lite_pipelines.expression.md#expressionmapkeys) | | (Public Preview) Creates an expression that returns the keys of a map. | | [mapMerge(secondMap, otherMaps)](./firestore_lite_pipelines.expression.md#expressionmapmerge) | | (Public Preview) Creates an expression that merges multiple map values. | | [mapRemove(key)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | | [mapRemove(keyExpr)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | +| [mapSet(key, value, moreKeyValues)](./firestore_lite_pipelines.expression.md#expressionmapset) | | (Public Preview) Creates an expression that returns a new map with the specified entries added or updated. | +| [mapValues()](./firestore_lite_pipelines.expression.md#expressionmapvalues) | | (Public Preview) Creates an expression that returns the values of a map. | | [maximum()](./firestore_lite_pipelines.expression.md#expressionmaximum) | | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | | [minimum()](./firestore_lite_pipelines.expression.md#expressionminimum) | | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | | [mod(expression)](./firestore_lite_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. | @@ -2504,6 +2508,33 @@ field("userInput").ltrim('"'); ``` +## Expression.mapEntries() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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" }, ...]`. + +Signature: + +```typescript +mapEntries(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the entries of the map. + +### Example + + +```typescript +// Get the entries of the 'address' map +field("address").mapEntries(); + +``` + ## Expression.mapGet() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2538,6 +2569,35 @@ field("address").mapGet("city"); ``` +## Expression.mapKeys() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the keys of a map. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +mapKeys(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the keys of the map. + +### Example + + +```typescript +// Get the keys of the 'address' map +field("address").mapKeys(); + +``` + ## Expression.mapMerge() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2643,6 +2703,73 @@ map({foo: 'bar', baz: true}).mapRemove(constant('baz')); ``` +## Expression.mapSet() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a new map with the specified entries added or updated. + +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`. + +Signature: + +```typescript +mapSet(key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| key | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The key to set. Must be a string or a constant string expression. | +| value | unknown | The value to set. | +| moreKeyValues | unknown\[\] | Additional key-value pairs to set. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the map with the entries set. + +### Example + + +```typescript +// Set the 'city' to "San Francisco" in the 'address' map +field("address").mapSet("city", "San Francisco"); + +``` + +## Expression.mapValues() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the values of a map. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +mapValues(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the values of the map. + +### Example + + +```typescript +// Get the values of the 'address' map +field("address").mapValues(); + +``` + ## Expression.maximum() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index b2580e7010..489a7c9996 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -275,11 +275,19 @@ https://github.com/firebase/firebase-js-sdk | [mapRemove(mapExpr, key)](./firestore_lite_pipelines.md#mapremove_23c7d51) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. | | [mapRemove(mapExpr, keyExpr)](./firestore_lite_pipelines.md#mapremove_9fbcaa3) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. | | function(mapExpression, ...) | +| [mapEntries(mapExpression)](./firestore_lite_pipelines.md#mapentries_9cf124c) | (Public Preview) 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" }, ...]. | | [mapGet(mapExpression, subField)](./firestore_lite_pipelines.md#mapget_688c050) | (Public Preview) Accesses a value from a map (object) expression using the provided key. | +| [mapKeys(mapExpression)](./firestore_lite_pipelines.md#mapkeys_9cf124c) | (Public Preview) Creates an expression that returns the keys of a map. | +| [mapSet(mapExpression, key, value, moreKeyValues)](./firestore_lite_pipelines.md#mapset_45b48ff) | (Public Preview) Creates an expression that returns a new map with the specified entries added or updated. | +| [mapValues(mapExpression)](./firestore_lite_pipelines.md#mapvalues_9cf124c) | (Public Preview) Creates an expression that returns the values of a map. | | function(mapField, ...) | +| [mapEntries(mapField)](./firestore_lite_pipelines.md#mapentries_83ad836) | (Public Preview) 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" }, ...]. | +| [mapKeys(mapField)](./firestore_lite_pipelines.md#mapkeys_83ad836) | (Public Preview) Creates an expression that returns the keys of a map. | | [mapMerge(mapField, secondMap, otherMaps)](./firestore_lite_pipelines.md#mapmerge_70a564b) | (Public Preview) Creates an expression that merges multiple map values. | | [mapRemove(mapField, key)](./firestore_lite_pipelines.md#mapremove_bd5726e) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. | | [mapRemove(mapField, keyExpr)](./firestore_lite_pipelines.md#mapremove_8406d13) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. | +| [mapSet(mapField, key, value, moreKeyValues)](./firestore_lite_pipelines.md#mapset_baadc2a) | (Public Preview) Creates an expression that returns a new map with the specified entries added or updated. | +| [mapValues(mapField)](./firestore_lite_pipelines.md#mapvalues_83ad836) | (Public Preview) Creates an expression that returns the values of a map. | | function(name, ...) | | [field(name)](./firestore_lite_pipelines.md#field_1eaaff4) | (Public Preview) Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). | | function(path, ...) | @@ -8520,6 +8528,42 @@ mapRemove(map({foo: 'bar', baz: true}), constant('baz')); ## function(mapExpression, ...) +### mapEntries(mapExpression) {:#mapentries_9cf124c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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" }, ...]`. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +export declare function mapEntries(mapExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the map to get the entries of. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the entries of the map. + +### Example + + +```typescript +// Get the entries of the map expression +mapEntries(map({"city": "San Francisco"})); + +``` + ### mapGet(mapExpression, subField) {:#mapget_688c050} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -8555,8 +8599,191 @@ mapGet(field("address"), "city"); ``` +### mapKeys(mapExpression) {:#mapkeys_9cf124c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the keys of a map. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +export declare function mapKeys(mapExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the map to get the keys of. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the keys of the map. + +### Example + + +```typescript +// Get the keys of the map expression +mapKeys(map({"city": "San Francisco"})); + +``` + +### mapSet(mapExpression, key, value, moreKeyValues) {:#mapset_45b48ff} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a new map with the specified entries added or updated. + +This 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`. + +Signature: + +```typescript +export declare function mapSet(mapExpression: Expression, key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the map. | +| key | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The key to set. Must be a string or a constant string expression. | +| value | unknown | The value to set. | +| moreKeyValues | unknown\[\] | Additional key-value pairs to set. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the map with the entries set. + +### Example + + +```typescript +// Set the 'city' to "San Francisco" +mapSet(map({"state": "California"}), "city", "San Francisco"); + +``` + +### mapValues(mapExpression) {:#mapvalues_9cf124c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the values of a map. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +export declare function mapValues(mapExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the map to get the values of. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the values of the map. + +### Example + + +```typescript +// Get the values of the map expression +mapValues(map({"city": "San Francisco"})); + +``` + ## function(mapField, ...) +### mapEntries(mapField) {:#mapentries_83ad836} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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" }, ...]`. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +export declare function mapEntries(mapField: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | The map field to get the entries of. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the entries of the map. + +### Example + + +```typescript +// Get the entries of the 'address' map field +mapEntries("address"); + +``` + +### mapKeys(mapField) {:#mapkeys_83ad836} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the keys of a map. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +export declare function mapKeys(mapField: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | The map field to get the keys of. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the keys of the map. + +### Example + + +```typescript +// Get the keys of the 'address' map field +mapKeys("address"); + +``` + ### mapMerge(mapField, secondMap, otherMaps) {:#mapmerge_70a564b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -8658,6 +8885,81 @@ mapRemove('address', constant('city')); ``` +### mapSet(mapField, key, value, moreKeyValues) {:#mapset_baadc2a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a new map with the specified entries added or updated. + +This 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`. + +Signature: + +```typescript +export declare function mapSet(mapField: string, key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | The map field to set entries in. | +| key | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The key to set. Must be a string or a constant string expression. | +| value | unknown | The value to set. | +| moreKeyValues | unknown\[\] | Additional key-value pairs to set. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the map with the entries set. + +### Example + + +```typescript +// Set the 'city' to 'San Francisco' in the 'address' map field +mapSet("address", "city", "San Francisco"); + +``` + +### mapValues(mapField) {:#mapvalues_83ad836} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the values of a map. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +export declare function mapValues(mapField: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | The map field to get the values of. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the values of the map. + +### Example + + +```typescript +// Get the values of the 'address' map field +mapValues("address"); + +``` + ## function(name, ...) ### field(name) {:#field_1eaaff4} diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 76d7aea010..3ac53774cc 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -117,10 +117,14 @@ field("optional_field").ifAbsent(field('default_field')) | [logicalMaximum(second, others)](./firestore_pipelines.expression.md#expressionlogicalmaximum) | | (Public Preview) Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. | | [logicalMinimum(second, others)](./firestore_pipelines.expression.md#expressionlogicalminimum) | | (Public Preview) Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. | | [ltrim(valueToTrim)](./firestore_pipelines.expression.md#expressionltrim) | | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | +| [mapEntries()](./firestore_pipelines.expression.md#expressionmapentries) | | (Public Preview) 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" }, ...]. | | [mapGet(subfield)](./firestore_pipelines.expression.md#expressionmapget) | | (Public Preview) Accesses a value from a map (object) field using the provided key. | +| [mapKeys()](./firestore_pipelines.expression.md#expressionmapkeys) | | (Public Preview) Creates an expression that returns the keys of a map. | | [mapMerge(secondMap, otherMaps)](./firestore_pipelines.expression.md#expressionmapmerge) | | (Public Preview) Creates an expression that merges multiple map values. | | [mapRemove(key)](./firestore_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | | [mapRemove(keyExpr)](./firestore_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | +| [mapSet(key, value, moreKeyValues)](./firestore_pipelines.expression.md#expressionmapset) | | (Public Preview) Creates an expression that returns a new map with the specified entries added or updated. | +| [mapValues()](./firestore_pipelines.expression.md#expressionmapvalues) | | (Public Preview) Creates an expression that returns the values of a map. | | [maximum()](./firestore_pipelines.expression.md#expressionmaximum) | | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | | [minimum()](./firestore_pipelines.expression.md#expressionminimum) | | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | | [mod(expression)](./firestore_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. | @@ -2504,6 +2508,33 @@ field("userInput").ltrim('"'); ``` +## Expression.mapEntries() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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" }, ...]`. + +Signature: + +```typescript +mapEntries(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the entries of the map. + +### Example + + +```typescript +// Get the entries of the 'address' map +field("address").mapEntries(); + +``` + ## Expression.mapGet() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2538,6 +2569,35 @@ field("address").mapGet("city"); ``` +## Expression.mapKeys() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the keys of a map. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +mapKeys(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the keys of the map. + +### Example + + +```typescript +// Get the keys of the 'address' map +field("address").mapKeys(); + +``` + ## Expression.mapMerge() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2643,6 +2703,73 @@ map({foo: 'bar', baz: true}).mapRemove(constant('baz')); ``` +## Expression.mapSet() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a new map with the specified entries added or updated. + +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`. + +Signature: + +```typescript +mapSet(key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| key | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The key to set. Must be a string or a constant string expression. | +| value | unknown | The value to set. | +| moreKeyValues | unknown\[\] | Additional key-value pairs to set. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the map with the entries set. + +### Example + + +```typescript +// Set the 'city' to "San Francisco" in the 'address' map +field("address").mapSet("city", "San Francisco"); + +``` + +## Expression.mapValues() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the values of a map. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +mapValues(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the values of the map. + +### Example + + +```typescript +// Get the values of the 'address' map +field("address").mapValues(); + +``` + ## Expression.maximum() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 4e92232c31..d6aea3a138 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -276,11 +276,19 @@ https://github.com/firebase/firebase-js-sdk | [mapRemove(mapExpr, key)](./firestore_pipelines.md#mapremove_23c7d51) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. | | [mapRemove(mapExpr, keyExpr)](./firestore_pipelines.md#mapremove_9fbcaa3) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. | | function(mapExpression, ...) | +| [mapEntries(mapExpression)](./firestore_pipelines.md#mapentries_9cf124c) | (Public Preview) 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" }, ...]. | | [mapGet(mapExpression, subField)](./firestore_pipelines.md#mapget_688c050) | (Public Preview) Accesses a value from a map (object) expression using the provided key. | +| [mapKeys(mapExpression)](./firestore_pipelines.md#mapkeys_9cf124c) | (Public Preview) Creates an expression that returns the keys of a map. | +| [mapSet(mapExpression, key, value, moreKeyValues)](./firestore_pipelines.md#mapset_45b48ff) | (Public Preview) Creates an expression that returns a new map with the specified entries added or updated. | +| [mapValues(mapExpression)](./firestore_pipelines.md#mapvalues_9cf124c) | (Public Preview) Creates an expression that returns the values of a map. | | function(mapField, ...) | +| [mapEntries(mapField)](./firestore_pipelines.md#mapentries_83ad836) | (Public Preview) 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" }, ...]. | +| [mapKeys(mapField)](./firestore_pipelines.md#mapkeys_83ad836) | (Public Preview) Creates an expression that returns the keys of a map. | | [mapMerge(mapField, secondMap, otherMaps)](./firestore_pipelines.md#mapmerge_70a564b) | (Public Preview) Creates an expression that merges multiple map values. | | [mapRemove(mapField, key)](./firestore_pipelines.md#mapremove_bd5726e) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. | | [mapRemove(mapField, keyExpr)](./firestore_pipelines.md#mapremove_8406d13) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. | +| [mapSet(mapField, key, value, moreKeyValues)](./firestore_pipelines.md#mapset_baadc2a) | (Public Preview) Creates an expression that returns a new map with the specified entries added or updated. | +| [mapValues(mapField)](./firestore_pipelines.md#mapvalues_83ad836) | (Public Preview) Creates an expression that returns the values of a map. | | function(name, ...) | | [field(name)](./firestore_pipelines.md#field_1eaaff4) | (Public Preview) Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). | | function(options, ...) | @@ -8550,6 +8558,42 @@ mapRemove(map({foo: 'bar', baz: true}), constant('baz')); ## function(mapExpression, ...) +### mapEntries(mapExpression) {:#mapentries_9cf124c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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" }, ...]`. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +export declare function mapEntries(mapExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the map to get the entries of. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the entries of the map. + +### Example + + +```typescript +// Get the entries of the map expression +mapEntries(map({"city": "San Francisco"})); + +``` + ### mapGet(mapExpression, subField) {:#mapget_688c050} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -8585,8 +8629,191 @@ mapGet(field("address"), "city"); ``` +### mapKeys(mapExpression) {:#mapkeys_9cf124c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the keys of a map. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +export declare function mapKeys(mapExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the map to get the keys of. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the keys of the map. + +### Example + + +```typescript +// Get the keys of the map expression +mapKeys(map({"city": "San Francisco"})); + +``` + +### mapSet(mapExpression, key, value, moreKeyValues) {:#mapset_45b48ff} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a new map with the specified entries added or updated. + +This 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`. + +Signature: + +```typescript +export declare function mapSet(mapExpression: Expression, key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the map. | +| key | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The key to set. Must be a string or a constant string expression. | +| value | unknown | The value to set. | +| moreKeyValues | unknown\[\] | Additional key-value pairs to set. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the map with the entries set. + +### Example + + +```typescript +// Set the 'city' to "San Francisco" +mapSet(map({"state": "California"}), "city", "San Francisco"); + +``` + +### mapValues(mapExpression) {:#mapvalues_9cf124c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the values of a map. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +export declare function mapValues(mapExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the map to get the values of. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the values of the map. + +### Example + + +```typescript +// Get the values of the map expression +mapValues(map({"city": "San Francisco"})); + +``` + ## function(mapField, ...) +### mapEntries(mapField) {:#mapentries_83ad836} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +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" }, ...]`. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +export declare function mapEntries(mapField: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | The map field to get the entries of. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the entries of the map. + +### Example + + +```typescript +// Get the entries of the 'address' map field +mapEntries("address"); + +``` + +### mapKeys(mapField) {:#mapkeys_83ad836} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the keys of a map. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +export declare function mapKeys(mapField: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | The map field to get the keys of. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the keys of the map. + +### Example + + +```typescript +// Get the keys of the 'address' map field +mapKeys("address"); + +``` + ### mapMerge(mapField, secondMap, otherMaps) {:#mapmerge_70a564b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -8688,6 +8915,81 @@ mapRemove('address', constant('city')); ``` +### mapSet(mapField, key, value, moreKeyValues) {:#mapset_baadc2a} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns a new map with the specified entries added or updated. + +This 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`. + +Signature: + +```typescript +export declare function mapSet(mapField: string, key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | The map field to set entries in. | +| key | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The key to set. Must be a string or a constant string expression. | +| value | unknown | The value to set. | +| moreKeyValues | unknown\[\] | Additional key-value pairs to set. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the map with the entries set. + +### Example + + +```typescript +// Set the 'city' to 'San Francisco' in the 'address' map field +mapSet("address", "city", "San Francisco"); + +``` + +### mapValues(mapField) {:#mapvalues_83ad836} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the values of a map. + +While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. + +Signature: + +```typescript +export declare function mapValues(mapField: string): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mapField | string | The map field to get the values of. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the values of the map. + +### Example + + +```typescript +// Get the values of the 'address' map field +mapValues("address"); + +``` + ## function(name, ...) ### field(name) {:#field_1eaaff4} diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index 8682d2eb07..ba61665ce7 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -149,6 +149,10 @@ export { stringReplaceAll, stringReplaceOne, mapGet, + mapSet, + mapKeys, + mapValues, + mapEntries, countAll, minimum, maximum, diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index c19e9c859c..5a6f8d7c7d 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -104,6 +104,10 @@ export { stringReplaceAll, stringReplaceOne, mapGet, + mapSet, + mapKeys, + mapValues, + mapEntries, countAll, count, sum, diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index c5718b3dc4..bbc15f133f 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -1605,6 +1605,97 @@ export abstract class Expression implements ProtoValueSerializable, UserData { ); } + /** + * @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: string | Expression, + value: unknown, + ...moreKeyValues: unknown[] + ): FunctionExpression { + const args = [ + this, + valueToDefaultExpr(key), + valueToDefaultExpr(value), + ...moreKeyValues.map(valueToDefaultExpr) + ]; + 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(): FunctionExpression { + 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(): FunctionExpression { + 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(): FunctionExpression { + return new FunctionExpression('map_entries', [this], 'mapEntries'); + } + /** * @beta * Creates an aggregation that counts the number of stage inputs with valid evaluations of the @@ -7480,6 +7571,199 @@ export function mapGet( return fieldOrExpression(fieldOrExpr).mapGet(subField); } +/** + * @beta + * Creates an expression that returns a new map with the specified entries added or updated. + * + * @remarks + * This 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 + * mapSet("address", "city", "San Francisco"); + * ``` + * + * @param mapField - The map field to set entries in. + * @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. + */ +export function mapSet( + mapField: string, + key: string | Expression, + value: unknown, + ...moreKeyValues: unknown[] +): FunctionExpression; + +/** + * @beta + * Creates an expression that returns a new map with the specified entries added or updated. + * + * @remarks + * This 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" + * mapSet(map({"state": "California"}), "city", "San Francisco"); + * ``` + * + * @param mapExpression - The expression representing the map. + * @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. + */ +export function mapSet( + mapExpression: Expression, + key: string | Expression, + value: unknown, + ...moreKeyValues: unknown[] +): FunctionExpression; +export function mapSet( + fieldOrExpr: string | Expression, + key: string | Expression, + value: unknown, + ...moreKeyValues: unknown[] +): FunctionExpression { + return fieldOrExpression(fieldOrExpr).mapSet(key, value, ...moreKeyValues); +} + +/** + * @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 + * mapKeys("address"); + * ``` + * + * @param mapField - The map field to get the keys of. + * @returns A new `Expression` representing the keys of the map. + */ +export function mapKeys(mapField: string): FunctionExpression; + +/** + * @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 map expression + * mapKeys(map({"city": "San Francisco"})); + * ``` + * + * @param mapExpression - The expression representing the map to get the keys of. + * @returns A new `Expression` representing the keys of the map. + */ +export function mapKeys(mapExpression: Expression): FunctionExpression; +export function mapKeys(fieldOrExpr: string | Expression): FunctionExpression { + return fieldOrExpression(fieldOrExpr).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 + * mapValues("address"); + * ``` + * + * @param mapField - The map field to get the values of. + * @returns A new `Expression` representing the values of the map. + */ +export function mapValues(mapField: string): FunctionExpression; + +/** + * @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 map expression + * mapValues(map({"city": "San Francisco"})); + * ``` + * + * @param mapExpression - The expression representing the map to get the values of. + * @returns A new `Expression` representing the values of the map. + */ +export function mapValues(mapExpression: Expression): FunctionExpression; +export function mapValues( + fieldOrExpr: string | Expression +): FunctionExpression { + return fieldOrExpression(fieldOrExpr).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" }, ...]`. + * + * @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 entries of the 'address' map field + * mapEntries("address"); + * ``` + * + * @param mapField - The map field to get the entries of. + * @returns A new `Expression` representing the entries of the map. + */ +export function mapEntries(mapField: string): FunctionExpression; + +/** + * @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" }, ...]`. + * + * @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 entries of the map expression + * mapEntries(map({"city": "San Francisco"})); + * ``` + * + * @param mapExpression - The expression representing the map to get the entries of. + * @returns A new `Expression` representing the entries of the map. + */ +export function mapEntries(mapExpression: Expression): FunctionExpression; +export function mapEntries( + fieldOrExpr: string | Expression +): FunctionExpression { + return fieldOrExpression(fieldOrExpr).mapEntries(); +} + /** * @beta * diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 5ce4607408..dd56faac17 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -75,6 +75,10 @@ import { lessThanOrEqual, arrayLength, mapGet, + mapSet, + mapKeys, + mapValues, + mapEntries, notEqual, or, regexContains, @@ -2902,6 +2906,116 @@ apiDescribe.skipClassic('Pipelines', persistence => { }); }); + it('test mapSet', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ existingField: map({ foo: 1 }) })) + .addFields( + mapSet('existingField', 'bar', 2).as('modifiedField'), + mapSet(map({}), 'a', 1).as('simple'), + mapSet(map({ a: 1 }), 'b', 2).as('add'), + mapSet(map({ a: 1 }), 'a', 2).as('overwrite'), + mapSet(map({ a: 1, b: 2 }), 'a', 3, 'c', 4).as('multi'), + mapSet(map({ a: 1 }), 'a', field('non_existent')).as('remove'), + mapSet(map({ a: 1 }), 'b', null).as('setNull'), + mapSet(map({ a: { b: 1 } }), 'a.b', 2).as('setDotted'), + mapSet(map({}), '', 'empty').as('setEmptyKey'), + mapSet(map({ a: 1 }), 'b', add(constant(1), constant(2))).as( + 'setExprVal' + ), + mapSet(map({}), 'obj', map({ hidden: true })).as('setNestedMap'), + mapSet(map({}), '~!@#$%^&*()_+', 'special').as('setSpecialChars') + ) + ); + expectResults(snapshot, { + existingField: { foo: 1 }, + modifiedField: { foo: 1, bar: 2 }, + simple: { a: 1 }, + add: { a: 1, b: 2 }, + overwrite: { a: 2 }, + multi: { a: 3, b: 2, c: 4 }, + remove: {}, + setNull: { a: 1, b: null }, + setDotted: { a: { b: 1 }, 'a.b': 2 }, + setEmptyKey: { '': 'empty' }, + setExprVal: { a: 1, b: 3 }, + setNestedMap: { obj: { hidden: true } }, + setSpecialChars: { '~!@#$%^&*()_+': 'special' } + }); + }); + + it('test mapKeys', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ existingField: map({ foo: 1 }) })) + .addFields( + mapKeys('existingField').as('existingKeys'), + mapKeys(map({ a: 1, b: 2 })).as('keys'), + mapKeys(map({})).as('empty_keys'), + mapKeys(map({ a: { nested: true } })).as('nested_keys') + ) + ); + + const res = snapshot.results[0].data(); + expect(res.existingKeys).to.have.members(['foo']); + expect(res.keys).to.have.members(['a', 'b']); + expect(res.empty_keys).to.deep.equal([]); + expect(res.nested_keys).to.have.members(['a']); + }); + + it('test mapValues', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ existingField: map({ foo: 1 }) })) + .addFields( + mapValues('existingField').as('existingValues'), + mapValues(map({ a: 1, b: 2 })).as('values'), + mapValues(map({})).as('empty_values'), + mapValues(map({ a: { nested: true } })).as('nested_values') + ) + ); + const res = snapshot.results[0].data(); + expect(res.existingValues).to.have.members([1]); + expect(res.values).to.have.members([1, 2]); + expect(res.empty_values).to.deep.equal([]); + expect(res.nested_values).to.deep.include.members([{ nested: true }]); + }); + + it('test mapEntries', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ existingField: map({ foo: 1 }) })) + .addFields( + mapEntries('existingField').as('existingEntries'), + mapEntries(map({ a: 1, b: 2 })).as('entries'), + mapEntries(map({})).as('empty_entries'), + mapEntries(map({ a: { nested: true } })).as('nested_entries') + ) + ); + const res = snapshot.results[0].data(); + expect(res.existingEntries).to.deep.include.members([{ k: 'foo', v: 1 }]); + expect(res.entries).to.deep.include.members([ + { k: 'a', v: 1 }, + { k: 'b', v: 2 } + ]); + expect(res.empty_entries).to.deep.equal([]); + expect(res.nested_entries).to.deep.include.members([ + { k: 'a', v: { nested: true } } + ]); + }); + describe('rawFunction', () => { it('add selectable', async () => { const snapshot = await execute( diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 01a02cb593..b5836b2b32 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -98,6 +98,10 @@ import { startsWith, endsWith, mapGet, + mapSet, + mapKeys, + mapValues, + mapEntries, countAll, minimum, maximum, @@ -2874,6 +2878,116 @@ describe.skipClassic('Firestore Pipelines', () => { }); }); + it('test mapSet', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ existingField: map({ foo: 1 }) })) + .addFields( + mapSet('existingField', 'bar', 2).as('modifiedField'), + mapSet(map({}), 'a', 1).as('simple'), + mapSet(map({ a: 1 }), 'b', 2).as('add'), + mapSet(map({ a: 1 }), 'a', 2).as('overwrite'), + mapSet(map({ a: 1, b: 2 }), 'a', 3, 'c', 4).as('multi'), + mapSet(map({ a: 1 }), 'a', field('non_existent')).as('remove'), + mapSet(map({ a: 1 }), 'b', null).as('setNull'), + mapSet(map({ a: { b: 1 } }), 'a.b', 2).as('setDotted'), + mapSet(map({}), '', 'empty').as('setEmptyKey'), + mapSet(map({ a: 1 }), 'b', add(constant(1), constant(2))).as( + 'setExprVal' + ), + mapSet(map({}), 'obj', map({ hidden: true })).as('setNestedMap'), + mapSet(map({}), '~!@#$%^&*()_+', 'special').as('setSpecialChars') + ) + ); + expectResults(snapshot, { + existingField: { foo: 1 }, + modifiedField: { foo: 1, bar: 2 }, + simple: { a: 1 }, + add: { a: 1, b: 2 }, + overwrite: { a: 2 }, + multi: { a: 3, b: 2, c: 4 }, + remove: {}, + setNull: { a: 1, b: null }, + setDotted: { a: { b: 1 }, 'a.b': 2 }, + setEmptyKey: { '': 'empty' }, + setExprVal: { a: 1, b: 3 }, + setNestedMap: { obj: { hidden: true } }, + setSpecialChars: { '~!@#$%^&*()_+': 'special' } + }); + }); + + it('test mapKeys', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ existingField: map({ foo: 1 }) })) + .addFields( + mapKeys('existingField').as('existingKeys'), + mapKeys(map({ a: 1, b: 2 })).as('keys'), + mapKeys(map({})).as('empty_keys'), + mapKeys(map({ a: { nested: true } })).as('nested_keys') + ) + ); + + const res = snapshot.results[0].data(); + expect(res.existingKeys).to.have.members(['foo']); + expect(res.keys).to.have.members(['a', 'b']); + expect(res.empty_keys).to.deep.equal([]); + expect(res.nested_keys).to.have.members(['a']); + }); + + it('test mapValues', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ existingField: map({ foo: 1 }) })) + .addFields( + mapValues('existingField').as('existingValues'), + mapValues(map({ a: 1, b: 2 })).as('values'), + mapValues(map({})).as('empty_values'), + mapValues(map({ a: { nested: true } })).as('nested_values') + ) + ); + const res = snapshot.results[0].data(); + expect(res.existingValues).to.have.members([1]); + expect(res.values).to.have.members([1, 2]); + expect(res.empty_values).to.deep.equal([]); + expect(res.nested_values).to.deep.include.members([{ nested: true }]); + }); + + it('test mapEntries', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ existingField: map({ foo: 1 }) })) + .addFields( + mapEntries('existingField').as('existingEntries'), + mapEntries(map({ a: 1, b: 2 })).as('entries'), + mapEntries(map({})).as('empty_entries'), + mapEntries(map({ a: { nested: true } })).as('nested_entries') + ) + ); + const res = snapshot.results[0].data(); + expect(res.existingEntries).to.deep.include.members([{ k: 'foo', v: 1 }]); + expect(res.entries).to.deep.include.members([ + { k: 'a', v: 1 }, + { k: 'b', v: 2 } + ]); + expect(res.empty_entries).to.deep.equal([]); + expect(res.nested_entries).to.deep.include.members([ + { k: 'a', v: { nested: true } } + ]); + }); + describe('rawFunction', () => { it('add selectable', async () => { const snapshot = await execute( From 5ab918f2b6af987129fb3e38d7d73e3487a73d58 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 25 Feb 2026 08:53:28 -0800 Subject: [PATCH 075/174] docs(firestore): Fix formatting error (#9594) --- .../firestore_lite_pipelines.expression.md | 30 ++++++++----------- .../firestore_pipelines.expression.md | 30 ++++++++----------- .../firestore/src/lite-api/expressions.ts | 5 ++-- 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index d742954fed..1f7be7857e 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -88,15 +88,8 @@ export declare abstract class Expression | [greaterThan(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than a constant value. | | [greaterThanOrEqual(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to another expression. | | [greaterThanOrEqual(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to a constant value. | -| [ifAbsent(elseValue)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of the this expression evaluation. | -| [ifAbsent(elseExpression)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or if that is -// absent, then returns the value of the field ` -field("optional_field").ifAbsent(field('default_field')) - -``` - | +| [ifAbsent(elseValue)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | +| [ifAbsent(elseExpression)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | | [ifError(catchExpr)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. | | [ifError(catchValue)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | | [isAbsent()](./firestore_lite_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. | @@ -1795,7 +1788,7 @@ field("score").greaterThanOrEqual(80); > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of the this expression evaluation. +Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of this expression evaluation. Signature: @@ -1832,13 +1825,6 @@ field("optional_field").ifAbsent("default_value") Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of this expression evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or if that is -// absent, then returns the value of the field ` -field("optional_field").ifAbsent(field('default_field')) - -``` - Signature: ```typescript @@ -1857,6 +1843,16 @@ ifAbsent(elseExpression: unknown): Expression; A new \[Expression\] representing the ifAbsent operation. +### Example + + +```typescript +// Returns the value of the optional field 'optional_field', or if that is +// absent, then returns the value of the field `default_field`. +field("optional_field").ifAbsent(field('default_field')) + +``` + ## Expression.ifError() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 3ac53774cc..9bd69b7d68 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -88,15 +88,8 @@ export declare abstract class Expression | [greaterThan(value)](./firestore_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than a constant value. | | [greaterThanOrEqual(expression)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to another expression. | | [greaterThanOrEqual(value)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to a constant value. | -| [ifAbsent(elseValue)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of the this expression evaluation. | -| [ifAbsent(elseExpression)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or if that is -// absent, then returns the value of the field ` -field("optional_field").ifAbsent(field('default_field')) - -``` - | +| [ifAbsent(elseValue)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | +| [ifAbsent(elseExpression)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | | [ifError(catchExpr)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. | | [ifError(catchValue)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | | [isAbsent()](./firestore_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. | @@ -1795,7 +1788,7 @@ field("score").greaterThanOrEqual(80); > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of the this expression evaluation. +Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of this expression evaluation. Signature: @@ -1832,13 +1825,6 @@ field("optional_field").ifAbsent("default_value") Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of this expression evaluation. -```typescript -// Returns the value of the optional field 'optional_field', or if that is -// absent, then returns the value of the field ` -field("optional_field").ifAbsent(field('default_field')) - -``` - Signature: ```typescript @@ -1857,6 +1843,16 @@ ifAbsent(elseExpression: unknown): Expression; A new \[Expression\] representing the ifAbsent operation. +### Example + + +```typescript +// Returns the value of the optional field 'optional_field', or if that is +// absent, then returns the value of the field `default_field`. +field("optional_field").ifAbsent(field('default_field')) + +``` + ## Expression.ifError() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index bbc15f133f..b52b39c226 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -2766,7 +2766,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { /** * @beta * Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else - * return the result of the this expression evaluation. + * return the result of this expression evaluation. * * @example * ```typescript @@ -2785,9 +2785,10 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else * return the result of this expression evaluation. * + * @example * ```typescript * // Returns the value of the optional field 'optional_field', or if that is - * // absent, then returns the value of the field ` + * // absent, then returns the value of the field `default_field`. * field("optional_field").ifAbsent(field('default_field')) * ``` * From 291851cd07702ee8638315ea10a44e41e85c0ba6 Mon Sep 17 00:00:00 2001 From: Google Open Source Bot Date: Fri, 27 Feb 2026 07:45:00 -0800 Subject: [PATCH 076/174] Version Packages (#9591) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/afraid-pigs-heal.md | 6 --- .changeset/cool-bulldogs-impress.md | 6 --- .changeset/eighty-ghosts-pull.md | 6 --- .changeset/fast-cherries-fold.md | 7 --- .changeset/few-dodos-ring.md | 6 --- .changeset/orange-bags-jog.md | 6 --- .changeset/tiny-jokes-compete.md | 6 --- integration/compat-interop/package.json | 28 +++++------ integration/firestore/package.json | 4 +- integration/messaging/package.json | 2 +- packages/ai/CHANGELOG.md | 12 +++++ packages/ai/package.json | 8 ++-- packages/analytics-compat/CHANGELOG.md | 9 ++++ packages/analytics-compat/package.json | 10 ++-- packages/analytics/CHANGELOG.md | 9 ++++ packages/analytics/package.json | 10 ++-- packages/app-check-compat/CHANGELOG.md | 9 ++++ packages/app-check-compat/package.json | 10 ++-- packages/app-check/CHANGELOG.md | 8 ++++ packages/app-check/package.json | 8 ++-- packages/app-compat/CHANGELOG.md | 9 ++++ packages/app-compat/package.json | 8 ++-- packages/app/CHANGELOG.md | 10 ++++ packages/app/package.json | 6 +-- packages/auth-compat/CHANGELOG.md | 9 ++++ packages/auth-compat/package.json | 10 ++-- packages/auth/CHANGELOG.md | 8 ++++ packages/auth/package.json | 8 ++-- packages/component/CHANGELOG.md | 7 +++ packages/component/package.json | 4 +- packages/data-connect/CHANGELOG.md | 12 +++++ packages/data-connect/package.json | 8 ++-- packages/database-compat/CHANGELOG.md | 10 ++++ packages/database-compat/package.json | 12 ++--- packages/database-types/CHANGELOG.md | 7 +++ packages/database-types/package.json | 4 +- packages/database/CHANGELOG.md | 8 ++++ packages/database/package.json | 8 ++-- packages/firebase/CHANGELOG.md | 49 +++++++++++++++++++ packages/firebase/package.json | 56 +++++++++++----------- packages/firestore-compat/CHANGELOG.md | 9 ++++ packages/firestore-compat/package.json | 10 ++-- packages/firestore/CHANGELOG.md | 20 ++++++++ packages/firestore/package.json | 12 ++--- packages/functions-compat/CHANGELOG.md | 9 ++++ packages/functions-compat/package.json | 10 ++-- packages/functions/CHANGELOG.md | 8 ++++ packages/functions/package.json | 8 ++-- packages/installations-compat/CHANGELOG.md | 9 ++++ packages/installations-compat/package.json | 10 ++-- packages/installations/CHANGELOG.md | 8 ++++ packages/installations/package.json | 8 ++-- packages/messaging-compat/CHANGELOG.md | 9 ++++ packages/messaging-compat/package.json | 10 ++-- packages/messaging/CHANGELOG.md | 9 ++++ packages/messaging/package.json | 10 ++-- packages/performance-compat/CHANGELOG.md | 9 ++++ packages/performance-compat/package.json | 10 ++-- packages/performance/CHANGELOG.md | 9 ++++ packages/performance/package.json | 10 ++-- packages/remote-config-compat/CHANGELOG.md | 9 ++++ packages/remote-config-compat/package.json | 10 ++-- packages/remote-config/CHANGELOG.md | 9 ++++ packages/remote-config/package.json | 10 ++-- packages/storage-compat/CHANGELOG.md | 9 ++++ packages/storage-compat/package.json | 12 ++--- packages/storage/CHANGELOG.md | 8 ++++ packages/storage/package.json | 10 ++-- packages/template/package.json | 2 +- packages/util/CHANGELOG.md | 6 +++ packages/util/package.json | 2 +- repo-scripts/size-analysis/package.json | 4 +- 72 files changed, 492 insertions(+), 219 deletions(-) delete mode 100644 .changeset/afraid-pigs-heal.md delete mode 100644 .changeset/cool-bulldogs-impress.md delete mode 100644 .changeset/eighty-ghosts-pull.md delete mode 100644 .changeset/fast-cherries-fold.md delete mode 100644 .changeset/few-dodos-ring.md delete mode 100644 .changeset/orange-bags-jog.md delete mode 100644 .changeset/tiny-jokes-compete.md diff --git a/.changeset/afraid-pigs-heal.md b/.changeset/afraid-pigs-heal.md deleted file mode 100644 index 5f4a4cd5a2..0000000000 --- a/.changeset/afraid-pigs-heal.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/firestore': minor ---- - -Support added for `mapSet`, `mapValues`, `mapEntries`, `mapKeys` Pipelines expressions. diff --git a/.changeset/cool-bulldogs-impress.md b/.changeset/cool-bulldogs-impress.md deleted file mode 100644 index f75fe44e9e..0000000000 --- a/.changeset/cool-bulldogs-impress.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -Added automatic function calling capability when using `ChatSession`. diff --git a/.changeset/eighty-ghosts-pull.md b/.changeset/eighty-ghosts-pull.md deleted file mode 100644 index e7425c2f0d..0000000000 --- a/.changeset/eighty-ghosts-pull.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/firestore': minor ---- - -Support added for the following string Pipeline expressions: `stringRepeat`, `stringReplaceOne`, `stringReplaceAll`, `stringIndexOf`, `ltrim`, `rtrim`. diff --git a/.changeset/fast-cherries-fold.md b/.changeset/fast-cherries-fold.md deleted file mode 100644 index 08d360dbf0..0000000000 --- a/.changeset/fast-cherries-fold.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@firebase/data-connect": minor -"@firebase/util": minor -"firebase": minor ---- - -Add Memory-Based caching to Queries in Firebase Data Connect. diff --git a/.changeset/few-dodos-ring.md b/.changeset/few-dodos-ring.md deleted file mode 100644 index f4182c1f4d..0000000000 --- a/.changeset/few-dodos-ring.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/firestore': minor ---- - -Add support for first, last, array_agg and array_agg_distinct expressions diff --git a/.changeset/orange-bags-jog.md b/.changeset/orange-bags-jog.md deleted file mode 100644 index 812cae7aae..0000000000 --- a/.changeset/orange-bags-jog.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/firestore': minor ---- - -Add support for rand and trunc pipeline expressions diff --git a/.changeset/tiny-jokes-compete.md b/.changeset/tiny-jokes-compete.md deleted file mode 100644 index 65f96cfe06..0000000000 --- a/.changeset/tiny-jokes-compete.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/firestore': minor ---- - -feat(firestore): Support added for the `isType` Pipeline expression. diff --git a/integration/compat-interop/package.json b/integration/compat-interop/package.json index ec184dc36b..0a82152099 100644 --- a/integration/compat-interop/package.json +++ b/integration/compat-interop/package.json @@ -8,20 +8,20 @@ "test:debug": "karma start --browsers Chrome --auto-watch" }, "dependencies": { - "@firebase/app": "0.14.8", - "@firebase/app-compat": "0.5.8", - "@firebase/analytics": "0.10.19", - "@firebase/analytics-compat": "0.2.25", - "@firebase/auth": "1.12.0", - "@firebase/auth-compat": "0.6.2", - "@firebase/functions": "0.13.1", - "@firebase/functions-compat": "0.4.1", - "@firebase/messaging": "0.12.23", - "@firebase/messaging-compat": "0.2.23", - "@firebase/performance": "0.7.9", - "@firebase/performance-compat": "0.2.22", - "@firebase/remote-config": "0.8.0", - "@firebase/remote-config-compat": "0.2.21" + "@firebase/app": "0.14.9", + "@firebase/app-compat": "0.5.9", + "@firebase/analytics": "0.10.20", + "@firebase/analytics-compat": "0.2.26", + "@firebase/auth": "1.12.1", + "@firebase/auth-compat": "0.6.3", + "@firebase/functions": "0.13.2", + "@firebase/functions-compat": "0.4.2", + "@firebase/messaging": "0.12.24", + "@firebase/messaging-compat": "0.2.24", + "@firebase/performance": "0.7.10", + "@firebase/performance-compat": "0.2.23", + "@firebase/remote-config": "0.8.1", + "@firebase/remote-config-compat": "0.2.22" }, "devDependencies": { "typescript": "5.5.4" diff --git a/integration/firestore/package.json b/integration/firestore/package.json index 12a872f550..2233e43af8 100644 --- a/integration/firestore/package.json +++ b/integration/firestore/package.json @@ -15,8 +15,8 @@ "test:memory:debug": "yarn build:memory; karma start --auto-watch --browsers Chrome" }, "dependencies": { - "@firebase/app": "0.14.8", - "@firebase/firestore": "4.11.0" + "@firebase/app": "0.14.9", + "@firebase/firestore": "4.12.0" }, "devDependencies": { "@types/mocha": "9.1.1", diff --git a/integration/messaging/package.json b/integration/messaging/package.json index 0ad87e6cff..c06e785902 100644 --- a/integration/messaging/package.json +++ b/integration/messaging/package.json @@ -9,7 +9,7 @@ "test:manual": "mocha --exit" }, "devDependencies": { - "firebase": "12.9.0", + "firebase": "12.10.0", "chai": "4.5.0", "chromedriver": "119.0.1", "express": "4.21.2", diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 6482ee77f9..08493eccd3 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/ai +## 2.9.0 + +### Minor Changes + +- [`47f8521`](https://github.com/firebase/firebase-js-sdk/commit/47f85219d570f05c196e0085f2892d1297308fed) [#9489](https://github.com/firebase/firebase-js-sdk/pull/9489) - Added automatic function calling capability when using `ChatSession`. + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/component@0.7.1 + ## 2.8.0 ### Minor Changes diff --git a/packages/ai/package.json b/packages/ai/package.json index 31be2be09b..a9534d657d 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/ai", - "version": "2.8.0", + "version": "2.9.0", "description": "The Firebase AI SDK", "author": "Firebase (https://firebase.google.com/)", "engines": { @@ -53,14 +53,14 @@ }, "dependencies": { "@firebase/app-check-interop-types": "0.3.3", - "@firebase/component": "0.7.0", + "@firebase/component": "0.7.1", "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/analytics-compat/CHANGELOG.md b/packages/analytics-compat/CHANGELOG.md index a175e1a29e..e2a573eef3 100644 --- a/packages/analytics-compat/CHANGELOG.md +++ b/packages/analytics-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/analytics-compat +## 0.2.26 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/analytics@0.10.20 + - @firebase/component@0.7.1 + ## 0.2.25 ### Patch Changes diff --git a/packages/analytics-compat/package.json b/packages/analytics-compat/package.json index e06390a870..114acb35d2 100644 --- a/packages/analytics-compat/package.json +++ b/packages/analytics-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/analytics-compat", - "version": "0.2.25", + "version": "0.2.26", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -22,7 +22,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.8", + "@firebase/app-compat": "0.5.9", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", @@ -52,10 +52,10 @@ }, "typings": "dist/src/index.d.ts", "dependencies": { - "@firebase/component": "0.7.0", - "@firebase/analytics": "0.10.19", + "@firebase/component": "0.7.1", + "@firebase/analytics": "0.10.20", "@firebase/analytics-types": "0.8.3", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/analytics/CHANGELOG.md b/packages/analytics/CHANGELOG.md index 1e82d5d173..789a88717e 100644 --- a/packages/analytics/CHANGELOG.md +++ b/packages/analytics/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/analytics +## 0.10.20 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/installations@0.6.20 + - @firebase/component@0.7.1 + ## 0.10.19 ### Patch Changes diff --git a/packages/analytics/package.json b/packages/analytics/package.json index c5edcf52d3..75350bf020 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/analytics", - "version": "0.10.19", + "version": "0.10.20", "description": "A analytics package for new firebase packages", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -39,15 +39,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.19", + "@firebase/installations": "0.6.20", "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", - "@firebase/component": "0.7.0", + "@firebase/util": "1.14.0", + "@firebase/component": "0.7.1", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "@rollup/plugin-commonjs": "21.1.0", diff --git a/packages/app-check-compat/CHANGELOG.md b/packages/app-check-compat/CHANGELOG.md index 8d8cca1a8d..a081ae457c 100644 --- a/packages/app-check-compat/CHANGELOG.md +++ b/packages/app-check-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/app-check-compat +## 0.4.1 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/app-check@0.11.1 + - @firebase/component@0.7.1 + ## 0.4.0 ### Minor Changes diff --git a/packages/app-check-compat/package.json b/packages/app-check-compat/package.json index 29da9f0595..6ae047d53b 100644 --- a/packages/app-check-compat/package.json +++ b/packages/app-check-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-check-compat", - "version": "0.4.0", + "version": "0.4.1", "description": "A compat App Check package for new firebase packages", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -34,16 +34,16 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/app-check": "0.11.0", + "@firebase/app-check": "0.11.1", "@firebase/app-check-types": "0.5.3", "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", - "@firebase/component": "0.7.0", + "@firebase/util": "1.14.0", + "@firebase/component": "0.7.1", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.8", + "@firebase/app-compat": "0.5.9", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-check/CHANGELOG.md b/packages/app-check/CHANGELOG.md index e28884ed1b..aae45703c6 100644 --- a/packages/app-check/CHANGELOG.md +++ b/packages/app-check/CHANGELOG.md @@ -1,5 +1,13 @@ # @firebase/app-check +## 0.11.1 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/component@0.7.1 + ## 0.11.0 ### Minor Changes diff --git a/packages/app-check/package.json b/packages/app-check/package.json index 25132c41e1..a2ebeff2db 100644 --- a/packages/app-check/package.json +++ b/packages/app-check/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-check", - "version": "0.11.0", + "version": "0.11.1", "description": "The App Check component of the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,14 +37,14 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/util": "1.13.0", - "@firebase/component": "0.7.0", + "@firebase/util": "1.14.0", + "@firebase/component": "0.7.1", "@firebase/logger": "0.5.0", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-compat/CHANGELOG.md b/packages/app-compat/CHANGELOG.md index 82e03235ca..2f30cf04eb 100644 --- a/packages/app-compat/CHANGELOG.md +++ b/packages/app-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/app-compat +## 0.5.9 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/app@0.14.9 + - @firebase/util@1.14.0 + - @firebase/component@0.7.1 + ## 0.5.8 ### Patch Changes diff --git a/packages/app-compat/package.json b/packages/app-compat/package.json index 36e8139e02..8a0693ed07 100644 --- a/packages/app-compat/package.json +++ b/packages/app-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-compat", - "version": "0.5.8", + "version": "0.5.9", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,10 +37,10 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/app": "0.14.8", - "@firebase/util": "1.13.0", + "@firebase/app": "0.14.9", + "@firebase/util": "1.14.0", "@firebase/logger": "0.5.0", - "@firebase/component": "0.7.0", + "@firebase/component": "0.7.1", "tslib": "^2.1.0" }, "devDependencies": { diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 5d69707fb3..996b20099a 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,15 @@ # @firebase/app +## 0.14.9 + +### Patch Changes + +- Update SDK_VERSION. + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/component@0.7.1 + ## 0.14.8 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 265ac8d873..256aea0f79 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app", - "version": "0.14.8", + "version": "0.14.9", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -39,9 +39,9 @@ "typings:internal": "node ../../scripts/build/use_typings.js ./dist/app.d.ts" }, "dependencies": { - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "@firebase/logger": "0.5.0", - "@firebase/component": "0.7.0", + "@firebase/component": "0.7.1", "idb": "7.1.1", "tslib": "^2.1.0" }, diff --git a/packages/auth-compat/CHANGELOG.md b/packages/auth-compat/CHANGELOG.md index 775c77b9af..152f7a1cd8 100644 --- a/packages/auth-compat/CHANGELOG.md +++ b/packages/auth-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/auth-compat +## 0.6.3 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/auth@1.12.1 + - @firebase/component@0.7.1 + ## 0.6.2 ### Patch Changes diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index ebd93672de..051a874eed 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth-compat", - "version": "0.6.2", + "version": "0.6.3", "description": "FirebaseAuth compatibility package that uses API style compatible with Firebase@8 and prior versions", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -49,15 +49,15 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/auth": "1.12.0", + "@firebase/auth": "1.12.1", "@firebase/auth-types": "0.13.0", - "@firebase/component": "0.7.0", - "@firebase/util": "1.13.0", + "@firebase/component": "0.7.1", + "@firebase/util": "1.14.0", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.8", + "@firebase/app-compat": "0.5.9", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/auth/CHANGELOG.md b/packages/auth/CHANGELOG.md index b19ebe3154..3b475e84c0 100644 --- a/packages/auth/CHANGELOG.md +++ b/packages/auth/CHANGELOG.md @@ -1,5 +1,13 @@ # @firebase/auth +## 1.12.1 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/component@0.7.1 + ## 1.12.0 ### Minor Changes diff --git a/packages/auth/package.json b/packages/auth/package.json index c9deabf6d3..df29557a63 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth", - "version": "1.12.0", + "version": "1.12.1", "description": "The Firebase Authenticaton component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/node/index.js", @@ -124,14 +124,14 @@ } }, "dependencies": { - "@firebase/component": "0.7.0", + "@firebase/component": "0.7.1", "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-strip": "3.0.4", "@types/express": "4.17.21", diff --git a/packages/component/CHANGELOG.md b/packages/component/CHANGELOG.md index b300eb047d..de0ee0660c 100644 --- a/packages/component/CHANGELOG.md +++ b/packages/component/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/component +## 0.7.1 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + ## 0.7.0 ### Minor Changes diff --git a/packages/component/package.json b/packages/component/package.json index 2b475f1217..061f3367ba 100644 --- a/packages/component/package.json +++ b/packages/component/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/component", - "version": "0.7.0", + "version": "0.7.1", "description": "Firebase Component Platform", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -31,7 +31,7 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "tslib": "^2.1.0" }, "license": "Apache-2.0", diff --git a/packages/data-connect/CHANGELOG.md b/packages/data-connect/CHANGELOG.md index b9223f267c..21fbb03304 100644 --- a/packages/data-connect/CHANGELOG.md +++ b/packages/data-connect/CHANGELOG.md @@ -1,5 +1,17 @@ ## Unreleased +## 0.4.0 + +### Minor Changes + +- [`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca) [#9439](https://github.com/firebase/firebase-js-sdk/pull/9439) - Add Memory-Based caching to Queries in Firebase Data Connect. + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/component@0.7.1 + ## 0.3.12 ### Patch Changes diff --git a/packages/data-connect/package.json b/packages/data-connect/package.json index 104e4d7f83..1370e46a83 100644 --- a/packages/data-connect/package.json +++ b/packages/data-connect/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/data-connect", - "version": "0.3.12", + "version": "0.4.0", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -49,13 +49,13 @@ }, "dependencies": { "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.7.0", + "@firebase/component": "0.7.1", "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/database-compat/CHANGELOG.md b/packages/database-compat/CHANGELOG.md index 9a4ec4fef6..c4aebb6163 100644 --- a/packages/database-compat/CHANGELOG.md +++ b/packages/database-compat/CHANGELOG.md @@ -1,5 +1,15 @@ # @firebase/database-compat +## 2.1.1 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/database@1.1.1 + - @firebase/component@0.7.1 + - @firebase/database-types@1.0.17 + ## 2.1.0 ### Minor Changes diff --git a/packages/database-compat/package.json b/packages/database-compat/package.json index c2cd0ae9ea..648986b1bd 100644 --- a/packages/database-compat/package.json +++ b/packages/database-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database-compat", - "version": "2.1.0", + "version": "2.1.1", "description": "The Realtime Database component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.js", @@ -49,15 +49,15 @@ "add-compat-overloads": "ts-node-script ../../scripts/build/create-overloads.ts -i ../database/dist/public.d.ts -o dist/database-compat/src/index.d.ts -a -r Database:types.FirebaseDatabase -r Query:types.Query -r DatabaseReference:types.Reference -r FirebaseApp:FirebaseAppCompat --moduleToEnhance @firebase/database" }, "dependencies": { - "@firebase/database": "1.1.0", - "@firebase/database-types": "1.0.16", + "@firebase/database": "1.1.1", + "@firebase/database-types": "1.0.17", "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", - "@firebase/component": "0.7.0", + "@firebase/util": "1.14.0", + "@firebase/component": "0.7.1", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.8", + "@firebase/app-compat": "0.5.9", "typescript": "5.5.4" }, "repository": { diff --git a/packages/database-types/CHANGELOG.md b/packages/database-types/CHANGELOG.md index d175477dcd..18a6a3226a 100644 --- a/packages/database-types/CHANGELOG.md +++ b/packages/database-types/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/database-types +## 1.0.17 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + ## 1.0.16 ### Patch Changes diff --git a/packages/database-types/package.json b/packages/database-types/package.json index b63337a061..967642d5c7 100644 --- a/packages/database-types/package.json +++ b/packages/database-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database-types", - "version": "1.0.16", + "version": "1.0.17", "description": "@firebase/database Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -13,7 +13,7 @@ ], "dependencies": { "@firebase/app-types": "0.9.3", - "@firebase/util": "1.13.0" + "@firebase/util": "1.14.0" }, "repository": { "directory": "packages/database-types", diff --git a/packages/database/CHANGELOG.md b/packages/database/CHANGELOG.md index 860266ce7a..bef7ecefb3 100644 --- a/packages/database/CHANGELOG.md +++ b/packages/database/CHANGELOG.md @@ -1,5 +1,13 @@ # Unreleased +## 1.1.1 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/component@0.7.1 + ## 1.1.0 ### Minor Changes diff --git a/packages/database/package.json b/packages/database/package.json index 642ddff7d1..a3d2d98ed4 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database", - "version": "1.1.0", + "version": "1.1.1", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -49,15 +49,15 @@ "peerDependencies": {}, "dependencies": { "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", - "@firebase/component": "0.7.0", + "@firebase/util": "1.14.0", + "@firebase/component": "0.7.1", "@firebase/app-check-interop-types": "0.3.3", "@firebase/auth-interop-types": "0.2.4", "faye-websocket": "0.11.4", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/firebase/CHANGELOG.md b/packages/firebase/CHANGELOG.md index ef42dca4d0..b941c52bc8 100644 --- a/packages/firebase/CHANGELOG.md +++ b/packages/firebase/CHANGELOG.md @@ -1,5 +1,54 @@ # firebase +## 12.10.0 + +### Minor Changes + +- [`14d9745`](https://github.com/firebase/firebase-js-sdk/commit/14d974550c1df023e563c22619dc68b9182946e0) [#9483](https://github.com/firebase/firebase-js-sdk/pull/9483) - Support added for `mapSet`, `mapValues`, `mapEntries`, `mapKeys` Pipelines expressions. + +- [`47f8521`](https://github.com/firebase/firebase-js-sdk/commit/47f85219d570f05c196e0085f2892d1297308fed) [#9489](https://github.com/firebase/firebase-js-sdk/pull/9489) - Added automatic function calling capability when using `ChatSession`. + +- [`f8996c4`](https://github.com/firebase/firebase-js-sdk/commit/f8996c4cec849db4d6f9dad1df728a49cc063b96) [#9479](https://github.com/firebase/firebase-js-sdk/pull/9479) - Support added for the following string Pipeline expressions: `stringRepeat`, `stringReplaceOne`, `stringReplaceAll`, `stringIndexOf`, `ltrim`, `rtrim`. + +- [`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca) [#9439](https://github.com/firebase/firebase-js-sdk/pull/9439) - Add Memory-Based caching to Queries in Firebase Data Connect. + +- [`659d9bb`](https://github.com/firebase/firebase-js-sdk/commit/659d9bb7987c1fb7bc9f3d772fe1c467f7e4f80f) [#9576](https://github.com/firebase/firebase-js-sdk/pull/9576) - Add support for first, last, array_agg and array_agg_distinct expressions + +- [`852162b`](https://github.com/firebase/firebase-js-sdk/commit/852162bc94935a826b548e71ac124749ab3e799f) [#9498](https://github.com/firebase/firebase-js-sdk/pull/9498) - Add support for rand and trunc pipeline expressions + +- [`6041509`](https://github.com/firebase/firebase-js-sdk/commit/60415091e1cb2481255343122a18c9f2845ca505) [#9484](https://github.com/firebase/firebase-js-sdk/pull/9484) - feat(firestore): Support added for the `isType` Pipeline expression. + +### Patch Changes + +- Updated dependencies [[`14d9745`](https://github.com/firebase/firebase-js-sdk/commit/14d974550c1df023e563c22619dc68b9182946e0), [`47f8521`](https://github.com/firebase/firebase-js-sdk/commit/47f85219d570f05c196e0085f2892d1297308fed), [`f8996c4`](https://github.com/firebase/firebase-js-sdk/commit/f8996c4cec849db4d6f9dad1df728a49cc063b96), [`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca), [`659d9bb`](https://github.com/firebase/firebase-js-sdk/commit/659d9bb7987c1fb7bc9f3d772fe1c467f7e4f80f), [`852162b`](https://github.com/firebase/firebase-js-sdk/commit/852162bc94935a826b548e71ac124749ab3e799f), [`6041509`](https://github.com/firebase/firebase-js-sdk/commit/60415091e1cb2481255343122a18c9f2845ca505)]: + - @firebase/firestore@4.12.0 + - @firebase/app@0.14.9 + - @firebase/ai@2.9.0 + - @firebase/data-connect@0.4.0 + - @firebase/util@1.14.0 + - @firebase/firestore-compat@0.4.6 + - @firebase/analytics@0.10.20 + - @firebase/app-check@0.11.1 + - @firebase/app-compat@0.5.9 + - @firebase/auth@1.12.1 + - @firebase/database@1.1.1 + - @firebase/functions@0.13.2 + - @firebase/installations@0.6.20 + - @firebase/messaging@0.12.24 + - @firebase/performance@0.7.10 + - @firebase/remote-config@0.8.1 + - @firebase/storage@0.14.1 + - @firebase/analytics-compat@0.2.26 + - @firebase/app-check-compat@0.4.1 + - @firebase/auth-compat@0.6.3 + - @firebase/database-compat@2.1.1 + - @firebase/functions-compat@0.4.2 + - @firebase/installations-compat@0.2.20 + - @firebase/messaging-compat@0.2.24 + - @firebase/performance-compat@0.2.23 + - @firebase/remote-config-compat@0.2.22 + - @firebase/storage-compat@0.4.1 + ## 12.9.0 ### Minor Changes diff --git a/packages/firebase/package.json b/packages/firebase/package.json index 592c9937df..30e7953033 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -1,6 +1,6 @@ { "name": "firebase", - "version": "12.9.0", + "version": "12.10.0", "description": "Firebase JavaScript library for web and Node.js", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -423,34 +423,34 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/ai": "2.8.0", - "@firebase/app": "0.14.8", - "@firebase/app-compat": "0.5.8", + "@firebase/ai": "2.9.0", + "@firebase/app": "0.14.9", + "@firebase/app-compat": "0.5.9", "@firebase/app-types": "0.9.3", - "@firebase/auth": "1.12.0", - "@firebase/auth-compat": "0.6.2", - "@firebase/data-connect": "0.3.12", - "@firebase/database": "1.1.0", - "@firebase/database-compat": "2.1.0", - "@firebase/firestore": "4.11.0", - "@firebase/firestore-compat": "0.4.5", - "@firebase/functions": "0.13.1", - "@firebase/functions-compat": "0.4.1", - "@firebase/installations": "0.6.19", - "@firebase/installations-compat": "0.2.19", - "@firebase/messaging": "0.12.23", - "@firebase/messaging-compat": "0.2.23", - "@firebase/storage": "0.14.0", - "@firebase/storage-compat": "0.4.0", - "@firebase/performance": "0.7.9", - "@firebase/performance-compat": "0.2.22", - "@firebase/remote-config": "0.8.0", - "@firebase/remote-config-compat": "0.2.21", - "@firebase/analytics": "0.10.19", - "@firebase/analytics-compat": "0.2.25", - "@firebase/app-check": "0.11.0", - "@firebase/app-check-compat": "0.4.0", - "@firebase/util": "1.13.0" + "@firebase/auth": "1.12.1", + "@firebase/auth-compat": "0.6.3", + "@firebase/data-connect": "0.4.0", + "@firebase/database": "1.1.1", + "@firebase/database-compat": "2.1.1", + "@firebase/firestore": "4.12.0", + "@firebase/firestore-compat": "0.4.6", + "@firebase/functions": "0.13.2", + "@firebase/functions-compat": "0.4.2", + "@firebase/installations": "0.6.20", + "@firebase/installations-compat": "0.2.20", + "@firebase/messaging": "0.12.24", + "@firebase/messaging-compat": "0.2.24", + "@firebase/storage": "0.14.1", + "@firebase/storage-compat": "0.4.1", + "@firebase/performance": "0.7.10", + "@firebase/performance-compat": "0.2.23", + "@firebase/remote-config": "0.8.1", + "@firebase/remote-config-compat": "0.2.22", + "@firebase/analytics": "0.10.20", + "@firebase/analytics-compat": "0.2.26", + "@firebase/app-check": "0.11.1", + "@firebase/app-check-compat": "0.4.1", + "@firebase/util": "1.14.0" }, "devDependencies": { "rollup": "2.79.2", diff --git a/packages/firestore-compat/CHANGELOG.md b/packages/firestore-compat/CHANGELOG.md index 3fdb7f3d79..87e4aac3b0 100644 --- a/packages/firestore-compat/CHANGELOG.md +++ b/packages/firestore-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/firestore-compat +## 0.4.6 + +### Patch Changes + +- Updated dependencies [[`14d9745`](https://github.com/firebase/firebase-js-sdk/commit/14d974550c1df023e563c22619dc68b9182946e0), [`f8996c4`](https://github.com/firebase/firebase-js-sdk/commit/f8996c4cec849db4d6f9dad1df728a49cc063b96), [`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca), [`659d9bb`](https://github.com/firebase/firebase-js-sdk/commit/659d9bb7987c1fb7bc9f3d772fe1c467f7e4f80f), [`852162b`](https://github.com/firebase/firebase-js-sdk/commit/852162bc94935a826b548e71ac124749ab3e799f), [`6041509`](https://github.com/firebase/firebase-js-sdk/commit/60415091e1cb2481255343122a18c9f2845ca505)]: + - @firebase/firestore@4.12.0 + - @firebase/util@1.14.0 + - @firebase/component@0.7.1 + ## 0.4.5 ### Patch Changes diff --git a/packages/firestore-compat/package.json b/packages/firestore-compat/package.json index 262ee0d1cb..bc7bd40355 100644 --- a/packages/firestore-compat/package.json +++ b/packages/firestore-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore-compat", - "version": "0.4.5", + "version": "0.4.6", "description": "The Cloud Firestore component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -46,14 +46,14 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/component": "0.7.0", - "@firebase/firestore": "4.11.0", - "@firebase/util": "1.13.0", + "@firebase/component": "0.7.1", + "@firebase/firestore": "4.12.0", + "@firebase/util": "1.14.0", "@firebase/firestore-types": "3.0.3", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.8", + "@firebase/app-compat": "0.5.9", "@types/eslint": "7.29.0", "rollup": "2.79.2", "rollup-plugin-sourcemaps": "0.6.3", diff --git a/packages/firestore/CHANGELOG.md b/packages/firestore/CHANGELOG.md index e798dbdd04..e1d1f14b1f 100644 --- a/packages/firestore/CHANGELOG.md +++ b/packages/firestore/CHANGELOG.md @@ -1,5 +1,25 @@ # @firebase/firestore +## 4.12.0 + +### Minor Changes + +- [`14d9745`](https://github.com/firebase/firebase-js-sdk/commit/14d974550c1df023e563c22619dc68b9182946e0) [#9483](https://github.com/firebase/firebase-js-sdk/pull/9483) - Support added for `mapSet`, `mapValues`, `mapEntries`, `mapKeys` Pipelines expressions. + +- [`f8996c4`](https://github.com/firebase/firebase-js-sdk/commit/f8996c4cec849db4d6f9dad1df728a49cc063b96) [#9479](https://github.com/firebase/firebase-js-sdk/pull/9479) - Support added for the following string Pipeline expressions: `stringRepeat`, `stringReplaceOne`, `stringReplaceAll`, `stringIndexOf`, `ltrim`, `rtrim`. + +- [`659d9bb`](https://github.com/firebase/firebase-js-sdk/commit/659d9bb7987c1fb7bc9f3d772fe1c467f7e4f80f) [#9576](https://github.com/firebase/firebase-js-sdk/pull/9576) - Add support for first, last, array_agg and array_agg_distinct expressions + +- [`852162b`](https://github.com/firebase/firebase-js-sdk/commit/852162bc94935a826b548e71ac124749ab3e799f) [#9498](https://github.com/firebase/firebase-js-sdk/pull/9498) - Add support for rand and trunc pipeline expressions + +- [`6041509`](https://github.com/firebase/firebase-js-sdk/commit/60415091e1cb2481255343122a18c9f2845ca505) [#9484](https://github.com/firebase/firebase-js-sdk/pull/9484) - feat(firestore): Support added for the `isType` Pipeline expression. + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/component@0.7.1 + ## 4.11.0 ### Minor Changes diff --git a/packages/firestore/package.json b/packages/firestore/package.json index e595b55e14..c8d69962e4 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore", - "version": "4.11.0", + "version": "4.12.0", "engines": { "node": ">=20.0.0" }, @@ -133,9 +133,9 @@ "lite/pipelines/pipelines.d.ts" ], "dependencies": { - "@firebase/component": "0.7.0", + "@firebase/component": "0.7.1", "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "@firebase/webchannel-wrapper": "1.0.5", "@grpc/grpc-js": "~1.9.0", "@grpc/proto-loader": "^0.7.8", @@ -145,9 +145,9 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.8", - "@firebase/app-compat": "0.5.8", - "@firebase/auth": "1.12.0", + "@firebase/app": "0.14.9", + "@firebase/app-compat": "0.5.9", + "@firebase/auth": "1.12.1", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", "@types/eslint": "7.29.0", diff --git a/packages/functions-compat/CHANGELOG.md b/packages/functions-compat/CHANGELOG.md index 81ea467964..d88ab9c0b5 100644 --- a/packages/functions-compat/CHANGELOG.md +++ b/packages/functions-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/functions-compat +## 0.4.2 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/functions@0.13.2 + - @firebase/component@0.7.1 + ## 0.4.1 ### Patch Changes diff --git a/packages/functions-compat/package.json b/packages/functions-compat/package.json index 6bdb22e507..dd3213c263 100644 --- a/packages/functions-compat/package.json +++ b/packages/functions-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/functions-compat", - "version": "0.4.1", + "version": "0.4.2", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -29,7 +29,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.8", + "@firebase/app-compat": "0.5.9", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", @@ -62,10 +62,10 @@ }, "typings": "dist/src/index.d.ts", "dependencies": { - "@firebase/component": "0.7.0", - "@firebase/functions": "0.13.1", + "@firebase/component": "0.7.1", + "@firebase/functions": "0.13.2", "@firebase/functions-types": "0.6.3", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/functions/CHANGELOG.md b/packages/functions/CHANGELOG.md index 8b98d691f2..1fbc6ded0a 100644 --- a/packages/functions/CHANGELOG.md +++ b/packages/functions/CHANGELOG.md @@ -1,5 +1,13 @@ # @firebase/functions +## 0.13.2 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/component@0.7.1 + ## 0.13.1 ### Patch Changes diff --git a/packages/functions/package.json b/packages/functions/package.json index fc9b48ff62..479deeb3de 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/functions", - "version": "0.13.1", + "version": "0.13.2", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -49,7 +49,7 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", @@ -65,11 +65,11 @@ }, "typings": "dist/src/index.d.ts", "dependencies": { - "@firebase/component": "0.7.0", + "@firebase/component": "0.7.1", "@firebase/messaging-interop-types": "0.2.3", "@firebase/auth-interop-types": "0.2.4", "@firebase/app-check-interop-types": "0.3.3", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/installations-compat/CHANGELOG.md b/packages/installations-compat/CHANGELOG.md index d9e0fad1ef..387599ea01 100644 --- a/packages/installations-compat/CHANGELOG.md +++ b/packages/installations-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/installations-compat +## 0.2.20 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/installations@0.6.20 + - @firebase/component@0.7.1 + ## 0.2.19 ### Patch Changes diff --git a/packages/installations-compat/package.json b/packages/installations-compat/package.json index 962a420d21..f56c83c8ce 100644 --- a/packages/installations-compat/package.json +++ b/packages/installations-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/installations-compat", - "version": "0.2.19", + "version": "0.2.20", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", "module": "dist/esm/index.esm.js", @@ -44,7 +44,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app-compat": "0.5.8", + "@firebase/app-compat": "0.5.9", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", @@ -57,10 +57,10 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.19", + "@firebase/installations": "0.6.20", "@firebase/installations-types": "0.5.3", - "@firebase/util": "1.13.0", - "@firebase/component": "0.7.0", + "@firebase/util": "1.14.0", + "@firebase/component": "0.7.1", "tslib": "^2.1.0" } } diff --git a/packages/installations/CHANGELOG.md b/packages/installations/CHANGELOG.md index 39cbde19a1..f18c606587 100644 --- a/packages/installations/CHANGELOG.md +++ b/packages/installations/CHANGELOG.md @@ -1,5 +1,13 @@ # @firebase/installations +## 0.6.20 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/component@0.7.1 + ## 0.6.19 ### Patch Changes diff --git a/packages/installations/package.json b/packages/installations/package.json index 84bd448f40..4658439941 100644 --- a/packages/installations/package.json +++ b/packages/installations/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/installations", - "version": "0.6.19", + "version": "0.6.20", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", "module": "dist/esm/index.esm.js", @@ -49,7 +49,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", @@ -62,8 +62,8 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/util": "1.13.0", - "@firebase/component": "0.7.0", + "@firebase/util": "1.14.0", + "@firebase/component": "0.7.1", "idb": "7.1.1", "tslib": "^2.1.0" } diff --git a/packages/messaging-compat/CHANGELOG.md b/packages/messaging-compat/CHANGELOG.md index 98946c9d22..2059809d5c 100644 --- a/packages/messaging-compat/CHANGELOG.md +++ b/packages/messaging-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/messaging-compat +## 0.2.24 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/messaging@0.12.24 + - @firebase/component@0.7.1 + ## 0.2.23 ### Patch Changes diff --git a/packages/messaging-compat/package.json b/packages/messaging-compat/package.json index 6281f9da5f..622379d8c0 100644 --- a/packages/messaging-compat/package.json +++ b/packages/messaging-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/messaging-compat", - "version": "0.2.23", + "version": "0.2.24", "license": "Apache-2.0", "description": "", "author": "Firebase (https://firebase.google.com/)", @@ -38,13 +38,13 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/messaging": "0.12.23", - "@firebase/component": "0.7.0", - "@firebase/util": "1.13.0", + "@firebase/messaging": "0.12.24", + "@firebase/component": "0.7.1", + "@firebase/util": "1.14.0", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.8", + "@firebase/app-compat": "0.5.9", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", "ts-essentials": "9.4.2", diff --git a/packages/messaging/CHANGELOG.md b/packages/messaging/CHANGELOG.md index 6fe7494899..4def7d21c4 100644 --- a/packages/messaging/CHANGELOG.md +++ b/packages/messaging/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/messaging +## 0.12.24 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/installations@0.6.20 + - @firebase/component@0.7.1 + ## 0.12.23 ### Patch Changes diff --git a/packages/messaging/package.json b/packages/messaging/package.json index a74df15bcf..79823aac17 100644 --- a/packages/messaging/package.json +++ b/packages/messaging/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/messaging", - "version": "0.12.23", + "version": "0.12.24", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -52,15 +52,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.19", + "@firebase/installations": "0.6.20", "@firebase/messaging-interop-types": "0.2.3", - "@firebase/util": "1.13.0", - "@firebase/component": "0.7.0", + "@firebase/util": "1.14.0", + "@firebase/component": "0.7.1", "idb": "7.1.1", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/performance-compat/CHANGELOG.md b/packages/performance-compat/CHANGELOG.md index 032e5fd54a..9b5392d771 100644 --- a/packages/performance-compat/CHANGELOG.md +++ b/packages/performance-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/performance-compat +## 0.2.23 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/performance@0.7.10 + - @firebase/component@0.7.1 + ## 0.2.22 ### Patch Changes diff --git a/packages/performance-compat/package.json b/packages/performance-compat/package.json index ab2b4e884f..d7ff76409b 100644 --- a/packages/performance-compat/package.json +++ b/packages/performance-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/performance-compat", - "version": "0.2.22", + "version": "0.2.23", "description": "The compatibility package of Firebase Performance", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -38,11 +38,11 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/performance": "0.7.9", + "@firebase/performance": "0.7.10", "@firebase/performance-types": "0.2.3", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "@firebase/logger": "0.5.0", - "@firebase/component": "0.7.0", + "@firebase/component": "0.7.1", "tslib": "^2.1.0" }, "devDependencies": { @@ -51,7 +51,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.8" + "@firebase/app-compat": "0.5.9" }, "repository": { "directory": "packages/performance-compat", diff --git a/packages/performance/CHANGELOG.md b/packages/performance/CHANGELOG.md index e55f9b69e0..5adf2d4037 100644 --- a/packages/performance/CHANGELOG.md +++ b/packages/performance/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/performance +## 0.7.10 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/installations@0.6.20 + - @firebase/component@0.7.1 + ## 0.7.9 ### Patch Changes diff --git a/packages/performance/package.json b/packages/performance/package.json index c70b1ed6a0..3c29a2a9bb 100644 --- a/packages/performance/package.json +++ b/packages/performance/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/performance", - "version": "0.7.9", + "version": "0.7.10", "description": "Firebase performance for web", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -39,15 +39,15 @@ }, "dependencies": { "@firebase/logger": "0.5.0", - "@firebase/installations": "0.6.19", - "@firebase/util": "1.13.0", - "@firebase/component": "0.7.0", + "@firebase/installations": "0.6.20", + "@firebase/util": "1.14.0", + "@firebase/component": "0.7.1", "tslib": "^2.1.0", "web-vitals": "^4.2.4" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/remote-config-compat/CHANGELOG.md b/packages/remote-config-compat/CHANGELOG.md index 9205251fc8..424897ed3f 100644 --- a/packages/remote-config-compat/CHANGELOG.md +++ b/packages/remote-config-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/remote-config-compat +## 0.2.22 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/remote-config@0.8.1 + - @firebase/component@0.7.1 + ## 0.2.21 ### Patch Changes diff --git a/packages/remote-config-compat/package.json b/packages/remote-config-compat/package.json index 0ff334df69..ed628b20fe 100644 --- a/packages/remote-config-compat/package.json +++ b/packages/remote-config-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/remote-config-compat", - "version": "0.2.21", + "version": "0.2.22", "description": "The compatibility package of Remote Config", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,11 +37,11 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/remote-config": "0.8.0", + "@firebase/remote-config": "0.8.1", "@firebase/remote-config-types": "0.5.0", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "@firebase/logger": "0.5.0", - "@firebase/component": "0.7.0", + "@firebase/component": "0.7.1", "tslib": "^2.1.0" }, "devDependencies": { @@ -50,7 +50,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.8" + "@firebase/app-compat": "0.5.9" }, "repository": { "directory": "packages/remote-config-compat", diff --git a/packages/remote-config/CHANGELOG.md b/packages/remote-config/CHANGELOG.md index 1799899da6..d7e9fe23d3 100644 --- a/packages/remote-config/CHANGELOG.md +++ b/packages/remote-config/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/remote-config +## 0.8.1 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/installations@0.6.20 + - @firebase/component@0.7.1 + ## 0.8.0 ### Minor Changes diff --git a/packages/remote-config/package.json b/packages/remote-config/package.json index 2d700d885a..da09d5165f 100644 --- a/packages/remote-config/package.json +++ b/packages/remote-config/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/remote-config", - "version": "0.8.0", + "version": "0.8.1", "description": "The Remote Config package of the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -40,15 +40,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.19", + "@firebase/installations": "0.6.20", "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", - "@firebase/component": "0.7.0", + "@firebase/util": "1.14.0", + "@firebase/component": "0.7.1", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/storage-compat/CHANGELOG.md b/packages/storage-compat/CHANGELOG.md index ec3d330843..1733f49979 100644 --- a/packages/storage-compat/CHANGELOG.md +++ b/packages/storage-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/storage-compat +## 0.4.1 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/storage@0.14.1 + - @firebase/component@0.7.1 + ## 0.4.0 ### Minor Changes diff --git a/packages/storage-compat/package.json b/packages/storage-compat/package.json index 32d2d2d116..4d80898948 100644 --- a/packages/storage-compat/package.json +++ b/packages/storage-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/storage-compat", - "version": "0.4.0", + "version": "0.4.1", "description": "The Firebase Firestore compatibility package", "author": "Firebase (https://firebase.google.com/)", "main": "./dist/index.cjs.js", @@ -37,15 +37,15 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/storage": "0.14.0", + "@firebase/storage": "0.14.1", "@firebase/storage-types": "0.8.3", - "@firebase/util": "1.13.0", - "@firebase/component": "0.7.0", + "@firebase/util": "1.14.0", + "@firebase/component": "0.7.1", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.8", - "@firebase/auth-compat": "0.6.2", + "@firebase/app-compat": "0.5.9", + "@firebase/auth-compat": "0.6.3", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/storage/CHANGELOG.md b/packages/storage/CHANGELOG.md index a8d7d80f3f..a0c2376aea 100644 --- a/packages/storage/CHANGELOG.md +++ b/packages/storage/CHANGELOG.md @@ -1,5 +1,13 @@ #Unreleased +## 0.14.1 + +### Patch Changes + +- Updated dependencies [[`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca)]: + - @firebase/util@1.14.0 + - @firebase/component@0.7.1 + ## 0.14.0 ### Minor Changes diff --git a/packages/storage/package.json b/packages/storage/package.json index c09be0c392..379f804fe7 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/storage", - "version": "0.14.0", + "version": "0.14.1", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -46,16 +46,16 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/util": "1.13.0", - "@firebase/component": "0.7.0", + "@firebase/util": "1.14.0", + "@firebase/component": "0.7.1", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.8", - "@firebase/auth": "1.12.0", + "@firebase/app": "0.14.9", + "@firebase/auth": "1.12.1", "rollup": "2.79.2", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", diff --git a/packages/template/package.json b/packages/template/package.json index 240b6bcf45..d1764b4350 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -48,7 +48,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/util/CHANGELOG.md b/packages/util/CHANGELOG.md index 38660ea5f5..48a4897bd2 100644 --- a/packages/util/CHANGELOG.md +++ b/packages/util/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/util +## 1.14.0 + +### Minor Changes + +- [`eebba69`](https://github.com/firebase/firebase-js-sdk/commit/eebba69e912b59e5f097a896e479d139c03d62ca) [#9439](https://github.com/firebase/firebase-js-sdk/pull/9439) - Add Memory-Based caching to Queries in Firebase Data Connect. + ## 1.13.0 ### Minor Changes diff --git a/packages/util/package.json b/packages/util/package.json index 8c44efc492..a3982578bb 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/util", - "version": "1.13.0", + "version": "1.14.0", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index 62b47514e8..dc2823cdea 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -20,7 +20,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "child-process-promise": "2.2.1", "glob": "7.2.3", "tmp": "0.2.3", @@ -40,7 +40,7 @@ "yargs": "17.7.2" }, "devDependencies": { - "@firebase/app": "0.14.8", + "@firebase/app": "0.14.9", "@firebase/logger": "0.5.0", "@types/webpack": "5.28.5" }, From 938dc3c107b0922be04605d44e956a8c7bc8f018 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:20:11 -0800 Subject: [PATCH 077/174] chore(deps): update peter-evans/find-comment digest to a4ef349 (#9580) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/check-changeset.yml | 2 +- .github/workflows/check-vertexai-responses.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-changeset.yml b/.github/workflows/check-changeset.yml index 741c47da67..30379bf45c 100644 --- a/.github/workflows/check-changeset.yml +++ b/.github/workflows/check-changeset.yml @@ -62,7 +62,7 @@ jobs: STEPS_CHECK_CHANGESET_OUTPUTS_BLOCKING_FAILURE: ${{steps.check-changeset.outputs.BLOCKING_FAILURE}} - name: Find Comment # This commit represents v3.1.0 - uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e + uses: peter-evans/find-comment@a4ef349b8c29f841860ce94ed82b20f0a39b6961 id: fc with: issue-number: ${{github.event.number}} diff --git a/.github/workflows/check-vertexai-responses.yml b/.github/workflows/check-vertexai-responses.yml index c1d6a5a07c..8dcbc2233f 100644 --- a/.github/workflows/check-vertexai-responses.yml +++ b/.github/workflows/check-vertexai-responses.yml @@ -39,7 +39,7 @@ jobs: working-directory: packages/ai/test-utils/vertexai-sdk-test-data - name: Find comment from previous run if exists # This commit represents v3.1.0 - uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e + uses: peter-evans/find-comment@a4ef349b8c29f841860ce94ed82b20f0a39b6961 id: fc with: issue-number: ${{github.event.number}} From 78384d32c5352bd25cdc3d12fc8f2f4b5d48a440 Mon Sep 17 00:00:00 2001 From: Mila <107142260+milaGGL@users.noreply.github.com> Date: Mon, 2 Mar 2026 10:21:25 -0500 Subject: [PATCH 078/174] feat(firestore): Add array expressions (#9492) --- .changeset/spotty-rocks-sin.md | 6 + .../firestore-lite-pipelines.api.md | 126 + common/api-review/firestore-pipelines.api.md | 126 + .../firestore_lite_pipelines.expression.md | 610 ++++ docs-devsite/firestore_lite_pipelines.md | 2698 ++++++++++++----- .../firestore_pipelines.expression.md | 610 ++++ docs-devsite/firestore_pipelines.md | 2698 ++++++++++++----- .../firestore/lite/pipelines/pipelines.ts | 15 +- packages/firestore/src/api_pipelines.ts | 15 +- .../firestore/src/lite-api/expressions.ts | 985 ++++++ .../test/integration/api/pipeline.test.ts | 601 ++++ packages/firestore/test/lite/pipeline.test.ts | 553 +++- 12 files changed, 7428 insertions(+), 1615 deletions(-) create mode 100644 .changeset/spotty-rocks-sin.md diff --git a/.changeset/spotty-rocks-sin.md b/.changeset/spotty-rocks-sin.md new file mode 100644 index 0000000000..572877ff25 --- /dev/null +++ b/.changeset/spotty-rocks-sin.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/firestore': minor +--- + +Add support for array expressions `arrayFirst`, `arrayFirstN`,`arrayLast`,`arrayLastN`,`arrayMinimum`,`arrayMinimumN`,`arrayMaximum`,`arrayMaximumN`,`arrayIndexOf`, `arrayLastIndexOf` and `arrayIndexOfAll` diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index 90ad11225d..1bf77934ab 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -119,6 +119,24 @@ export function arrayContainsAny(array: Expression, values: Expression): Boolean // @beta export function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; +// @beta +export function arrayFirst(fieldName: string): FunctionExpression; + +// @beta +export function arrayFirst(arrayExpression: Expression): FunctionExpression; + +// @beta +export function arrayFirstN(fieldName: string, n: number): FunctionExpression; + +// @beta +export function arrayFirstN(fieldName: string, n: Expression): FunctionExpression; + +// @beta +export function arrayFirstN(arrayExpression: Expression, n: number): FunctionExpression; + +// @beta +export function arrayFirstN(arrayExpression: Expression, n: Expression): FunctionExpression; + // @beta export function arrayGet(arrayField: string, offset: number): FunctionExpression; @@ -131,12 +149,84 @@ export function arrayGet(arrayExpression: Expression, offset: number): FunctionE // @beta export function arrayGet(arrayExpression: Expression, offsetExpr: Expression): FunctionExpression; +// @beta +export function arrayIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; + +// @beta +export function arrayIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; + +// @beta +export function arrayIndexOfAll(fieldName: string, search: unknown | Expression): FunctionExpression; + +// @beta +export function arrayIndexOfAll(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; + +// @beta +export function arrayLast(fieldName: string): FunctionExpression; + +// @beta +export function arrayLast(arrayExpression: Expression): FunctionExpression; + +// @beta +export function arrayLastIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; + +// @beta +export function arrayLastIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; + +// @beta +export function arrayLastN(fieldName: string, n: number): FunctionExpression; + +// @beta +export function arrayLastN(fieldName: string, n: Expression): FunctionExpression; + +// @beta +export function arrayLastN(arrayExpression: Expression, n: number): FunctionExpression; + +// @beta +export function arrayLastN(arrayExpression: Expression, n: Expression): FunctionExpression; + // @beta export function arrayLength(fieldName: string): FunctionExpression; // @beta export function arrayLength(array: Expression): FunctionExpression; +// @beta +export function arrayMaximum(fieldName: string): FunctionExpression; + +// @beta +export function arrayMaximum(arrayExpression: Expression): FunctionExpression; + +// @beta +export function arrayMaximumN(fieldName: string, n: number): FunctionExpression; + +// @beta +export function arrayMaximumN(fieldName: string, n: Expression): FunctionExpression; + +// @beta +export function arrayMaximumN(arrayExpression: Expression, n: number): FunctionExpression; + +// @beta +export function arrayMaximumN(arrayExpression: Expression, n: Expression): FunctionExpression; + +// @beta +export function arrayMinimum(fieldName: string): FunctionExpression; + +// @beta +export function arrayMinimum(arrayExpression: Expression): FunctionExpression; + +// @beta +export function arrayMinimumN(fieldName: string, n: number): FunctionExpression; + +// @beta +export function arrayMinimumN(fieldName: string, n: Expression): FunctionExpression; + +// @beta +export function arrayMinimumN(arrayExpression: Expression, n: number): FunctionExpression; + +// @beta +export function arrayMinimumN(arrayExpression: Expression, n: Expression): FunctionExpression; + // @beta export function arraySum(fieldName: string): FunctionExpression; @@ -407,12 +497,48 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ arrayContainsAny(arrayExpression: Expression): BooleanExpression; /* Excluded from this release type: _readUserData */ + arrayFirst(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayFirstN(n: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayFirstN(n: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ arrayGet(offset: number): FunctionExpression; /* Excluded from this release type: _readUserData */ arrayGet(offsetExpr: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ + arrayIndexOf(search: unknown): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayIndexOf(search: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayIndexOfAll(search: unknown): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayIndexOfAll(search: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayLast(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayLastIndexOf(search: unknown): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayLastIndexOf(search: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayLastN(n: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayLastN(n: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ arrayLength(): FunctionExpression; /* Excluded from this release type: _readUserData */ + arrayMaximum(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayMaximumN(n: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayMaximumN(n: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayMinimum(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayMinimumN(n: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayMinimumN(n: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ arrayReverse(): FunctionExpression; /* Excluded from this release type: _readUserData */ arraySum(): FunctionExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index df058daa1d..1c5044113d 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -119,6 +119,24 @@ export function arrayContainsAny(array: Expression, values: Expression): Boolean // @beta export function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; +// @beta +export function arrayFirst(fieldName: string): FunctionExpression; + +// @beta +export function arrayFirst(arrayExpression: Expression): FunctionExpression; + +// @beta +export function arrayFirstN(fieldName: string, n: number): FunctionExpression; + +// @beta +export function arrayFirstN(fieldName: string, n: Expression): FunctionExpression; + +// @beta +export function arrayFirstN(arrayExpression: Expression, n: number): FunctionExpression; + +// @beta +export function arrayFirstN(arrayExpression: Expression, n: Expression): FunctionExpression; + // @beta export function arrayGet(arrayField: string, offset: number): FunctionExpression; @@ -131,12 +149,84 @@ export function arrayGet(arrayExpression: Expression, offset: number): FunctionE // @beta export function arrayGet(arrayExpression: Expression, offsetExpr: Expression): FunctionExpression; +// @beta +export function arrayIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; + +// @beta +export function arrayIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; + +// @beta +export function arrayIndexOfAll(fieldName: string, search: unknown | Expression): FunctionExpression; + +// @beta +export function arrayIndexOfAll(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; + +// @beta +export function arrayLast(fieldName: string): FunctionExpression; + +// @beta +export function arrayLast(arrayExpression: Expression): FunctionExpression; + +// @beta +export function arrayLastIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; + +// @beta +export function arrayLastIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; + +// @beta +export function arrayLastN(fieldName: string, n: number): FunctionExpression; + +// @beta +export function arrayLastN(fieldName: string, n: Expression): FunctionExpression; + +// @beta +export function arrayLastN(arrayExpression: Expression, n: number): FunctionExpression; + +// @beta +export function arrayLastN(arrayExpression: Expression, n: Expression): FunctionExpression; + // @beta export function arrayLength(fieldName: string): FunctionExpression; // @beta export function arrayLength(array: Expression): FunctionExpression; +// @beta +export function arrayMaximum(fieldName: string): FunctionExpression; + +// @beta +export function arrayMaximum(arrayExpression: Expression): FunctionExpression; + +// @beta +export function arrayMaximumN(fieldName: string, n: number): FunctionExpression; + +// @beta +export function arrayMaximumN(fieldName: string, n: Expression): FunctionExpression; + +// @beta +export function arrayMaximumN(arrayExpression: Expression, n: number): FunctionExpression; + +// @beta +export function arrayMaximumN(arrayExpression: Expression, n: Expression): FunctionExpression; + +// @beta +export function arrayMinimum(fieldName: string): FunctionExpression; + +// @beta +export function arrayMinimum(arrayExpression: Expression): FunctionExpression; + +// @beta +export function arrayMinimumN(fieldName: string, n: number): FunctionExpression; + +// @beta +export function arrayMinimumN(fieldName: string, n: Expression): FunctionExpression; + +// @beta +export function arrayMinimumN(arrayExpression: Expression, n: number): FunctionExpression; + +// @beta +export function arrayMinimumN(arrayExpression: Expression, n: Expression): FunctionExpression; + // @beta export function arraySum(fieldName: string): FunctionExpression; @@ -410,12 +500,48 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ arrayContainsAny(arrayExpression: Expression): BooleanExpression; /* Excluded from this release type: _readUserData */ + arrayFirst(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayFirstN(n: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayFirstN(n: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ arrayGet(offset: number): FunctionExpression; /* Excluded from this release type: _readUserData */ arrayGet(offsetExpr: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ + arrayIndexOf(search: unknown): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayIndexOf(search: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayIndexOfAll(search: unknown): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayIndexOfAll(search: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayLast(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayLastIndexOf(search: unknown): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayLastIndexOf(search: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayLastN(n: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayLastN(n: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ arrayLength(): FunctionExpression; /* Excluded from this release type: _readUserData */ + arrayMaximum(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayMaximumN(n: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayMaximumN(n: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayMinimum(): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayMinimumN(n: number): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayMinimumN(n: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ arrayReverse(): FunctionExpression; /* Excluded from this release type: _readUserData */ arraySum(): FunctionExpression; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index 1f7be7857e..d838997115 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -48,9 +48,27 @@ export declare abstract class Expression | [arrayContainsAll(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. | | [arrayContainsAny(values)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. | | [arrayContainsAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. | +| [arrayFirst()](./firestore_lite_pipelines.expression.md#expressionarrayfirst) | | (Public Preview) Returns the first element of the array. | +| [arrayFirstN(n)](./firestore_lite_pipelines.expression.md#expressionarrayfirstn) | | (Public Preview) Returns the first n elements of the array. | +| [arrayFirstN(n)](./firestore_lite_pipelines.expression.md#expressionarrayfirstn) | | (Public Preview) Returns the first n elements of the array. | | [arrayGet(offset)](./firestore_lite_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | | [arrayGet(offsetExpr)](./firestore_lite_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionarrayindexof) | | (Public Preview) Returns the first index of the search value in the array, or -1 if not found. | +| [arrayIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionarrayindexof) | | (Public Preview) Returns the first index of the search value in the array, or -1 if not found. | +| [arrayIndexOfAll(search)](./firestore_lite_pipelines.expression.md#expressionarrayindexofall) | | (Public Preview) Returns all indices of the search value in the array. | +| [arrayIndexOfAll(search)](./firestore_lite_pipelines.expression.md#expressionarrayindexofall) | | (Public Preview) Returns all indices of the search value in the array. | +| [arrayLast()](./firestore_lite_pipelines.expression.md#expressionarraylast) | | (Public Preview) Returns the last element of the array. | +| [arrayLastIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionarraylastindexof) | | (Public Preview) Returns the last index of the search value in the array, or -1 if not found. | +| [arrayLastIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionarraylastindexof) | | (Public Preview) Returns the last index of the search value in the array, or -1 if not found. | +| [arrayLastN(n)](./firestore_lite_pipelines.expression.md#expressionarraylastn) | | (Public Preview) Returns the last n elements of the array. | +| [arrayLastN(n)](./firestore_lite_pipelines.expression.md#expressionarraylastn) | | (Public Preview) Returns the last n elements of the array. | | [arrayLength()](./firestore_lite_pipelines.expression.md#expressionarraylength) | | (Public Preview) Creates an expression that calculates the length of an array. | +| [arrayMaximum()](./firestore_lite_pipelines.expression.md#expressionarraymaximum) | | (Public Preview) Returns the maximum value in the array. | +| [arrayMaximumN(n)](./firestore_lite_pipelines.expression.md#expressionarraymaximumn) | | (Public Preview) Returns the largest n elements of the array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMaximumN(n)](./firestore_lite_pipelines.expression.md#expressionarraymaximumn) | | (Public Preview) Returns the largest n elements of the array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimum()](./firestore_lite_pipelines.expression.md#expressionarrayminimum) | | (Public Preview) Returns the minimum value in the array. | +| [arrayMinimumN(n)](./firestore_lite_pipelines.expression.md#expressionarrayminimumn) | | (Public Preview) Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimumN(n)](./firestore_lite_pipelines.expression.md#expressionarrayminimumn) | | (Public Preview) Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [arrayReverse()](./firestore_lite_pipelines.expression.md#expressionarrayreverse) | | (Public Preview) Creates an expression that reverses an array. | | [arraySum()](./firestore_lite_pipelines.expression.md#expressionarraysum) | | (Public Preview) Creates an expression that computes the sum of the elements in an array. | | [as(name)](./firestore_lite_pipelines.expression.md#expressionas) | | (Public Preview) 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. | @@ -551,6 +569,101 @@ field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); ``` +## Expression.arrayFirst() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the first element of the array. + +Signature: + +```typescript +arrayFirst(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the first element. + +### Example + + +```typescript +// Get the first element of the 'myArray' field. +field("myArray").arrayFirst(); + +``` + +## Expression.arrayFirstN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the first `n` elements of the array. + +Signature: + +```typescript +arrayFirstN(n: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | number | The number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the first `n` elements. + +### Example + + +```typescript +// Get the first 3 elements of the 'myArray' field. +field("myArray").arrayFirstN(3); + +``` + +## Expression.arrayFirstN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the first `n` elements of the array. + +Signature: + +```typescript +arrayFirstN(n: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the first `n` elements. + +### Example + + +```typescript +// Get the first n elements of the 'myArray' field. +field("myArray").arrayFirstN(field("count")); + +``` + ## Expression.arrayGet() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -620,6 +733,305 @@ field('tags').arrayGet(field('favoriteTag')); ``` +## Expression.arrayIndexOf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the first index of the search value in the array, or -1 if not found. + +Signature: + +```typescript +arrayIndexOf(search: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | unknown | The value to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the index. + +### Example + + +```typescript +// Get the first index of the value 3 in the 'myArray' field. +field("myArray").arrayIndexOf(3); + +``` + +## Expression.arrayIndexOf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the first index of the search value in the array, or -1 if not found. + +Signature: + +```typescript +arrayIndexOf(search: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the value to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the index. + +### Example + + +```typescript +// Get the first index of the value in 'searchVal' field in the 'myArray' field. +field("myArray").arrayIndexOf(field("searchVal")); + +``` + +## Expression.arrayIndexOfAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all indices of the search value in the array. + +Signature: + +```typescript +arrayIndexOfAll(search: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | unknown | The value to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the indices. + +### Example + + +```typescript +// Get all indices of the value 3 in the 'myArray' field. +field("myArray").arrayIndexOfAll(3); + +``` + +## Expression.arrayIndexOfAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all indices of the search value in the array. + +Signature: + +```typescript +arrayIndexOfAll(search: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the value to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the indices. + +### Example + + +```typescript +// Get all indices of the value in 'searchVal' field in the 'myArray' field. +field("myArray").arrayIndexOfAll(field("searchVal")); + +``` + +## Expression.arrayLast() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the last element of the array. + +Signature: + +```typescript +arrayLast(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the last element. + +### Example + + +```typescript +// Get the last element of the 'myArray' field. +field("myArray").arrayLast(); + +``` + +## Expression.arrayLastIndexOf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the last index of the search value in the array, or -1 if not found. + +Signature: + +```typescript +arrayLastIndexOf(search: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | unknown | The value to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the index. + +### Example + + +```typescript +// Get the last index of the value 3 in the 'myArray' field. +field("myArray").arrayLastIndexOf(3); + +``` + +## Expression.arrayLastIndexOf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the last index of the search value in the array, or -1 if not found. + +Signature: + +```typescript +arrayLastIndexOf(search: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the value to search for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the index. + +### Example + + +```typescript +// Get the last index of the value in 'searchVal' field in the 'myArray' field. +field("myArray").arrayLastIndexOf(field("searchVal")); + +``` + +## Expression.arrayLastN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the last `n` elements of the array. + +Signature: + +```typescript +arrayLastN(n: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | number | The number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the last `n` elements. + +### Example + + +```typescript +// Get the last 3 elements of the 'myArray' field. +field("myArray").arrayLastN(3); + +``` + +## Expression.arrayLastN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the last `n` elements of the array. + +Signature: + +```typescript +arrayLastN(n: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the last `n` elements. + +### Example + + +```typescript +// Get the last n elements of the 'myArray' field. +field("myArray").arrayLastN(field("count")); + +``` + ## Expression.arrayLength() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -647,6 +1059,204 @@ field("cart").arrayLength(); ``` +## Expression.arrayMaximum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the maximum value in the array. + +Signature: + +```typescript +arrayMaximum(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the maximum value. + +### Example + + +```typescript +// Get the maximum value of the 'myArray' field. +field("myArray").arrayMaximum(); + +``` + +## Expression.arrayMaximumN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the largest `n` elements of the array. + +Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. + +Signature: + +```typescript +arrayMaximumN(n: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | number | The number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the largest `n` elements. + +### Example + + +```typescript +// Get the largest 3 elements of the 'myArray' field. +field("myArray").arrayMaximumN(3); + +``` + +## Expression.arrayMaximumN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the largest `n` elements of the array. + +Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. + +Signature: + +```typescript +arrayMaximumN(n: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the largest `n` elements. + +### Example + + +```typescript +// Get the largest n elements of the 'myArray' field. +field("myArray").arrayMaximumN(field("count")); + +``` + +## Expression.arrayMinimum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the minimum value in the array. + +Signature: + +```typescript +arrayMinimum(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the minimum value. + +### Example + + +```typescript +// Get the minimum value of the 'myArray' field. +field("myArray").arrayMinimum(); + +``` + +## Expression.arrayMinimumN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the smallest `n` elements of the array. + +Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. + +Signature: + +```typescript +arrayMinimumN(n: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | number | The number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the smallest `n` elements. + +### Example + + +```typescript +// Get the smallest 3 elements of the 'myArray' field. +field("myArray").arrayMinimumN(3); + +``` + +## Expression.arrayMinimumN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the smallest `n` elements of the array. + +Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. + +Signature: + +```typescript +arrayMinimumN(n: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the smallest `n` elements. + +### Example + + +```typescript +// Get the smallest n elements of the 'myArray' field. +field("myArray").arrayMinimumN(field("count")); + +``` + ## Expression.arrayReverse() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 489a7c9996..39be81e193 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -28,8 +28,23 @@ https://github.com/firebase/firebase-js-sdk | [arrayContainsAny(array, values)](./firestore_lite_pipelines.md#arraycontainsany_c381a96) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. | | [arrayLength(array)](./firestore_lite_pipelines.md#arraylength_195e339) | (Public Preview) Creates an expression that calculates the length of an array expression. | | function(arrayExpression, ...) | +| [arrayFirst(arrayExpression)](./firestore_lite_pipelines.md#arrayfirst_f574e12) | (Public Preview) Creates an expression that returns the first element of an array. | +| [arrayFirstN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayfirstn_bff7f91) | (Public Preview) Creates an expression that returns the first n elements of an array. | +| [arrayFirstN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayfirstn_19b4ef8) | (Public Preview) Creates an expression that returns the first n elements of an array. | | [arrayGet(arrayExpression, offset)](./firestore_lite_pipelines.md#arrayget_f2e27cc) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | | [arrayGet(arrayExpression, offsetExpr)](./firestore_lite_pipelines.md#arrayget_484550d) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayIndexOf(arrayExpression, search)](./firestore_lite_pipelines.md#arrayindexof_694a0b4) | (Public Preview) Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. | +| [arrayIndexOfAll(arrayExpression, search)](./firestore_lite_pipelines.md#arrayindexofall_694a0b4) | (Public Preview) Creates an expression that returns all indices of the search value in an array. | +| [arrayLast(arrayExpression)](./firestore_lite_pipelines.md#arraylast_f574e12) | (Public Preview) Creates an expression that returns the last element of an array. | +| [arrayLastIndexOf(arrayExpression, search)](./firestore_lite_pipelines.md#arraylastindexof_694a0b4) | (Public Preview) Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. | +| [arrayLastN(arrayExpression, n)](./firestore_lite_pipelines.md#arraylastn_bff7f91) | (Public Preview) Creates an expression that returns the last n elements of an array. | +| [arrayLastN(arrayExpression, n)](./firestore_lite_pipelines.md#arraylastn_19b4ef8) | (Public Preview) Creates an expression that returns the last n elements of an array. | +| [arrayMaximum(arrayExpression)](./firestore_lite_pipelines.md#arraymaximum_f574e12) | (Public Preview) Creates an expression that returns the maximum value in an array. | +| [arrayMaximumN(arrayExpression, n)](./firestore_lite_pipelines.md#arraymaximumn_bff7f91) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMaximumN(arrayExpression, n)](./firestore_lite_pipelines.md#arraymaximumn_19b4ef8) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimum(arrayExpression)](./firestore_lite_pipelines.md#arrayminimum_f574e12) | (Public Preview) Creates an expression that returns the minimum value in an array. | +| [arrayMinimumN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayminimumn_bff7f91) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimumN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayminimumn_19b4ef8) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [join(arrayExpression, delimiterExpression)](./firestore_lite_pipelines.md#join_313e6aa) | (Public Preview) Creates an expression that joins the elements of an array into a string. | | [join(arrayExpression, delimiter)](./firestore_lite_pipelines.md#join_d088d29) | (Public Preview) Creates an expression that joins the elements of an array into a string. | | function(arrayField, ...) | @@ -133,7 +148,22 @@ https://github.com/firebase/firebase-js-sdk | [arrayContainsAll(fieldName, arrayExpression)](./firestore_lite_pipelines.md#arraycontainsall_48da8d9) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. | | [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. | | [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_1b4f7cd) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. | +| [arrayFirst(fieldName)](./firestore_lite_pipelines.md#arrayfirst_e5b0480) | (Public Preview) Creates an expression that returns the first element of an array. | +| [arrayFirstN(fieldName, n)](./firestore_lite_pipelines.md#arrayfirstn_597a4d9) | (Public Preview) Creates an expression that returns the first n elements of an array. | +| [arrayFirstN(fieldName, n)](./firestore_lite_pipelines.md#arrayfirstn_1a86a2c) | (Public Preview) Creates an expression that returns the first n elements of an array. | +| [arrayIndexOf(fieldName, search)](./firestore_lite_pipelines.md#arrayindexof_5e4c2c3) | (Public Preview) Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. | +| [arrayIndexOfAll(fieldName, search)](./firestore_lite_pipelines.md#arrayindexofall_5e4c2c3) | (Public Preview) Creates an expression that returns all indices of the search value in an array. | +| [arrayLast(fieldName)](./firestore_lite_pipelines.md#arraylast_e5b0480) | (Public Preview) Creates an expression that returns the last element of an array. | +| [arrayLastIndexOf(fieldName, search)](./firestore_lite_pipelines.md#arraylastindexof_5e4c2c3) | (Public Preview) Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. | +| [arrayLastN(fieldName, n)](./firestore_lite_pipelines.md#arraylastn_597a4d9) | (Public Preview) Creates an expression that returns the last n elements of an array. | +| [arrayLastN(fieldName, n)](./firestore_lite_pipelines.md#arraylastn_1a86a2c) | (Public Preview) Creates an expression that returns the last n elements of an array. | | [arrayLength(fieldName)](./firestore_lite_pipelines.md#arraylength_e5b0480) | (Public Preview) Creates an expression that calculates the length of an array in a specified field. | +| [arrayMaximum(fieldName)](./firestore_lite_pipelines.md#arraymaximum_e5b0480) | (Public Preview) Creates an expression that returns the maximum value in an array. | +| [arrayMaximumN(fieldName, n)](./firestore_lite_pipelines.md#arraymaximumn_597a4d9) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMaximumN(fieldName, n)](./firestore_lite_pipelines.md#arraymaximumn_1a86a2c) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimum(fieldName)](./firestore_lite_pipelines.md#arrayminimum_e5b0480) | (Public Preview) Creates an expression that returns the minimum value in an array. | +| [arrayMinimumN(fieldName, n)](./firestore_lite_pipelines.md#arrayminimumn_597a4d9) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimumN(fieldName, n)](./firestore_lite_pipelines.md#arrayminimumn_1a86a2c) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [arraySum(fieldName)](./firestore_lite_pipelines.md#arraysum_e5b0480) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | | [ascending(fieldName)](./firestore_lite_pipelines.md#ascending_e5b0480) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. | | [average(fieldName)](./firestore_lite_pipelines.md#average_e5b0480) | (Public Preview) Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. | @@ -752,150 +782,146 @@ arrayLength(field("cart")); ## function(arrayExpression, ...) -### arrayGet(arrayExpression, offset) {:#arrayget_f2e27cc} +### arrayFirst(arrayExpression) {:#arrayfirst_f574e12} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +Creates an expression that returns the first element of an array. Signature: ```typescript -export declare function arrayGet(arrayExpression: Expression, offset: number): FunctionExpression; +export declare function arrayFirst(arrayExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to an array. | -| offset | number | The index of the element to return. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the 'arrayGet' operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the first element. ### Example ```typescript -// Return the value in the tags field array at index 1. -arrayGet(field('tags'), 1); +// Get the first tag from the 'tags' array field +arrayFirst(field("tags")); ``` -### arrayGet(arrayExpression, offsetExpr) {:#arrayget_484550d} +### arrayFirstN(arrayExpression, n) {:#arrayfirstn_bff7f91} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +Creates an expression that returns the first `n` elements of an array. Signature: ```typescript -export declare function arrayGet(arrayExpression: Expression, offsetExpr: Expression): FunctionExpression; +export declare function arrayFirstN(arrayExpression: Expression, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to an array. | -| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | number | The number of elements to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the 'arrayGet' operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the first `n` elements. ### Example ```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -arrayGet(field('tags'), field('favoriteTag')); +// Get the first 3 elements from an array expression +arrayFirstN(field("tags"), 3); ``` -### join(arrayExpression, delimiterExpression) {:#join_313e6aa} +### arrayFirstN(arrayExpression, n) {:#arrayfirstn_19b4ef8} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that joins the elements of an array into a string. +Creates an expression that returns the first `n` elements of an array. Signature: ```typescript -export declare function join(arrayExpression: Expression, delimiterExpression: Expression): Expression; +export declare function arrayFirstN(arrayExpression: Expression, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | -| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: -[Expression](./firestore_lite_pipelines.expression.md#expression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new Expression representing the join operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the first `n` elements. ### Example ```typescript -// Join an array of string using the delimiter from the 'separator' field. -join(array(['foo', 'bar']), field("separator")) +// Get the first n elements from an array expression +arrayFirstN(field("tags"), field("count")); ``` -### join(arrayExpression, delimiter) {:#join_d088d29} +### arrayGet(arrayExpression, offset) {:#arrayget_f2e27cc} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that joins the elements of an array into a string. +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: ```typescript -export declare function join(arrayExpression: Expression, delimiter: string): Expression; +export declare function arrayGet(arrayExpression: Expression, offset: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | -| delimiter | string | The string to use as a delimiter. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to an array. | +| offset | number | The index of the element to return. | Returns: -[Expression](./firestore_lite_pipelines.expression.md#expression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new Expression representing the join operation. +A new `Expression` representing the 'arrayGet' operation. ### Example ```typescript -// Join the elements of the 'tags' field with a comma and space. -join(field("tags"), ", ") +// Return the value in the tags field array at index 1. +arrayGet(field('tags'), 1); ``` -## function(arrayField, ...) - -### arrayGet(arrayField, offset) {:#arrayget_3f58471} +### arrayGet(arrayExpression, offsetExpr) {:#arrayget_484550d} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -905,15 +931,15 @@ Creates an expression that indexes into an array from the beginning or end and r Signature: ```typescript -export declare function arrayGet(arrayField: string, offset: number): FunctionExpression; +export declare function arrayGet(arrayExpression: Expression, offsetExpr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayField | string | The name of the array field. | -| offset | number | The index of the element to return. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to an array. | +| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | Returns: @@ -925,1432 +951,2492 @@ A new `Expression` representing the 'arrayGet' operation. ```typescript -// Return the value in the tags field array at index 1. -arrayGet('tags', 1); +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet(field('tags'), field('favoriteTag')); ``` -### arrayGet(arrayField, offsetExpr) {:#arrayget_1904c9a} +### arrayIndexOf(arrayExpression, search) {:#arrayindexof_694a0b4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. Signature: ```typescript -export declare function arrayGet(arrayField: string, offsetExpr: Expression): FunctionExpression; +export declare function arrayIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayField | string | The name of the array field. | -| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array to search. | +| search | unknown \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The value to search for. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the 'arrayGet' operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index. ### Example ```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -arrayGet('tags', field('favoriteTag')); +// Get the index of "politics" in the 'tags' array field +arrayIndexOf(field("tags"), "politics"); ``` -## function(arrayFieldName, ...) - -### join(arrayFieldName, delimiter) {:#join_478ef36} +### arrayIndexOfAll(arrayExpression, search) {:#arrayindexofall_694a0b4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that joins the elements of an array into a string. +Creates an expression that returns all indices of the search value in an array. Signature: ```typescript -export declare function join(arrayFieldName: string, delimiter: string): Expression; +export declare function arrayIndexOfAll(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayFieldName | string | The name of the field containing the array. | -| delimiter | string | The string to use as a delimiter. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array to search. | +| search | unknown \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The value to search for. | Returns: -[Expression](./firestore_lite_pipelines.expression.md#expression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new Expression representing the join operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the indices. ### Example ```typescript -// Join the elements of the 'tags' field with a comma and space. -join("tags", ", ") +// Get all indices of 5 in the 'scores' array field +arrayIndexOfAll(field("scores"), 5); ``` -### join(arrayFieldName, delimiterExpression) {:#join_829294c} +### arrayLast(arrayExpression) {:#arraylast_f574e12} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that joins the elements of an array into a string. +Creates an expression that returns the last element of an array. Signature: ```typescript -export declare function join(arrayFieldName: string, delimiterExpression: Expression): Expression; +export declare function arrayLast(arrayExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayFieldName | string | The name of the field containing the array. | -| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | Returns: -[Expression](./firestore_lite_pipelines.expression.md#expression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new Expression representing the join operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the last element. ### Example ```typescript -// Join the elements of the 'tags' field with the delimiter from the 'separator' field. -join('tags', field("separator")) +// Get the last tag from the 'tags' array field +arrayLast(field("tags")); ``` -## function(base, ...) - -### pow(base, exponent) {:#pow_e4a9e64} +### arrayLastIndexOf(arrayExpression, search) {:#arraylastindexof_694a0b4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the value of the base expression raised to the power of the exponent expression. +Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. Signature: ```typescript -export declare function pow(base: Expression, exponent: Expression): FunctionExpression; +export declare function arrayLastIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | -| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array to search. | +| search | unknown \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The value to search for. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the power operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index. ### Example ```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -pow(field("base"), field("exponent")); +// Get the last index of "politics" in the 'tags' array field +arrayLastIndexOf(field("tags"), "politics"); ``` -### pow(base, exponent) {:#pow_93eae7f} +### arrayLastN(arrayExpression, n) {:#arraylastn_bff7f91} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the value of the base expression raised to the power of the exponent. +Creates an expression that returns the last `n` elements of an array. Signature: ```typescript -export declare function pow(base: Expression, exponent: number): FunctionExpression; +export declare function arrayLastN(arrayExpression: Expression, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | -| exponent | number | The constant value to raise the base to the power of. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | number | The number of elements to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the power operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the last `n` elements. ### Example ```typescript -// Raise the value of the 'base' field to the power of 2. -pow(field("base"), 2); +// Get the last 3 elements from an array expression +arrayLastN(field("tags"), 3); ``` -### pow(base, exponent) {:#pow_a237721} +### arrayLastN(arrayExpression, n) {:#arraylastn_19b4ef8} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the value of the base field raised to the power of the exponent expression. +Creates an expression that returns the last `n` elements of an array. Signature: ```typescript -export declare function pow(base: string, exponent: Expression): FunctionExpression; +export declare function arrayLastN(arrayExpression: Expression, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| base | string | The name of the field to raise to the power of the exponent. | -| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the power operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the last `n` elements. ### Example ```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -pow("base", field("exponent")); +// Get the last n elements from an array expression +arrayLastN(field("tags"), field("count")); ``` -### pow(base, exponent) {:#pow_f4d7908} +### arrayMaximum(arrayExpression) {:#arraymaximum_f574e12} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the value of the base field raised to the power of the exponent. +Creates an expression that returns the maximum value in an array. Signature: ```typescript -export declare function pow(base: string, exponent: number): FunctionExpression; +export declare function arrayMaximum(arrayExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| base | string | The name of the field to raise to the power of the exponent. | -| exponent | number | The constant value to raise the base to the power of. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the power operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the maximum value. ### Example ```typescript -// Raise the value of the 'base' field to the power of 2. -pow("base", 2); +// Get the maximum value from the 'scores' array field +arrayMaximum(field("scores")); ``` -## function(booleanExpr, ...) - -### countIf(booleanExpr) {:#countif_c5b8fb1} +### arrayMaximumN(arrayExpression, n) {:#arraymaximumn_bff7f91} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. +Creates an expression that returns the largest `n` elements of an array. + +Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function countIf(booleanExpr: BooleanExpression): AggregateFunction; +export declare function arrayMaximumN(arrayExpression: Expression, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| booleanExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The boolean expression to evaluate on each input. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | number | The number of elements to return. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `AggregateFunction` representing the 'countIf' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the largest `n` elements. ### Example ```typescript -// Count the number of documents where 'is_active' field equals true -countIf(field("is_active").equal(true)).as("numActiveDocuments"); +// Get the top 3 elements from an array expression +arrayMaximumN(field("scores"), 3); ``` -### not(booleanExpr) {:#not_c5b8fb1} +### arrayMaximumN(arrayExpression, n) {:#arraymaximumn_19b4ef8} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that negates a filter condition. +Creates an expression that returns the largest `n` elements of an array. + +Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function not(booleanExpr: BooleanExpression): BooleanExpression; +export declare function arrayMaximumN(arrayExpression: Expression, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| booleanExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The filter condition to negate. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the negated filter condition. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the largest `n` elements. ### Example ```typescript -// Find documents where the 'completed' field is NOT true -not(equal("completed", true)); +// Get the top n elements from an array expression +arrayMaximumN(field("scores"), field("count")); ``` -## function(condition, ...) - -### conditional(condition, thenExpr, elseExpr) {:#conditional_07a206d} +### arrayMinimum(arrayExpression) {:#arrayminimum_f574e12} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. +Creates an expression that returns the minimum value in an array. Signature: ```typescript -export declare function conditional(condition: BooleanExpression, thenExpr: Expression, elseExpr: Expression): FunctionExpression; +export declare function arrayMinimum(arrayExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| condition | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The condition to evaluate. | -| thenExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is true. | -| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the conditional expression. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the minimum value. ### Example ```typescript -// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". -conditional( - greaterThan("age", 18), constant("Adult"), constant("Minor")); +// Get the minimum value from the 'scores' array field +arrayMinimum(field("scores")); ``` -## function(documentPath, ...) - -### documentId(documentPath) {:#documentid_cef293c} +### arrayMinimumN(arrayExpression, n) {:#arrayminimumn_bff7f91} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the document ID from a path. +Creates an expression that returns the smallest `n` elements of an array. + +Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function documentId(documentPath: string | DocumentReference): FunctionExpression; +export declare function arrayMinimumN(arrayExpression: Expression, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| documentPath | string \| [DocumentReference](./firestore_lite.documentreference.md#documentreference_class) | | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | number | The number of elements to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the smallest `n` elements. ### Example ```typescript -// Get the document ID from a path. -documentId(myDocumentReference); +// Get the bottom 3 scores from the 'scores' array field +arrayMinimumN(field("scores"), 3); ``` -## function(documentPathExpr, ...) - -### documentId(documentPathExpr) {:#documentid_9a69021} +### arrayMinimumN(arrayExpression, n) {:#arrayminimumn_19b4ef8} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the document ID from a path. +Creates an expression that returns the smallest `n` elements of an array. + +Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function documentId(documentPathExpr: Expression): FunctionExpression; +export declare function arrayMinimumN(arrayExpression: Expression, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| documentPathExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the smallest `n` elements. ### Example ```typescript -// Get the document ID from a path. -documentId(field("__path__")); +// Get the bottom n scores from the 'scores' array field +arrayMinimumN(field("scores"), field("count")); ``` -## function(element, ...) - -### notEqualAny(element, values) {:#notequalany_c2c5bcb} +### join(arrayExpression, delimiterExpression) {:#join_313e6aa} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is not equal to any of the provided values or expressions. +Creates an expression that joins the elements of an array into a string. Signature: ```typescript -export declare function notEqualAny(element: Expression, values: Array): BooleanExpression; +export declare function join(arrayExpression: Expression, delimiterExpression: Expression): Expression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values to check against. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | +| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[Expression](./firestore_lite_pipelines.expression.md#expression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. +A new Expression representing the join operation. ### Example ```typescript -// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' -notEqualAny(field("status"), ["pending", field("rejectedStatus")]); +// Join an array of string using the delimiter from the 'separator' field. +join(array(['foo', 'bar']), field("separator")) ``` -### notEqualAny(element, arrayExpression) {:#notequalany_16b2851} +### join(arrayExpression, delimiter) {:#join_d088d29} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is not equal to any of the provided values or expressions. +Creates an expression that joins the elements of an array into a string. Signature: ```typescript -export declare function notEqualAny(element: Expression, arrayExpression: Expression): BooleanExpression; +export declare function join(arrayExpression: Expression, delimiter: string): Expression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The values to check against. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | +| delimiter | string | The string to use as a delimiter. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[Expression](./firestore_lite_pipelines.expression.md#expression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. +A new Expression representing the join operation. ### Example ```typescript -// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' -notEqualAny(field("status"), ["pending", field("rejectedStatus")]); +// Join the elements of the 'tags' field with a comma and space. +join(field("tags"), ", ") ``` -## function(elements, ...) +## function(arrayField, ...) -### array(elements) {:#array_7d853aa} +### arrayGet(arrayField, offset) {:#arrayget_3f58471} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that creates a Firestore array value from an input array. +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: ```typescript -export declare function array(elements: unknown[]): FunctionExpression; +export declare function arrayGet(arrayField: string, offset: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| elements | unknown\[\] | The input array to evaluate in the expression. | +| arrayField | string | The name of the array field. | +| offset | number | The index of the element to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the array function. +A new `Expression` representing the 'arrayGet' operation. ### Example ```typescript -// Create an array value from the input array and reference the 'baz' field value from the input document. -array(['bar', Field.of('baz')]).as('foo'); +// Return the value in the tags field array at index 1. +arrayGet('tags', 1); ``` -### map(elements) {:#map_ce5dee1} +### arrayGet(arrayField, offsetExpr) {:#arrayget_1904c9a} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that creates a Firestore map value from an input object. +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: ```typescript -export declare function map(elements: Record): FunctionExpression; +export declare function arrayGet(arrayField: string, offsetExpr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| elements | Record<string, unknown> | The input map to evaluate in the expression. | +| arrayField | string | The name of the array field. | +| offsetExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the map function. +A new `Expression` representing the 'arrayGet' operation. ### Example ```typescript -// Create a map from the input object and reference the 'baz' field value from the input document. -map({foo: 'bar', baz: Field.of('baz')}).as('data'); +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet('tags', field('favoriteTag')); ``` -## function(expr, ...) +## function(arrayFieldName, ...) -### abs(expr) {:#abs_005f3d4} +### join(arrayFieldName, delimiter) {:#join_478ef36} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the absolute value of a numeric value. +Creates an expression that joins the elements of an array into a string. Signature: ```typescript -export declare function abs(expr: Expression): FunctionExpression; +export declare function join(arrayFieldName: string, delimiter: string): Expression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compute the absolute value of. | +| arrayFieldName | string | The name of the field containing the array. | +| delimiter | string | The string to use as a delimiter. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +A new Expression representing the join operation. + +### Example + + +```typescript +// Join the elements of the 'tags' field with a comma and space. +join("tags", ", ") + +``` + +### join(arrayFieldName, delimiterExpression) {:#join_829294c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + +Signature: + +```typescript +export declare function join(arrayFieldName: string, delimiterExpression: Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayFieldName | string | The name of the field containing the array. | +| delimiterExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +A new Expression representing the join operation. + +### Example + + +```typescript +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +join('tags', field("separator")) + +``` + +## function(base, ...) + +### pow(base, exponent) {:#pow_e4a9e64} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base expression raised to the power of the exponent expression. + +Signature: + +```typescript +export declare function pow(base: Expression, exponent: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | +| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. +A new `Expression` representing the power operation. -### ascending(expr) {:#ascending_005f3d4} +### Example + + +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow(field("base"), field("exponent")); + +``` + +### pow(base, exponent) {:#pow_93eae7f} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. +Creates an expression that returns the value of the base expression raised to the power of the exponent. Signature: ```typescript -export declare function ascending(expr: Expression): Ordering; +export declare function pow(base: Expression, exponent: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to create an ascending ordering for. | +| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | +| exponent | number | The constant value to raise the base to the power of. | Returns: -[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Ordering` for ascending sorting. +A new `Expression` representing the power operation. ### Example ```typescript -// Sort documents by the 'name' field in lowercase in ascending order -firestore.pipeline().collection("users") - .sort(ascending(field("name").toLower())); +// Raise the value of the 'base' field to the power of 2. +pow(field("base"), 2); ``` -### byteLength(expr) {:#bytelength_005f3d4} +### pow(base, exponent) {:#pow_a237721} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. +Creates an expression that returns the value of the base field raised to the power of the exponent expression. Signature: ```typescript -export declare function byteLength(expr: Expression): FunctionExpression; +export declare function pow(base: string, exponent: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string. | +| base | string | The name of the field to raise to the power of the exponent. | +| exponent | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string in bytes. +A new `Expression` representing the power operation. ### Example ```typescript -// Calculate the length of the 'myString' field in bytes. -byteLength(field("myString")); +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow("base", field("exponent")); ``` -### countDistinct(expr) {:#countdistinct_3c28b08} +### pow(base, exponent) {:#pow_f4d7908} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that counts the number of distinct values of a field. +Creates an expression that returns the value of the base field raised to the power of the exponent. Signature: ```typescript -export declare function countDistinct(expr: Expression | string): AggregateFunction; +export declare function pow(base: string, exponent: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string | The expression or field to count distinct values of. | +| base | string | The name of the field to raise to the power of the exponent. | +| exponent | number | The constant value to raise the base to the power of. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the power operation. + +### Example + + +```typescript +// Raise the value of the 'base' field to the power of 2. +pow("base", 2); + +``` + +## function(booleanExpr, ...) + +### countIf(booleanExpr) {:#countif_c5b8fb1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. + +Signature: + +```typescript +export declare function countIf(booleanExpr: BooleanExpression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| booleanExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The boolean expression to evaluate on each input. | Returns: [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -A new `AggregateFunction` representing the 'count\_distinct' aggregation. +A new `AggregateFunction` representing the 'countIf' aggregation. -### descending(expr) {:#descending_005f3d4} +### Example + + +```typescript +// Count the number of documents where 'is_active' field equals true +countIf(field("is_active").equal(true)).as("numActiveDocuments"); + +``` + +### not(booleanExpr) {:#not_c5b8fb1} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. +Creates an expression that negates a filter condition. Signature: ```typescript -export declare function descending(expr: Expression): Ordering; +export declare function not(booleanExpr: BooleanExpression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to create a descending ordering for. | +| booleanExpr | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The filter condition to negate. | Returns: -[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new `Ordering` for descending sorting. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the negated filter condition. ### Example ```typescript -// Sort documents by the 'name' field in lowercase in descending order -firestore.pipeline().collection("users") - .sort(descending(field("name").toLower())); +// Find documents where the 'completed' field is NOT true +not(equal("completed", true)); ``` -### floor(expr) {:#floor_005f3d4} +## function(condition, ...) + +### conditional(condition, thenExpr, elseExpr) {:#conditional_07a206d} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the floor of a numeric value. +Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. Signature: ```typescript -export declare function floor(expr: Expression): FunctionExpression; +export declare function conditional(condition: BooleanExpression, thenExpr: Expression, elseExpr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compute the floor of. | +| condition | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The condition to evaluate. | +| thenExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is true. | +| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the floor of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the conditional expression. -### timestampToUnixMicros(expr) {:#timestamptounixmicros_005f3d4} +### Example + + +```typescript +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +conditional( + greaterThan("age", 18), constant("Adult"), constant("Minor")); + +``` + +## function(documentPath, ...) + +### documentId(documentPath) {:#documentid_cef293c} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +Creates an expression that returns the document ID from a path. Signature: ```typescript -export declare function timestampToUnixMicros(expr: Expression): FunctionExpression; +export declare function documentId(documentPath: string | DocumentReference): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| documentPath | string \| [DocumentReference](./firestore_lite.documentreference.md#documentreference_class) | | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of microseconds since epoch. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. ### Example ```typescript -// Convert the 'timestamp' field to microseconds since epoch. -timestampToUnixMicros(field("timestamp")); +// Get the document ID from a path. +documentId(myDocumentReference); ``` -### timestampToUnixMillis(expr) {:#timestamptounixmillis_005f3d4} +## function(documentPathExpr, ...) + +### documentId(documentPathExpr) {:#documentid_9a69021} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the document ID from a path. + +Signature: + +```typescript +export declare function documentId(documentPathExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| documentPathExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. + +### Example + + +```typescript +// Get the document ID from a path. +documentId(field("__path__")); + +``` + +## function(element, ...) + +### notEqualAny(element, values) {:#notequalany_c2c5bcb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to any of the provided values or expressions. + +Signature: + +```typescript +export declare function notEqualAny(element: Expression, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values to check against. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. + +### Example + + +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + +### notEqualAny(element, arrayExpression) {:#notequalany_16b2851} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to any of the provided values or expressions. + +Signature: + +```typescript +export declare function notEqualAny(element: Expression, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The values to check against. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. + +### Example + + +```typescript +// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + +## function(elements, ...) + +### array(elements) {:#array_7d853aa} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that creates a Firestore array value from an input array. + +Signature: + +```typescript +export declare function array(elements: unknown[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elements | unknown\[\] | The input array to evaluate in the expression. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the array function. + +### Example + + +```typescript +// Create an array value from the input array and reference the 'baz' field value from the input document. +array(['bar', Field.of('baz')]).as('foo'); + +``` + +### map(elements) {:#map_ce5dee1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that creates a Firestore map value from an input object. + +Signature: + +```typescript +export declare function map(elements: Record): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elements | Record<string, unknown> | The input map to evaluate in the expression. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the map function. + +### Example + + +```typescript +// Create a map from the input object and reference the 'baz' field value from the input document. +map({foo: 'bar', baz: Field.of('baz')}).as('data'); + +``` + +## function(expr, ...) + +### abs(expr) {:#abs_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the absolute value of a numeric value. + +Signature: + +```typescript +export declare function abs(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compute the absolute value of. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. + +### ascending(expr) {:#ascending_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. + +Signature: + +```typescript +export declare function ascending(expr: Expression): Ordering; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to create an ascending ordering for. | + +Returns: + +[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) + +A new `Ordering` for ascending sorting. + +### Example + + +```typescript +// Sort documents by the 'name' field in lowercase in ascending order +firestore.pipeline().collection("users") + .sort(ascending(field("name").toLower())); + +``` + +### byteLength(expr) {:#bytelength_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. + +Signature: + +```typescript +export declare function byteLength(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string in bytes. + +### Example + + +```typescript +// Calculate the length of the 'myString' field in bytes. +byteLength(field("myString")); + +``` + +### countDistinct(expr) {:#countdistinct_3c28b08} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of distinct values of a field. + +Signature: + +```typescript +export declare function countDistinct(expr: Expression | string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| string | The expression or field to count distinct values of. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'count\_distinct' aggregation. + +### descending(expr) {:#descending_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. + +Signature: + +```typescript +export declare function descending(expr: Expression): Ordering; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to create a descending ordering for. | + +Returns: + +[Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) + +A new `Ordering` for descending sorting. + +### Example + + +```typescript +// Sort documents by the 'name' field in lowercase in descending order +firestore.pipeline().collection("users") + .sort(descending(field("name").toLower())); + +``` + +### floor(expr) {:#floor_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the floor of a numeric value. + +Signature: + +```typescript +export declare function floor(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compute the floor of. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the floor of the numeric value. + +### timestampToUnixMicros(expr) {:#timestamptounixmicros_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +Signature: + +```typescript +export declare function timestampToUnixMicros(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of microseconds since epoch. + +### Example + + +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros(field("timestamp")); + +``` + +### timestampToUnixMillis(expr) {:#timestamptounixmillis_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +Signature: + +```typescript +export declare function timestampToUnixMillis(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of milliseconds since epoch. + +### Example + + +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis(field("timestamp")); + +``` + +### timestampToUnixSeconds(expr) {:#timestamptounixseconds_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +Signature: + +```typescript +export declare function timestampToUnixSeconds(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of seconds since epoch. + +### Example + + +```typescript +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds(field("timestamp")); + +``` + +### unixMicrosToTimestamp(expr) {:#unixmicrostotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +Signature: + +```typescript +export declare function unixMicrosToTimestamp(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of microseconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. + +### Example + + +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp(field("microseconds")); + +``` + +### unixMillisToTimestamp(expr) {:#unixmillistotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +Signature: + +```typescript +export declare function unixMillisToTimestamp(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of milliseconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. + +### Example + + +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp(field("milliseconds")); + +``` + +### unixSecondsToTimestamp(expr) {:#unixsecondstotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +Signature: + +```typescript +export declare function unixSecondsToTimestamp(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of seconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. + +### Example + + +```typescript +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp(field("seconds")); + +``` + +## function(expression, ...) + +### arrayAgg(expression) {:#arrayagg_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +export declare function arrayAgg(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to collect values from. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg' aggregation. + +### Example + + +```typescript +// Collect all tags from books into an array +arrayAgg(field("tags")).as("allTags"); + +``` + +### arrayAggDistinct(expression) {:#arrayaggdistinct_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +export declare function arrayAggDistinct(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to collect values from. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg\_distinct' aggregation. + +### Example + + +```typescript +// Collect all distinct tags from books into an array +arrayAggDistinct(field("tags")).as("allDistinctTags"); + +``` + +### arraySum(expression) {:#arraysum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. + +Signature: + +```typescript +export declare function arraySum(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric array, which the sum will be computed for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the sum of the elements in the array. + +### Example + + +```typescript +// Compute the sum of the elements in the 'scores' field. +arraySum(field("scores")); + +``` + +### average(expression) {:#average_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. + +Signature: + +```typescript +export declare function average(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the values to average. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'average' aggregation. + +### Example + + +```typescript +// Calculate the average age of users +average(field("age")).as("averageAge"); + +``` + +### ceil(expression) {:#ceil_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. + +Signature: + +```typescript +export declare function ceil(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the ceiling will be computed for. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ceiling of the numeric value. + +### Example + + +```typescript +// Compute the ceiling of the 'price' field. +ceil(field("price")); + +``` + +### collectionId(expression) {:#collectionid_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. + +Signature: + +```typescript +export declare function collectionId(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a path, which the collection ID will be extracted from. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the collectionId operation. + +### Example + + +```typescript +// Get the collection ID from a path. +collectionId(field("__name__")); + +``` + +### count(expression) {:#count_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. + +Signature: + +```typescript +export declare function count(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to count. | + +Returns: + +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'count' aggregation. + +### Example + + +```typescript +// Count the number of items where the price is greater than 10 +count(field("price").greaterThan(10)).as("expensiveItemCount"); + +``` + +### divide(expression, value) {:#divide_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides an expression by a constant value. + +Signature: + +```typescript +export declare function divide(expression: Expression, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to be divided. | +| value | unknown | The constant value to divide by. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the division operation. + +### Example + + +```typescript +// Divide the 'value' field by 10 +divide(field("value"), 10); + +``` + +### equal(expression, value) {:#equal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is equal to a constant value. + +Signature: + +```typescript +export declare function equal(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +A new `Expression` representing the equality comparison. + +### Example + + +```typescript +// Check if the 'age' field is equal to 21 +equal(field("age"), 21); + +``` + +### equalAny(expression, values) {:#equalany_7e759b5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. + +Signature: + +```typescript +export declare function equalAny(expression: Expression, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression whose results to compare. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values to check against. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. + +### Example + + +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny(field("category"), [constant("Electronics"), field("primaryType")]); + +``` + +### equalAny(expression, arrayExpression) {:#equalany_214ce68} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +Creates an expression that checks if an expression is equal to any of the provided values. Signature: ```typescript -export declare function timestampToUnixMillis(expr: Expression): FunctionExpression; +export declare function equalAny(expression: Expression, arrayExpression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression whose results to compare. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of milliseconds since epoch. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. ### Example ```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -timestampToUnixMillis(field("timestamp")); +// Check if the 'category' field is set to a value in the disabledCategories field +equalAny(field("category"), field('disabledCategories')); ``` -### timestampToUnixSeconds(expr) {:#timestamptounixseconds_005f3d4} +### exp(expression) {:#exp_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). +Creates an expression that computes e to the power of the expression's result. Signature: ```typescript -export declare function timestampToUnixSeconds(expr: Expression): FunctionExpression; +export declare function exp(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of seconds since epoch. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the exp of the numeric value. ### Example ```typescript -// Convert the 'timestamp' field to seconds since epoch. -timestampToUnixSeconds(field("timestamp")); +// Compute e to the power of 2. +exp(constant(2)); ``` -### unixMicrosToTimestamp(expr) {:#unixmicrostotimestamp_005f3d4} +### first(expression) {:#first_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +Creates an aggregation that finds the first value of an expression across multiple stage inputs. Signature: ```typescript -export declare function unixMicrosToTimestamp(expr: Expression): FunctionExpression; +export declare function first(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of microseconds since epoch. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the first value of. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'first' aggregation. ### Example ```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -unixMicrosToTimestamp(field("microseconds")); +// Find the first value of the 'rating' field +first(field("rating")).as("firstRating"); ``` -### unixMillisToTimestamp(expr) {:#unixmillistotimestamp_005f3d4} +### greaterThan(expression, value) {:#greaterthan_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +Creates an expression that checks if an expression is greater than a constant value. Signature: ```typescript -export declare function unixMillisToTimestamp(expr: Expression): FunctionExpression; +export declare function greaterThan(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of milliseconds since epoch. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. +A new `Expression` representing the greater than comparison. ### Example ```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -unixMillisToTimestamp(field("milliseconds")); +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), 18); ``` -### unixSecondsToTimestamp(expr) {:#unixsecondstotimestamp_005f3d4} +### greaterThanOrEqual(expression, value) {:#greaterthanorequal_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +Creates an expression that checks if an expression is greater than or equal to a constant value. Signature: ```typescript -export declare function unixSecondsToTimestamp(expr: Expression): FunctionExpression; +export declare function greaterThanOrEqual(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the number of seconds since epoch. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. +A new `Expression` representing the greater than or equal to comparison. ### Example ```typescript -// Interpret the 'seconds' field as seconds since epoch. -unixSecondsToTimestamp(field("seconds")); +// Check if the 'quantity' field is greater than or equal to 10 +greaterThanOrEqual(field("quantity"), 10); ``` -## function(expression, ...) - -### arrayAgg(expression) {:#arrayagg_1138a27} +### isType(expression, type) {:#istype_27398ce} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. +Creates an expression that checks if the result of an expression is of the given type. -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. +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. Signature: ```typescript -export declare function arrayAgg(expression: Expression): AggregateFunction; +export declare function isType(expression: Expression, type: Type): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to collect values from. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | +| type | [Type](./firestore_lite_pipelines.md#type) | The type to check for. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg' aggregation. +A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise. ### Example ```typescript -// Collect all tags from books into an array -arrayAgg(field("tags")).as("allTags"); +// Check if the result of a calculation is a number +isType(add('count', 1), 'number') ``` -### arrayAggDistinct(expression) {:#arrayaggdistinct_1138a27} +### last(expression) {:#last_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. - -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. +Creates an aggregation that finds the last value of an expression across multiple stage inputs. Signature: ```typescript -export declare function arrayAggDistinct(expression: Expression): AggregateFunction; +export declare function last(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to collect values from. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the last value of. | Returns: [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg\_distinct' aggregation. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'last' aggregation. ### Example ```typescript -// Collect all distinct tags from books into an array -arrayAggDistinct(field("tags")).as("allDistinctTags"); +// Find the last value of the 'rating' field +last(field("rating")).as("lastRating"); ``` -### arraySum(expression) {:#arraysum_1138a27} +### length\_2(expression) {:#length_2_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the sum of the elements in an array. +Creates an expression that calculates the length of a string, array, map, vector, or bytes. Signature: ```typescript -export declare function arraySum(expression: Expression): FunctionExpression; +declare function length_2(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric array, which the sum will be computed for. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the sum of the elements in the array. +A new `Expression` representing the length of the string, array, map, vector, or bytes. ### Example ```typescript -// Compute the sum of the elements in the 'scores' field. -arraySum(field("scores")); +// Get the length of the 'name' field. +length(field("name")); + +// Get the number of items in the 'cart' array. +length(field("cart")); ``` -### average(expression) {:#average_1138a27} +### lessThan(expression, value) {:#lessthan_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. +Creates an expression that checks if an expression is less than a constant value. Signature: ```typescript -export declare function average(expression: Expression): AggregateFunction; +export declare function lessThan(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the values to average. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'average' aggregation. +A new `Expression` representing the less than comparison. ### Example ```typescript -// Calculate the average age of users -average(field("age")).as("averageAge"); +// Check if the 'age' field is less than 30 +lessThan(field("age"), 30); ``` -### ceil(expression) {:#ceil_1138a27} +### lessThanOrEqual(expression, value) {:#lessthanorequal_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the ceiling of a numeric value. +Creates an expression that checks if an expression is less than or equal to a constant value. Signature: ```typescript -export declare function ceil(expression: Expression): FunctionExpression; +export declare function lessThanOrEqual(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the ceiling will be computed for. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ceiling of the numeric value. +A new `Expression` representing the less than or equal to comparison. ### Example ```typescript -// Compute the ceiling of the 'price' field. -ceil(field("price")); +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), 20); ``` -### collectionId(expression) {:#collectionid_1138a27} +### ln(expression) {:#ln_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the collection ID from a path. +Creates an expression that computes the natural logarithm of a numeric value. Signature: ```typescript -export declare function collectionId(expression: Expression): FunctionExpression; +export declare function ln(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a path, which the collection ID will be extracted from. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the natural logarithm will be computed for. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the collectionId operation. +A new `Expression` representing the natural logarithm of the numeric value. ### Example ```typescript -// Get the collection ID from a path. -collectionId(field("__name__")); +// Compute the natural logarithm of the 'value' field. +ln(field("value")); ``` -### count(expression) {:#count_1138a27} +### log(expression, base) {:#log_ac183e2} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. +Creates an expression that computes the logarithm of an expression to a given base. Signature: ```typescript -export declare function count(expression: Expression): AggregateFunction; +export declare function log(expression: Expression, base: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to count. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | +| base | number | The base of the logarithm. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'count' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. ### Example ```typescript -// Count the number of items where the price is greater than 10 -count(field("price").greaterThan(10)).as("expensiveItemCount"); +// Compute the logarithm of the 'value' field with base 10. +log(field("value"), 10); ``` -### divide(expression, value) {:#divide_01df3cf} +### log(expression, base) {:#log_1894737} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that divides an expression by a constant value. +Creates an expression that computes the logarithm of an expression to a given base. Signature: ```typescript -export declare function divide(expression: Expression, value: unknown): FunctionExpression; +export declare function log(expression: Expression, base: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to be divided. | -| value | unknown | The constant value to divide by. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | +| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The base of the logarithm. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the division operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. ### Example ```typescript -// Divide the 'value' field by 10 -divide(field("value"), 10); +// Compute the logarithm of the 'value' field with the base in the 'base' field. +log(field("value"), field("base")); ``` -### equal(expression, value) {:#equal_01df3cf} +### log10(expression) {:#log10_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is equal to a constant value. +Creates an expression that computes the base-10 logarithm of a numeric value. Signature: ```typescript -export declare function equal(expression: Expression, value: unknown): BooleanExpression; +export declare function log10(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the equality comparison. +A new `Expression` representing the base-10 logarithm of the numeric value. ### Example ```typescript -// Check if the 'age' field is equal to 21 -equal(field("age"), 21); +// Compute the base-10 logarithm of the 'value' field. +log10(field("value")); ``` -### equalAny(expression, values) {:#equalany_7e759b5} +### ltrim(expression, valueToTrim) {:#ltrim_775e2f2} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. +Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. Signature: ```typescript -export declare function equalAny(expression: Expression, values: Array): BooleanExpression; +export declare function ltrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression whose results to compare. | -| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The values to check against. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. ### Example ```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -equalAny(field("category"), [constant("Electronics"), field("primaryType")]); +// Trim whitespace from the beginning of the 'userInput' field +ltrim(field("userInput")); + +// Trim quotes from the beginning of the 'userInput' field +ltrim(field("userInput"), '"'); ``` -### equalAny(expression, arrayExpression) {:#equalany_214ce68} +### maximum(expression) {:#maximum_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is equal to any of the provided values. +Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. Signature: ```typescript -export declare function equalAny(expression: Expression, arrayExpression: Expression): BooleanExpression; +export declare function maximum(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression whose results to compare. | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the maximum value of. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'maximum' aggregation. ### Example ```typescript -// Check if the 'category' field is set to a value in the disabledCategories field -equalAny(field("category"), field('disabledCategories')); +// Find the highest score in a leaderboard +maximum(field("score")).as("highestScore"); ``` -### exp(expression) {:#exp_1138a27} +### minimum(expression) {:#minimum_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes e to the power of the expression's result. +Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. Signature: ```typescript -export declare function exp(expression: Expression): FunctionExpression; +export declare function minimum(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the minimum value of. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the exp of the numeric value. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'minimum' aggregation. ### Example ```typescript -// Compute e to the power of 2. -exp(constant(2)); +// Find the lowest price of all products +minimum(field("price")).as("lowestPrice"); ``` -### first(expression) {:#first_1138a27} +### mod(expression, value) {:#mod_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that finds the first value of an expression across multiple stage inputs. +Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. Signature: ```typescript -export declare function first(expression: Expression): AggregateFunction; +export declare function mod(expression: Expression, value: unknown): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the first value of. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The dividend expression. | +| value | unknown | The divisor constant. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'first' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the modulo operation. ### Example ```typescript -// Find the first value of the 'rating' field -first(field("rating")).as("firstRating"); +// Calculate the remainder of dividing 'field1' by 5. +mod(field("field1"), 5); ``` -### greaterThan(expression, value) {:#greaterthan_01df3cf} +### notEqual(expression, value) {:#notequal_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is greater than a constant value. +Creates an expression that checks if an expression is not equal to a constant value. Signature: ```typescript -export declare function greaterThan(expression: Expression, value: unknown): BooleanExpression; +export declare function notEqual(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters @@ -2364,1600 +3450,1602 @@ export declare function greaterThan(expression: Expression, value: unknown): Boo [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new `Expression` representing the greater than comparison. +A new `Expression` representing the inequality comparison. ### Example ```typescript -// Check if the 'age' field is greater than 18 -greaterThan(field("age"), 18); +// Check if the 'status' field is not equal to "completed" +notEqual(field("status"), "completed"); ``` -### greaterThanOrEqual(expression, value) {:#greaterthanorequal_01df3cf} +### round(expression) {:#round_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is greater than or equal to a constant value. +Creates an expression that rounds a numeric value to the nearest whole number. Signature: ```typescript -export declare function greaterThanOrEqual(expression: Expression, value: unknown): BooleanExpression; +export declare function round(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the greater than or equal to comparison. +A new `Expression` representing the rounded value. ### Example ```typescript -// Check if the 'quantity' field is greater than or equal to 10 -greaterThanOrEqual(field("quantity"), 10); +// Round the value of the 'price' field. +round(field("price")); ``` -### isType(expression, type) {:#istype_27398ce} +### round(expression, decimalPlaces) {:#round_a3a92d0} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if the result of an expression is of the given type. - -Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. +Creates an expression that rounds a numeric value to the specified number of decimal places. Signature: ```typescript -export declare function isType(expression: Expression, type: Type): BooleanExpression; +export declare function round(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | -| type | [Type](./firestore_lite_pipelines.md#type) | The type to check for. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | +| decimalPlaces | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise. +A new `Expression` representing the rounded value. ### Example ```typescript -// Check if the result of a calculation is a number -isType(add('count', 1), 'number') +// Round the value of the 'price' field to two decimal places. +round(field("price"), constant(2)); ``` -### last(expression) {:#last_1138a27} +### rtrim(expression, valueToTrim) {:#rtrim_775e2f2} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that finds the last value of an expression across multiple stage inputs. +Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. Signature: ```typescript -export declare function last(expression: Expression): AggregateFunction; +export declare function rtrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the last value of. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'last' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. ### Example ```typescript -// Find the last value of the 'rating' field -last(field("rating")).as("lastRating"); +// Trim whitespace from the end of the 'userInput' field +rtrim(field("userInput")); + +// Trim quotes from the end of the 'userInput' field +rtrim(field("userInput"), '"'); ``` -### length\_2(expression) {:#length_2_1138a27} +### split(expression, delimiter) {:#split_5b5612b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that calculates the length of a string, array, map, vector, or bytes. +Creates an expression that splits a string into an array of substrings based on the provided delimiter. Signature: ```typescript -declare function length_2(expression: Expression): FunctionExpression; +export declare function split(expression: Expression, delimiter: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split the result of this expression. | +| delimiter | string | Split on this delimiter. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the length of the string, array, map, vector, or bytes. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. ### Example ```typescript -// Get the length of the 'name' field. -length(field("name")); - -// Get the number of items in the 'cart' array. -length(field("cart")); +// Split the 'scoresCsv' field on delimiter ',' +split(field('scoresCsv'), ',') ``` -### lessThan(expression, value) {:#lessthan_01df3cf} +### split(expression, delimiter) {:#split_5a171ed} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is less than a constant value. +Creates an expression that splits a string into an array of substrings based on the provided delimiter. Signature: ```typescript -export declare function lessThan(expression: Expression, value: unknown): BooleanExpression; +export declare function split(expression: Expression, delimiter: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split the result of this expression. | +| delimiter | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the less than comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. ### Example ```typescript -// Check if the 'age' field is less than 30 -lessThan(field("age"), 30); +// Split the 'scores' field on delimiter ',' or ':' depending on the stored format +split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':')) ``` -### lessThanOrEqual(expression, value) {:#lessthanorequal_01df3cf} +### sqrt(expression) {:#sqrt_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is less than or equal to a constant value. +Creates an expression that computes the square root of a numeric value. Signature: ```typescript -export declare function lessThanOrEqual(expression: Expression, value: unknown): BooleanExpression; +export declare function sqrt(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the square root will be computed for. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the less than or equal to comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the square root of the numeric value. ### Example ```typescript -// Check if the 'quantity' field is less than or equal to 20 -lessThan(field("quantity"), 20); +// Compute the square root of the 'value' field. +sqrt(field("value")); ``` -### ln(expression) {:#ln_1138a27} +### stringIndexOf(expression, search) {:#stringindexof_6dfca5f} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the natural logarithm of a numeric value. +Creates an expression that finds the index of the first occurrence of a substring or byte sequence. Signature: ```typescript -export declare function ln(expression: Expression): FunctionExpression; +export declare function stringIndexOf(expression: Expression, search: string | Expression | Bytes): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the natural logarithm will be computed for. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| search | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the natural logarithm of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index of the first occurrence. ### Example ```typescript -// Compute the natural logarithm of the 'value' field. -ln(field("value")); +// Find the index of "foo" in the 'text' field +stringIndexOf(field("text"), "foo"); ``` -### log(expression, base) {:#log_ac183e2} +### stringRepeat(expression, repetitions) {:#stringrepeat_a55ba16} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the logarithm of an expression to a given base. +Creates an expression that repeats a string or byte array a specified number of times. Signature: ```typescript -export declare function log(expression: Expression, base: number): FunctionExpression; +export declare function stringRepeat(expression: Expression, repetitions: number | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | -| base | number | The base of the logarithm. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| repetitions | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The number of times to repeat the string or byte array. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the repeated string or byte array. ### Example ```typescript -// Compute the logarithm of the 'value' field with base 10. -log(field("value"), 10); +// Repeat the 'label' field 3 times +stringRepeat(field("label"), 3); ``` -### log(expression, base) {:#log_1894737} +### stringReplaceAll(expression, find, replacement) {:#stringreplaceall_197ecbe} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the logarithm of an expression to a given base. +Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. Signature: ```typescript -export declare function log(expression: Expression, base: Expression): FunctionExpression; +export declare function stringReplaceAll(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | -| base | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The base of the logarithm. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| find | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The replacement string or byte sequence. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with replacements. ### Example ```typescript -// Compute the logarithm of the 'value' field with the base in the 'base' field. -log(field("value"), field("base")); +// Replace all occurrences of "foo" with "bar" in the 'text' field +stringReplaceAll(field("text"), "foo", "bar"); ``` -### log10(expression) {:#log10_1138a27} +### stringReplaceOne(expression, find, replacement) {:#stringreplaceone_197ecbe} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the base-10 logarithm of a numeric value. +Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. Signature: ```typescript -export declare function log10(expression: Expression): FunctionExpression; +export declare function stringReplaceOne(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| find | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The replacement string or byte sequence. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the base-10 logarithm of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with the replacement. ### Example ```typescript -// Compute the base-10 logarithm of the 'value' field. -log10(field("value")); +// Replace the first occurrence of "foo" with "bar" in the 'text' field +stringReplaceOne(field("text"), "foo", "bar"); ``` -### ltrim(expression, valueToTrim) {:#ltrim_775e2f2} +### subtract(expression, value) {:#subtract_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. +Creates an expression that subtracts a constant value from an expression. Signature: ```typescript -export declare function ltrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; +export declare function subtract(expression: Expression, value: unknown): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | -| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract from. | +| value | unknown | The constant value to subtract. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the subtraction operation. ### Example ```typescript -// Trim whitespace from the beginning of the 'userInput' field -ltrim(field("userInput")); - -// Trim quotes from the beginning of the 'userInput' field -ltrim(field("userInput"), '"'); +// Subtract the constant value 2 from the 'value' field +subtract(field("value"), 2); ``` -### maximum(expression) {:#maximum_1138a27} +### sum(expression) {:#sum_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. +Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. Signature: ```typescript -export declare function maximum(expression: Expression): AggregateFunction; +export declare function sum(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the maximum value of. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to sum up. | Returns: [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'maximum' aggregation. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'sum' aggregation. ### Example ```typescript -// Find the highest score in a leaderboard -maximum(field("score")).as("highestScore"); +// Calculate the total revenue from a set of orders +sum(field("orderAmount")).as("totalRevenue"); ``` -### minimum(expression) {:#minimum_1138a27} +### trunc(expression) {:#trunc_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. +Creates an expression that truncates the numeric value of an expression to an integer. Signature: ```typescript -export declare function minimum(expression: Expression): AggregateFunction; +export declare function trunc(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to find the minimum value of. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be truncated. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'minimum' aggregation. +A new `Expression` representing the truncated value. ### Example ```typescript -// Find the lowest price of all products -minimum(field("price")).as("lowestPrice"); +// Truncate the value of the 'rating' field. +trunc(field("rating")); ``` -### mod(expression, value) {:#mod_01df3cf} +### trunc(expression, decimalPlaces) {:#trunc_a3a92d0} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. +Creates an expression that truncates a numeric value to the specified number of decimal places. Signature: ```typescript -export declare function mod(expression: Expression, value: unknown): FunctionExpression; +export declare function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The dividend expression. | -| value | unknown | The divisor constant. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be truncated. | +| decimalPlaces | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A constant or expression specifying the truncation precision in decimal places. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the modulo operation. +A new `Expression` representing the truncated value. ### Example ```typescript -// Calculate the remainder of dividing 'field1' by 5. -mod(field("field1"), 5); +// Truncate the value of the 'rating' field to two decimal places. +trunc(field("rating"), constant(2)); ``` -### notEqual(expression, value) {:#notequal_01df3cf} +### type(expression) {:#type_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is not equal to a constant value. +Creates an expression that returns the data type of an expression's result. Signature: ```typescript -export declare function notEqual(expression: Expression, value: unknown): BooleanExpression; +export declare function type(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the inequality comparison. +A new `Expression` representing the data type. ### Example ```typescript -// Check if the 'status' field is not equal to "completed" -notEqual(field("status"), "completed"); +// Get the data type of a conditional expression +type(conditional(exists('foo'), constant(1), constant(true))) ``` -### round(expression) {:#round_1138a27} +## function(field, ...) + +### isAbsent(field) {:#isabsent_0fb8cd4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that rounds a numeric value to the nearest whole number. +Creates an expression that returns `true` if a field is absent. Otherwise, returns `false` even if the field value is `null`. Signature: ```typescript -export declare function round(expression: Expression): FunctionExpression; +export declare function isAbsent(field: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | +| field | string | The field to check. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new `Expression` representing the rounded value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'isAbsent' check. ### Example ```typescript -// Round the value of the 'price' field. -round(field("price")); +// Check if the field `value` is absent. +isAbsent("value"); ``` -### round(expression, decimalPlaces) {:#round_a3a92d0} +### reverse(field) {:#reverse_0fb8cd4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that rounds a numeric value to the specified number of decimal places. +Creates an expression that reverses a string value in the specified field. Signature: ```typescript -export declare function round(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; +export declare function reverse(field: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | -| decimalPlaces | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. | +| field | string | The name of the field representing the string to reverse. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the rounded value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. ### Example ```typescript -// Round the value of the 'price' field to two decimal places. -round(field("price"), constant(2)); +// Reverse the value of the 'myString' field. +reverse("myString"); ``` -### rtrim(expression, valueToTrim) {:#rtrim_775e2f2} +### stringReverse(field) {:#stringreverse_0fb8cd4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. +Creates an expression that reverses a string value in the specified field. Signature: ```typescript -export declare function rtrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; +export declare function stringReverse(field: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | -| valueToTrim | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | +| field | string | The name of the field representing the string to reverse. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. ### Example ```typescript -// Trim whitespace from the end of the 'userInput' field -rtrim(field("userInput")); - -// Trim quotes from the end of the 'userInput' field -rtrim(field("userInput"), '"'); +// Reverse the value of the 'myString' field. +strReverse("myString"); ``` -### split(expression, delimiter) {:#split_5b5612b} +### substring(field, position, length) {:#substring_0d9573a} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that splits a string into an array of substrings based on the provided delimiter. +Creates an expression that returns a substring of a string or byte array. Signature: ```typescript -export declare function split(expression: Expression, delimiter: string): FunctionExpression; +export declare function substring(field: string, position: number, length?: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split the result of this expression. | -| delimiter | string | Split on this delimiter. | +| field | string | The name of a field containing a string or byte array to compute the substring from. | +| position | number | Index of the first character of the substring. | +| length | number | Length of the substring. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. +### substring(field, position, length) {:#substring_05cb14e} -### Example +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> +Creates an expression that returns a substring of a string or byte array. -```typescript -// Split the 'scoresCsv' field on delimiter ',' -split(field('scoresCsv'), ',') +Signature: +```typescript +export declare function substring(field: string, position: Expression, length?: Expression): FunctionExpression; ``` -### split(expression, delimiter) {:#split_5a171ed} +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | string | The name of a field containing a string or byte array to compute the substring from. | +| position | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that returns the index of the first character of the substring. | +| length | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that returns the length of the substring. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +## function(fieldName, ...) + +### abs(fieldName) {:#abs_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that splits a string into an array of substrings based on the provided delimiter. +Creates an expression that computes the absolute value of a numeric value. Signature: ```typescript -export declare function split(expression: Expression, delimiter: Expression): FunctionExpression; +export declare function abs(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split the result of this expression. | -| delimiter | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. | +| fieldName | string | The field to compute the absolute value of. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. - -### Example - - -```typescript -// Split the 'scores' field on delimiter ',' or ':' depending on the stored format -split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':')) - -``` +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. -### sqrt(expression) {:#sqrt_1138a27} +### add(fieldName, second) {:#add_b75bb8b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the square root of a numeric value. +Creates an expression that adds a field's value to an expression. Signature: ```typescript -export declare function sqrt(expression: Expression): FunctionExpression; +export declare function add(fieldName: string, second: Expression | unknown): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the square root will be computed for. | +| fieldName | string | The name of the field containing the value to add. | +| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the square root of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the addition operation. ### Example ```typescript -// Compute the square root of the 'value' field. -sqrt(field("value")); +// Add the value of the 'quantity' field and the 'reserve' field. +add("quantity", field("reserve")); ``` -### stringIndexOf(expression, search) {:#stringindexof_6dfca5f} +### arrayAgg(fieldName) {:#arrayagg_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that finds the index of the first occurrence of a substring or byte sequence. +Creates an aggregation that collects all values of a field across multiple stage inputs into an array. + +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. Signature: ```typescript -export declare function stringIndexOf(expression: Expression, search: string | Expression | Bytes): FunctionExpression; +export declare function arrayAgg(fieldName: string): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | -| search | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| fieldName | string | The name of the field to collect values from. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index of the first occurrence. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg' aggregation. ### Example ```typescript -// Find the index of "foo" in the 'text' field -stringIndexOf(field("text"), "foo"); +// Collect all tags from books into an array +arrayAgg("tags").as("allTags"); ``` -### stringRepeat(expression, repetitions) {:#stringrepeat_a55ba16} +### arrayAggDistinct(fieldName) {:#arrayaggdistinct_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that repeats a string or byte array a specified number of times. +Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. + +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. Signature: ```typescript -export declare function stringRepeat(expression: Expression, repetitions: number | Expression): FunctionExpression; +export declare function arrayAggDistinct(fieldName: string): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | -| repetitions | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The number of times to repeat the string or byte array. | +| fieldName | string | The name of the field to collect values from. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the repeated string or byte array. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg\_distinct' aggregation. ### Example ```typescript -// Repeat the 'label' field 3 times -stringRepeat(field("label"), 3); +// Collect all distinct tags from books into an array +arrayAggDistinct("tags").as("allDistinctTags"); ``` -### stringReplaceAll(expression, find, replacement) {:#stringreplaceall_197ecbe} +### arrayContains(fieldName, element) {:#arraycontains_aaace4a} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. +Creates an expression that checks if a field's array value contains a specific element. Signature: ```typescript -export declare function stringReplaceAll(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +export declare function arrayContains(fieldName: string, element: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | -| find | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | -| replacement | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The replacement string or byte sequence. | +| fieldName | string | The field name to check. | +| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The element to search for in the array. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with replacements. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. ### Example ```typescript -// Replace all occurrences of "foo" with "bar" in the 'text' field -stringReplaceAll(field("text"), "foo", "bar"); +// Check if the 'colors' array contains the value of field 'selectedColor' +arrayContains("colors", field("selectedColor")); ``` -### stringReplaceOne(expression, find, replacement) {:#stringreplaceone_197ecbe} +### arrayContains(fieldName, element) {:#arraycontains_999590f} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. +Creates an expression that checks if a field's array value contains a specific value. Signature: ```typescript -export declare function stringReplaceOne(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +export declare function arrayContains(fieldName: string, element: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | -| find | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The substring or byte sequence to search for. | -| replacement | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| [Bytes](./firestore_lite.bytes.md#bytes_class) | The replacement string or byte sequence. | +| fieldName | string | The field name to check. | +| element | unknown | The element to search for in the array. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with the replacement. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. ### Example ```typescript -// Replace the first occurrence of "foo" with "bar" in the 'text' field -stringReplaceOne(field("text"), "foo", "bar"); +// Check if the 'colors' array contains "red" +arrayContains("colors", "red"); ``` -### subtract(expression, value) {:#subtract_01df3cf} +### arrayContainsAll(fieldName, values) {:#arraycontainsall_8060b23} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that subtracts a constant value from an expression. +Creates an expression that checks if a field's array value contains all the specified values or expressions. Signature: ```typescript -export declare function subtract(expression: Expression, value: unknown): FunctionExpression; +export declare function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to subtract from. | -| value | unknown | The constant value to subtract. | +| fieldName | string | The field name to check. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the subtraction operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. ### Example ```typescript -// Subtract the constant value 2 from the 'value' field -subtract(field("value"), 2); +// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" +arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); ``` -### sum(expression) {:#sum_1138a27} +### arrayContainsAll(fieldName, arrayExpression) {:#arraycontainsall_48da8d9} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. +Creates an expression that checks if a field's array value contains all the specified values or expressions. Signature: ```typescript -export declare function sum(expression: Expression): AggregateFunction; +export declare function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to sum up. | +| fieldName | string | The field name to check. | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'sum' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. ### Example ```typescript -// Calculate the total revenue from a set of orders -sum(field("orderAmount")).as("totalRevenue"); +// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" +arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); ``` -### trunc(expression) {:#trunc_1138a27} +### arrayContainsAny(fieldName, values) {:#arraycontainsany_8060b23} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that truncates the numeric value of an expression to an integer. +Creates an expression that checks if a field's array value contains any of the specified elements. Signature: ```typescript -export declare function trunc(expression: Expression): FunctionExpression; +export declare function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be truncated. | +| fieldName | string | The field name to check. | +| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new `Expression` representing the truncated value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. ### Example ```typescript -// Truncate the value of the 'rating' field. -trunc(field("rating")); +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +arrayContainsAny("categories", [field("cate1"), "Science"]); ``` -### trunc(expression, decimalPlaces) {:#trunc_a3a92d0} +### arrayContainsAny(fieldName, values) {:#arraycontainsany_1b4f7cd} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that truncates a numeric value to the specified number of decimal places. +Creates an expression that checks if a field's array value contains any of the specified elements. Signature: ```typescript -export declare function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; +export declare function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be truncated. | -| decimalPlaces | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | A constant or expression specifying the truncation precision in decimal places. | +| fieldName | string | The field name to check. | +| values | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array field. | Returns: -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) -A new `Expression` representing the truncated value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. ### Example ```typescript -// Truncate the value of the 'rating' field to two decimal places. -trunc(field("rating"), constant(2)); +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +arrayContainsAny("categories", array([field("cate1"), "Science"])); ``` -### type(expression) {:#type_1138a27} +### arrayFirst(fieldName) {:#arrayfirst_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the data type of an expression's result. +Creates an expression that returns the first element of an array. Signature: ```typescript -export declare function type(expression: Expression): FunctionExpression; +export declare function arrayFirst(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | +| fieldName | string | The name of the field containing the array. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the data type. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the first element. ### Example ```typescript -// Get the data type of a conditional expression -type(conditional(exists('foo'), constant(1), constant(true))) +// Get the first tag from the 'tags' array field +arrayFirst("tags"); ``` -## function(field, ...) - -### isAbsent(field) {:#isabsent_0fb8cd4} +### arrayFirstN(fieldName, n) {:#arrayfirstn_597a4d9} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns `true` if a field is absent. Otherwise, returns `false` even if the field value is `null`. +Creates an expression that returns the first `n` elements of an array. Signature: ```typescript -export declare function isAbsent(field: string): BooleanExpression; +export declare function arrayFirstN(fieldName: string, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| field | string | The field to check. | +| fieldName | string | The name of the field containing the array. | +| n | number | The number of elements to return. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'isAbsent' check. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the first `n` elements. ### Example ```typescript -// Check if the field `value` is absent. -isAbsent("value"); +// Get the first 3 tags from the 'tags' array field +arrayFirstN("tags", 3); ``` -### reverse(field) {:#reverse_0fb8cd4} +### arrayFirstN(fieldName, n) {:#arrayfirstn_1a86a2c} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that reverses a string value in the specified field. +Creates an expression that returns the first `n` elements of an array. Signature: ```typescript -export declare function reverse(field: string): FunctionExpression; +export declare function arrayFirstN(fieldName: string, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| field | string | The name of the field representing the string to reverse. | +| fieldName | string | The name of the field containing the array. | +| n | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the first `n` elements. ### Example ```typescript -// Reverse the value of the 'myString' field. -reverse("myString"); +// Get the first n tags from the 'tags' array field +arrayFirstN("tags", field("count")); ``` -### stringReverse(field) {:#stringreverse_0fb8cd4} +### arrayIndexOf(fieldName, search) {:#arrayindexof_5e4c2c3} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that reverses a string value in the specified field. +Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. Signature: ```typescript -export declare function stringReverse(field: string): FunctionExpression; +export declare function arrayIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| field | string | The name of the field representing the string to reverse. | +| fieldName | string | The name of the field containing the array to search. | +| search | unknown \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The value to search for. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index. ### Example ```typescript -// Reverse the value of the 'myString' field. -strReverse("myString"); +// Get the index of "politics" in the 'tags' array field +arrayIndexOf("tags", "politics"); ``` -### substring(field, position, length) {:#substring_0d9573a} +### arrayIndexOfAll(fieldName, search) {:#arrayindexofall_5e4c2c3} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns a substring of a string or byte array. +Creates an expression that returns all indices of the search value in an array. Signature: ```typescript -export declare function substring(field: string, position: number, length?: number): FunctionExpression; +export declare function arrayIndexOfAll(fieldName: string, search: unknown | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| field | string | The name of a field containing a string or byte array to compute the substring from. | -| position | number | Index of the first character of the substring. | -| length | number | Length of the substring. | +| fieldName | string | The name of the field containing the array to search. | +| search | unknown \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The value to search for. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -### substring(field, position, length) {:#substring_05cb14e} - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the indices. -Creates an expression that returns a substring of a string or byte array. +### Example -Signature: ```typescript -export declare function substring(field: string, position: Expression, length?: Expression): FunctionExpression; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| field | string | The name of a field containing a string or byte array to compute the substring from. | -| position | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that returns the index of the first character of the substring. | -| length | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that returns the length of the substring. | +// Get all indices of 5 in the 'scores' array field +arrayIndexOfAll("scores", 5); -Returns: - -[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) - -## function(fieldName, ...) +``` -### abs(fieldName) {:#abs_e5b0480} +### arrayLast(fieldName) {:#arraylast_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the absolute value of a numeric value. +Creates an expression that returns the last element of an array. Signature: ```typescript -export declare function abs(fieldName: string): FunctionExpression; +export declare function arrayLast(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field to compute the absolute value of. | +| fieldName | string | The name of the field containing the array. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the last element. -### add(fieldName, second) {:#add_b75bb8b} +### Example + + +```typescript +// Get the last tag from the 'tags' array field +arrayLast("tags"); + +``` + +### arrayLastIndexOf(fieldName, search) {:#arraylastindexof_5e4c2c3} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that adds a field's value to an expression. +Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. Signature: ```typescript -export declare function add(fieldName: string, second: Expression | unknown): FunctionExpression; +export declare function arrayLastIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the value to add. | -| second | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | +| fieldName | string | The name of the field containing the array to search. | +| search | unknown \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The value to search for. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the addition operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index. ### Example ```typescript -// Add the value of the 'quantity' field and the 'reserve' field. -add("quantity", field("reserve")); +// Get the last index of "politics" in the 'tags' array field +arrayLastIndexOf("tags", "politics"); ``` -### arrayAgg(fieldName) {:#arrayagg_e5b0480} +### arrayLastN(fieldName, n) {:#arraylastn_597a4d9} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that collects all values of a field across multiple stage inputs into an array. - -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. +Creates an expression that returns the last `n` elements of an array. Signature: ```typescript -export declare function arrayAgg(fieldName: string): AggregateFunction; +export declare function arrayLastN(fieldName: string, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to collect values from. | +| fieldName | string | The name of the field containing the array. | +| n | number | The number of elements to return. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the last `n` elements. ### Example ```typescript -// Collect all tags from books into an array -arrayAgg("tags").as("allTags"); +// Get the last 3 tags from the 'tags' array field +arrayLastN("tags", 3); ``` -### arrayAggDistinct(fieldName) {:#arrayaggdistinct_e5b0480} +### arrayLastN(fieldName, n) {:#arraylastn_1a86a2c} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. - -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. +Creates an expression that returns the last `n` elements of an array. Signature: ```typescript -export declare function arrayAggDistinct(fieldName: string): AggregateFunction; +export declare function arrayLastN(fieldName: string, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to collect values from. | +| fieldName | string | The name of the field containing the array. | +| n | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: -[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg\_distinct' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the last `n` elements. ### Example ```typescript -// Collect all distinct tags from books into an array -arrayAggDistinct("tags").as("allDistinctTags"); +// Get the last n tags from the 'tags' array field +arrayLastN("tags", field("count")); ``` -### arrayContains(fieldName, element) {:#arraycontains_aaace4a} +### arrayLength(fieldName) {:#arraylength_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if a field's array value contains a specific element. +Creates an expression that calculates the length of an array in a specified field. Signature: ```typescript -export declare function arrayContains(fieldName: string, element: Expression): BooleanExpression; +export declare function arrayLength(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| element | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The element to search for in the array. | +| fieldName | string | The name of the field containing an array to calculate the length of. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the array. ### Example ```typescript -// Check if the 'colors' array contains the value of field 'selectedColor' -arrayContains("colors", field("selectedColor")); +// Get the number of items in field 'cart' +arrayLength('cart'); ``` -### arrayContains(fieldName, element) {:#arraycontains_999590f} +### arrayMaximum(fieldName) {:#arraymaximum_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if a field's array value contains a specific value. +Creates an expression that returns the maximum value in an array. Signature: ```typescript -export declare function arrayContains(fieldName: string, element: unknown): BooleanExpression; +export declare function arrayMaximum(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| element | unknown | The element to search for in the array. | +| fieldName | string | The name of the field containing the array. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the maximum value. ### Example ```typescript -// Check if the 'colors' array contains "red" -arrayContains("colors", "red"); +// Get the maximum value from the 'scores' array field +arrayMaximum("scores"); ``` -### arrayContainsAll(fieldName, values) {:#arraycontainsall_8060b23} +### arrayMaximumN(fieldName, n) {:#arraymaximumn_597a4d9} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if a field's array value contains all the specified values or expressions. +Creates an expression that returns the largest `n` elements of an array. + +Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; +export declare function arrayMaximumN(fieldName: string, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | +| fieldName | string | The name of the field containing the array. | +| n | number | The number of elements to return. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the largest `n` elements. ### Example ```typescript -// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" -arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); +// Get the top 3 scores from the 'scores' array field +arrayMaximumN("scores", 3); ``` -### arrayContainsAll(fieldName, arrayExpression) {:#arraycontainsall_48da8d9} +### arrayMaximumN(fieldName, n) {:#arraymaximumn_1a86a2c} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if a field's array value contains all the specified values or expressions. +Creates an expression that returns the largest `n` elements of an array. + +Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; +export declare function arrayMaximumN(fieldName: string, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The elements to check for in the array. | +| fieldName | string | The name of the field containing the array. | +| n | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the largest `n` elements. ### Example ```typescript -// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" -arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); +// Get the top n scores from the 'scores' array field +arrayMaximumN("scores", field("count")); ``` -### arrayContainsAny(fieldName, values) {:#arraycontainsany_8060b23} +### arrayMinimum(fieldName) {:#arrayminimum_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if a field's array value contains any of the specified elements. +Creates an expression that returns the minimum value in an array. Signature: ```typescript -export declare function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; +export declare function arrayMinimum(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| values | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | +| fieldName | string | The name of the field containing the array. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the minimum value. ### Example ```typescript -// Check if the 'groups' array contains either the value from the 'userGroup' field -// or the value "guest" -arrayContainsAny("categories", [field("cate1"), "Science"]); +// Get the minimum value from the 'scores' array field +arrayMinimum("scores"); ``` -### arrayContainsAny(fieldName, values) {:#arraycontainsany_1b4f7cd} +### arrayMinimumN(fieldName, n) {:#arrayminimumn_597a4d9} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if a field's array value contains any of the specified elements. +Creates an expression that returns the smallest `n` elements of an array. + +Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; +export declare function arrayMinimumN(fieldName: string, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| values | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array field. | +| fieldName | string | The name of the field containing the array. | +| n | number | The number of elements to return. | Returns: -[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the smallest `n` elements. ### Example ```typescript -// Check if the 'groups' array contains either the value from the 'userGroup' field -// or the value "guest" -arrayContainsAny("categories", array([field("cate1"), "Science"])); +// Get the bottom 3 scores from the 'scores' array field +arrayMinimumN("scores", 3); ``` -### arrayLength(fieldName) {:#arraylength_e5b0480} +### arrayMinimumN(fieldName, n) {:#arrayminimumn_1a86a2c} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that calculates the length of an array in a specified field. +Creates an expression that returns the smallest `n` elements of an array. + +Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function arrayLength(fieldName: string): FunctionExpression; +export declare function arrayMinimumN(fieldName: string, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing an array to calculate the length of. | +| fieldName | string | The name of the field containing the array. | +| n | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the array. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the smallest `n` elements. ### Example ```typescript -// Get the number of items in field 'cart' -arrayLength('cart'); +// Get the bottom n scores from the 'scores' array field +arrayMinimumN(field("scores"), field("count")); ``` diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 9bd69b7d68..7e7c510b2a 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -48,9 +48,27 @@ export declare abstract class Expression | [arrayContainsAll(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. | | [arrayContainsAny(values)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. | | [arrayContainsAny(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. | +| [arrayFirst()](./firestore_pipelines.expression.md#expressionarrayfirst) | | (Public Preview) Returns the first element of the array. | +| [arrayFirstN(n)](./firestore_pipelines.expression.md#expressionarrayfirstn) | | (Public Preview) Returns the first n elements of the array. | +| [arrayFirstN(n)](./firestore_pipelines.expression.md#expressionarrayfirstn) | | (Public Preview) Returns the first n elements of the array. | | [arrayGet(offset)](./firestore_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | | [arrayGet(offsetExpr)](./firestore_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayIndexOf(search)](./firestore_pipelines.expression.md#expressionarrayindexof) | | (Public Preview) Returns the first index of the search value in the array, or -1 if not found. | +| [arrayIndexOf(search)](./firestore_pipelines.expression.md#expressionarrayindexof) | | (Public Preview) Returns the first index of the search value in the array, or -1 if not found. | +| [arrayIndexOfAll(search)](./firestore_pipelines.expression.md#expressionarrayindexofall) | | (Public Preview) Returns all indices of the search value in the array. | +| [arrayIndexOfAll(search)](./firestore_pipelines.expression.md#expressionarrayindexofall) | | (Public Preview) Returns all indices of the search value in the array. | +| [arrayLast()](./firestore_pipelines.expression.md#expressionarraylast) | | (Public Preview) Returns the last element of the array. | +| [arrayLastIndexOf(search)](./firestore_pipelines.expression.md#expressionarraylastindexof) | | (Public Preview) Returns the last index of the search value in the array, or -1 if not found. | +| [arrayLastIndexOf(search)](./firestore_pipelines.expression.md#expressionarraylastindexof) | | (Public Preview) Returns the last index of the search value in the array, or -1 if not found. | +| [arrayLastN(n)](./firestore_pipelines.expression.md#expressionarraylastn) | | (Public Preview) Returns the last n elements of the array. | +| [arrayLastN(n)](./firestore_pipelines.expression.md#expressionarraylastn) | | (Public Preview) Returns the last n elements of the array. | | [arrayLength()](./firestore_pipelines.expression.md#expressionarraylength) | | (Public Preview) Creates an expression that calculates the length of an array. | +| [arrayMaximum()](./firestore_pipelines.expression.md#expressionarraymaximum) | | (Public Preview) Returns the maximum value in the array. | +| [arrayMaximumN(n)](./firestore_pipelines.expression.md#expressionarraymaximumn) | | (Public Preview) Returns the largest n elements of the array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMaximumN(n)](./firestore_pipelines.expression.md#expressionarraymaximumn) | | (Public Preview) Returns the largest n elements of the array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimum()](./firestore_pipelines.expression.md#expressionarrayminimum) | | (Public Preview) Returns the minimum value in the array. | +| [arrayMinimumN(n)](./firestore_pipelines.expression.md#expressionarrayminimumn) | | (Public Preview) Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimumN(n)](./firestore_pipelines.expression.md#expressionarrayminimumn) | | (Public Preview) Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [arrayReverse()](./firestore_pipelines.expression.md#expressionarrayreverse) | | (Public Preview) Creates an expression that reverses an array. | | [arraySum()](./firestore_pipelines.expression.md#expressionarraysum) | | (Public Preview) Creates an expression that computes the sum of the elements in an array. | | [as(name)](./firestore_pipelines.expression.md#expressionas) | | (Public Preview) 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. | @@ -551,6 +569,101 @@ field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); ``` +## Expression.arrayFirst() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the first element of the array. + +Signature: + +```typescript +arrayFirst(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the first element. + +### Example + + +```typescript +// Get the first element of the 'myArray' field. +field("myArray").arrayFirst(); + +``` + +## Expression.arrayFirstN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the first `n` elements of the array. + +Signature: + +```typescript +arrayFirstN(n: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | number | The number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the first `n` elements. + +### Example + + +```typescript +// Get the first 3 elements of the 'myArray' field. +field("myArray").arrayFirstN(3); + +``` + +## Expression.arrayFirstN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the first `n` elements of the array. + +Signature: + +```typescript +arrayFirstN(n: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the first `n` elements. + +### Example + + +```typescript +// Get the first n elements of the 'myArray' field. +field("myArray").arrayFirstN(field("count")); + +``` + ## Expression.arrayGet() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -620,6 +733,305 @@ field('tags').arrayGet(field('favoriteTag')); ``` +## Expression.arrayIndexOf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the first index of the search value in the array, or -1 if not found. + +Signature: + +```typescript +arrayIndexOf(search: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | unknown | The value to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the index. + +### Example + + +```typescript +// Get the first index of the value 3 in the 'myArray' field. +field("myArray").arrayIndexOf(3); + +``` + +## Expression.arrayIndexOf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the first index of the search value in the array, or -1 if not found. + +Signature: + +```typescript +arrayIndexOf(search: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the value to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the index. + +### Example + + +```typescript +// Get the first index of the value in 'searchVal' field in the 'myArray' field. +field("myArray").arrayIndexOf(field("searchVal")); + +``` + +## Expression.arrayIndexOfAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all indices of the search value in the array. + +Signature: + +```typescript +arrayIndexOfAll(search: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | unknown | The value to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the indices. + +### Example + + +```typescript +// Get all indices of the value 3 in the 'myArray' field. +field("myArray").arrayIndexOfAll(3); + +``` + +## Expression.arrayIndexOfAll() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns all indices of the search value in the array. + +Signature: + +```typescript +arrayIndexOfAll(search: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the value to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the indices. + +### Example + + +```typescript +// Get all indices of the value in 'searchVal' field in the 'myArray' field. +field("myArray").arrayIndexOfAll(field("searchVal")); + +``` + +## Expression.arrayLast() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the last element of the array. + +Signature: + +```typescript +arrayLast(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the last element. + +### Example + + +```typescript +// Get the last element of the 'myArray' field. +field("myArray").arrayLast(); + +``` + +## Expression.arrayLastIndexOf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the last index of the search value in the array, or -1 if not found. + +Signature: + +```typescript +arrayLastIndexOf(search: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | unknown | The value to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the index. + +### Example + + +```typescript +// Get the last index of the value 3 in the 'myArray' field. +field("myArray").arrayLastIndexOf(3); + +``` + +## Expression.arrayLastIndexOf() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the last index of the search value in the array, or -1 if not found. + +Signature: + +```typescript +arrayLastIndexOf(search: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| search | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the value to search for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the index. + +### Example + + +```typescript +// Get the last index of the value in 'searchVal' field in the 'myArray' field. +field("myArray").arrayLastIndexOf(field("searchVal")); + +``` + +## Expression.arrayLastN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the last `n` elements of the array. + +Signature: + +```typescript +arrayLastN(n: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | number | The number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the last `n` elements. + +### Example + + +```typescript +// Get the last 3 elements of the 'myArray' field. +field("myArray").arrayLastN(3); + +``` + +## Expression.arrayLastN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the last `n` elements of the array. + +Signature: + +```typescript +arrayLastN(n: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the last `n` elements. + +### Example + + +```typescript +// Get the last n elements of the 'myArray' field. +field("myArray").arrayLastN(field("count")); + +``` + ## Expression.arrayLength() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -647,6 +1059,204 @@ field("cart").arrayLength(); ``` +## Expression.arrayMaximum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the maximum value in the array. + +Signature: + +```typescript +arrayMaximum(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the maximum value. + +### Example + + +```typescript +// Get the maximum value of the 'myArray' field. +field("myArray").arrayMaximum(); + +``` + +## Expression.arrayMaximumN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the largest `n` elements of the array. + +Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. + +Signature: + +```typescript +arrayMaximumN(n: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | number | The number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the largest `n` elements. + +### Example + + +```typescript +// Get the largest 3 elements of the 'myArray' field. +field("myArray").arrayMaximumN(3); + +``` + +## Expression.arrayMaximumN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the largest `n` elements of the array. + +Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. + +Signature: + +```typescript +arrayMaximumN(n: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the largest `n` elements. + +### Example + + +```typescript +// Get the largest n elements of the 'myArray' field. +field("myArray").arrayMaximumN(field("count")); + +``` + +## Expression.arrayMinimum() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the minimum value in the array. + +Signature: + +```typescript +arrayMinimum(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the minimum value. + +### Example + + +```typescript +// Get the minimum value of the 'myArray' field. +field("myArray").arrayMinimum(); + +``` + +## Expression.arrayMinimumN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the smallest `n` elements of the array. + +Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. + +Signature: + +```typescript +arrayMinimumN(n: number): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | number | The number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the smallest `n` elements. + +### Example + + +```typescript +// Get the smallest 3 elements of the 'myArray' field. +field("myArray").arrayMinimumN(3); + +``` + +## Expression.arrayMinimumN() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns the smallest `n` elements of the array. + +Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. + +Signature: + +```typescript +arrayMinimumN(n: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| n | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the smallest `n` elements. + +### Example + + +```typescript +// Get the smallest n elements of the 'myArray' field. +field("myArray").arrayMinimumN(field("count")); + +``` + ## Expression.arrayReverse() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index d6aea3a138..74a94359da 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -28,8 +28,23 @@ https://github.com/firebase/firebase-js-sdk | [arrayContainsAny(array, values)](./firestore_pipelines.md#arraycontainsany_c381a96) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. | | [arrayLength(array)](./firestore_pipelines.md#arraylength_195e339) | (Public Preview) Creates an expression that calculates the length of an array expression. | | function(arrayExpression, ...) | +| [arrayFirst(arrayExpression)](./firestore_pipelines.md#arrayfirst_f574e12) | (Public Preview) Creates an expression that returns the first element of an array. | +| [arrayFirstN(arrayExpression, n)](./firestore_pipelines.md#arrayfirstn_bff7f91) | (Public Preview) Creates an expression that returns the first n elements of an array. | +| [arrayFirstN(arrayExpression, n)](./firestore_pipelines.md#arrayfirstn_19b4ef8) | (Public Preview) Creates an expression that returns the first n elements of an array. | | [arrayGet(arrayExpression, offset)](./firestore_pipelines.md#arrayget_f2e27cc) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | | [arrayGet(arrayExpression, offsetExpr)](./firestore_pipelines.md#arrayget_484550d) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayIndexOf(arrayExpression, search)](./firestore_pipelines.md#arrayindexof_694a0b4) | (Public Preview) Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. | +| [arrayIndexOfAll(arrayExpression, search)](./firestore_pipelines.md#arrayindexofall_694a0b4) | (Public Preview) Creates an expression that returns all indices of the search value in an array. | +| [arrayLast(arrayExpression)](./firestore_pipelines.md#arraylast_f574e12) | (Public Preview) Creates an expression that returns the last element of an array. | +| [arrayLastIndexOf(arrayExpression, search)](./firestore_pipelines.md#arraylastindexof_694a0b4) | (Public Preview) Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. | +| [arrayLastN(arrayExpression, n)](./firestore_pipelines.md#arraylastn_bff7f91) | (Public Preview) Creates an expression that returns the last n elements of an array. | +| [arrayLastN(arrayExpression, n)](./firestore_pipelines.md#arraylastn_19b4ef8) | (Public Preview) Creates an expression that returns the last n elements of an array. | +| [arrayMaximum(arrayExpression)](./firestore_pipelines.md#arraymaximum_f574e12) | (Public Preview) Creates an expression that returns the maximum value in an array. | +| [arrayMaximumN(arrayExpression, n)](./firestore_pipelines.md#arraymaximumn_bff7f91) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMaximumN(arrayExpression, n)](./firestore_pipelines.md#arraymaximumn_19b4ef8) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimum(arrayExpression)](./firestore_pipelines.md#arrayminimum_f574e12) | (Public Preview) Creates an expression that returns the minimum value in an array. | +| [arrayMinimumN(arrayExpression, n)](./firestore_pipelines.md#arrayminimumn_bff7f91) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimumN(arrayExpression, n)](./firestore_pipelines.md#arrayminimumn_19b4ef8) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [join(arrayExpression, delimiterExpression)](./firestore_pipelines.md#join_313e6aa) | (Public Preview) Creates an expression that joins the elements of an array into a string. | | [join(arrayExpression, delimiter)](./firestore_pipelines.md#join_d088d29) | (Public Preview) Creates an expression that joins the elements of an array into a string. | | function(arrayField, ...) | @@ -133,7 +148,22 @@ https://github.com/firebase/firebase-js-sdk | [arrayContainsAll(fieldName, arrayExpression)](./firestore_pipelines.md#arraycontainsall_48da8d9) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. | | [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. | | [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_1b4f7cd) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. | +| [arrayFirst(fieldName)](./firestore_pipelines.md#arrayfirst_e5b0480) | (Public Preview) Creates an expression that returns the first element of an array. | +| [arrayFirstN(fieldName, n)](./firestore_pipelines.md#arrayfirstn_597a4d9) | (Public Preview) Creates an expression that returns the first n elements of an array. | +| [arrayFirstN(fieldName, n)](./firestore_pipelines.md#arrayfirstn_1a86a2c) | (Public Preview) Creates an expression that returns the first n elements of an array. | +| [arrayIndexOf(fieldName, search)](./firestore_pipelines.md#arrayindexof_5e4c2c3) | (Public Preview) Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. | +| [arrayIndexOfAll(fieldName, search)](./firestore_pipelines.md#arrayindexofall_5e4c2c3) | (Public Preview) Creates an expression that returns all indices of the search value in an array. | +| [arrayLast(fieldName)](./firestore_pipelines.md#arraylast_e5b0480) | (Public Preview) Creates an expression that returns the last element of an array. | +| [arrayLastIndexOf(fieldName, search)](./firestore_pipelines.md#arraylastindexof_5e4c2c3) | (Public Preview) Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. | +| [arrayLastN(fieldName, n)](./firestore_pipelines.md#arraylastn_597a4d9) | (Public Preview) Creates an expression that returns the last n elements of an array. | +| [arrayLastN(fieldName, n)](./firestore_pipelines.md#arraylastn_1a86a2c) | (Public Preview) Creates an expression that returns the last n elements of an array. | | [arrayLength(fieldName)](./firestore_pipelines.md#arraylength_e5b0480) | (Public Preview) Creates an expression that calculates the length of an array in a specified field. | +| [arrayMaximum(fieldName)](./firestore_pipelines.md#arraymaximum_e5b0480) | (Public Preview) Creates an expression that returns the maximum value in an array. | +| [arrayMaximumN(fieldName, n)](./firestore_pipelines.md#arraymaximumn_597a4d9) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMaximumN(fieldName, n)](./firestore_pipelines.md#arraymaximumn_1a86a2c) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimum(fieldName)](./firestore_pipelines.md#arrayminimum_e5b0480) | (Public Preview) Creates an expression that returns the minimum value in an array. | +| [arrayMinimumN(fieldName, n)](./firestore_pipelines.md#arrayminimumn_597a4d9) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimumN(fieldName, n)](./firestore_pipelines.md#arrayminimumn_1a86a2c) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [arraySum(fieldName)](./firestore_pipelines.md#arraysum_e5b0480) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | | [ascending(fieldName)](./firestore_pipelines.md#ascending_e5b0480) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. | | [average(fieldName)](./firestore_pipelines.md#average_e5b0480) | (Public Preview) Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. | @@ -758,150 +788,146 @@ arrayLength(field("cart")); ## function(arrayExpression, ...) -### arrayGet(arrayExpression, offset) {:#arrayget_f2e27cc} +### arrayFirst(arrayExpression) {:#arrayfirst_f574e12} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +Creates an expression that returns the first element of an array. Signature: ```typescript -export declare function arrayGet(arrayExpression: Expression, offset: number): FunctionExpression; +export declare function arrayFirst(arrayExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to an array. | -| offset | number | The index of the element to return. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the 'arrayGet' operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the first element. ### Example ```typescript -// Return the value in the tags field array at index 1. -arrayGet(field('tags'), 1); +// Get the first tag from the 'tags' array field +arrayFirst(field("tags")); ``` -### arrayGet(arrayExpression, offsetExpr) {:#arrayget_484550d} +### arrayFirstN(arrayExpression, n) {:#arrayfirstn_bff7f91} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +Creates an expression that returns the first `n` elements of an array. Signature: ```typescript -export declare function arrayGet(arrayExpression: Expression, offsetExpr: Expression): FunctionExpression; +export declare function arrayFirstN(arrayExpression: Expression, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to an array. | -| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | number | The number of elements to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the 'arrayGet' operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the first `n` elements. ### Example ```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -arrayGet(field('tags'), field('favoriteTag')); +// Get the first 3 elements from an array expression +arrayFirstN(field("tags"), 3); ``` -### join(arrayExpression, delimiterExpression) {:#join_313e6aa} +### arrayFirstN(arrayExpression, n) {:#arrayfirstn_19b4ef8} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that joins the elements of an array into a string. +Creates an expression that returns the first `n` elements of an array. Signature: ```typescript -export declare function join(arrayExpression: Expression, delimiterExpression: Expression): Expression; +export declare function arrayFirstN(arrayExpression: Expression, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | -| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: -[Expression](./firestore_pipelines.expression.md#expression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new Expression representing the join operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the first `n` elements. ### Example ```typescript -// Join an array of string using the delimiter from the 'separator' field. -join(array(['foo', 'bar']), field("separator")) +// Get the first n elements from an array expression +arrayFirstN(field("tags"), field("count")); ``` -### join(arrayExpression, delimiter) {:#join_d088d29} +### arrayGet(arrayExpression, offset) {:#arrayget_f2e27cc} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that joins the elements of an array into a string. +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: ```typescript -export declare function join(arrayExpression: Expression, delimiter: string): Expression; +export declare function arrayGet(arrayExpression: Expression, offset: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | -| delimiter | string | The string to use as a delimiter. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to an array. | +| offset | number | The index of the element to return. | Returns: -[Expression](./firestore_pipelines.expression.md#expression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new Expression representing the join operation. +A new `Expression` representing the 'arrayGet' operation. ### Example ```typescript -// Join the elements of the 'tags' field with a comma and space. -join(field("tags"), ", ") +// Return the value in the tags field array at index 1. +arrayGet(field('tags'), 1); ``` -## function(arrayField, ...) - -### arrayGet(arrayField, offset) {:#arrayget_3f58471} +### arrayGet(arrayExpression, offsetExpr) {:#arrayget_484550d} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -911,15 +937,15 @@ Creates an expression that indexes into an array from the beginning or end and r Signature: ```typescript -export declare function arrayGet(arrayField: string, offset: number): FunctionExpression; +export declare function arrayGet(arrayExpression: Expression, offsetExpr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayField | string | The name of the array field. | -| offset | number | The index of the element to return. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to an array. | +| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | Returns: @@ -931,1432 +957,2492 @@ A new `Expression` representing the 'arrayGet' operation. ```typescript -// Return the value in the tags field array at index 1. -arrayGet('tags', 1); +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet(field('tags'), field('favoriteTag')); ``` -### arrayGet(arrayField, offsetExpr) {:#arrayget_1904c9a} +### arrayIndexOf(arrayExpression, search) {:#arrayindexof_694a0b4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. +Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. Signature: ```typescript -export declare function arrayGet(arrayField: string, offsetExpr: Expression): FunctionExpression; +export declare function arrayIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayField | string | The name of the array field. | -| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array to search. | +| search | unknown \| [Expression](./firestore_pipelines.expression.md#expression_class) | The value to search for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the 'arrayGet' operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index. ### Example ```typescript -// Return the value in the tags field array at index specified by field -// 'favoriteTag'. -arrayGet('tags', field('favoriteTag')); +// Get the index of "politics" in the 'tags' array field +arrayIndexOf(field("tags"), "politics"); ``` -## function(arrayFieldName, ...) - -### join(arrayFieldName, delimiter) {:#join_478ef36} +### arrayIndexOfAll(arrayExpression, search) {:#arrayindexofall_694a0b4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that joins the elements of an array into a string. +Creates an expression that returns all indices of the search value in an array. Signature: ```typescript -export declare function join(arrayFieldName: string, delimiter: string): Expression; +export declare function arrayIndexOfAll(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayFieldName | string | The name of the field containing the array. | -| delimiter | string | The string to use as a delimiter. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array to search. | +| search | unknown \| [Expression](./firestore_pipelines.expression.md#expression_class) | The value to search for. | Returns: -[Expression](./firestore_pipelines.expression.md#expression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new Expression representing the join operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the indices. ### Example ```typescript -// Join the elements of the 'tags' field with a comma and space. -join("tags", ", ") +// Get all indices of 5 in the 'scores' array field +arrayIndexOfAll(field("scores"), 5); ``` -### join(arrayFieldName, delimiterExpression) {:#join_829294c} +### arrayLast(arrayExpression) {:#arraylast_f574e12} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that joins the elements of an array into a string. +Creates an expression that returns the last element of an array. Signature: ```typescript -export declare function join(arrayFieldName: string, delimiterExpression: Expression): Expression; +export declare function arrayLast(arrayExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| arrayFieldName | string | The name of the field containing the array. | -| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | Returns: -[Expression](./firestore_pipelines.expression.md#expression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new Expression representing the join operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the last element. ### Example ```typescript -// Join the elements of the 'tags' field with the delimiter from the 'separator' field. -join('tags', field("separator")) +// Get the last tag from the 'tags' array field +arrayLast(field("tags")); ``` -## function(base, ...) - -### pow(base, exponent) {:#pow_e4a9e64} +### arrayLastIndexOf(arrayExpression, search) {:#arraylastindexof_694a0b4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the value of the base expression raised to the power of the exponent expression. +Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. Signature: ```typescript -export declare function pow(base: Expression, exponent: Expression): FunctionExpression; +export declare function arrayLastIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | -| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array to search. | +| search | unknown \| [Expression](./firestore_pipelines.expression.md#expression_class) | The value to search for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the power operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index. ### Example ```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -pow(field("base"), field("exponent")); +// Get the last index of "politics" in the 'tags' array field +arrayLastIndexOf(field("tags"), "politics"); ``` -### pow(base, exponent) {:#pow_93eae7f} +### arrayLastN(arrayExpression, n) {:#arraylastn_bff7f91} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the value of the base expression raised to the power of the exponent. +Creates an expression that returns the last `n` elements of an array. Signature: ```typescript -export declare function pow(base: Expression, exponent: number): FunctionExpression; +export declare function arrayLastN(arrayExpression: Expression, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | -| exponent | number | The constant value to raise the base to the power of. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | number | The number of elements to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the power operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the last `n` elements. ### Example ```typescript -// Raise the value of the 'base' field to the power of 2. -pow(field("base"), 2); +// Get the last 3 elements from an array expression +arrayLastN(field("tags"), 3); ``` -### pow(base, exponent) {:#pow_a237721} +### arrayLastN(arrayExpression, n) {:#arraylastn_19b4ef8} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the value of the base field raised to the power of the exponent expression. +Creates an expression that returns the last `n` elements of an array. Signature: ```typescript -export declare function pow(base: string, exponent: Expression): FunctionExpression; +export declare function arrayLastN(arrayExpression: Expression, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| base | string | The name of the field to raise to the power of the exponent. | -| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the power operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the last `n` elements. ### Example ```typescript -// Raise the value of the 'base' field to the power of the 'exponent' field. -pow("base", field("exponent")); +// Get the last n elements from an array expression +arrayLastN(field("tags"), field("count")); ``` -### pow(base, exponent) {:#pow_f4d7908} +### arrayMaximum(arrayExpression) {:#arraymaximum_f574e12} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the value of the base field raised to the power of the exponent. +Creates an expression that returns the maximum value in an array. Signature: ```typescript -export declare function pow(base: string, exponent: number): FunctionExpression; +export declare function arrayMaximum(arrayExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| base | string | The name of the field to raise to the power of the exponent. | -| exponent | number | The constant value to raise the base to the power of. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the power operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the maximum value. ### Example ```typescript -// Raise the value of the 'base' field to the power of 2. -pow("base", 2); +// Get the maximum value from the 'scores' array field +arrayMaximum(field("scores")); ``` -## function(booleanExpr, ...) - -### countIf(booleanExpr) {:#countif_c5b8fb1} +### arrayMaximumN(arrayExpression, n) {:#arraymaximumn_bff7f91} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. +Creates an expression that returns the largest `n` elements of an array. + +Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function countIf(booleanExpr: BooleanExpression): AggregateFunction; +export declare function arrayMaximumN(arrayExpression: Expression, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| booleanExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The boolean expression to evaluate on each input. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | number | The number of elements to return. | Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `AggregateFunction` representing the 'countIf' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the largest `n` elements. ### Example ```typescript -// Count the number of documents where 'is_active' field equals true -countIf(field("is_active").equal(true)).as("numActiveDocuments"); +// Get the top 3 elements from an array expression +arrayMaximumN(field("scores"), 3); ``` -### not(booleanExpr) {:#not_c5b8fb1} +### arrayMaximumN(arrayExpression, n) {:#arraymaximumn_19b4ef8} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that negates a filter condition. +Creates an expression that returns the largest `n` elements of an array. + +Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function not(booleanExpr: BooleanExpression): BooleanExpression; +export declare function arrayMaximumN(arrayExpression: Expression, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| booleanExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The filter condition to negate. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the negated filter condition. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the largest `n` elements. ### Example ```typescript -// Find documents where the 'completed' field is NOT true -not(equal("completed", true)); +// Get the top n elements from an array expression +arrayMaximumN(field("scores"), field("count")); ``` -## function(condition, ...) - -### conditional(condition, thenExpr, elseExpr) {:#conditional_07a206d} +### arrayMinimum(arrayExpression) {:#arrayminimum_f574e12} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. +Creates an expression that returns the minimum value in an array. Signature: ```typescript -export declare function conditional(condition: BooleanExpression, thenExpr: Expression, elseExpr: Expression): FunctionExpression; +export declare function arrayMinimum(arrayExpression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| condition | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The condition to evaluate. | -| thenExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is true. | -| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the conditional expression. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the minimum value. ### Example ```typescript -// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". -conditional( - greaterThan("age", 18), constant("Adult"), constant("Minor")); +// Get the minimum value from the 'scores' array field +arrayMinimum(field("scores")); ``` -## function(documentPath, ...) - -### documentId(documentPath) {:#documentid_cef293c} +### arrayMinimumN(arrayExpression, n) {:#arrayminimumn_bff7f91} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the document ID from a path. +Creates an expression that returns the smallest `n` elements of an array. + +Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function documentId(documentPath: string | DocumentReference): FunctionExpression; +export declare function arrayMinimumN(arrayExpression: Expression, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| documentPath | string \| [DocumentReference](./firestore_.documentreference.md#documentreference_class) | | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | number | The number of elements to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the smallest `n` elements. ### Example ```typescript -// Get the document ID from a path. -documentId(myDocumentReference); +// Get the bottom 3 scores from the 'scores' array field +arrayMinimumN(field("scores"), 3); ``` -## function(documentPathExpr, ...) - -### documentId(documentPathExpr) {:#documentid_9a69021} +### arrayMinimumN(arrayExpression, n) {:#arrayminimumn_19b4ef8} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the document ID from a path. +Creates an expression that returns the smallest `n` elements of an array. + +Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function documentId(documentPathExpr: Expression): FunctionExpression; +export declare function arrayMinimumN(arrayExpression: Expression, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| documentPathExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | +| n | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the smallest `n` elements. ### Example ```typescript -// Get the document ID from a path. -documentId(field("__path__")); +// Get the bottom n scores from the 'scores' array field +arrayMinimumN(field("scores"), field("count")); ``` -## function(element, ...) - -### notEqualAny(element, values) {:#notequalany_c2c5bcb} +### join(arrayExpression, delimiterExpression) {:#join_313e6aa} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is not equal to any of the provided values or expressions. +Creates an expression that joins the elements of an array into a string. Signature: ```typescript -export declare function notEqualAny(element: Expression, values: Array): BooleanExpression; +export declare function join(arrayExpression: Expression, delimiterExpression: Expression): Expression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values to check against. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | +| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[Expression](./firestore_pipelines.expression.md#expression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. +A new Expression representing the join operation. ### Example ```typescript -// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' -notEqualAny(field("status"), ["pending", field("rejectedStatus")]); +// Join an array of string using the delimiter from the 'separator' field. +join(array(['foo', 'bar']), field("separator")) ``` -### notEqualAny(element, arrayExpression) {:#notequalany_16b2851} +### join(arrayExpression, delimiter) {:#join_d088d29} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is not equal to any of the provided values or expressions. +Creates an expression that joins the elements of an array into a string. Signature: ```typescript -export declare function notEqualAny(element: Expression, arrayExpression: Expression): BooleanExpression; +export declare function join(arrayExpression: Expression, delimiter: string): Expression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The values to check against. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array. | +| delimiter | string | The string to use as a delimiter. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[Expression](./firestore_pipelines.expression.md#expression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. +A new Expression representing the join operation. ### Example ```typescript -// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' -notEqualAny(field("status"), ["pending", field("rejectedStatus")]); +// Join the elements of the 'tags' field with a comma and space. +join(field("tags"), ", ") ``` -## function(elements, ...) +## function(arrayField, ...) -### array(elements) {:#array_7d853aa} +### arrayGet(arrayField, offset) {:#arrayget_3f58471} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that creates a Firestore array value from an input array. +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: ```typescript -export declare function array(elements: unknown[]): FunctionExpression; +export declare function arrayGet(arrayField: string, offset: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| elements | unknown\[\] | The input array to evaluate in the expression. | +| arrayField | string | The name of the array field. | +| offset | number | The index of the element to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the array function. +A new `Expression` representing the 'arrayGet' operation. ### Example ```typescript -// Create an array value from the input array and reference the 'baz' field value from the input document. -array(['bar', Field.of('baz')]).as('foo'); +// Return the value in the tags field array at index 1. +arrayGet('tags', 1); ``` -### map(elements) {:#map_ce5dee1} +### arrayGet(arrayField, offsetExpr) {:#arrayget_1904c9a} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that creates a Firestore map value from an input object. +Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: ```typescript -export declare function map(elements: Record): FunctionExpression; +export declare function arrayGet(arrayField: string, offsetExpr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| elements | Record<string, unknown> | The input map to evaluate in the expression. | +| arrayField | string | The name of the array field. | +| offsetExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to the index of the element to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the map function. +A new `Expression` representing the 'arrayGet' operation. ### Example ```typescript -// Create a map from the input object and reference the 'baz' field value from the input document. -map({foo: 'bar', baz: Field.of('baz')}).as('data'); +// Return the value in the tags field array at index specified by field +// 'favoriteTag'. +arrayGet('tags', field('favoriteTag')); ``` -## function(expr, ...) +## function(arrayFieldName, ...) -### abs(expr) {:#abs_005f3d4} +### join(arrayFieldName, delimiter) {:#join_478ef36} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the absolute value of a numeric value. +Creates an expression that joins the elements of an array into a string. Signature: ```typescript -export declare function abs(expr: Expression): FunctionExpression; +export declare function join(arrayFieldName: string, delimiter: string): Expression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compute the absolute value of. | +| arrayFieldName | string | The name of the field containing the array. | +| delimiter | string | The string to use as a delimiter. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +A new Expression representing the join operation. + +### Example + + +```typescript +// Join the elements of the 'tags' field with a comma and space. +join("tags", ", ") + +``` + +### join(arrayFieldName, delimiterExpression) {:#join_829294c} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that joins the elements of an array into a string. + +Signature: + +```typescript +export declare function join(arrayFieldName: string, delimiterExpression: Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayFieldName | string | The name of the field containing the array. | +| delimiterExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that evaluates to the delimiter string. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +A new Expression representing the join operation. + +### Example + + +```typescript +// Join the elements of the 'tags' field with the delimiter from the 'separator' field. +join('tags', field("separator")) + +``` + +## function(base, ...) + +### pow(base, exponent) {:#pow_e4a9e64} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the value of the base expression raised to the power of the exponent expression. + +Signature: + +```typescript +export declare function pow(base: Expression, exponent: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | +| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. +A new `Expression` representing the power operation. -### ascending(expr) {:#ascending_005f3d4} +### Example + + +```typescript +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow(field("base"), field("exponent")); + +``` + +### pow(base, exponent) {:#pow_93eae7f} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. +Creates an expression that returns the value of the base expression raised to the power of the exponent. Signature: ```typescript -export declare function ascending(expr: Expression): Ordering; +export declare function pow(base: Expression, exponent: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to create an ascending ordering for. | +| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise to the power of the exponent. | +| exponent | number | The constant value to raise the base to the power of. | Returns: -[Ordering](./firestore_pipelines.ordering.md#ordering_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Ordering` for ascending sorting. +A new `Expression` representing the power operation. ### Example ```typescript -// Sort documents by the 'name' field in lowercase in ascending order -firestore.pipeline().collection("users") - .sort(ascending(field("name").toLower())); +// Raise the value of the 'base' field to the power of 2. +pow(field("base"), 2); ``` -### byteLength(expr) {:#bytelength_005f3d4} +### pow(base, exponent) {:#pow_a237721} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. +Creates an expression that returns the value of the base field raised to the power of the exponent expression. Signature: ```typescript -export declare function byteLength(expr: Expression): FunctionExpression; +export declare function pow(base: string, exponent: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string. | +| base | string | The name of the field to raise to the power of the exponent. | +| exponent | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to raise the base to the power of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string in bytes. +A new `Expression` representing the power operation. ### Example ```typescript -// Calculate the length of the 'myString' field in bytes. -byteLength(field("myString")); +// Raise the value of the 'base' field to the power of the 'exponent' field. +pow("base", field("exponent")); ``` -### countDistinct(expr) {:#countdistinct_3c28b08} +### pow(base, exponent) {:#pow_f4d7908} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that counts the number of distinct values of a field. +Creates an expression that returns the value of the base field raised to the power of the exponent. Signature: ```typescript -export declare function countDistinct(expr: Expression | string): AggregateFunction; +export declare function pow(base: string, exponent: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) \| string | The expression or field to count distinct values of. | +| base | string | The name of the field to raise to the power of the exponent. | +| exponent | number | The constant value to raise the base to the power of. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the power operation. + +### Example + + +```typescript +// Raise the value of the 'base' field to the power of 2. +pow("base", 2); + +``` + +## function(booleanExpr, ...) + +### countIf(booleanExpr) {:#countif_c5b8fb1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. + +Signature: + +```typescript +export declare function countIf(booleanExpr: BooleanExpression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| booleanExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The boolean expression to evaluate on each input. | Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -A new `AggregateFunction` representing the 'count\_distinct' aggregation. +A new `AggregateFunction` representing the 'countIf' aggregation. -### descending(expr) {:#descending_005f3d4} +### Example + + +```typescript +// Count the number of documents where 'is_active' field equals true +countIf(field("is_active").equal(true)).as("numActiveDocuments"); + +``` + +### not(booleanExpr) {:#not_c5b8fb1} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. +Creates an expression that negates a filter condition. Signature: ```typescript -export declare function descending(expr: Expression): Ordering; +export declare function not(booleanExpr: BooleanExpression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to create a descending ordering for. | +| booleanExpr | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The filter condition to negate. | Returns: -[Ordering](./firestore_pipelines.ordering.md#ordering_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new `Ordering` for descending sorting. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the negated filter condition. ### Example ```typescript -// Sort documents by the 'name' field in lowercase in descending order -firestore.pipeline().collection("users") - .sort(descending(field("name").toLower())); +// Find documents where the 'completed' field is NOT true +not(equal("completed", true)); ``` -### floor(expr) {:#floor_005f3d4} +## function(condition, ...) + +### conditional(condition, thenExpr, elseExpr) {:#conditional_07a206d} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the floor of a numeric value. +Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. Signature: ```typescript -export declare function floor(expr: Expression): FunctionExpression; +export declare function conditional(condition: BooleanExpression, thenExpr: Expression, elseExpr: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compute the floor of. | +| condition | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The condition to evaluate. | +| thenExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is true. | +| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to evaluate if the condition is false. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the floor of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the conditional expression. -### timestampToUnixMicros(expr) {:#timestamptounixmicros_005f3d4} +### Example + + +```typescript +// If 'age' is greater than 18, return "Adult"; otherwise, return "Minor". +conditional( + greaterThan("age", 18), constant("Adult"), constant("Minor")); + +``` + +## function(documentPath, ...) + +### documentId(documentPath) {:#documentid_cef293c} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +Creates an expression that returns the document ID from a path. Signature: ```typescript -export declare function timestampToUnixMicros(expr: Expression): FunctionExpression; +export declare function documentId(documentPath: string | DocumentReference): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| documentPath | string \| [DocumentReference](./firestore_.documentreference.md#documentreference_class) | | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of microseconds since epoch. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. ### Example ```typescript -// Convert the 'timestamp' field to microseconds since epoch. -timestampToUnixMicros(field("timestamp")); +// Get the document ID from a path. +documentId(myDocumentReference); ``` -### timestampToUnixMillis(expr) {:#timestamptounixmillis_005f3d4} +## function(documentPathExpr, ...) + +### documentId(documentPathExpr) {:#documentid_9a69021} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the document ID from a path. + +Signature: + +```typescript +export declare function documentId(documentPathExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| documentPathExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the documentId operation. + +### Example + + +```typescript +// Get the document ID from a path. +documentId(field("__path__")); + +``` + +## function(element, ...) + +### notEqualAny(element, values) {:#notequalany_c2c5bcb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to any of the provided values or expressions. + +Signature: + +```typescript +export declare function notEqualAny(element: Expression, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values to check against. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. + +### Example + + +```typescript +// Check if the 'status' field is neither "pending" nor the value of 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + +### notEqualAny(element, arrayExpression) {:#notequalany_16b2851} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is not equal to any of the provided values or expressions. + +Signature: + +```typescript +export declare function notEqualAny(element: Expression, arrayExpression: Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The values to check against. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'NOT IN' comparison. + +### Example + + +```typescript +// Check if the 'status' field is neither "pending" nor the value of the field 'rejectedStatus' +notEqualAny(field("status"), ["pending", field("rejectedStatus")]); + +``` + +## function(elements, ...) + +### array(elements) {:#array_7d853aa} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that creates a Firestore array value from an input array. + +Signature: + +```typescript +export declare function array(elements: unknown[]): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elements | unknown\[\] | The input array to evaluate in the expression. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the array function. + +### Example + + +```typescript +// Create an array value from the input array and reference the 'baz' field value from the input document. +array(['bar', Field.of('baz')]).as('foo'); + +``` + +### map(elements) {:#map_ce5dee1} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that creates a Firestore map value from an input object. + +Signature: + +```typescript +export declare function map(elements: Record): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elements | Record<string, unknown> | The input map to evaluate in the expression. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the map function. + +### Example + + +```typescript +// Create a map from the input object and reference the 'baz' field value from the input document. +map({foo: 'bar', baz: Field.of('baz')}).as('data'); + +``` + +## function(expr, ...) + +### abs(expr) {:#abs_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the absolute value of a numeric value. + +Signature: + +```typescript +export declare function abs(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compute the absolute value of. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. + +### ascending(expr) {:#ascending_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. + +Signature: + +```typescript +export declare function ascending(expr: Expression): Ordering; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to create an ascending ordering for. | + +Returns: + +[Ordering](./firestore_pipelines.ordering.md#ordering_class) + +A new `Ordering` for ascending sorting. + +### Example + + +```typescript +// Sort documents by the 'name' field in lowercase in ascending order +firestore.pipeline().collection("users") + .sort(ascending(field("name").toLower())); + +``` + +### byteLength(expr) {:#bytelength_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. + +Signature: + +```typescript +export declare function byteLength(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the string in bytes. + +### Example + + +```typescript +// Calculate the length of the 'myString' field in bytes. +byteLength(field("myString")); + +``` + +### countDistinct(expr) {:#countdistinct_3c28b08} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of distinct values of a field. + +Signature: + +```typescript +export declare function countDistinct(expr: Expression | string): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) \| string | The expression or field to count distinct values of. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new `AggregateFunction` representing the 'count\_distinct' aggregation. + +### descending(expr) {:#descending_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. + +Signature: + +```typescript +export declare function descending(expr: Expression): Ordering; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to create a descending ordering for. | + +Returns: + +[Ordering](./firestore_pipelines.ordering.md#ordering_class) + +A new `Ordering` for descending sorting. + +### Example + + +```typescript +// Sort documents by the 'name' field in lowercase in descending order +firestore.pipeline().collection("users") + .sort(descending(field("name").toLower())); + +``` + +### floor(expr) {:#floor_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the floor of a numeric value. + +Signature: + +```typescript +export declare function floor(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compute the floor of. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the floor of the numeric value. + +### timestampToUnixMicros(expr) {:#timestamptounixmicros_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +Signature: + +```typescript +export declare function timestampToUnixMicros(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of microseconds since epoch. + +### Example + + +```typescript +// Convert the 'timestamp' field to microseconds since epoch. +timestampToUnixMicros(field("timestamp")); + +``` + +### timestampToUnixMillis(expr) {:#timestamptounixmillis_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +Signature: + +```typescript +export declare function timestampToUnixMillis(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of milliseconds since epoch. + +### Example + + +```typescript +// Convert the 'timestamp' field to milliseconds since epoch. +timestampToUnixMillis(field("timestamp")); + +``` + +### timestampToUnixSeconds(expr) {:#timestamptounixseconds_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). + +Signature: + +```typescript +export declare function timestampToUnixSeconds(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of seconds since epoch. + +### Example + + +```typescript +// Convert the 'timestamp' field to seconds since epoch. +timestampToUnixSeconds(field("timestamp")); + +``` + +### unixMicrosToTimestamp(expr) {:#unixmicrostotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +Signature: + +```typescript +export declare function unixMicrosToTimestamp(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of microseconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. + +### Example + + +```typescript +// Interpret the 'microseconds' field as microseconds since epoch. +unixMicrosToTimestamp(field("microseconds")); + +``` + +### unixMillisToTimestamp(expr) {:#unixmillistotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +Signature: + +```typescript +export declare function unixMillisToTimestamp(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of milliseconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. + +### Example + + +```typescript +// Interpret the 'milliseconds' field as milliseconds since epoch. +unixMillisToTimestamp(field("milliseconds")); + +``` + +### unixSecondsToTimestamp(expr) {:#unixsecondstotimestamp_005f3d4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. + +Signature: + +```typescript +export declare function unixSecondsToTimestamp(expr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of seconds since epoch. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. + +### Example + + +```typescript +// Interpret the 'seconds' field as seconds since epoch. +unixSecondsToTimestamp(field("seconds")); + +``` + +## function(expression, ...) + +### arrayAgg(expression) {:#arrayagg_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +export declare function arrayAgg(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to collect values from. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg' aggregation. + +### Example + + +```typescript +// Collect all tags from books into an array +arrayAgg(field("tags")).as("allTags"); + +``` + +### arrayAggDistinct(expression) {:#arrayaggdistinct_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. + +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. + +Signature: + +```typescript +export declare function arrayAggDistinct(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to collect values from. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg\_distinct' aggregation. + +### Example + + +```typescript +// Collect all distinct tags from books into an array +arrayAggDistinct(field("tags")).as("allDistinctTags"); + +``` + +### arraySum(expression) {:#arraysum_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the sum of the elements in an array. + +Signature: + +```typescript +export declare function arraySum(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric array, which the sum will be computed for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the sum of the elements in the array. + +### Example + + +```typescript +// Compute the sum of the elements in the 'scores' field. +arraySum(field("scores")); + +``` + +### average(expression) {:#average_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. + +Signature: + +```typescript +export declare function average(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the values to average. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'average' aggregation. + +### Example + + +```typescript +// Calculate the average age of users +average(field("age")).as("averageAge"); + +``` + +### ceil(expression) {:#ceil_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that computes the ceiling of a numeric value. + +Signature: + +```typescript +export declare function ceil(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the ceiling will be computed for. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ceiling of the numeric value. + +### Example + + +```typescript +// Compute the ceiling of the 'price' field. +ceil(field("price")); + +``` + +### collectionId(expression) {:#collectionid_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the collection ID from a path. + +Signature: + +```typescript +export declare function collectionId(expression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a path, which the collection ID will be extracted from. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the collectionId operation. + +### Example + + +```typescript +// Get the collection ID from a path. +collectionId(field("__name__")); + +``` + +### count(expression) {:#count_1138a27} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. + +Signature: + +```typescript +export declare function count(expression: Expression): AggregateFunction; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to count. | + +Returns: + +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) + +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'count' aggregation. + +### Example + + +```typescript +// Count the number of items where the price is greater than 10 +count(field("price").greaterThan(10)).as("expensiveItemCount"); + +``` + +### divide(expression, value) {:#divide_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that divides an expression by a constant value. + +Signature: + +```typescript +export declare function divide(expression: Expression, value: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to be divided. | +| value | unknown | The constant value to divide by. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the division operation. + +### Example + + +```typescript +// Divide the 'value' field by 10 +divide(field("value"), 10); + +``` + +### equal(expression, value) {:#equal_01df3cf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression is equal to a constant value. + +Signature: + +```typescript +export declare function equal(expression: Expression, value: unknown): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +A new `Expression` representing the equality comparison. + +### Example + + +```typescript +// Check if the 'age' field is equal to 21 +equal(field("age"), 21); + +``` + +### equalAny(expression, values) {:#equalany_7e759b5} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. + +Signature: + +```typescript +export declare function equalAny(expression: Expression, values: Array): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression whose results to compare. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values to check against. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. + +### Example + + +```typescript +// Check if the 'category' field is either "Electronics" or value of field 'primaryType' +equalAny(field("category"), [constant("Electronics"), field("primaryType")]); + +``` + +### equalAny(expression, arrayExpression) {:#equalany_214ce68} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). +Creates an expression that checks if an expression is equal to any of the provided values. Signature: ```typescript -export declare function timestampToUnixMillis(expr: Expression): FunctionExpression; +export declare function equalAny(expression: Expression, arrayExpression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression whose results to compare. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of milliseconds since epoch. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. ### Example ```typescript -// Convert the 'timestamp' field to milliseconds since epoch. -timestampToUnixMillis(field("timestamp")); +// Check if the 'category' field is set to a value in the disabledCategories field +equalAny(field("category"), field('disabledCategories')); ``` -### timestampToUnixSeconds(expr) {:#timestamptounixseconds_005f3d4} +### exp(expression) {:#exp_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). +Creates an expression that computes e to the power of the expression's result. Signature: ```typescript -export declare function timestampToUnixSeconds(expr: Expression): FunctionExpression; +export declare function exp(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the number of seconds since epoch. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the exp of the numeric value. ### Example ```typescript -// Convert the 'timestamp' field to seconds since epoch. -timestampToUnixSeconds(field("timestamp")); +// Compute e to the power of 2. +exp(constant(2)); ``` -### unixMicrosToTimestamp(expr) {:#unixmicrostotimestamp_005f3d4} +### first(expression) {:#first_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +Creates an aggregation that finds the first value of an expression across multiple stage inputs. Signature: ```typescript -export declare function unixMicrosToTimestamp(expr: Expression): FunctionExpression; +export declare function first(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of microseconds since epoch. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the first value of. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'first' aggregation. ### Example ```typescript -// Interpret the 'microseconds' field as microseconds since epoch. -unixMicrosToTimestamp(field("microseconds")); +// Find the first value of the 'rating' field +first(field("rating")).as("firstRating"); ``` -### unixMillisToTimestamp(expr) {:#unixmillistotimestamp_005f3d4} +### greaterThan(expression, value) {:#greaterthan_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +Creates an expression that checks if an expression is greater than a constant value. Signature: ```typescript -export declare function unixMillisToTimestamp(expr: Expression): FunctionExpression; +export declare function greaterThan(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of milliseconds since epoch. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. +A new `Expression` representing the greater than comparison. ### Example ```typescript -// Interpret the 'milliseconds' field as milliseconds since epoch. -unixMillisToTimestamp(field("milliseconds")); +// Check if the 'age' field is greater than 18 +greaterThan(field("age"), 18); ``` -### unixSecondsToTimestamp(expr) {:#unixsecondstotimestamp_005f3d4} +### greaterThanOrEqual(expression, value) {:#greaterthanorequal_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. +Creates an expression that checks if an expression is greater than or equal to a constant value. Signature: ```typescript -export declare function unixSecondsToTimestamp(expr: Expression): FunctionExpression; +export declare function greaterThanOrEqual(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the number of seconds since epoch. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the timestamp. +A new `Expression` representing the greater than or equal to comparison. ### Example ```typescript -// Interpret the 'seconds' field as seconds since epoch. -unixSecondsToTimestamp(field("seconds")); +// Check if the 'quantity' field is greater than or equal to 10 +greaterThanOrEqual(field("quantity"), 10); ``` -## function(expression, ...) - -### arrayAgg(expression) {:#arrayagg_1138a27} +### isType(expression, type) {:#istype_27398ce} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. +Creates an expression that checks if the result of an expression is of the given type. -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. +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. Signature: ```typescript -export declare function arrayAgg(expression: Expression): AggregateFunction; +export declare function isType(expression: Expression, type: Type): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to collect values from. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | +| type | [Type](./firestore_pipelines.md#type) | The type to check for. | Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg' aggregation. +A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise. ### Example ```typescript -// Collect all tags from books into an array -arrayAgg(field("tags")).as("allTags"); +// Check if the result of a calculation is a number +isType(add('count', 1), 'number') ``` -### arrayAggDistinct(expression) {:#arrayaggdistinct_1138a27} +### last(expression) {:#last_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. - -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. +Creates an aggregation that finds the last value of an expression across multiple stage inputs. Signature: ```typescript -export declare function arrayAggDistinct(expression: Expression): AggregateFunction; +export declare function last(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to collect values from. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the last value of. | Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg\_distinct' aggregation. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'last' aggregation. ### Example ```typescript -// Collect all distinct tags from books into an array -arrayAggDistinct(field("tags")).as("allDistinctTags"); +// Find the last value of the 'rating' field +last(field("rating")).as("lastRating"); ``` -### arraySum(expression) {:#arraysum_1138a27} +### length\_2(expression) {:#length_2_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the sum of the elements in an array. +Creates an expression that calculates the length of a string, array, map, vector, or bytes. Signature: ```typescript -export declare function arraySum(expression: Expression): FunctionExpression; +declare function length_2(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric array, which the sum will be computed for. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the sum of the elements in the array. +A new `Expression` representing the length of the string, array, map, vector, or bytes. ### Example ```typescript -// Compute the sum of the elements in the 'scores' field. -arraySum(field("scores")); +// Get the length of the 'name' field. +length(field("name")); + +// Get the number of items in the 'cart' array. +length(field("cart")); ``` -### average(expression) {:#average_1138a27} +### lessThan(expression, value) {:#lessthan_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. +Creates an expression that checks if an expression is less than a constant value. Signature: ```typescript -export declare function average(expression: Expression): AggregateFunction; +export declare function lessThan(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the values to average. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'average' aggregation. +A new `Expression` representing the less than comparison. ### Example ```typescript -// Calculate the average age of users -average(field("age")).as("averageAge"); +// Check if the 'age' field is less than 30 +lessThan(field("age"), 30); ``` -### ceil(expression) {:#ceil_1138a27} +### lessThanOrEqual(expression, value) {:#lessthanorequal_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the ceiling of a numeric value. +Creates an expression that checks if an expression is less than or equal to a constant value. Signature: ```typescript -export declare function ceil(expression: Expression): FunctionExpression; +export declare function lessThanOrEqual(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the ceiling will be computed for. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | +| value | unknown | The constant value to compare to. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ceiling of the numeric value. +A new `Expression` representing the less than or equal to comparison. ### Example ```typescript -// Compute the ceiling of the 'price' field. -ceil(field("price")); +// Check if the 'quantity' field is less than or equal to 20 +lessThan(field("quantity"), 20); ``` -### collectionId(expression) {:#collectionid_1138a27} +### ln(expression) {:#ln_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the collection ID from a path. +Creates an expression that computes the natural logarithm of a numeric value. Signature: ```typescript -export declare function collectionId(expression: Expression): FunctionExpression; +export declare function ln(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a path, which the collection ID will be extracted from. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the natural logarithm will be computed for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the collectionId operation. +A new `Expression` representing the natural logarithm of the numeric value. ### Example ```typescript -// Get the collection ID from a path. -collectionId(field("__name__")); +// Compute the natural logarithm of the 'value' field. +ln(field("value")); ``` -### count(expression) {:#count_1138a27} +### log(expression, base) {:#log_ac183e2} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. +Creates an expression that computes the logarithm of an expression to a given base. Signature: ```typescript -export declare function count(expression: Expression): AggregateFunction; +export declare function log(expression: Expression, base: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to count. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | +| base | number | The base of the logarithm. | Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'count' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. ### Example ```typescript -// Count the number of items where the price is greater than 10 -count(field("price").greaterThan(10)).as("expensiveItemCount"); +// Compute the logarithm of the 'value' field with base 10. +log(field("value"), 10); ``` -### divide(expression, value) {:#divide_01df3cf} +### log(expression, base) {:#log_1894737} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that divides an expression by a constant value. +Creates an expression that computes the logarithm of an expression to a given base. Signature: ```typescript -export declare function divide(expression: Expression, value: unknown): FunctionExpression; +export declare function log(expression: Expression, base: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to be divided. | -| value | unknown | The constant value to divide by. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | +| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The base of the logarithm. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the division operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. ### Example ```typescript -// Divide the 'value' field by 10 -divide(field("value"), 10); +// Compute the logarithm of the 'value' field with the base in the 'base' field. +log(field("value"), field("base")); ``` -### equal(expression, value) {:#equal_01df3cf} +### log10(expression) {:#log10_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is equal to a constant value. +Creates an expression that computes the base-10 logarithm of a numeric value. Signature: ```typescript -export declare function equal(expression: Expression, value: unknown): BooleanExpression; +export declare function log10(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the equality comparison. +A new `Expression` representing the base-10 logarithm of the numeric value. ### Example ```typescript -// Check if the 'age' field is equal to 21 -equal(field("age"), 21); +// Compute the base-10 logarithm of the 'value' field. +log10(field("value")); ``` -### equalAny(expression, values) {:#equalany_7e759b5} +### ltrim(expression, valueToTrim) {:#ltrim_775e2f2} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. +Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. Signature: ```typescript -export declare function equalAny(expression: Expression, values: Array): BooleanExpression; +export declare function ltrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression whose results to compare. | -| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The values to check against. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. ### Example ```typescript -// Check if the 'category' field is either "Electronics" or value of field 'primaryType' -equalAny(field("category"), [constant("Electronics"), field("primaryType")]); +// Trim whitespace from the beginning of the 'userInput' field +ltrim(field("userInput")); + +// Trim quotes from the beginning of the 'userInput' field +ltrim(field("userInput"), '"'); ``` -### equalAny(expression, arrayExpression) {:#equalany_214ce68} +### maximum(expression) {:#maximum_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is equal to any of the provided values. +Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. Signature: ```typescript -export declare function equalAny(expression: Expression, arrayExpression: Expression): BooleanExpression; +export declare function maximum(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression whose results to compare. | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for equality to the input. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the maximum value of. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'IN' comparison. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'maximum' aggregation. ### Example ```typescript -// Check if the 'category' field is set to a value in the disabledCategories field -equalAny(field("category"), field('disabledCategories')); +// Find the highest score in a leaderboard +maximum(field("score")).as("highestScore"); ``` -### exp(expression) {:#exp_1138a27} +### minimum(expression) {:#minimum_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes e to the power of the expression's result. +Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. Signature: ```typescript -export declare function exp(expression: Expression): FunctionExpression; +export declare function minimum(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the minimum value of. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the exp of the numeric value. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'minimum' aggregation. ### Example ```typescript -// Compute e to the power of 2. -exp(constant(2)); +// Find the lowest price of all products +minimum(field("price")).as("lowestPrice"); ``` -### first(expression) {:#first_1138a27} +### mod(expression, value) {:#mod_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that finds the first value of an expression across multiple stage inputs. +Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. Signature: ```typescript -export declare function first(expression: Expression): AggregateFunction; +export declare function mod(expression: Expression, value: unknown): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the first value of. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The dividend expression. | +| value | unknown | The divisor constant. | Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'first' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the modulo operation. ### Example ```typescript -// Find the first value of the 'rating' field -first(field("rating")).as("firstRating"); +// Calculate the remainder of dividing 'field1' by 5. +mod(field("field1"), 5); ``` -### greaterThan(expression, value) {:#greaterthan_01df3cf} +### notEqual(expression, value) {:#notequal_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is greater than a constant value. +Creates an expression that checks if an expression is not equal to a constant value. Signature: ```typescript -export declare function greaterThan(expression: Expression, value: unknown): BooleanExpression; +export declare function notEqual(expression: Expression, value: unknown): BooleanExpression; ``` #### Parameters @@ -2370,1600 +3456,1602 @@ export declare function greaterThan(expression: Expression, value: unknown): Boo [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new `Expression` representing the greater than comparison. +A new `Expression` representing the inequality comparison. ### Example ```typescript -// Check if the 'age' field is greater than 18 -greaterThan(field("age"), 18); +// Check if the 'status' field is not equal to "completed" +notEqual(field("status"), "completed"); ``` -### greaterThanOrEqual(expression, value) {:#greaterthanorequal_01df3cf} +### round(expression) {:#round_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is greater than or equal to a constant value. +Creates an expression that rounds a numeric value to the nearest whole number. Signature: ```typescript -export declare function greaterThanOrEqual(expression: Expression, value: unknown): BooleanExpression; +export declare function round(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the greater than or equal to comparison. +A new `Expression` representing the rounded value. ### Example ```typescript -// Check if the 'quantity' field is greater than or equal to 10 -greaterThanOrEqual(field("quantity"), 10); +// Round the value of the 'price' field. +round(field("price")); ``` -### isType(expression, type) {:#istype_27398ce} +### round(expression, decimalPlaces) {:#round_a3a92d0} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if the result of an expression is of the given type. - -Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. +Creates an expression that rounds a numeric value to the specified number of decimal places. Signature: ```typescript -export declare function isType(expression: Expression, type: Type): BooleanExpression; +export declare function round(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | -| type | [Type](./firestore_pipelines.md#type) | The type to check for. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | +| decimalPlaces | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise. +A new `Expression` representing the rounded value. ### Example ```typescript -// Check if the result of a calculation is a number -isType(add('count', 1), 'number') +// Round the value of the 'price' field to two decimal places. +round(field("price"), constant(2)); ``` -### last(expression) {:#last_1138a27} +### rtrim(expression, valueToTrim) {:#rtrim_775e2f2} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that finds the last value of an expression across multiple stage inputs. +Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. Signature: ```typescript -export declare function last(expression: Expression): AggregateFunction; +export declare function rtrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the last value of. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'last' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. ### Example ```typescript -// Find the last value of the 'rating' field -last(field("rating")).as("lastRating"); +// Trim whitespace from the end of the 'userInput' field +rtrim(field("userInput")); + +// Trim quotes from the end of the 'userInput' field +rtrim(field("userInput"), '"'); ``` -### length\_2(expression) {:#length_2_1138a27} +### split(expression, delimiter) {:#split_5b5612b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that calculates the length of a string, array, map, vector, or bytes. +Creates an expression that splits a string into an array of substrings based on the provided delimiter. Signature: ```typescript -declare function length_2(expression: Expression): FunctionExpression; +export declare function split(expression: Expression, delimiter: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a string, array, map, vector, or bytes, which the length will be calculated for. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | Split the result of this expression. | +| delimiter | string | Split on this delimiter. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the length of the string, array, map, vector, or bytes. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. ### Example ```typescript -// Get the length of the 'name' field. -length(field("name")); - -// Get the number of items in the 'cart' array. -length(field("cart")); +// Split the 'scoresCsv' field on delimiter ',' +split(field('scoresCsv'), ',') ``` -### lessThan(expression, value) {:#lessthan_01df3cf} +### split(expression, delimiter) {:#split_5a171ed} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is less than a constant value. +Creates an expression that splits a string into an array of substrings based on the provided delimiter. Signature: ```typescript -export declare function lessThan(expression: Expression, value: unknown): BooleanExpression; +export declare function split(expression: Expression, delimiter: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | Split the result of this expression. | +| delimiter | [Expression](./firestore_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the less than comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. ### Example ```typescript -// Check if the 'age' field is less than 30 -lessThan(field("age"), 30); +// Split the 'scores' field on delimiter ',' or ':' depending on the stored format +split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':')) ``` -### lessThanOrEqual(expression, value) {:#lessthanorequal_01df3cf} +### sqrt(expression) {:#sqrt_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is less than or equal to a constant value. +Creates an expression that computes the square root of a numeric value. Signature: ```typescript -export declare function lessThanOrEqual(expression: Expression, value: unknown): BooleanExpression; +export declare function sqrt(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the square root will be computed for. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the less than or equal to comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the square root of the numeric value. ### Example ```typescript -// Check if the 'quantity' field is less than or equal to 20 -lessThan(field("quantity"), 20); +// Compute the square root of the 'value' field. +sqrt(field("value")); ``` -### ln(expression) {:#ln_1138a27} +### stringIndexOf(expression, search) {:#stringindexof_6dfca5f} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the natural logarithm of a numeric value. +Creates an expression that finds the index of the first occurrence of a substring or byte sequence. Signature: ```typescript -export declare function ln(expression: Expression): FunctionExpression; +export declare function stringIndexOf(expression: Expression, search: string | Expression | Bytes): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the natural logarithm will be computed for. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| search | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the natural logarithm of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index of the first occurrence. ### Example ```typescript -// Compute the natural logarithm of the 'value' field. -ln(field("value")); +// Find the index of "foo" in the 'text' field +stringIndexOf(field("text"), "foo"); ``` -### log(expression, base) {:#log_ac183e2} +### stringRepeat(expression, repetitions) {:#stringrepeat_a55ba16} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the logarithm of an expression to a given base. +Creates an expression that repeats a string or byte array a specified number of times. Signature: ```typescript -export declare function log(expression: Expression, base: number): FunctionExpression; +export declare function stringRepeat(expression: Expression, repetitions: number | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | -| base | number | The base of the logarithm. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| repetitions | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | The number of times to repeat the string or byte array. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the repeated string or byte array. ### Example ```typescript -// Compute the logarithm of the 'value' field with base 10. -log(field("value"), 10); +// Repeat the 'label' field 3 times +stringRepeat(field("label"), 3); ``` -### log(expression, base) {:#log_1894737} +### stringReplaceAll(expression, find, replacement) {:#stringreplaceall_197ecbe} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the logarithm of an expression to a given base. +Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. Signature: ```typescript -export declare function log(expression: Expression, base: Expression): FunctionExpression; +export declare function stringReplaceAll(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the logarithm will be computed for. | -| base | [Expression](./firestore_pipelines.expression.md#expression_class) | The base of the logarithm. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| find | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The replacement string or byte sequence. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the logarithm of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with replacements. ### Example ```typescript -// Compute the logarithm of the 'value' field with the base in the 'base' field. -log(field("value"), field("base")); +// Replace all occurrences of "foo" with "bar" in the 'text' field +stringReplaceAll(field("text"), "foo", "bar"); ``` -### log10(expression) {:#log10_1138a27} +### stringReplaceOne(expression, find, replacement) {:#stringreplaceone_197ecbe} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the base-10 logarithm of a numeric value. +Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. Signature: ```typescript -export declare function log10(expression: Expression): FunctionExpression; +export declare function stringReplaceOne(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the base-10 logarithm will be computed for. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | +| find | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| replacement | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The replacement string or byte sequence. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the base-10 logarithm of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with the replacement. ### Example ```typescript -// Compute the base-10 logarithm of the 'value' field. -log10(field("value")); +// Replace the first occurrence of "foo" with "bar" in the 'text' field +stringReplaceOne(field("text"), "foo", "bar"); ``` -### ltrim(expression, valueToTrim) {:#ltrim_775e2f2} +### subtract(expression, value) {:#subtract_01df3cf} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. +Creates an expression that subtracts a constant value from an expression. Signature: ```typescript -export declare function ltrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; +export declare function subtract(expression: Expression, value: unknown): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | -| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract from. | +| value | unknown | The constant value to subtract. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the subtraction operation. ### Example ```typescript -// Trim whitespace from the beginning of the 'userInput' field -ltrim(field("userInput")); - -// Trim quotes from the beginning of the 'userInput' field -ltrim(field("userInput"), '"'); +// Subtract the constant value 2 from the 'value' field +subtract(field("value"), 2); ``` -### maximum(expression) {:#maximum_1138a27} +### sum(expression) {:#sum_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. +Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. Signature: ```typescript -export declare function maximum(expression: Expression): AggregateFunction; +export declare function sum(expression: Expression): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the maximum value of. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to sum up. | Returns: [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'maximum' aggregation. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'sum' aggregation. ### Example ```typescript -// Find the highest score in a leaderboard -maximum(field("score")).as("highestScore"); +// Calculate the total revenue from a set of orders +sum(field("orderAmount")).as("totalRevenue"); ``` -### minimum(expression) {:#minimum_1138a27} +### trunc(expression) {:#trunc_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. +Creates an expression that truncates the numeric value of an expression to an integer. Signature: ```typescript -export declare function minimum(expression: Expression): AggregateFunction; +export declare function trunc(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to find the minimum value of. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be truncated. | Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'minimum' aggregation. +A new `Expression` representing the truncated value. ### Example ```typescript -// Find the lowest price of all products -minimum(field("price")).as("lowestPrice"); +// Truncate the value of the 'rating' field. +trunc(field("rating")); ``` -### mod(expression, value) {:#mod_01df3cf} +### trunc(expression, decimalPlaces) {:#trunc_a3a92d0} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. +Creates an expression that truncates a numeric value to the specified number of decimal places. Signature: ```typescript -export declare function mod(expression: Expression, value: unknown): FunctionExpression; +export declare function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The dividend expression. | -| value | unknown | The divisor constant. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be truncated. | +| decimalPlaces | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | A constant or expression specifying the truncation precision in decimal places. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the modulo operation. +A new `Expression` representing the truncated value. ### Example ```typescript -// Calculate the remainder of dividing 'field1' by 5. -mod(field("field1"), 5); +// Truncate the value of the 'rating' field to two decimal places. +trunc(field("rating"), constant(2)); ``` -### notEqual(expression, value) {:#notequal_01df3cf} +### type(expression) {:#type_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if an expression is not equal to a constant value. +Creates an expression that returns the data type of an expression's result. Signature: ```typescript -export declare function notEqual(expression: Expression, value: unknown): BooleanExpression; +export declare function type(expression: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to compare. | -| value | unknown | The constant value to compare to. | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the inequality comparison. +A new `Expression` representing the data type. ### Example ```typescript -// Check if the 'status' field is not equal to "completed" -notEqual(field("status"), "completed"); +// Get the data type of a conditional expression +type(conditional(exists('foo'), constant(1), constant(true))) ``` -### round(expression) {:#round_1138a27} +## function(field, ...) + +### isAbsent(field) {:#isabsent_0fb8cd4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that rounds a numeric value to the nearest whole number. +Creates an expression that returns `true` if a field is absent. Otherwise, returns `false` even if the field value is `null`. Signature: ```typescript -export declare function round(expression: Expression): FunctionExpression; +export declare function isAbsent(field: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | +| field | string | The field to check. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new `Expression` representing the rounded value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'isAbsent' check. ### Example ```typescript -// Round the value of the 'price' field. -round(field("price")); +// Check if the field `value` is absent. +isAbsent("value"); ``` -### round(expression, decimalPlaces) {:#round_a3a92d0} +### reverse(field) {:#reverse_0fb8cd4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that rounds a numeric value to the specified number of decimal places. +Creates an expression that reverses a string value in the specified field. Signature: ```typescript -export declare function round(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; +export declare function reverse(field: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be rounded. | -| decimalPlaces | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | A constant or expression specifying the rounding precision in decimal places. | +| field | string | The name of the field representing the string to reverse. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the rounded value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. ### Example ```typescript -// Round the value of the 'price' field to two decimal places. -round(field("price"), constant(2)); +// Reverse the value of the 'myString' field. +reverse("myString"); ``` -### rtrim(expression, valueToTrim) {:#rtrim_775e2f2} +### stringReverse(field) {:#stringreverse_0fb8cd4} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. +Creates an expression that reverses a string value in the specified field. Signature: ```typescript -export declare function rtrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; +export declare function stringReverse(field: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | -| valueToTrim | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | Optional. A string or byte array containing the characters/bytes to trim. If not specified, whitespace will be trimmed. | +| field | string | The name of the field representing the string to reverse. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the trimmed string or byte array. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. ### Example ```typescript -// Trim whitespace from the end of the 'userInput' field -rtrim(field("userInput")); - -// Trim quotes from the end of the 'userInput' field -rtrim(field("userInput"), '"'); +// Reverse the value of the 'myString' field. +strReverse("myString"); ``` -### split(expression, delimiter) {:#split_5b5612b} +### substring(field, position, length) {:#substring_0d9573a} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that splits a string into an array of substrings based on the provided delimiter. +Creates an expression that returns a substring of a string or byte array. Signature: ```typescript -export declare function split(expression: Expression, delimiter: string): FunctionExpression; +export declare function substring(field: string, position: number, length?: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | Split the result of this expression. | -| delimiter | string | Split on this delimiter. | +| field | string | The name of a field containing a string or byte array to compute the substring from. | +| position | number | Index of the first character of the substring. | +| length | number | Length of the substring. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. +### substring(field, position, length) {:#substring_05cb14e} -### Example +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> +Creates an expression that returns a substring of a string or byte array. -```typescript -// Split the 'scoresCsv' field on delimiter ',' -split(field('scoresCsv'), ',') +Signature: +```typescript +export declare function substring(field: string, position: Expression, length?: Expression): FunctionExpression; ``` -### split(expression, delimiter) {:#split_5a171ed} +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | string | The name of a field containing a string or byte array to compute the substring from. | +| position | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that returns the index of the first character of the substring. | +| length | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that returns the length of the substring. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +## function(fieldName, ...) + +### abs(fieldName) {:#abs_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that splits a string into an array of substrings based on the provided delimiter. +Creates an expression that computes the absolute value of a numeric value. Signature: ```typescript -export declare function split(expression: Expression, delimiter: Expression): FunctionExpression; +export declare function abs(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | Split the result of this expression. | -| delimiter | [Expression](./firestore_pipelines.expression.md#expression_class) | Split on this delimiter returned by evaluating this expression. | +| fieldName | string | The field to compute the absolute value of. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the split function. - -### Example - - -```typescript -// Split the 'scores' field on delimiter ',' or ':' depending on the stored format -split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':')) - -``` +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. -### sqrt(expression) {:#sqrt_1138a27} +### add(fieldName, second) {:#add_b75bb8b} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the square root of a numeric value. +Creates an expression that adds a field's value to an expression. Signature: ```typescript -export declare function sqrt(expression: Expression): FunctionExpression; +export declare function add(fieldName: string, second: Expression | unknown): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which the square root will be computed for. | +| fieldName | string | The name of the field containing the value to add. | +| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the square root of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the addition operation. ### Example ```typescript -// Compute the square root of the 'value' field. -sqrt(field("value")); +// Add the value of the 'quantity' field and the 'reserve' field. +add("quantity", field("reserve")); ``` -### stringIndexOf(expression, search) {:#stringindexof_6dfca5f} +### arrayAgg(fieldName) {:#arrayagg_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that finds the index of the first occurrence of a substring or byte sequence. +Creates an aggregation that collects all values of a field across multiple stage inputs into an array. + +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. Signature: ```typescript -export declare function stringIndexOf(expression: Expression, search: string | Expression | Bytes): FunctionExpression; +export declare function arrayAgg(fieldName: string): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | -| search | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | +| fieldName | string | The name of the field to collect values from. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index of the first occurrence. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg' aggregation. ### Example ```typescript -// Find the index of "foo" in the 'text' field -stringIndexOf(field("text"), "foo"); +// Collect all tags from books into an array +arrayAgg("tags").as("allTags"); ``` -### stringRepeat(expression, repetitions) {:#stringrepeat_a55ba16} +### arrayAggDistinct(fieldName) {:#arrayaggdistinct_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that repeats a string or byte array a specified number of times. +Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. + +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. Signature: ```typescript -export declare function stringRepeat(expression: Expression, repetitions: number | Expression): FunctionExpression; +export declare function arrayAggDistinct(fieldName: string): AggregateFunction; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | -| repetitions | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | The number of times to repeat the string or byte array. | +| fieldName | string | The name of the field to collect values from. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the repeated string or byte array. +A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg\_distinct' aggregation. ### Example ```typescript -// Repeat the 'label' field 3 times -stringRepeat(field("label"), 3); +// Collect all distinct tags from books into an array +arrayAggDistinct("tags").as("allDistinctTags"); ``` -### stringReplaceAll(expression, find, replacement) {:#stringreplaceall_197ecbe} +### arrayContains(fieldName, element) {:#arraycontains_aaace4a} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. +Creates an expression that checks if a field's array value contains a specific element. Signature: ```typescript -export declare function stringReplaceAll(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +export declare function arrayContains(fieldName: string, element: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | -| find | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | -| replacement | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The replacement string or byte sequence. | +| fieldName | string | The field name to check. | +| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The element to search for in the array. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with replacements. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. ### Example ```typescript -// Replace all occurrences of "foo" with "bar" in the 'text' field -stringReplaceAll(field("text"), "foo", "bar"); +// Check if the 'colors' array contains the value of field 'selectedColor' +arrayContains("colors", field("selectedColor")); ``` -### stringReplaceOne(expression, find, replacement) {:#stringreplaceone_197ecbe} +### arrayContains(fieldName, element) {:#arraycontains_999590f} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. +Creates an expression that checks if a field's array value contains a specific value. Signature: ```typescript -export declare function stringReplaceOne(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; +export declare function arrayContains(fieldName: string, element: unknown): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the string or byte array. | -| find | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The substring or byte sequence to search for. | -| replacement | string \| [Expression](./firestore_pipelines.expression.md#expression_class) \| [Bytes](./firestore_.bytes.md#bytes_class) | The replacement string or byte sequence. | +| fieldName | string | The field name to check. | +| element | unknown | The element to search for in the array. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the string or byte array with the replacement. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. ### Example ```typescript -// Replace the first occurrence of "foo" with "bar" in the 'text' field -stringReplaceOne(field("text"), "foo", "bar"); +// Check if the 'colors' array contains "red" +arrayContains("colors", "red"); ``` -### subtract(expression, value) {:#subtract_01df3cf} +### arrayContainsAll(fieldName, values) {:#arraycontainsall_8060b23} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that subtracts a constant value from an expression. +Creates an expression that checks if a field's array value contains all the specified values or expressions. Signature: ```typescript -export declare function subtract(expression: Expression, value: unknown): FunctionExpression; +export declare function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to subtract from. | -| value | unknown | The constant value to subtract. | +| fieldName | string | The field name to check. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the subtraction operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. ### Example ```typescript -// Subtract the constant value 2 from the 'value' field -subtract(field("value"), 2); +// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" +arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); ``` -### sum(expression) {:#sum_1138a27} +### arrayContainsAll(fieldName, arrayExpression) {:#arraycontainsall_48da8d9} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. +Creates an expression that checks if a field's array value contains all the specified values or expressions. Signature: ```typescript -export declare function sum(expression: Expression): AggregateFunction; +export declare function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to sum up. | +| fieldName | string | The field name to check. | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. | Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'sum' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. ### Example ```typescript -// Calculate the total revenue from a set of orders -sum(field("orderAmount")).as("totalRevenue"); +// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" +arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); ``` -### trunc(expression) {:#trunc_1138a27} +### arrayContainsAny(fieldName, values) {:#arraycontainsany_8060b23} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that truncates the numeric value of an expression to an integer. +Creates an expression that checks if a field's array value contains any of the specified elements. Signature: ```typescript -export declare function trunc(expression: Expression): FunctionExpression; +export declare function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be truncated. | +| fieldName | string | The field name to check. | +| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new `Expression` representing the truncated value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. ### Example ```typescript -// Truncate the value of the 'rating' field. -trunc(field("rating")); +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +arrayContainsAny("categories", [field("cate1"), "Science"]); ``` -### trunc(expression, decimalPlaces) {:#trunc_a3a92d0} +### arrayContainsAny(fieldName, values) {:#arraycontainsany_1b4f7cd} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that truncates a numeric value to the specified number of decimal places. +Creates an expression that checks if a field's array value contains any of the specified elements. Signature: ```typescript -export declare function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; +export declare function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to a numeric value, which will be truncated. | -| decimalPlaces | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | A constant or expression specifying the truncation precision in decimal places. | +| fieldName | string | The field name to check. | +| values | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array field. | Returns: -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) -A new `Expression` representing the truncated value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. ### Example ```typescript -// Truncate the value of the 'rating' field to two decimal places. -trunc(field("rating"), constant(2)); +// Check if the 'groups' array contains either the value from the 'userGroup' field +// or the value "guest" +arrayContainsAny("categories", array([field("cate1"), "Science"])); ``` -### type(expression) {:#type_1138a27} +### arrayFirst(fieldName) {:#arrayfirst_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns the data type of an expression's result. +Creates an expression that returns the first element of an array. Signature: ```typescript -export declare function type(expression: Expression): FunctionExpression; +export declare function arrayFirst(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | | +| fieldName | string | The name of the field containing the array. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the data type. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the first element. ### Example ```typescript -// Get the data type of a conditional expression -type(conditional(exists('foo'), constant(1), constant(true))) +// Get the first tag from the 'tags' array field +arrayFirst("tags"); ``` -## function(field, ...) - -### isAbsent(field) {:#isabsent_0fb8cd4} +### arrayFirstN(fieldName, n) {:#arrayfirstn_597a4d9} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns `true` if a field is absent. Otherwise, returns `false` even if the field value is `null`. +Creates an expression that returns the first `n` elements of an array. Signature: ```typescript -export declare function isAbsent(field: string): BooleanExpression; +export declare function arrayFirstN(fieldName: string, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| field | string | The field to check. | +| fieldName | string | The name of the field containing the array. | +| n | number | The number of elements to return. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'isAbsent' check. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the first `n` elements. ### Example ```typescript -// Check if the field `value` is absent. -isAbsent("value"); +// Get the first 3 tags from the 'tags' array field +arrayFirstN("tags", 3); ``` -### reverse(field) {:#reverse_0fb8cd4} +### arrayFirstN(fieldName, n) {:#arrayfirstn_1a86a2c} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that reverses a string value in the specified field. +Creates an expression that returns the first `n` elements of an array. Signature: ```typescript -export declare function reverse(field: string): FunctionExpression; +export declare function arrayFirstN(fieldName: string, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| field | string | The name of the field representing the string to reverse. | +| fieldName | string | The name of the field containing the array. | +| n | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the first `n` elements. ### Example ```typescript -// Reverse the value of the 'myString' field. -reverse("myString"); +// Get the first n tags from the 'tags' array field +arrayFirstN("tags", field("count")); ``` -### stringReverse(field) {:#stringreverse_0fb8cd4} +### arrayIndexOf(fieldName, search) {:#arrayindexof_5e4c2c3} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that reverses a string value in the specified field. +Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. Signature: ```typescript -export declare function stringReverse(field: string): FunctionExpression; +export declare function arrayIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| field | string | The name of the field representing the string to reverse. | +| fieldName | string | The name of the field containing the array to search. | +| search | unknown \| [Expression](./firestore_pipelines.expression.md#expression_class) | The value to search for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the reversed string. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index. ### Example ```typescript -// Reverse the value of the 'myString' field. -strReverse("myString"); +// Get the index of "politics" in the 'tags' array field +arrayIndexOf("tags", "politics"); ``` -### substring(field, position, length) {:#substring_0d9573a} +### arrayIndexOfAll(fieldName, search) {:#arrayindexofall_5e4c2c3} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that returns a substring of a string or byte array. +Creates an expression that returns all indices of the search value in an array. Signature: ```typescript -export declare function substring(field: string, position: number, length?: number): FunctionExpression; +export declare function arrayIndexOfAll(fieldName: string, search: unknown | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| field | string | The name of a field containing a string or byte array to compute the substring from. | -| position | number | Index of the first character of the substring. | -| length | number | Length of the substring. | +| fieldName | string | The name of the field containing the array to search. | +| search | unknown \| [Expression](./firestore_pipelines.expression.md#expression_class) | The value to search for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -### substring(field, position, length) {:#substring_05cb14e} - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the indices. -Creates an expression that returns a substring of a string or byte array. +### Example -Signature: ```typescript -export declare function substring(field: string, position: Expression, length?: Expression): FunctionExpression; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| field | string | The name of a field containing a string or byte array to compute the substring from. | -| position | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that returns the index of the first character of the substring. | -| length | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that returns the length of the substring. | +// Get all indices of 5 in the 'scores' array field +arrayIndexOfAll("scores", 5); -Returns: - -[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) - -## function(fieldName, ...) +``` -### abs(fieldName) {:#abs_e5b0480} +### arrayLast(fieldName) {:#arraylast_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that computes the absolute value of a numeric value. +Creates an expression that returns the last element of an array. Signature: ```typescript -export declare function abs(fieldName: string): FunctionExpression; +export declare function arrayLast(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field to compute the absolute value of. | +| fieldName | string | The name of the field containing the array. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the absolute value of the numeric value. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the last element. -### add(fieldName, second) {:#add_b75bb8b} +### Example + + +```typescript +// Get the last tag from the 'tags' array field +arrayLast("tags"); + +``` + +### arrayLastIndexOf(fieldName, search) {:#arraylastindexof_5e4c2c3} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that adds a field's value to an expression. +Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. Signature: ```typescript -export declare function add(fieldName: string, second: Expression | unknown): FunctionExpression; +export declare function arrayLastIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing the value to add. | -| second | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The second expression or literal to add. | +| fieldName | string | The name of the field containing the array to search. | +| search | unknown \| [Expression](./firestore_pipelines.expression.md#expression_class) | The value to search for. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the addition operation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the index. ### Example ```typescript -// Add the value of the 'quantity' field and the 'reserve' field. -add("quantity", field("reserve")); +// Get the last index of "politics" in the 'tags' array field +arrayLastIndexOf("tags", "politics"); ``` -### arrayAgg(fieldName) {:#arrayagg_e5b0480} +### arrayLastN(fieldName, n) {:#arraylastn_597a4d9} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that collects all values of a field across multiple stage inputs into an array. - -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. +Creates an expression that returns the last `n` elements of an array. Signature: ```typescript -export declare function arrayAgg(fieldName: string): AggregateFunction; +export declare function arrayLastN(fieldName: string, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to collect values from. | +| fieldName | string | The name of the field containing the array. | +| n | number | The number of elements to return. | Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the last `n` elements. ### Example ```typescript -// Collect all tags from books into an array -arrayAgg("tags").as("allTags"); +// Get the last 3 tags from the 'tags' array field +arrayLastN("tags", 3); ``` -### arrayAggDistinct(fieldName) {:#arrayaggdistinct_e5b0480} +### arrayLastN(fieldName, n) {:#arraylastn_1a86a2c} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. - -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. +Creates an expression that returns the last `n` elements of an array. Signature: ```typescript -export declare function arrayAggDistinct(fieldName: string): AggregateFunction; +export declare function arrayLastN(fieldName: string, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field to collect values from. | +| fieldName | string | The name of the field containing the array. | +| n | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: -[AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) representing the 'array\_agg\_distinct' aggregation. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the last `n` elements. ### Example ```typescript -// Collect all distinct tags from books into an array -arrayAggDistinct("tags").as("allDistinctTags"); +// Get the last n tags from the 'tags' array field +arrayLastN("tags", field("count")); ``` -### arrayContains(fieldName, element) {:#arraycontains_aaace4a} +### arrayLength(fieldName) {:#arraylength_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if a field's array value contains a specific element. +Creates an expression that calculates the length of an array in a specified field. Signature: ```typescript -export declare function arrayContains(fieldName: string, element: Expression): BooleanExpression; +export declare function arrayLength(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| element | [Expression](./firestore_pipelines.expression.md#expression_class) | The element to search for in the array. | +| fieldName | string | The name of the field containing an array to calculate the length of. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the array. ### Example ```typescript -// Check if the 'colors' array contains the value of field 'selectedColor' -arrayContains("colors", field("selectedColor")); +// Get the number of items in field 'cart' +arrayLength('cart'); ``` -### arrayContains(fieldName, element) {:#arraycontains_999590f} +### arrayMaximum(fieldName) {:#arraymaximum_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if a field's array value contains a specific value. +Creates an expression that returns the maximum value in an array. Signature: ```typescript -export declare function arrayContains(fieldName: string, element: unknown): BooleanExpression; +export declare function arrayMaximum(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| element | unknown | The element to search for in the array. | +| fieldName | string | The name of the field containing the array. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the maximum value. ### Example ```typescript -// Check if the 'colors' array contains "red" -arrayContains("colors", "red"); +// Get the maximum value from the 'scores' array field +arrayMaximum("scores"); ``` -### arrayContainsAll(fieldName, values) {:#arraycontainsall_8060b23} +### arrayMaximumN(fieldName, n) {:#arraymaximumn_597a4d9} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if a field's array value contains all the specified values or expressions. +Creates an expression that returns the largest `n` elements of an array. + +Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; +export declare function arrayMaximumN(fieldName: string, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | +| fieldName | string | The name of the field containing the array. | +| n | number | The number of elements to return. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the largest `n` elements. ### Example ```typescript -// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" -arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); +// Get the top 3 scores from the 'scores' array field +arrayMaximumN("scores", 3); ``` -### arrayContainsAll(fieldName, arrayExpression) {:#arraycontainsall_48da8d9} +### arrayMaximumN(fieldName, n) {:#arraymaximumn_1a86a2c} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if a field's array value contains all the specified values or expressions. +Creates an expression that returns the largest `n` elements of an array. + +Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; +export declare function arrayMaximumN(fieldName: string, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The elements to check for in the array. | +| fieldName | string | The name of the field containing the array. | +| n | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_all' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the largest `n` elements. ### Example ```typescript -// Check if the 'tags' array contains both of the values from field 'tag1', the value "SciFi", and "Adventure" -arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); +// Get the top n scores from the 'scores' array field +arrayMaximumN("scores", field("count")); ``` -### arrayContainsAny(fieldName, values) {:#arraycontainsany_8060b23} +### arrayMinimum(fieldName) {:#arrayminimum_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if a field's array value contains any of the specified elements. +Creates an expression that returns the minimum value in an array. Signature: ```typescript -export declare function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; +export declare function arrayMinimum(fieldName: string): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| values | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | The elements to check for in the array. | +| fieldName | string | The name of the field containing the array. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the minimum value. ### Example ```typescript -// Check if the 'groups' array contains either the value from the 'userGroup' field -// or the value "guest" -arrayContainsAny("categories", [field("cate1"), "Science"]); +// Get the minimum value from the 'scores' array field +arrayMinimum("scores"); ``` -### arrayContainsAny(fieldName, values) {:#arraycontainsany_1b4f7cd} +### arrayMinimumN(fieldName, n) {:#arrayminimumn_597a4d9} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that checks if a field's array value contains any of the specified elements. +Creates an expression that returns the smallest `n` elements of an array. + +Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; +export declare function arrayMinimumN(fieldName: string, n: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The field name to check. | -| values | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression that evaluates to an array, whose elements to check for in the array field. | +| fieldName | string | The name of the field containing the array. | +| n | number | The number of elements to return. | Returns: -[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the 'array\_contains\_any' comparison. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the smallest `n` elements. ### Example ```typescript -// Check if the 'groups' array contains either the value from the 'userGroup' field -// or the value "guest" -arrayContainsAny("categories", array([field("cate1"), "Science"])); +// Get the bottom 3 scores from the 'scores' array field +arrayMinimumN("scores", 3); ``` -### arrayLength(fieldName) {:#arraylength_e5b0480} +### arrayMinimumN(fieldName, n) {:#arrayminimumn_1a86a2c} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Creates an expression that calculates the length of an array in a specified field. +Creates an expression that returns the smallest `n` elements of an array. + +Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. Signature: ```typescript -export declare function arrayLength(fieldName: string): FunctionExpression; +export declare function arrayMinimumN(fieldName: string, n: Expression): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | The name of the field containing an array to calculate the length of. | +| fieldName | string | The name of the field containing the array. | +| n | [Expression](./firestore_pipelines.expression.md#expression_class) | An expression evaluating to the number of elements to return. | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the length of the array. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the smallest `n` elements. ### Example ```typescript -// Get the number of items in field 'cart' -arrayLength('cart'); +// Get the bottom n scores from the 'scores' array field +arrayMinimumN(field("scores"), field("count")); ``` diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index ba61665ce7..8f99754be7 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -87,7 +87,6 @@ export { Expression, field, and, - array, constant, add, subtract, @@ -112,11 +111,24 @@ export { lessThanOrEqual, greaterThan, greaterThanOrEqual, + array, arrayConcat, arrayContains, arrayContainsAny, arrayContainsAll, + arrayFirst, + arrayFirstN, + arrayGet, + arrayIndexOf, + arrayIndexOfAll, + arrayLast, + arrayLastIndexOf, + arrayLastN, arrayLength, + arrayMaximum, + arrayMaximumN, + arrayMinimum, + arrayMinimumN, equalAny, notEqualAny, xor, @@ -174,7 +186,6 @@ export { timestampSubtract, ascending, descending, - arrayGet, abs, sum, countDistinct, diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index 5a6f8d7c7d..f9b1e7ec5d 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -67,11 +67,24 @@ export { lessThanOrEqual, greaterThan, greaterThanOrEqual, + array, arrayConcat, arrayContains, arrayContainsAny, arrayContainsAll, + arrayFirst, + arrayFirstN, + arrayGet, + arrayIndexOf, + arrayIndexOfAll, + arrayLast, + arrayLastIndexOf, + arrayLastN, arrayLength, + arrayMaximum, + arrayMaximumN, + arrayMinimum, + arrayMinimumN, equalAny, notEqualAny, xor, @@ -135,8 +148,6 @@ export { ascending, descending, countIf, - array, - arrayGet, isError, ifError, isAbsent, diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index b52b39c226..f3cb3da30c 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -1504,6 +1504,345 @@ export abstract class Expression implements ProtoValueSerializable, UserData { 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(): FunctionExpression { + return new FunctionExpression('array_first', [this], 'arrayFirst'); + } + + /** + * @beta + * Returns the first `n` elements of the array. + * + * @example + * ```typescript + * // Get the first 3 elements of the 'myArray' field. + * field("myArray").arrayFirstN(3); + * ``` + * + * @param n - The number of elements to return. + * @returns A new `Expression` representing the first `n` elements. + */ + arrayFirstN(n: number): FunctionExpression; + + /** + * @beta + * Returns the first `n` elements of the array. + * + * @example + * ```typescript + * // Get the first n elements of the 'myArray' field. + * field("myArray").arrayFirstN(field("count")); + * ``` + * + * @param n - An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the first `n` elements. + */ + arrayFirstN(n: Expression): FunctionExpression; + arrayFirstN(n: number | Expression): FunctionExpression { + return new FunctionExpression( + 'array_first_n', + [this, valueToDefaultExpr(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(): FunctionExpression { + return new FunctionExpression('array_last', [this], 'arrayLast'); + } + + /** + * @beta + * Returns the last `n` elements of the array. + * + * @example + * ```typescript + * // Get the last 3 elements of the 'myArray' field. + * field("myArray").arrayLastN(3); + * ``` + * + * @param n - The number of elements to return. + * @returns A new `Expression` representing the last `n` elements. + */ + arrayLastN(n: number): FunctionExpression; + + /** + * @beta + * Returns the last `n` elements of the array. + * + * @example + * ```typescript + * // Get the last n elements of the 'myArray' field. + * field("myArray").arrayLastN(field("count")); + * ``` + * + * @param n - An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the last `n` elements. + */ + arrayLastN(n: Expression): FunctionExpression; + arrayLastN(n: number | Expression): FunctionExpression { + return new FunctionExpression( + 'array_last_n', + [this, valueToDefaultExpr(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(): FunctionExpression { + return new FunctionExpression('maximum', [this], 'arrayMaximum'); + } + + /** + * @beta + * Returns the largest `n` elements of the array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the largest 3 elements of the 'myArray' field. + * field("myArray").arrayMaximumN(3); + * ``` + * + * @param n - The number of elements to return. + * @returns A new `Expression` representing the largest `n` elements. + */ + arrayMaximumN(n: number): FunctionExpression; + + /** + * @beta + * Returns the largest `n` elements of the array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the largest n elements of the 'myArray' field. + * field("myArray").arrayMaximumN(field("count")); + * ``` + * + * @param n - An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the largest `n` elements. + */ + arrayMaximumN(n: Expression): FunctionExpression; + arrayMaximumN(n: number | Expression): FunctionExpression { + return new FunctionExpression( + 'maximum_n', + [this, valueToDefaultExpr(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(): FunctionExpression { + return new FunctionExpression('minimum', [this], 'arrayMinimum'); + } + + /** + * @beta + * Returns the smallest `n` elements of the array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the smallest 3 elements of the 'myArray' field. + * field("myArray").arrayMinimumN(3); + * ``` + * + * @param n - The number of elements to return. + * @returns A new `Expression` representing the smallest `n` elements. + */ + arrayMinimumN(n: number): FunctionExpression; + + /** + * @beta + * Returns the smallest `n` elements of the array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the smallest n elements of the 'myArray' field. + * field("myArray").arrayMinimumN(field("count")); + * ``` + * + * @param n - An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the smallest `n` elements. + */ + arrayMinimumN(n: Expression): FunctionExpression; + arrayMinimumN(n: number | Expression): FunctionExpression { + return new FunctionExpression( + 'minimum_n', + [this, valueToDefaultExpr(n)], + 'arrayMinimumN' + ); + } + + /** + * @beta + * Returns the first index of the search value in the array, or -1 if not found. + * + * @example + * ```typescript + * // Get the first index of the value 3 in the 'myArray' field. + * field("myArray").arrayIndexOf(3); + * ``` + * + * @param search - The value to search for. + * @returns A new `Expression` representing the index. + */ + arrayIndexOf(search: unknown): FunctionExpression; + + /** + * @beta + * Returns the first index of the search value in the array, or -1 if not found. + * + * @example + * ```typescript + * // Get the first index of the value in 'searchVal' field in the 'myArray' field. + * field("myArray").arrayIndexOf(field("searchVal")); + * ``` + * + * @param search - An expression evaluating to the value to search for. + * @returns A new `Expression` representing the index. + */ + arrayIndexOf(search: Expression): FunctionExpression; + arrayIndexOf(search: unknown | Expression): FunctionExpression { + return new FunctionExpression( + 'array_index_of', + [this, valueToDefaultExpr(search), valueToDefaultExpr('first')], + 'arrayIndexOf' + ); + } + + /** + * @beta + * Returns the last index of the search value in the array, or -1 if not found. + * + * @example + * ```typescript + * // Get the last index of the value 3 in the 'myArray' field. + * field("myArray").arrayLastIndexOf(3); + * ``` + * + * @param search - The value to search for. + * @returns A new `Expression` representing the index. + */ + arrayLastIndexOf(search: unknown): FunctionExpression; + + /** + * @beta + * Returns the last index of the search value in the array, or -1 if not found. + * + * @example + * ```typescript + * // Get the last index of the value in 'searchVal' field in the 'myArray' field. + * field("myArray").arrayLastIndexOf(field("searchVal")); + * ``` + * + * @param search - An expression evaluating to the value to search for. + * @returns A new `Expression` representing the index. + */ + arrayLastIndexOf(search: Expression): FunctionExpression; + arrayLastIndexOf(search: unknown | Expression): FunctionExpression { + return new FunctionExpression( + 'array_index_of', + [this, valueToDefaultExpr(search), valueToDefaultExpr('last')], + 'arrayLastIndexOf' + ); + } + + /** + * @beta + * Returns all indices of the search value in the array. + * + * @example + * ```typescript + * // Get all indices of the value 3 in the 'myArray' field. + * field("myArray").arrayIndexOfAll(3); + * ``` + * + * @param search - The value to search for. + * @returns A new `Expression` representing the indices. + */ + arrayIndexOfAll(search: unknown): FunctionExpression; + + /** + * @beta + * Returns all indices of the search value in the array. + * + * @example + * ```typescript + * // Get all indices of the value in 'searchVal' field in the 'myArray' field. + * field("myArray").arrayIndexOfAll(field("searchVal")); + * ``` + * + * @param search - An expression evaluating to the value to search for. + * @returns A new `Expression` representing the indices. + */ + arrayIndexOfAll(search: Expression): FunctionExpression; + arrayIndexOfAll(search: unknown | Expression): FunctionExpression { + return new FunctionExpression( + 'array_index_of_all', + [this, valueToDefaultExpr(search)], + 'arrayIndexOfAll' + ); + } + /** * @beta * Creates an expression that calculates the length of this string expression in bytes. @@ -6437,6 +6776,652 @@ export function regexContains( return leftExpr.regexContains(patternExpr); } +/** + * @beta + * + * Creates an expression that returns the first element of an array. + * + * @example + * ```typescript + * // Get the first tag from the 'tags' array field + * arrayFirst("tags"); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the first element. + */ +export function arrayFirst(fieldName: string): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first element of an array. + * + * @example + * ```typescript + * // Get the first tag from the 'tags' array field + * arrayFirst(field("tags")); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the first element. + */ +export function arrayFirst(arrayExpression: Expression): FunctionExpression; +export function arrayFirst(array: Expression | string): FunctionExpression { + return fieldOrExpression(array).arrayFirst(); +} + +/** + * @beta + * + * Creates an expression that returns the first `n` elements of an array. + * + * @example + * ```typescript + * // Get the first 3 tags from the 'tags' array field + * arrayFirstN("tags", 3); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @param n - The number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the first `n` elements. + */ +export function arrayFirstN(fieldName: string, n: number): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first `n` elements of an array. + * + * @example + * ```typescript + * // Get the first n tags from the 'tags' array field + * arrayFirstN("tags", field("count")); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @param n - An expression evaluating to the number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the first `n` elements. + */ +export function arrayFirstN( + fieldName: string, + n: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first `n` elements of an array. + * + * @example + * ```typescript + * // Get the first 3 elements from an array expression + * arrayFirstN(field("tags"), 3); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @param n - The number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the first `n` elements. + */ +export function arrayFirstN( + arrayExpression: Expression, + n: number +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first `n` elements of an array. + * + * @example + * ```typescript + * // Get the first n elements from an array expression + * arrayFirstN(field("tags"), field("count")); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @param n - An expression evaluating to the number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the first `n` elements. + */ +export function arrayFirstN( + arrayExpression: Expression, + n: Expression +): FunctionExpression; +export function arrayFirstN( + array: Expression | string, + n: Expression | number +): FunctionExpression { + return fieldOrExpression(array).arrayFirstN(valueToDefaultExpr(n)); +} + +/** + * @beta + * + * Creates an expression that returns the last element of an array. + * + * @example + * ```typescript + * // Get the last tag from the 'tags' array field + * arrayLast("tags"); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the last element. + */ +export function arrayLast(fieldName: string): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the last element of an array. + * + * @example + * ```typescript + * // Get the last tag from the 'tags' array field + * arrayLast(field("tags")); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the last element. + */ +export function arrayLast(arrayExpression: Expression): FunctionExpression; +export function arrayLast(array: Expression | string): FunctionExpression { + return fieldOrExpression(array).arrayLast(); +} + +/** + * @beta + * + * Creates an expression that returns the last `n` elements of an array. + * + * @example + * ```typescript + * // Get the last 3 tags from the 'tags' array field + * arrayLastN("tags", 3); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @param n - The number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the last `n` elements. + */ +export function arrayLastN(fieldName: string, n: number): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the last `n` elements of an array. + * + * @example + * ```typescript + * // Get the last n tags from the 'tags' array field + * arrayLastN("tags", field("count")); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @param n - An expression evaluating to the number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the last `n` elements. + */ +export function arrayLastN( + fieldName: string, + n: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the last `n` elements of an array. + * + * @example + * ```typescript + * // Get the last 3 elements from an array expression + * arrayLastN(field("tags"), 3); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @param n - The number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the last `n` elements. + */ +export function arrayLastN( + arrayExpression: Expression, + n: number +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the last `n` elements of an array. + * + * @example + * ```typescript + * // Get the last n elements from an array expression + * arrayLastN(field("tags"), field("count")); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @param n - An expression evaluating to the number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the last `n` elements. + */ +export function arrayLastN( + arrayExpression: Expression, + n: Expression +): FunctionExpression; +export function arrayLastN( + array: Expression | string, + n: Expression | number +): FunctionExpression { + return fieldOrExpression(array).arrayLastN(valueToDefaultExpr(n)); +} + +/** + * @beta + * + * Creates an expression that returns the maximum value in an array. + * + * @example + * ```typescript + * // Get the maximum value from the 'scores' array field + * arrayMaximum("scores"); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the maximum value. + */ +export function arrayMaximum(fieldName: string): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the maximum value in an array. + * + * @example + * ```typescript + * // Get the maximum value from the 'scores' array field + * arrayMaximum(field("scores")); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the maximum value. + */ +export function arrayMaximum(arrayExpression: Expression): FunctionExpression; +export function arrayMaximum(array: Expression | string): FunctionExpression { + return fieldOrExpression(array).arrayMaximum(); +} + +/** + * @beta + * + * Creates an expression that returns the largest `n` elements of an array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the top 3 scores from the 'scores' array field + * arrayMaximumN("scores", 3); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @param n - The number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the largest `n` elements. + */ +export function arrayMaximumN(fieldName: string, n: number): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the largest `n` elements of an array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the top n scores from the 'scores' array field + * arrayMaximumN("scores", field("count")); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @param n - An expression evaluating to the number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the largest `n` elements. + */ +export function arrayMaximumN( + fieldName: string, + n: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the largest `n` elements of an array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the top 3 elements from an array expression + * arrayMaximumN(field("scores"), 3); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @param n - The number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the largest `n` elements. + */ +export function arrayMaximumN( + arrayExpression: Expression, + n: number +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the largest `n` elements of an array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the top n elements from an array expression + * arrayMaximumN(field("scores"), field("count")); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @param n - An expression evaluating to the number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the largest `n` elements. + */ +export function arrayMaximumN( + arrayExpression: Expression, + n: Expression +): FunctionExpression; +export function arrayMaximumN( + array: Expression | string, + n: Expression | number +): FunctionExpression { + return fieldOrExpression(array).arrayMaximumN(valueToDefaultExpr(n)); +} + +/** + * @beta + * + * Creates an expression that returns the minimum value in an array. + * + * @example + * ```typescript + * // Get the minimum value from the 'scores' array field + * arrayMinimum("scores"); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the minimum value. + */ +export function arrayMinimum(fieldName: string): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the minimum value in an array. + * + * @example + * ```typescript + * // Get the minimum value from the 'scores' array field + * arrayMinimum(field("scores")); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the minimum value. + */ +export function arrayMinimum(arrayExpression: Expression): FunctionExpression; +export function arrayMinimum(array: Expression | string): FunctionExpression { + return fieldOrExpression(array).arrayMinimum(); +} + +/** + * @beta + * + * Creates an expression that returns the smallest `n` elements of an array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the bottom 3 scores from the 'scores' array field + * arrayMinimumN("scores", 3); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @param n - The number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the smallest `n` elements. + */ +export function arrayMinimumN(fieldName: string, n: number): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the smallest `n` elements of an array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the bottom n scores from the 'scores' array field + * arrayMinimumN(field("scores"), field("count")); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @param n - An expression evaluating to the number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the smallest `n` elements. + */ +export function arrayMinimumN( + fieldName: string, + n: Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the smallest `n` elements of an array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the bottom 3 scores from the 'scores' array field + * arrayMinimumN(field("scores"), 3); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @param n - The number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the smallest `n` elements. + */ +export function arrayMinimumN( + arrayExpression: Expression, + n: number +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the smallest `n` elements of an array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the bottom n scores from the 'scores' array field + * arrayMinimumN(field("scores"), field("count")); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @param n - An expression evaluating to the number of elements to return. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the smallest `n` elements. + */ +export function arrayMinimumN( + arrayExpression: Expression, + n: Expression +): FunctionExpression; +export function arrayMinimumN( + array: Expression | string, + n: Expression | number +): FunctionExpression { + return fieldOrExpression(array).arrayMinimumN(valueToDefaultExpr(n)); +} + +/** + * @beta + * + * Creates an expression that returns the first index of the search value in an array. + * Returns -1 if the value is not found. + * + * @example + * ```typescript + * // Get the index of "politics" in the 'tags' array field + * arrayIndexOf("tags", "politics"); + * ``` + * + * @param fieldName - The name of the field containing the array to search. + * @param search - The value to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the index. + */ +export function arrayIndexOf( + fieldName: string, + search: unknown | Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first index of the search value in an array. + * Returns -1 if the value is not found. + * + * @example + * ```typescript + * // Get the index of "politics" in the 'tags' array field + * arrayIndexOf(field("tags"), "politics"); + * ``` + * + * @param arrayExpression - The expression representing the array to search. + * @param search - The value to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the index. + */ +export function arrayIndexOf( + arrayExpression: Expression, + search: unknown | Expression +): FunctionExpression; +export function arrayIndexOf( + array: Expression | string, + search: unknown | Expression +): FunctionExpression { + return fieldOrExpression(array).arrayIndexOf(valueToDefaultExpr(search)); +} + +/** + * @beta + * + * Creates an expression that returns the last index of the search value in an array. + * Returns -1 if the value is not found. + * + * @example + * ```typescript + * // Get the last index of "politics" in the 'tags' array field + * arrayLastIndexOf("tags", "politics"); + * ``` + * + * @param fieldName - The name of the field containing the array to search. + * @param search - The value to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the index. + */ +export function arrayLastIndexOf( + fieldName: string, + search: unknown | Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the last index of the search value in an array. + * Returns -1 if the value is not found. + * + * @example + * ```typescript + * // Get the last index of "politics" in the 'tags' array field + * arrayLastIndexOf(field("tags"), "politics"); + * ``` + * + * @param arrayExpression - The expression representing the array to search. + * @param search - The value to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the index. + */ +export function arrayLastIndexOf( + arrayExpression: Expression, + search: unknown | Expression +): FunctionExpression; +export function arrayLastIndexOf( + array: Expression | string, + search: unknown | Expression +): FunctionExpression { + return fieldOrExpression(array).arrayLastIndexOf(valueToDefaultExpr(search)); +} + +/** + * @beta + * + * Creates an expression that returns all indices of the search value in an array. + * + * @example + * ```typescript + * // Get all indices of 5 in the 'scores' array field + * arrayIndexOfAll("scores", 5); + * ``` + * + * @param fieldName - The name of the field containing the array to search. + * @param search - The value to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the indices. + */ +export function arrayIndexOfAll( + fieldName: string, + search: unknown | Expression +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns all indices of the search value in an array. + * + * @example + * ```typescript + * // Get all indices of 5 in the 'scores' array field + * arrayIndexOfAll(field("scores"), 5); + * ``` + * + * @param arrayExpression - The expression representing the array to search. + * @param search - The value to search for. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the indices. + */ +export function arrayIndexOfAll( + arrayExpression: Expression, + search: unknown | Expression +): FunctionExpression; +export function arrayIndexOfAll( + array: Expression | string, + search: unknown | Expression +): FunctionExpression { + return fieldOrExpression(array).arrayIndexOfAll(valueToDefaultExpr(search)); +} + /** * @beta * diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index dd56faac17..efe414a71a 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -112,6 +112,9 @@ import { subtract, isAbsent, timestampSubtract, + arrayIndexOf, + arrayLastIndexOf, + arrayIndexOfAll, mapRemove, mapMerge, documentId, @@ -122,6 +125,14 @@ import { FindNearestStageOptions, AggregateFunction, arrayGet, + arrayFirst, + arrayFirstN, + arrayLast, + arrayLastN, + arrayMaximum, + arrayMaximumN, + arrayMinimum, + arrayMinimumN, ascending, byteLength, FunctionExpression, @@ -3182,6 +3193,596 @@ apiDescribe.skipClassic('Pipelines', persistence => { expectResults(snapshot, ...expectedResults); }); + it('supports arrayFirst', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayFirst('tags').as('firstTag')) + ); + const expectedResults = [ + { + firstTag: 'adventure' + }, + { + firstTag: 'politics' + }, + { + firstTag: 'classic' + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayFirst().as('firstTag')) + ); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null + }) + ) + .select( + arrayFirst('empty').as('emptyResult'), + arrayFirst('nullVal').as('nullResult'), + arrayFirst('nonExistent').as('absentResult') + ) + ); + + expectResults(snapshot, { + // no emptyResult because arrayFirst returns UNSET for empty arrays + nullResult: null, + absentResult: null + }); + }); + + it('supports arrayFirstN', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayFirstN('tags', 2).as('firstTwoTags')) + ); + const expectedResults = [ + { + firstTwoTags: ['adventure', 'magic'] + }, + { + firstTwoTags: ['politics', 'desert'] + }, + { + firstTwoTags: ['classic', 'social commentary'] + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayFirstN(2).as('firstTwoTags')) + ); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null + }) + ) + .select( + arrayFirstN('empty', 1).as('emptyResult'), + arrayFirstN('nullVal', 1).as('nullResult'), + arrayFirstN('nonExistent', 1).as('absentResult') + ) + ); + + expectResults(snapshot, { + emptyResult: [], + nullResult: null, + absentResult: null + }); + }); + + it('supports arrayLast', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayLast('tags').as('lastTag')) + ); + const expectedResults = [ + { + lastTag: 'epic' + }, + { + lastTag: 'ecology' + }, + { + lastTag: 'love' + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayLast().as('lastTag')) + ); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null + }) + ) + .select( + arrayLast('empty').as('emptyResult'), + arrayLast('nullVal').as('nullResult'), + arrayLast('nonExistent').as('absentResult') + ) + ); + + expectResults(snapshot, { + // no emptyResult because arrayLast returns UNSET for empty arrays + nullResult: null, + absentResult: null + }); + }); + + it('supports arrayLastN', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayLastN('tags', 2).as('lastTwoTags')) + ); + const expectedResults = [ + { + lastTwoTags: ['magic', 'epic'] + }, + { + lastTwoTags: ['desert', 'ecology'] + }, + { + lastTwoTags: ['social commentary', 'love'] + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayLastN(2).as('lastTwoTags')) + ); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null + }) + ) + .select( + arrayLastN('empty', 1).as('emptyResult'), + arrayLastN('nullVal', 1).as('nullResult'), + arrayLastN('nonExistent', 1).as('absentResult') + ) + ); + + expectResults(snapshot, { + emptyResult: [], + nullResult: null, + absentResult: null + }); + }); + + it('supports arrayMaximum', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(arrayMaximum('tags').as('maxTag')) + ); + const expectedResults = [ + { + maxTag: 'magic' + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('tags').arrayMaximum().as('maxTag')) + ); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent and mixed types + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null, + mixed: [1, '2', 3, '10'] // Strings > Numbers in Firestore + }) + ) + .select( + arrayMaximum('empty').as('emptyResult'), + arrayMaximum('nullVal').as('nullResult'), + arrayMaximum('nonExistent').as('absentResult'), + arrayMaximum('mixed').as('mixedResult') + ) + ); + + expectResults(snapshot, { + emptyResult: null, + nullResult: null, + absentResult: null, + mixedResult: '2' // "2" > "10" > 3 > 1 + }); + }); + + it('supports arrayMaximumN', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(arrayMaximumN('tags', 2).as('maxTwoTags')) + ); + const expectedResults = [ + { + maxTwoTags: ['magic', 'epic'] + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('tags').arrayMaximumN(2).as('maxTwoTags')) + ); + expectResults(snapshot, ...expectedResults); + }); + + it('supports arrayMinimum', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(arrayMinimum('tags').as('minTag')) + ); + const expectedResults = [ + { + minTag: 'adventure' + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('tags').arrayMinimum().as('minTag')) + ); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent and mixed types + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null, + mixed: [1, '2', 3, '10'] // Strings > Numbers in Firestore + }) + ) + .select( + arrayMinimum('empty').as('emptyResult'), + arrayMinimum('nullVal').as('nullResult'), + arrayMinimum('nonExistent').as('absentResult'), + arrayMinimum('mixed').as('mixedResult') + ) + ); + + expectResults(snapshot, { + emptyResult: null, + nullResult: null, + absentResult: null, + mixedResult: 1 // 1 < 3 < "10" < "2" + }); + }); + + it('supports arrayMinimumN', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(arrayMinimumN('tags', 2).as('minTwoTags')) + ); + const expectedResults = [ + { + minTwoTags: ['adventure', 'epic'] + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('tags').arrayMinimumN(2).as('minTwoTags')) + ); + expectResults(snapshot, ...expectedResults); + }); + + it('supports arrayIndexOf', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + arrayIndexOf('tags', 'adventure').as('indexFirst'), + arrayIndexOf(field('tags'), 'magic').as('indexSecond'), + field('tags').arrayIndexOf('adventure').as('indexFirst2'), + arrayIndexOf('tags', 'nonexistent').as('indexNone'), + arrayIndexOf('empty', 'anything').as('indexEmpty') + ) + ); + + const expectedResults = [ + { + indexFirst: 0, + indexSecond: 1, + indexFirst2: 0, + indexNone: -1, + indexEmpty: null + } + ]; + expectResults(snapshot, ...expectedResults); + + // Test with duplicate values + const snapshotDuplicates = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, 2, 3, 2, 1] + }) + ) + .select( + arrayIndexOf('arr', 2).as('firstIndex'), + arrayLastIndexOf('arr', 2).as('lastIndex') + ) + ); + + expectResults(snapshotDuplicates, { + firstIndex: 1, + lastIndex: 3 + }); + + // Test with null value + const snapshotNull = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, null, 3, 2, 1], + nullArr: null + }) + ) + .select( + arrayIndexOf('arr', null).as('firstIndex'), + arrayIndexOf('nullArr', null).as('firstIndexNull') + ) + ); + + expectResults(snapshotNull, { + firstIndex: 1, + firstIndexNull: null + }); + }); + + it('supports arrayLastIndexOf', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + arrayLastIndexOf('tags', 'adventure').as('lastIndexFirst'), + arrayLastIndexOf(field('tags'), 'epic').as('lastIndexLast'), + field('tags').arrayLastIndexOf('adventure').as('lastIndexFirst2'), + arrayLastIndexOf('tags', 'nonexistent').as('lastIndexNone'), + arrayLastIndexOf('empty', 'anything').as('lastIndexEmpty') + ) + ); + + const expectedResults = [ + { + lastIndexFirst: 0, + lastIndexLast: 2, + lastIndexFirst2: 0, + lastIndexNone: -1, + lastIndexEmpty: null + } + ]; + expectResults(snapshot, ...expectedResults); + + // Test with duplicate values + const snapshotDuplicates = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, 2, 3, 2, 1] + }) + ) + .select( + arrayIndexOf('arr', 2).as('firstIndex'), + arrayLastIndexOf('arr', 2).as('lastIndex') + ) + ); + + expectResults(snapshotDuplicates, { + firstIndex: 1, + lastIndex: 3 + }); + }); + + it('supports arrayIndexOfAll', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + arrayIndexOfAll('tags', 'adventure').as('indicesFirst'), + arrayIndexOfAll(field('tags'), 'epic').as('indicesLast'), + field('tags').arrayIndexOfAll('nonexistent').as('indicesNone'), + arrayIndexOfAll('empty', 'anything').as('indicesEmpty') + ) + ); + + const expectedResults = [ + { + indicesFirst: [0], + indicesLast: [2], + indicesNone: [], + indicesEmpty: null + } + ]; + expectResults(snapshot, ...expectedResults); + + // Test with duplicate values + const snapshotDuplicates = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, 2, 3, 2, 1] + }) + ) + .select( + arrayIndexOfAll('arr', 1).as('indices1'), + arrayIndexOfAll('arr', 2).as('indices2') + ) + ); + + expectResults(snapshotDuplicates, { + indices1: [0, 4], + indices2: [1, 3] + }); + + // Test with null values + const snapshotNulls = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, null, 3, null, 1], + nullArr: null + }) + ) + .select( + arrayIndexOfAll('arr', null).as('indices1'), + arrayIndexOfAll('nullArr', null).as('indicesNull') + ) + ); + + expectResults(snapshotNulls, { + indices1: [1, 3], + indicesNull: null + }); + }); + it('supports map', async () => { const snapshot = await execute( firestore diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index b5836b2b32..a1bb9ac137 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -162,7 +162,18 @@ import { currentTimestamp, ifAbsent, join, - arraySum + arraySum, + arrayFirst, + arrayFirstN, + arrayLast, + arrayLastN, + arrayMaximum, + arrayMaximumN, + arrayMinimum, + arrayMinimumN, + arrayIndexOf, + arrayIndexOfAll, + arrayLastIndexOf } from './pipeline_export'; use(chaiAsPromised); @@ -3154,6 +3165,546 @@ describe.skipClassic('Firestore Pipelines', () => { expectResults(snapshot, ...expectedResults); }); + it('supports arrayFirst', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayFirst('tags').as('firstTag')) + ); + const expectedResults = [ + { + firstTag: 'adventure' + }, + { + firstTag: 'politics' + }, + { + firstTag: 'classic' + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayFirst().as('firstTag')) + ); + expectResults(snapshot, ...expectedResults); + }); + + it('supports arrayFirstN', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayFirstN('tags', 2).as('firstTwoTags')) + ); + const expectedResults = [ + { + firstTwoTags: ['adventure', 'magic'] + }, + { + firstTwoTags: ['politics', 'desert'] + }, + { + firstTwoTags: ['classic', 'social commentary'] + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayFirstN(2).as('firstTwoTags')) + ); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null + }) + ) + .select( + arrayFirstN('empty', 1).as('emptyResult'), + arrayFirstN('nullVal', 1).as('nullResult'), + arrayFirstN('nonExistent', 1).as('absentResult') + ) + ); + + expectResults(snapshot, { + emptyResult: [], + nullResult: null, + absentResult: null + }); + }); + + it('supports arrayLast', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayLast('tags').as('lastTag')) + ); + const expectedResults = [ + { + lastTag: 'epic' + }, + { + lastTag: 'ecology' + }, + { + lastTag: 'love' + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayLast().as('lastTag')) + ); + expectResults(snapshot, ...expectedResults); + }); + + it('supports arrayLastN', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayLastN('tags', 2).as('lastTwoTags')) + ); + const expectedResults = [ + { + lastTwoTags: ['magic', 'epic'] + }, + { + lastTwoTags: ['desert', 'ecology'] + }, + { + lastTwoTags: ['social commentary', 'love'] + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayLastN(2).as('lastTwoTags')) + ); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null + }) + ) + .select( + arrayLastN('empty', 1).as('emptyResult'), + arrayLastN('nullVal', 1).as('nullResult'), + arrayLastN('nonExistent', 1).as('absentResult') + ) + ); + + expectResults(snapshot, { + emptyResult: [], + nullResult: null, + absentResult: null + }); + }); + + it('supports arrayMaximum', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(arrayMaximum('tags').as('maxTag')) + ); + const expectedResults = [ + { + maxTag: 'magic' + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('tags').arrayMaximum().as('maxTag')) + ); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent and mixed types + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null, + mixed: [1, '2', 3, '10'] // Strings > Numbers in Firestore + }) + ) + .select( + arrayMaximum('empty').as('emptyResult'), + arrayMaximum('nullVal').as('nullResult'), + arrayMaximum('nonExistent').as('absentResult'), + arrayMaximum('mixed').as('mixedResult') + ) + ); + + expectResults(snapshot, { + emptyResult: null, + nullResult: null, + absentResult: null, + mixedResult: '2' // "2" > "10" > 3 > 1 + }); + }); + + it('supports arrayMaximumN', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(arrayMaximumN('tags', 2).as('maxTwoTags')) + ); + const expectedResults = [ + { + maxTwoTags: ['magic', 'epic'] + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('tags').arrayMaximumN(2).as('maxTwoTags')) + ); + expectResults(snapshot, ...expectedResults); + }); + + it('supports arrayMinimum', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(arrayMinimum('tags').as('minTag')) + ); + const expectedResults = [ + { + minTag: 'adventure' + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('tags').arrayMinimum().as('minTag')) + ); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent and mixed types + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null, + mixed: [1, '2', 3, '10'] // Strings > Numbers in Firestore + }) + ) + .select( + arrayMinimum('empty').as('emptyResult'), + arrayMinimum('nullVal').as('nullResult'), + arrayMinimum('nonExistent').as('absentResult'), + arrayMinimum('mixed').as('mixedResult') + ) + ); + + expectResults(snapshot, { + emptyResult: null, + nullResult: null, + absentResult: null, + mixedResult: 1 // 1 < 3 < "10" < "2" + }); + }); + + it('supports arrayMinimumN', async () => { + let snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(arrayMinimumN('tags', 2).as('minTwoTags')) + ); + const expectedResults = [ + { + minTwoTags: ['adventure', 'epic'] + } + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('tags').arrayMinimumN(2).as('minTwoTags')) + ); + expectResults(snapshot, ...expectedResults); + }); + + it('supports arrayIndexOf', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + arrayIndexOf('tags', 'adventure').as('indexFirst'), + arrayIndexOf(field('tags'), 'magic').as('indexSecond'), + field('tags').arrayIndexOf('adventure').as('indexFirst2'), + arrayIndexOf('tags', 'nonexistent').as('indexNone'), + arrayIndexOf('empty', 'anything').as('indexEmpty') + ) + ); + + const expectedResults = [ + { + indexFirst: 0, + indexSecond: 1, + indexFirst2: 0, + indexNone: -1, + indexEmpty: null + } + ]; + expectResults(snapshot, ...expectedResults); + + // Test with duplicate values + const snapshotDuplicates = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, 2, 3, 2, 1] + }) + ) + .select( + arrayIndexOf('arr', 2).as('firstIndex'), + arrayLastIndexOf('arr', 2).as('lastIndex') + ) + ); + + expectResults(snapshotDuplicates, { + firstIndex: 1, + lastIndex: 3 + }); + + // Test with null values + const snapshotNulls = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, null, 3, 2, 1], + nullArr: null + }) + ) + .select( + arrayIndexOf('arr', null).as('firstIndex'), + arrayIndexOf('nullArr', null).as('firstIndexNull') + ) + ); + + expectResults(snapshotNulls, { + firstIndex: 1, + firstIndexNull: null + }); + }); + + it('supports arrayLastIndexOf', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + arrayLastIndexOf('tags', 'adventure').as('lastIndexFirst'), + arrayLastIndexOf(field('tags'), 'epic').as('lastIndexLast'), + field('tags').arrayLastIndexOf('adventure').as('lastIndexFirst2'), + arrayLastIndexOf('tags', 'nonexistent').as('lastIndexNone'), + arrayLastIndexOf('empty', 'anything').as('lastIndexEmpty') + ) + ); + + const expectedResults = [ + { + lastIndexFirst: 0, + lastIndexLast: 2, + lastIndexFirst2: 0, + lastIndexNone: -1, + lastIndexEmpty: null + } + ]; + expectResults(snapshot, ...expectedResults); + + // Test with duplicate values + const snapshotDuplicates = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, 2, 3, 2, 1] + }) + ) + .select( + arrayIndexOf('arr', 2).as('firstIndex'), + arrayLastIndexOf('arr', 2).as('lastIndex') + ) + ); + + expectResults(snapshotDuplicates, { + firstIndex: 1, + lastIndex: 3 + }); + }); + + it('supports arrayIndexOfAll', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + arrayIndexOfAll('tags', 'adventure').as('indicesFirst'), + arrayIndexOfAll(field('tags'), 'epic').as('indicesLast'), + field('tags').arrayIndexOfAll('nonexistent').as('indicesNone'), + arrayIndexOfAll('empty', 'anything').as('indicesEmpty') + ) + ); + + const expectedResults = [ + { + indicesFirst: [0], + indicesLast: [2], + indicesNone: [], + indicesEmpty: null + } + ]; + expectResults(snapshot, ...expectedResults); + + // Test with duplicate values + const snapshotDuplicates = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, 2, 3, 2, 1] + }) + ) + .select( + arrayIndexOfAll('arr', 1).as('indices1'), + arrayIndexOfAll('arr', 2).as('indices2') + ) + ); + + expectResults(snapshotDuplicates, { + indices1: [0, 4], + indices2: [1, 3] + }); + + // Test with null values + const snapshotNulls = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, null, 3, null, 1], + nullArr: null + }) + ) + .select( + arrayIndexOfAll('arr', null).as('indices1'), + arrayIndexOfAll('nullArr', null).as('indicesNull') + ) + ); + + expectResults(snapshotNulls, { + indices1: [1, 3], + indicesNull: null + }); + }); + it('supports map', async () => { const snapshot = await execute( firestore From 22476e1bc42eb243d9dc5f73663e13784bb21f09 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 2 Mar 2026 10:20:47 -0800 Subject: [PATCH 079/174] Have renovate ignore typescript (#9575) --- renovate.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index 84f519c91c..1b0b15f7db 100644 --- a/renovate.json +++ b/renovate.json @@ -17,7 +17,8 @@ "typedoc", "@microsoft/tsdoc", "idb", - "karma-webpack" + "karma-webpack", + "typescript" ], "ignorePaths": ["auth/demo", "auth/cordova/demo", "auth-compat/demo"], "assignees": ["@hsubox76"], From a60f3d0d1a6ba8aa7388bba0d952d692ad74a146 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 2 Mar 2026 10:21:33 -0800 Subject: [PATCH 080/174] fix(ai): Add a warning when setting top-level params in hybrid mode (#9577) --- packages/ai/src/api.test.ts | 25 +++++++++++++++++++++++-- packages/ai/src/api.ts | 19 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/packages/ai/src/api.test.ts b/packages/ai/src/api.test.ts index 3a56f3a8fe..43e6d80984 100644 --- a/packages/ai/src/api.test.ts +++ b/packages/ai/src/api.test.ts @@ -14,7 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImagenModelParams, ModelParams, AIErrorCode } from './types'; +import { + ImagenModelParams, + ModelParams, + AIErrorCode, + InferenceMode +} from './types'; import { AIError } from './errors'; import { getAI, @@ -28,12 +33,17 @@ import { getTemplateImagenModel, TemplateImagenModel } from './api'; -import { expect } from 'chai'; +import { expect, use } from 'chai'; +import { stub } from 'sinon'; import { AI } from './public-types'; import { GenerativeModel } from './models/generative-model'; import { GoogleAIBackend, VertexAIBackend } from './backend'; import { getFullApp } from '../test-utils/get-fake-firebase-services'; import { AI_TYPE } from './constants'; +import { logger } from './logger'; +import sinonChai from 'sinon-chai'; + +use(sinonChai); const fakeAI: AI = { app: { @@ -148,6 +158,17 @@ describe('Top level API', () => { expect(genModel).to.be.an.instanceOf(GenerativeModel); expect(genModel.model).to.equal('publishers/google/models/my-model'); }); + it('getGenerativeModel warns in hybrid mode if top-level params are set', () => { + const warnStub = stub(logger, 'warn'); + const genModel = getGenerativeModel(fakeAI, { + mode: InferenceMode.PREFER_ON_DEVICE, + generationConfig: {} + }); + expect(genModel).to.be.an.instanceOf(GenerativeModel); + expect(warnStub).to.be.calledWithMatch(InferenceMode.PREFER_ON_DEVICE); + expect(warnStub).to.be.calledWithMatch('generationConfig'); + warnStub.restore(); + }); it('getImagenModel throws if no model is provided', () => { try { getImagenModel(fakeAI, {} as ImagenModelParams); diff --git a/packages/ai/src/api.ts b/packages/ai/src/api.ts index 759d02c5b8..aaf7fe4219 100644 --- a/packages/ai/src/api.ts +++ b/packages/ai/src/api.ts @@ -41,6 +41,7 @@ import { GoogleAIBackend } from './backend'; import { WebSocketHandlerImpl } from './websocket'; import { TemplateGenerativeModel } from './models/template-generative-model'; import { TemplateImagenModel } from './models/template-imagen-model'; +import { logger } from './logger'; export { ChatSession } from './methods/chat-session'; export { LiveSession } from './methods/live-session'; @@ -117,6 +118,12 @@ export function getAI(app: FirebaseApp = getApp(), options?: AIOptions): AI { return aiInstance; } +const hybridParamKeys: Array = [ + 'mode', + 'onDeviceParams', + 'inCloudParams' +]; + /** * Returns a {@link GenerativeModel} class with methods for inference * and other functionality. @@ -132,6 +139,18 @@ export function getGenerativeModel( const hybridParams = modelParams as HybridParams; let inCloudParams: ModelParams; if (hybridParams.mode) { + for (const param of Object.keys(modelParams)) { + if (!hybridParamKeys.includes(param as keyof HybridParams)) { + logger.warn( + `When a hybrid inference mode is specified (mode is currently set` + + ` to ${hybridParams.mode}), "${param}" cannot be ` + + `configured at the top level. Configuration for in-cloud and ` + + `on-device must be done separately in inCloudParams and onDeviceParams. ` + + `Configuration values set outside of inCloudParams and onDeviceParams will` + + ` be ignored.` + ); + } + } inCloudParams = hybridParams.inCloudParams || { model: DEFAULT_HYBRID_IN_CLOUD_MODEL }; From fb6f56994ecf7efbc033448b1f18b3422b24a12f Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 2 Mar 2026 13:56:28 -0800 Subject: [PATCH 081/174] fix(fdc): Fixed Flaky Cache Test (#9612) --- packages/data-connect/test/unit/caching.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/data-connect/test/unit/caching.test.ts b/packages/data-connect/test/unit/caching.test.ts index e8e1b6535d..114f448ffa 100644 --- a/packages/data-connect/test/unit/caching.test.ts +++ b/packages/data-connect/test/unit/caching.test.ts @@ -328,7 +328,7 @@ describe('caching', () => { const resultTree = await dc._queryManager.getFromResultTreeCache( queryRef(dc, titleQueryId) ); - expect(resultTree?.data).to.deep.eq(titleResponse.data); + expect(resultTree && resultTree.data).to.deep.eq(titleResponse.data); const genreQueryId = 'genreQuery'; await updateCacheData( dc, @@ -519,7 +519,8 @@ function setup(): { firebaseApp: FirebaseApp; dc: DataConnect } { }; const dc = getDataConnect(connectorConfig, { cacheSettings: { - cacheProvider: makeMemoryCacheProvider() + cacheProvider: makeMemoryCacheProvider(), + maxAgeSeconds: 5 } }); return { firebaseApp: app, dc }; From 2f7f426dec37efd75bad8dcc87cdd769ed4f7752 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 3 Mar 2026 09:36:05 -0800 Subject: [PATCH 082/174] Remove updateEmulatorBanner (#9608) --- .changeset/yellow-poets-teach.md | 11 ++ common/api-review/util.api.md | 3 - packages/auth/src/core/auth/emulator.ts | 8 +- packages/data-connect/src/api/DataConnect.ts | 7 +- packages/database/src/api/Database.ts | 4 +- packages/firestore/src/lite-api/database.ts | 4 +- packages/functions/src/service.ts | 7 +- packages/storage/src/service.ts | 4 +- packages/util/src/emulator.ts | 178 ------------------- 9 files changed, 17 insertions(+), 209 deletions(-) create mode 100644 .changeset/yellow-poets-teach.md diff --git a/.changeset/yellow-poets-teach.md b/.changeset/yellow-poets-teach.md new file mode 100644 index 0000000000..ff7cda7d43 --- /dev/null +++ b/.changeset/yellow-poets-teach.md @@ -0,0 +1,11 @@ +--- +'@firebase/data-connect': patch +'@firebase/firestore': patch +'@firebase/functions': patch +'@firebase/database': patch +'@firebase/storage': patch +'@firebase/auth': patch +'@firebase/util': minor +--- + +Remove `updateEmulatorBanner()`. (No release note needed.) diff --git a/common/api-review/util.api.md b/common/api-review/util.api.md index 349cd392de..8398fdcbcc 100644 --- a/common/api-review/util.api.md +++ b/common/api-review/util.api.md @@ -490,9 +490,6 @@ export interface Subscribe { // @public (undocumented) export type Unsubscribe = () => void; -// @public -export function updateEmulatorBanner(name: string, isRunningEmulator: boolean): void; - // Warning: (ae-missing-release-tag) "validateArgCount" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public diff --git a/packages/auth/src/core/auth/emulator.ts b/packages/auth/src/core/auth/emulator.ts index 15da907286..c4026e821a 100644 --- a/packages/auth/src/core/auth/emulator.ts +++ b/packages/auth/src/core/auth/emulator.ts @@ -18,12 +18,7 @@ import { Auth } from '../../model/public_types'; import { AuthErrorCode } from '../errors'; import { _assert } from '../util/assert'; import { _castAuth } from './auth_impl'; -import { - deepEqual, - isCloudWorkstation, - pingServer, - updateEmulatorBanner -} from '@firebase/util'; +import { deepEqual, isCloudWorkstation, pingServer } from '@firebase/util'; /** * Changes the {@link Auth} instance to communicate with the Firebase Auth Emulator, instead of production @@ -105,7 +100,6 @@ export function connectAuthEmulator( // Workaround to get cookies in Firebase Studio if (isCloudWorkstation(host)) { void pingServer(`${protocol}//${host}${portStr}`); - updateEmulatorBanner('Auth', true); } else if (!disableWarnings) { emitEmulatorWarning(); } diff --git a/packages/data-connect/src/api/DataConnect.ts b/packages/data-connect/src/api/DataConnect.ts index 46cfb73f93..3c463a399a 100644 --- a/packages/data-connect/src/api/DataConnect.ts +++ b/packages/data-connect/src/api/DataConnect.ts @@ -24,11 +24,7 @@ import { import { AppCheckInternalComponentName } from '@firebase/app-check-interop-types'; import { FirebaseAuthInternalName } from '@firebase/auth-interop-types'; import { Provider } from '@firebase/component'; -import { - isCloudWorkstation, - pingServer, - updateEmulatorBanner -} from '@firebase/util'; +import { isCloudWorkstation, pingServer } from '@firebase/util'; import { DataConnectCache, MemoryStub } from '../cache/Cache'; import { InternalCacheProvider } from '../cache/CacheProvider'; @@ -281,7 +277,6 @@ export function connectDataConnectEmulator( // Workaround to get cookies in Firebase Studio if (isCloudWorkstation(host)) { void pingServer(`https://${host}${port ? `:${port}` : ''}`); - updateEmulatorBanner('Data Connect', true); } dc.enableEmulator({ host, port, sslEnabled }); } diff --git a/packages/database/src/api/Database.ts b/packages/database/src/api/Database.ts index 338255be46..515e278b5c 100644 --- a/packages/database/src/api/Database.ts +++ b/packages/database/src/api/Database.ts @@ -31,8 +31,7 @@ import { EmulatorMockTokenOptions, getDefaultEmulatorHostnameAndPort, isCloudWorkstation, - pingServer, - updateEmulatorBanner + pingServer } from '@firebase/util'; import { AppCheckTokenProvider } from '../core/AppCheckTokenProvider'; @@ -394,7 +393,6 @@ export function connectDatabaseEmulator( // Workaround to get cookies in Firebase Studio if (isCloudWorkstation(host)) { void pingServer(host); - updateEmulatorBanner('Database', true); } // Modify the repo to apply emulator settings diff --git a/packages/firestore/src/lite-api/database.ts b/packages/firestore/src/lite-api/database.ts index 6af324e4ba..8e7fdb27e9 100644 --- a/packages/firestore/src/lite-api/database.ts +++ b/packages/firestore/src/lite-api/database.ts @@ -28,8 +28,7 @@ import { EmulatorMockTokenOptions, getDefaultEmulatorHostnameAndPort, isCloudWorkstation, - pingServer, - updateEmulatorBanner + pingServer } from '@firebase/util'; import { @@ -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( diff --git a/packages/functions/src/service.ts b/packages/functions/src/service.ts index 6e2eddda3a..6a0ddeaa8d 100644 --- a/packages/functions/src/service.ts +++ b/packages/functions/src/service.ts @@ -30,11 +30,7 @@ import { Provider } from '@firebase/component'; import { FirebaseAuthInternalName } from '@firebase/auth-interop-types'; import { MessagingInternalComponentName } from '@firebase/messaging-interop-types'; import { AppCheckInternalComponentName } from '@firebase/app-check-interop-types'; -import { - isCloudWorkstation, - pingServer, - updateEmulatorBanner -} from '@firebase/util'; +import { isCloudWorkstation, pingServer } from '@firebase/util'; export const DEFAULT_REGION = 'us-central1'; @@ -186,7 +182,6 @@ export function connectFunctionsEmulator( // Workaround to get cookies in Firebase Studio if (useSsl) { void pingServer(functionsInstance.emulatorOrigin + '/backends'); - updateEmulatorBanner('Functions', true); } } diff --git a/packages/storage/src/service.ts b/packages/storage/src/service.ts index a4252c7787..7e2090ccd2 100644 --- a/packages/storage/src/service.ts +++ b/packages/storage/src/service.ts @@ -46,8 +46,7 @@ import { createMockUserToken, EmulatorMockTokenOptions, isCloudWorkstation, - pingServer, - updateEmulatorBanner + pingServer } from '@firebase/util'; import { Connection, ConnectionType } from './implementation/connection'; @@ -151,7 +150,6 @@ export function connectStorageEmulator( // Workaround to get cookies in Firebase Studio if (useSsl) { void pingServer(`https://${storage.host}/b`); - updateEmulatorBanner('Storage', true); } storage._isUsingEmulator = true; storage._protocol = useSsl ? 'https' : 'http'; diff --git a/packages/util/src/emulator.ts b/packages/util/src/emulator.ts index 1c4d4ae7a7..2850b5be37 100644 --- a/packages/util/src/emulator.ts +++ b/packages/util/src/emulator.ts @@ -16,7 +16,6 @@ */ import { base64urlEncodeWithoutPadding } from './crypt'; -import { isCloudWorkstation } from './url'; // Firebase Auth tokens contain snake_case claims following the JWT standard / convention. /* eslint-disable camelcase */ @@ -141,180 +140,3 @@ export function createMockUserToken( signature ].join('.'); } - -interface EmulatorStatusMap { - [name: string]: boolean; -} -const emulatorStatus: EmulatorStatusMap = {}; - -interface EmulatorSummary { - prod: string[]; - emulator: string[]; -} - -// Checks whether any products are running on an emulator -function getEmulatorSummary(): EmulatorSummary { - const summary: EmulatorSummary = { - prod: [], - emulator: [] - }; - for (const key of Object.keys(emulatorStatus)) { - if (emulatorStatus[key]) { - summary.emulator.push(key); - } else { - summary.prod.push(key); - } - } - return summary; -} - -function getOrCreateEl(id: string): { created: boolean; element: HTMLElement } { - let parentDiv = document.getElementById(id); - let created = false; - if (!parentDiv) { - parentDiv = document.createElement('div'); - parentDiv.setAttribute('id', id); - created = true; - } - return { created, element: parentDiv }; -} - -let previouslyDismissed = false; -/** - * Updates Emulator Banner. Primarily used for Firebase Studio - * @param name - * @param isRunningEmulator - * @public - */ -export function updateEmulatorBanner( - name: string, - isRunningEmulator: boolean -): void { - if ( - typeof window === 'undefined' || - typeof document === 'undefined' || - !isCloudWorkstation(window.location.host) || - emulatorStatus[name] === isRunningEmulator || - emulatorStatus[name] || // If already set to use emulator, can't go back to prod. - previouslyDismissed - ) { - return; - } - - emulatorStatus[name] = isRunningEmulator; - - function prefixedId(id: string): string { - return `__firebase__banner__${id}`; - } - const bannerId = '__firebase__banner'; - const summary = getEmulatorSummary(); - const showError = summary.prod.length > 0; - - function tearDown(): void { - const element = document.getElementById(bannerId); - if (element) { - element.remove(); - } - } - - function setupBannerStyles(bannerEl: HTMLElement): void { - bannerEl.style.display = 'flex'; - bannerEl.style.background = '#7faaf0'; - bannerEl.style.position = 'fixed'; - bannerEl.style.bottom = '5px'; - bannerEl.style.left = '5px'; - bannerEl.style.padding = '.5em'; - bannerEl.style.borderRadius = '5px'; - bannerEl.style.alignItems = 'center'; - } - - function setupIconStyles(prependIcon: SVGElement, iconId: string): void { - prependIcon.setAttribute('width', '24'); - prependIcon.setAttribute('id', iconId); - prependIcon.setAttribute('height', '24'); - prependIcon.setAttribute('viewBox', '0 0 24 24'); - prependIcon.setAttribute('fill', 'none'); - prependIcon.style.marginLeft = '-6px'; - } - - function setupCloseBtn(): HTMLSpanElement { - const closeBtn = document.createElement('span'); - closeBtn.style.cursor = 'pointer'; - closeBtn.style.marginLeft = '16px'; - closeBtn.style.fontSize = '24px'; - closeBtn.innerHTML = ' ×'; - closeBtn.onclick = () => { - previouslyDismissed = true; - tearDown(); - }; - return closeBtn; - } - - function setupLinkStyles( - learnMoreLink: HTMLAnchorElement, - learnMoreId: string - ): void { - learnMoreLink.setAttribute('id', learnMoreId); - learnMoreLink.innerText = 'Learn more'; - learnMoreLink.href = - 'https://firebase.google.com/docs/studio/preview-apps#preview-backend'; - learnMoreLink.setAttribute('target', '__blank'); - learnMoreLink.style.paddingLeft = '5px'; - learnMoreLink.style.textDecoration = 'underline'; - } - - function setupDom(): void { - const banner = getOrCreateEl(bannerId); - const firebaseTextId = prefixedId('text'); - const firebaseText: HTMLSpanElement = - document.getElementById(firebaseTextId) || document.createElement('span'); - const learnMoreId = prefixedId('learnmore'); - const learnMoreLink: HTMLAnchorElement = - (document.getElementById(learnMoreId) as HTMLAnchorElement) || - document.createElement('a'); - const prependIconId = prefixedId('preprendIcon'); - const prependIcon: SVGElement = - (document.getElementById( - prependIconId - ) as HTMLOrSVGElement as SVGElement) || - document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - if (banner.created) { - // update styles - const bannerEl = banner.element; - setupBannerStyles(bannerEl); - setupLinkStyles(learnMoreLink, learnMoreId); - const closeBtn = setupCloseBtn(); - setupIconStyles(prependIcon, prependIconId); - bannerEl.append(prependIcon, firebaseText, learnMoreLink, closeBtn); - document.body.appendChild(bannerEl); - } - - if (showError) { - firebaseText.innerText = `Preview backend disconnected.`; - prependIcon.innerHTML = ` - - - - - - -`; - } else { - prependIcon.innerHTML = ` - - - - - - -`; - firebaseText.innerText = 'Preview backend running in this workspace.'; - } - firebaseText.setAttribute('id', firebaseTextId); - } - if (document.readyState === 'loading') { - window.addEventListener('DOMContentLoaded', setupDom); - } else { - setupDom(); - } -} From 753c1749cb26f1e2bb90300bafd864c15f49fea1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:08:15 -0800 Subject: [PATCH 083/174] build(deps): bump underscore in /packages/auth/demo/functions (#9617) Bumps [underscore](https://github.com/jashkenas/underscore) from 1.13.6 to 1.13.8. - [Commits](https://github.com/jashkenas/underscore/compare/1.13.6...1.13.8) --- updated-dependencies: - dependency-name: underscore dependency-version: 1.13.8 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/auth/demo/functions/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/auth/demo/functions/yarn.lock b/packages/auth/demo/functions/yarn.lock index a8eb80b657..ca875abee2 100644 --- a/packages/auth/demo/functions/yarn.lock +++ b/packages/auth/demo/functions/yarn.lock @@ -1728,9 +1728,9 @@ uglify-js@^3.7.7: integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== underscore@~1.13.2: - version "1.13.6" - resolved "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" - integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== + version "1.13.8" + resolved "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz#a93a21186c049dbf0e847496dba72b7bd8c1e92b" + integrity sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" From 1b0b2ed9bbc27cc4918f6a2b84cf88056c018ecf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:08:55 -0800 Subject: [PATCH 084/174] build(deps): bump fast-xml-parser (#9616) Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) from 4.3.5 to 4.5.4. - [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases) - [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.3.5...v4.5.4) --- updated-dependencies: - dependency-name: fast-xml-parser dependency-version: 4.5.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/auth-compat/demo/functions/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/auth-compat/demo/functions/yarn.lock b/packages/auth-compat/demo/functions/yarn.lock index a8eb80b657..dced704185 100644 --- a/packages/auth-compat/demo/functions/yarn.lock +++ b/packages/auth-compat/demo/functions/yarn.lock @@ -763,9 +763,9 @@ fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3: integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== fast-xml-parser@^4.2.2: - version "4.3.5" - resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.5.tgz#e2f2a2ae8377e9c3dc321b151e58f420ca7e5ccc" - integrity sha512-sWvP1Pl8H03B8oFJpFR3HE31HUfwtX7Rlf9BNsvdpujD4n7WMhfmu8h9wOV2u+c1k0ZilTADhPqypzx2J690ZQ== + version "4.5.4" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.4.tgz#64e52ddf1308001893bd225d5b1768840511c797" + integrity sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ== dependencies: strnum "^1.0.5" From 6ca7af5544c32d118cbbef82fcc222bc59647fa9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:09:58 -0800 Subject: [PATCH 085/174] build(deps): bump fast-xml-parser in /packages/auth/demo/functions (#9615) Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) from 4.3.5 to 4.5.4. - [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases) - [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.3.5...v4.5.4) --- updated-dependencies: - dependency-name: fast-xml-parser dependency-version: 4.5.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/auth/demo/functions/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/auth/demo/functions/yarn.lock b/packages/auth/demo/functions/yarn.lock index ca875abee2..b5514e3120 100644 --- a/packages/auth/demo/functions/yarn.lock +++ b/packages/auth/demo/functions/yarn.lock @@ -763,9 +763,9 @@ fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3: integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== fast-xml-parser@^4.2.2: - version "4.3.5" - resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.5.tgz#e2f2a2ae8377e9c3dc321b151e58f420ca7e5ccc" - integrity sha512-sWvP1Pl8H03B8oFJpFR3HE31HUfwtX7Rlf9BNsvdpujD4n7WMhfmu8h9wOV2u+c1k0ZilTADhPqypzx2J690ZQ== + version "4.5.4" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.4.tgz#64e52ddf1308001893bd225d5b1768840511c797" + integrity sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ== dependencies: strnum "^1.0.5" From f6b9085209ab1e8f12aba6a3ab0dd5b60af9bf3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:10:26 -0800 Subject: [PATCH 086/174] build(deps): bump minimatch in /packages/auth-compat/demo (#9601) Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.0.4 to 3.1.5. - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.5) --- updated-dependencies: - dependency-name: minimatch dependency-version: 3.1.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/auth-compat/demo/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/auth-compat/demo/yarn.lock b/packages/auth-compat/demo/yarn.lock index dc56599d4f..290adb95d9 100644 --- a/packages/auth-compat/demo/yarn.lock +++ b/packages/auth-compat/demo/yarn.lock @@ -2958,9 +2958,9 @@ min-indent@^1.0.0: integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + version "3.1.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== dependencies: brace-expansion "^1.1.7" From 1b9593be1afb0525bdecdccd34a3280c43c40b13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:11:36 -0800 Subject: [PATCH 087/174] build(deps): bump minimatch in /packages/rules-unit-testing/functions (#9595) Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.1.2 to 3.1.4. - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.4) --- updated-dependencies: - dependency-name: minimatch dependency-version: 3.1.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/rules-unit-testing/functions/yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/rules-unit-testing/functions/yarn.lock b/packages/rules-unit-testing/functions/yarn.lock index fa4168e298..259673db25 100644 --- a/packages/rules-unit-testing/functions/yarn.lock +++ b/packages/rules-unit-testing/functions/yarn.lock @@ -1345,16 +1345,16 @@ mime@^3.0.0: integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + version "3.1.4" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.4.tgz#89d910ea3970a77ac8edfd30340ccd038b758079" + integrity sha512-twmL+S8+7yIsE9wsqgzU3E8/LumN3M3QELrBZ20OdmQ9jB2JvW5oZtBEmft84k/Gs5CG9mqtWc6Y9vW+JEzGxw== dependencies: brace-expansion "^1.1.7" minimatch@^5.0.1: - version "5.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz#0939d7d6f0898acbd1508abe534d1929368a8fff" - integrity sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg== + version "5.1.8" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.8.tgz#32a16ebcccd6421c674430acb199b8806c68169b" + integrity sha512-7RN35vit8DeBclkofOVmBY0eDAZZQd1HzmukRdSyz95CRh8FT54eqnbj0krQr3mrHR6sfRyYkyhwBWjoV5uqlQ== dependencies: brace-expansion "^2.0.1" From a36b45b8cd8ef10f871034da521413b929361c40 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:15:27 -0800 Subject: [PATCH 088/174] chore(deps): update peter-evans/create-or-update-comment digest to e2426b4 (#9579) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/check-changeset.yml | 6 +++--- .github/workflows/check-vertexai-responses.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-changeset.yml b/.github/workflows/check-changeset.yml index 30379bf45c..83e6151636 100644 --- a/.github/workflows/check-changeset.yml +++ b/.github/workflows/check-changeset.yml @@ -70,7 +70,7 @@ jobs: - name: Create comment (missing packages) if: ${{!steps.fc.outputs.comment-id && steps.check-changeset.outputs.CHANGESET_ERROR_MESSAGE}} # This commit represents v4.0.0 - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 + uses: peter-evans/create-or-update-comment@e2426b4b1346fd5e8c731c0bbe368063ea0286ac with: issue-number: ${{github.event.number}} body: | @@ -79,7 +79,7 @@ jobs: - name: Update comment (missing packages) if: ${{steps.fc.outputs.comment-id && steps.check-changeset.outputs.CHANGESET_ERROR_MESSAGE}} # This commit represents v4.0.0 - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 + uses: peter-evans/create-or-update-comment@e2426b4b1346fd5e8c731c0bbe368063ea0286ac with: comment-id: ${{steps.fc.outputs.comment-id}} edit-mode: replace @@ -89,7 +89,7 @@ jobs: - name: Update comment (no missing packages) if: ${{steps.fc.outputs.comment-id && !steps.check-changeset.outputs.CHANGESET_ERROR_MESSAGE}} # This commit represents v4.0.0 - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 + uses: peter-evans/create-or-update-comment@e2426b4b1346fd5e8c731c0bbe368063ea0286ac with: comment-id: ${{steps.fc.outputs.comment-id}} edit-mode: replace diff --git a/.github/workflows/check-vertexai-responses.yml b/.github/workflows/check-vertexai-responses.yml index 8dcbc2233f..fd5dcd21e3 100644 --- a/.github/workflows/check-vertexai-responses.yml +++ b/.github/workflows/check-vertexai-responses.yml @@ -47,7 +47,7 @@ jobs: - name: Comment on PR if newer version is available if: ${{env.cloned_tag != env.latest_tag && !steps.fc.outputs.comment-id}} # This commit represents v4.0.0 - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 + uses: peter-evans/create-or-update-comment@e2426b4b1346fd5e8c731c0bbe368063ea0286ac with: issue-number: ${{github.event.number}} body: > From a8055e8a7d820eb56f23b14f25aa07f794835142 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:16:42 -0800 Subject: [PATCH 089/174] build(deps): bump minimatch in /packages/auth/demo/functions (#9592) Bumps [minimatch](https://github.com/isaacs/minimatch) from 5.1.6 to 5.1.7. - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](https://github.com/isaacs/minimatch/compare/v5.1.6...v5.1.7) --- updated-dependencies: - dependency-name: minimatch dependency-version: 5.1.7 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/auth/demo/functions/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/auth/demo/functions/yarn.lock b/packages/auth/demo/functions/yarn.lock index b5514e3120..edc7dd71ca 100644 --- a/packages/auth/demo/functions/yarn.lock +++ b/packages/auth/demo/functions/yarn.lock @@ -1299,9 +1299,9 @@ mime@^3.0.0: integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + version "5.1.7" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.7.tgz#9bce540b26998f278d34784a3dd25d96f5054d6d" + integrity sha512-FjiwU9HaHW6YB3H4a1sFudnv93lvydNjz2lmyUXR6IwKhGI+bgL3SOZrBGn6kvvX2pJvhEkGSGjyTHN47O4rqA== dependencies: brace-expansion "^2.0.1" From 316478dc1c75737a53743db6574e11349f6b20eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:19:26 -0800 Subject: [PATCH 090/174] build(deps): bump axios from 1.7.9 to 1.13.5 (#9574) Bumps [axios](https://github.com/axios/axios) from 1.7.9 to 1.13.5. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.7.9...v1.13.5) --- updated-dependencies: - dependency-name: axios dependency-version: 1.13.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6a6ca5c3cf..7a24df2fc1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4443,12 +4443,12 @@ aws4@^1.8.0: integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== axios@^1.6.0: - version "1.7.9" - resolved "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" - integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw== + version "1.13.5" + resolved "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz#5e464688fa127e11a660a2c49441c009f6567a43" + integrity sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q== dependencies: - follow-redirects "^1.15.6" - form-data "^4.0.0" + follow-redirects "^1.15.11" + form-data "^4.0.5" proxy-from-env "^1.1.0" b4a@^1.6.4: @@ -7778,11 +7778,16 @@ fn.name@1.x.x: resolved "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.0.0, follow-redirects@^1.15.6: +follow-redirects@^1.0.0: version "1.15.9" resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== +follow-redirects@^1.15.11: + version "1.15.11" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340" + integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== + for-each@^0.3.3: version "0.3.4" resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.4.tgz#814517ffc303d1399b2564d8165318e735d0341c" @@ -7842,6 +7847,17 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.5: + version "4.0.5" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053" + integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" From e2f24d45327f245fb4810f21043cd47a65d5b7cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:20:14 -0800 Subject: [PATCH 091/174] build(deps): bump ajv in /packages/auth-compat/demo (#9585) Bumps [ajv](https://github.com/ajv-validator/ajv) from 6.12.6 to 6.14.0. - [Release notes](https://github.com/ajv-validator/ajv/releases) - [Commits](https://github.com/ajv-validator/ajv/compare/v6.12.6...v6.14.0) --- updated-dependencies: - dependency-name: ajv dependency-version: 6.14.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/auth-compat/demo/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/auth-compat/demo/yarn.lock b/packages/auth-compat/demo/yarn.lock index 290adb95d9..1125f5e9ff 100644 --- a/packages/auth-compat/demo/yarn.lock +++ b/packages/auth-compat/demo/yarn.lock @@ -1064,9 +1064,9 @@ aggregate-error@^3.0.0: indent-string "^4.0.0" ajv@^6.12.3: - version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + version "6.14.0" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz#fd067713e228210636ebb08c60bd3765d6dbe73a" + integrity sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" From c9c083f09d98fe5dce0039f6a9bdde56f5889ebb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:35:58 -0800 Subject: [PATCH 092/174] build(deps): bump fast-xml-parser (#9607) Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) from 4.3.2 to 4.5.4. - [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases) - [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.3.2...v4.5.4) --- updated-dependencies: - dependency-name: fast-xml-parser dependency-version: 4.5.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/rules-unit-testing/functions/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rules-unit-testing/functions/yarn.lock b/packages/rules-unit-testing/functions/yarn.lock index 259673db25..42e67eed61 100644 --- a/packages/rules-unit-testing/functions/yarn.lock +++ b/packages/rules-unit-testing/functions/yarn.lock @@ -777,9 +777,9 @@ fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3: integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== fast-xml-parser@^4.2.2: - version "4.3.2" - resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.2.tgz#761e641260706d6e13251c4ef8e3f5694d4b0d79" - integrity sha512-rmrXUXwbJedoXkStenj1kkljNF7ugn5ZjR9FJcwmCfcCbtOMDghPajbc+Tck6vE6F5XsDmx+Pr2le9fw8+pXBg== + version "4.5.4" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.4.tgz#64e52ddf1308001893bd225d5b1768840511c797" + integrity sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ== dependencies: strnum "^1.0.5" From e79b8f74e6168ed4fd8e130b4763167ddb2cba3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:36:22 -0800 Subject: [PATCH 093/174] build(deps): bump basic-ftp from 5.0.5 to 5.2.0 (#9598) Bumps [basic-ftp](https://github.com/patrickjuchli/basic-ftp) from 5.0.5 to 5.2.0. - [Release notes](https://github.com/patrickjuchli/basic-ftp/releases) - [Changelog](https://github.com/patrickjuchli/basic-ftp/blob/master/CHANGELOG.md) - [Commits](https://github.com/patrickjuchli/basic-ftp/compare/v5.0.5...v5.2.0) --- updated-dependencies: - dependency-name: basic-ftp dependency-version: 5.2.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7a24df2fc1..ad913eb48b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4597,9 +4597,9 @@ basic-auth@^2.0.1, basic-auth@~2.0.1: safe-buffer "5.1.2" basic-ftp@^5.0.2: - version "5.0.5" - resolved "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz#14a474f5fffecca1f4f406f1c26b18f800225ac0" - integrity sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg== + version "5.2.0" + resolved "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.0.tgz#7c2dff63c918bde60e6bad1f2ff93dcf5137a40a" + integrity sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw== bcrypt-pbkdf@^1.0.0: version "1.0.2" From 76e68216d371875947a75a0e20edf33f19ac3a38 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:36:56 -0800 Subject: [PATCH 094/174] build(deps-dev): bump rollup in /packages/auth-compat/demo (#9599) Bumps [rollup](https://github.com/rollup/rollup) from 2.79.1 to 2.80.0. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/v2.80.0/CHANGELOG.md) - [Commits](https://github.com/rollup/rollup/compare/v2.79.1...v2.80.0) --- updated-dependencies: - dependency-name: rollup dependency-version: 2.80.0 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/auth-compat/demo/package.json | 2 +- packages/auth-compat/demo/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/auth-compat/demo/package.json b/packages/auth-compat/demo/package.json index 8e14417423..f1e850cada 100644 --- a/packages/auth-compat/demo/package.json +++ b/packages/auth-compat/demo/package.json @@ -29,7 +29,7 @@ "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "4.1.0", "@rollup/plugin-node-resolve": "16.0.0", - "rollup": "2.79.1", + "rollup": "2.80.0", "rollup-plugin-replace": "2.2.0", "rollup-plugin-sourcemaps": "0.6.3", "rollup-plugin-typescript2": "0.31.2", diff --git a/packages/auth-compat/demo/yarn.lock b/packages/auth-compat/demo/yarn.lock index 1125f5e9ff..3b8e3cb9e9 100644 --- a/packages/auth-compat/demo/yarn.lock +++ b/packages/auth-compat/demo/yarn.lock @@ -4017,10 +4017,10 @@ rollup-pluginutils@^2.6.0: dependencies: estree-walker "^0.6.1" -rollup@2.79.1: - version "2.79.1" - resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" - integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== +rollup@2.80.0: + version "2.80.0" + resolved "https://registry.npmjs.org/rollup/-/rollup-2.80.0.tgz#a82efc15b748e986a7c76f0f771221b1fa108a2c" + integrity sha512-cIFJOD1DESzpjOBl763Kp1AH7UE/0fcdHe6rZXUdQ9c50uvgigvW97u3IcSeBwOkgqL/PXPBktBCh0KEu5L8XQ== optionalDependencies: fsevents "~2.3.2" From 792c616712165041ce52f2fca16f28ab56199709 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 5 Mar 2026 12:37:04 -0800 Subject: [PATCH 095/174] chore: Add a dependabot.yml to better configure its behavior (#9620) --- .github/dependabot.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..c98f8fb04d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,20 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directories: + - "/" + - "/packages/*" + - "/integration/*" + - "/e2e/*" + - "/repo-scripts/**/*" + exclude-paths: + - "packages/auth/demo" + - "packages/auth/cordova/demo" + - "packages/auth-compat/demo" + schedule: + interval: "daily" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" From f44d8265009c019f7cd13cdfdc7615a87d276f15 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 6 Mar 2026 00:53:53 -0500 Subject: [PATCH 096/174] firestore: improve documentation about CRUD promises and when they resolve (#8887) --- docs-devsite/firestore_.md | 48 ++++--- packages/firestore/src/api/reference_impl.ts | 139 ++++++++++++++++--- 2 files changed, 147 insertions(+), 40 deletions(-) diff --git a/docs-devsite/firestore_.md b/docs-devsite/firestore_.md index 3787d34b27..1bd4ddbe2f 100644 --- a/docs-devsite/firestore_.md +++ b/docs-devsite/firestore_.md @@ -110,10 +110,10 @@ https://github.com/firebase/firebase-js-sdk | [and(queryConstraints)](./firestore_.md#and_e72c712) | Creates a new [QueryCompositeFilterConstraint](./firestore_.querycompositefilterconstraint.md#querycompositefilterconstraint_class) that is a conjunction of the given filter constraints. A conjunction filter includes a document if it satisfies all of the given filters. | | [or(queryConstraints)](./firestore_.md#or_e72c712) | Creates a new [QueryCompositeFilterConstraint](./firestore_.querycompositefilterconstraint.md#querycompositefilterconstraint_class) that is a disjunction of the given filter constraints. A disjunction filter includes a document if it satisfies any of the given filters. | | function(reference, ...) | -| [addDoc(reference, data)](./firestore_.md#adddoc_6e783ff) | Add a new document to specified CollectionReference with the given data, assigning it a document ID automatically. | +| [addDoc(reference, data)](./firestore_.md#adddoc_6e783ff) | Add a new document to specified CollectionReference with the given data, assigning it a document ID automatically.Note that the returned Promise does \_not\_ resolve until the document is successfully created to the remote Firestore backend and, similarly, is not rejected until the remote Firestore backend reports an error creating the given document. So if the client cannot reach the backend (for example, due to being offline) then the returned Promise will not resolve for a potentially-long time (for example, until the client has gone back online). That being said, the given document \_will\_ be immediately created in the local cache and will be incorporated into future "get" operations as if it had been successfully created in the remote Firestore server, a feature of Firestore called "latency compensation". The document will \_eventually\_ be created in the remote Firestore backend once a connection can be established. Therefore, it is usually undesirable to await the Promise returned from this function because the indefinite amount of time before which the promise resolves or rejects can block application logic unnecessarily. | | [collection(reference, path, pathSegments)](./firestore_.md#collection_568f98d) | Gets a CollectionReference instance that refers to a subcollection of reference at the specified relative path. | | [collection(reference, path, pathSegments)](./firestore_.md#collection_70b4396) | Gets a CollectionReference instance that refers to a subcollection of reference at the specified relative path. | -| [deleteDoc(reference)](./firestore_.md#deletedoc_4569087) | Deletes the document referred to by the specified DocumentReference. | +| [deleteDoc(reference)](./firestore_.md#deletedoc_4569087) | Deletes the document referred to by the specified DocumentReference.Note that the returned Promise does \_not\_ resolve until the document is successfully deleted from the remote Firestore backend and, similarly, is not rejected until the remote Firestore backend reports an error deleting the given document. So if the client cannot reach the backend (for example, due to being offline) then the returned Promise will not resolve for a potentially-long time (for example, until the client has gone back online). That being said, the given data \_will\_ be immediately deleted from the local cache and will be reflected in future "get" operations as if it had been successfully deleted from the remote Firestore server, a feature of Firestore called "latency compensation". The document will \_eventually\_ be deleted from the remote Firestore backend once a connection can be established. Therefore, it is usually undesirable to await the Promise returned from this function because the indefinite amount of time before which the promise resolves or rejects can block application logic unnecessarily. | | [doc(reference, path, pathSegments)](./firestore_.md#doc_568f98d) | Gets a DocumentReference instance that refers to a document within reference at the specified relative path. If no path is specified, an automatically-generated unique ID will be used for the returned DocumentReference. | | [doc(reference, path, pathSegments)](./firestore_.md#doc_70b4396) | Gets a DocumentReference instance that refers to a document within reference at the specified relative path. | | [getDoc(reference)](./firestore_.md#getdoc_4569087) | Reads the document referred to by this DocumentReference.Note: getDoc() attempts to provide up-to-date data when possible by waiting for data from the server, but it may return cached data or fail if you are offline and the server cannot be reached. To specify this behavior, invoke [getDocFromCache()](./firestore_.md#getdocfromcache_4569087) or [getDocFromServer()](./firestore_.md#getdocfromserver_4569087). | @@ -123,10 +123,10 @@ https://github.com/firebase/firebase-js-sdk | [onSnapshot(reference, options, observer)](./firestore_.md#onsnapshot_86b6b9e) | Attaches a listener for DocumentSnapshot events. You may either pass individual onNext and onError callbacks or pass a single observer object with next and error callbacks.NOTE: Although an onCompletion callback can be provided, it will never be called because the snapshot stream is never-ending. | | [onSnapshot(reference, onNext, onError, onCompletion)](./firestore_.md#onsnapshot_905f42c) | Attaches a listener for DocumentSnapshot events. You may either pass individual onNext and onError callbacks or pass a single observer object with next and error callbacks.NOTE: Although an onCompletion callback can be provided, it will never be called because the snapshot stream is never-ending. | | [onSnapshot(reference, options, onNext, onError, onCompletion)](./firestore_.md#onsnapshot_0c39991) | Attaches a listener for DocumentSnapshot events. You may either pass individual onNext and onError callbacks or pass a single observer object with next and error callbacks.NOTE: Although an onCompletion callback can be provided, it will never be called because the snapshot stream is never-ending. | -| [setDoc(reference, data)](./firestore_.md#setdoc_ee215ad) | Writes to the document referred to by this DocumentReference. If the document does not yet exist, it will be created. | -| [setDoc(reference, data, options)](./firestore_.md#setdoc_ff80739) | Writes to the document referred to by the specified DocumentReference. If the document does not yet exist, it will be created. If you provide merge or mergeFields, the provided data can be merged into an existing document. | -| [updateDoc(reference, data)](./firestore_.md#updatedoc_51a65e3) | Updates fields in the document referred to by the specified DocumentReference. The update will fail if applied to a document that does not exist. | -| [updateDoc(reference, field, value, moreFieldsAndValues)](./firestore_.md#updatedoc_7c28659) | Updates fields in the document referred to by the specified DocumentReference The update will fail if applied to a document that does not exist.Nested fields can be updated by providing dot-separated field path strings or by providing FieldPath objects. | +| [setDoc(reference, data)](./firestore_.md#setdoc_ee215ad) | Writes to the document referred to by this DocumentReference. If the document does not yet exist, it will be created.Note that the returned Promise does \_not\_ resolve until the data is successfully written to the remote Firestore backend and, similarly, is not rejected until the remote Firestore backend reports an error saving the given data. So if the client cannot reach the backend (for example, due to being offline) then the returned Promise will not resolve for a potentially-long time (for example, until the client has gone back online). That being said, the given data \_will\_ be immediately saved to the local cache and will be incorporated into future "get" operations as if it had been successfully written to the remote Firestore server, a feature of Firestore called "latency compensation". The data will \_eventually\_ be written to the remote Firestore backend once a connection can be established. Therefore, it is usually undesirable to await the Promise returned from this function because the indefinite amount of time before which the promise resolves or rejects can block application logic unnecessarily. | +| [setDoc(reference, data, options)](./firestore_.md#setdoc_ff80739) | Writes to the document referred to by the specified DocumentReference. If the document does not yet exist, it will be created. If you provide merge or mergeFields, the provided data can be merged into an existing document.Note that the returned Promise does \_not\_ resolve until the data is successfully written to the remote Firestore backend and, similarly, is not rejected until the remote Firestore backend reports an error saving the given data. So if the client cannot reach the backend (for example, due to being offline) then the returned Promise will not resolve for a potentially-long time (for example, until the client has gone back online). That being said, the given data \_will\_ be immediately saved to the local cache and will be incorporated into future "get" operations as if it had been successfully written to the remote Firestore server, a feature of Firestore called "latency compensation". The data will \_eventually\_ be written to the remote Firestore backend once a connection can be established. Therefore, it is usually undesirable to await the Promise returned from this function because the indefinite amount of time before which the promise resolves or rejects can block application logic unnecessarily. | +| [updateDoc(reference, data)](./firestore_.md#updatedoc_51a65e3) | Updates fields in the document referred to by the specified DocumentReference. The update will fail if applied to a document that does not exist.Note that the returned Promise does \_not\_ resolve until the data is successfully written to the remote Firestore backend and, similarly, is not rejected until the remote Firestore backend reports an error saving the given data. So if the client cannot reach the backend (for example, due to being offline) then the returned Promise will not resolve for a potentially-long time (for example, until the client has gone back online). That being said, the given data \_will\_ be immediately saved to the local cache and will be incorporated into future "get" operations as if it had been successfully written to the remote Firestore server, a feature of Firestore called "latency compensation". The data will \_eventually\_ be written to the remote Firestore backend once a connection can be established. Therefore, it is usually undesirable to await the Promise returned from this function because the indefinite amount of time before which the promise resolves or rejects can block application logic unnecessarily. | +| [updateDoc(reference, field, value, moreFieldsAndValues)](./firestore_.md#updatedoc_7c28659) | Updates fields in the document referred to by the specified DocumentReference The update will fail if applied to a document that does not exist.Nested fields can be updated by providing dot-separated field path strings or by providing FieldPath objects.Note that the returned Promise does \_not\_ resolve until the data is successfully written to the remote Firestore backend and, similarly, is not rejected until the remote Firestore backend reports an error saving the given data. So if the client cannot reach the backend (for example, due to being offline) then the returned Promise will not resolve for a potentially-long time (for example, until the client has gone back online). That being said, the given data \_will\_ be immediately saved to the local cache and will be incorporated into future "get" operations as if it had been successfully written to the remote Firestore server, a feature of Firestore called "latency compensation". The data will \_eventually\_ be written to the remote Firestore backend once a connection can be established. Therefore, it is usually undesirable to await the Promise returned from this function because the indefinite amount of time before which the promise resolves or rejects can block application logic unnecessarily. | | function(settings, ...) | | [memoryLocalCache(settings)](./firestore_.md#memorylocalcache_05f4bf2) | Creates an instance of MemoryLocalCache. The instance can be set to FirestoreSettings.cache to tell the SDK which cache layer to use. | | [memoryLruGarbageCollector(settings)](./firestore_.md#memorylrugarbagecollector_5ee014c) | Creates an instance of MemoryLruGarbageCollector.A target size can be specified as part of the setting parameter. The collector will start deleting documents once the cache size exceeds the given size. The default cache size is 40MB (40 \* 1024 \* 1024 bytes). | @@ -1935,7 +1935,7 @@ export declare function getDocs( Promise<[QuerySnapshot](./firestore_.querysnapshot.md#querysnapshot_class)<AppModelType, DbModelType>> -A `Promise` that will be resolved with the results of the query. +A `Promise` that resolves with the results of the query. ### getDocsFromCache(query) {:#getdocsfromcache_4e56953} @@ -1957,7 +1957,7 @@ export declare function getDocsFromCache<AppModelType, DbModelType>> -A `Promise` that will be resolved with the results of the query. +A `Promise` that resolves with the results of the query. ### getDocsFromServer(query) {:#getdocsfromserver_4e56953} @@ -1979,7 +1979,7 @@ export declare function getDocsFromServer<AppModelType, DbModelType>> -A `Promise` that will be resolved with the results of the query. +A `Promise` that resolves with the results of the query. ### onSnapshot(query, observer) {:#onsnapshot_8d14049} @@ -2198,6 +2198,8 @@ The newly created [QueryCompositeFilterConstraint](./firestore_.querycompositefi Add a new document to specified `CollectionReference` with the given data, assigning it a document ID automatically. +Note that the returned `Promise` does \_not\_ resolve until the document is successfully created to the remote Firestore backend and, similarly, is not rejected until the remote Firestore backend reports an error creating the given document. So if the client cannot reach the backend (for example, due to being offline) then the returned `Promise` will not resolve for a potentially-long time (for example, until the client has gone back online). That being said, the given document \_will\_ be immediately created in the local cache and will be incorporated into future "get" operations as if it had been successfully created in the remote Firestore server, a feature of Firestore called "latency compensation". The document will \_eventually\_ be created in the remote Firestore backend once a connection can be established. Therefore, it is usually undesirable to `await` the `Promise` returned from this function because the indefinite amount of time before which the promise resolves or rejects can block application logic unnecessarily. + Signature: ```typescript @@ -2215,7 +2217,7 @@ export declare function addDoc(r Promise<[DocumentReference](./firestore_.documentreference.md#documentreference_class)<AppModelType, DbModelType>> -A `Promise` resolved with a `DocumentReference` pointing to the newly created document after it has been written to the backend (Note that it won't resolve while you're offline). +A `Promise` that resolves once the docoument has been successfully created in the backend or rejects once the backend reports an error creating the document. ### collection(reference, path, pathSegments) {:#collection_568f98d} @@ -2277,6 +2279,8 @@ If the final path has an even number of segments and does not point to a collect Deletes the document referred to by the specified `DocumentReference`. +Note that the returned `Promise` does \_not\_ resolve until the document is successfully deleted from the remote Firestore backend and, similarly, is not rejected until the remote Firestore backend reports an error deleting the given document. So if the client cannot reach the backend (for example, due to being offline) then the returned `Promise` will not resolve for a potentially-long time (for example, until the client has gone back online). That being said, the given data \_will\_ be immediately deleted from the local cache and will be reflected in future "get" operations as if it had been successfully deleted from the remote Firestore server, a feature of Firestore called "latency compensation". The document will \_eventually\_ be deleted from the remote Firestore backend once a connection can be established. Therefore, it is usually undesirable to `await` the `Promise` returned from this function because the indefinite amount of time before which the promise resolves or rejects can block application logic unnecessarily. + Signature: ```typescript @@ -2293,7 +2297,7 @@ export declare function deleteDoc(r Promise<[DocumentSnapshot](./firestore_.documentsnapshot.md#documentsnapshot_class)<AppModelType, DbModelType>> -A Promise resolved with a `DocumentSnapshot` containing the current document contents. +A `Promise` that resolves with a `DocumentSnapshot` containing the document contents. ### getDocFromCache(reference) {:#getdocfromcache_4569087} @@ -2395,7 +2399,7 @@ export declare function getDocFromCache<AppModelType, DbModelType>> -A `Promise` resolved with a `DocumentSnapshot` containing the current document contents. +A `Promise` that resolves with a `DocumentSnapshot` containing the document contents. ### getDocFromServer(reference) {:#getdocfromserver_4569087} @@ -2417,7 +2421,7 @@ export declare function getDocFromServer<AppModelType, DbModelType>> -A `Promise` resolved with a `DocumentSnapshot` containing the current document contents. +A `Promise` that resolves with a `DocumentSnapshot` containing the document contents. ### onSnapshot(reference, observer) {:#onsnapshot_0312fd7} @@ -2537,6 +2541,8 @@ An unsubscribe function that can be called to cancel the snapshot listener. Writes to the document referred to by this `DocumentReference`. If the document does not yet exist, it will be created. +Note that the returned `Promise` does \_not\_ resolve until the data is successfully written to the remote Firestore backend and, similarly, is not rejected until the remote Firestore backend reports an error saving the given data. So if the client cannot reach the backend (for example, due to being offline) then the returned `Promise` will not resolve for a potentially-long time (for example, until the client has gone back online). That being said, the given data \_will\_ be immediately saved to the local cache and will be incorporated into future "get" operations as if it had been successfully written to the remote Firestore server, a feature of Firestore called "latency compensation". The data will \_eventually\_ be written to the remote Firestore backend once a connection can be established. Therefore, it is usually undesirable to `await` the `Promise` returned from this function because the indefinite amount of time before which the promise resolves or rejects can block application logic unnecessarily. + Signature: ```typescript @@ -2554,12 +2560,14 @@ export declare function setDoc(r Promise<void> -A `Promise` resolved once the data has been successfully written to the backend (note that it won't resolve while you're offline). +A `Promise` that resolves once the data has been successfully written to the backend or rejects once the backend reports an error writing the data. ### setDoc(reference, data, options) {:#setdoc_ff80739} Writes to the document referred to by the specified `DocumentReference`. If the document does not yet exist, it will be created. If you provide `merge` or `mergeFields`, the provided data can be merged into an existing document. +Note that the returned `Promise` does \_not\_ resolve until the data is successfully written to the remote Firestore backend and, similarly, is not rejected until the remote Firestore backend reports an error saving the given data. So if the client cannot reach the backend (for example, due to being offline) then the returned `Promise` will not resolve for a potentially-long time (for example, until the client has gone back online). That being said, the given data \_will\_ be immediately saved to the local cache and will be incorporated into future "get" operations as if it had been successfully written to the remote Firestore server, a feature of Firestore called "latency compensation". The data will \_eventually\_ be written to the remote Firestore backend once a connection can be established. Therefore, it is usually undesirable to `await` the `Promise` returned from this function because the indefinite amount of time before which the promise resolves or rejects can block application logic unnecessarily. + Signature: ```typescript @@ -2578,12 +2586,14 @@ export declare function setDoc(r Promise<void> -A Promise resolved once the data has been successfully written to the backend (note that it won't resolve while you're offline). +A `Promise` that resolves once the data has been successfully written to the backend or rejects once the backend reports an error writing the data. ### updateDoc(reference, data) {:#updatedoc_51a65e3} Updates fields in the document referred to by the specified `DocumentReference`. The update will fail if applied to a document that does not exist. +Note that the returned `Promise` does \_not\_ resolve until the data is successfully written to the remote Firestore backend and, similarly, is not rejected until the remote Firestore backend reports an error saving the given data. So if the client cannot reach the backend (for example, due to being offline) then the returned `Promise` will not resolve for a potentially-long time (for example, until the client has gone back online). That being said, the given data \_will\_ be immediately saved to the local cache and will be incorporated into future "get" operations as if it had been successfully written to the remote Firestore server, a feature of Firestore called "latency compensation". The data will \_eventually\_ be written to the remote Firestore backend once a connection can be established. Therefore, it is usually undesirable to `await` the `Promise` returned from this function because the indefinite amount of time before which the promise resolves or rejects can block application logic unnecessarily. + Signature: ```typescript @@ -2601,7 +2611,7 @@ export declare function updateDocSignature: ```typescript @@ -2628,7 +2640,7 @@ export declare function updateDoc( reference: DocumentReference @@ -132,8 +132,8 @@ export function getDoc( * Reads the document referred to by this `DocumentReference` from cache. * Returns an error if the document is not currently cached. * - * @returns A `Promise` resolved with a `DocumentSnapshot` containing the - * current document contents. + * @returns A `Promise` that resolves with a `DocumentSnapshot` containing the + * document contents. */ export function getDocFromCache( reference: DocumentReference @@ -166,8 +166,8 @@ export function getDocFromCache( * Reads the document referred to by this `DocumentReference` from the server. * Returns an error if the network is not available. * - * @returns A `Promise` resolved with a `DocumentSnapshot` containing the - * current document contents. + * @returns A `Promise` that resolves with a `DocumentSnapshot` containing the + * document contents. */ export function getDocFromServer< AppModelType, @@ -195,7 +195,7 @@ export function getDocFromServer< * you are offline and the server cannot be reached. To specify this behavior, * invoke {@link getDocsFromCache} or {@link getDocsFromServer}. * - * @returns A `Promise` that will be resolved with the results of the query. + * @returns A `Promise` that resolves with the results of the query. */ export function getDocs( query: Query @@ -225,7 +225,7 @@ export function getDocs( * Returns an empty result set if no documents matching the query are currently * cached. * - * @returns A `Promise` that will be resolved with the results of the query. + * @returns A `Promise` that resolves with the results of the query. */ export function getDocsFromCache< AppModelType, @@ -253,7 +253,7 @@ export function getDocsFromCache< * Executes the query and returns the results as a `QuerySnapshot` from the * server. Returns an error if the network is not available. * - * @returns A `Promise` that will be resolved with the results of the query. + * @returns A `Promise` that resolves with the results of the query. */ export function getDocsFromServer< AppModelType, @@ -277,10 +277,26 @@ export function getDocsFromServer< * Writes to the document referred to by this `DocumentReference`. If the * document does not yet exist, it will be created. * + * Note that the returned `Promise` does _not_ resolve until the data is + * successfully written to the remote Firestore backend and, similarly, is not + * rejected until the remote Firestore backend reports an error saving the given + * data. So if the client cannot reach the backend (for example, due to being + * offline) then the returned `Promise` will not resolve for a potentially-long + * time (for example, until the client has gone back online). That being said, + * the given data _will_ be immediately saved to the local cache and will be + * incorporated into future "get" operations as if it had been successfully + * written to the remote Firestore server, a feature of Firestore called + * "latency compensation". The data will _eventually_ be written to the remote + * Firestore backend once a connection can be established. Therefore, it is + * usually undesirable to `await` the `Promise` returned from this function + * because the indefinite amount of time before which the promise resolves or + * rejects can block application logic unnecessarily. + * * @param reference - A reference to the document to write. * @param data - A map of the fields and values for the document. - * @returns A `Promise` resolved once the data has been successfully written - * to the backend (note that it won't resolve while you're offline). + * @returns A `Promise` that resolves once the data has been successfully + * written to the backend or rejects once the backend reports an error writing + * the data. */ export function setDoc( reference: DocumentReference, @@ -291,11 +307,27 @@ export function setDoc( * the document does not yet exist, it will be created. If you provide `merge` * or `mergeFields`, the provided data can be merged into an existing document. * + * Note that the returned `Promise` does _not_ resolve until the data is + * successfully written to the remote Firestore backend and, similarly, is not + * rejected until the remote Firestore backend reports an error saving the given + * data. So if the client cannot reach the backend (for example, due to being + * offline) then the returned `Promise` will not resolve for a potentially-long + * time (for example, until the client has gone back online). That being said, + * the given data _will_ be immediately saved to the local cache and will be + * incorporated into future "get" operations as if it had been successfully + * written to the remote Firestore server, a feature of Firestore called + * "latency compensation". The data will _eventually_ be written to the remote + * Firestore backend once a connection can be established. Therefore, it is + * usually undesirable to `await` the `Promise` returned from this function + * because the indefinite amount of time before which the promise resolves or + * rejects can block application logic unnecessarily. + * * @param reference - A reference to the document to write. * @param data - A map of the fields and values for the document. * @param options - An object to configure the set behavior. - * @returns A Promise resolved once the data has been successfully written - * to the backend (note that it won't resolve while you're offline). + * @returns A `Promise` that resolves once the data has been successfully + * written to the backend or rejects once the backend reports an error writing + * the data. */ export function setDoc( reference: DocumentReference, @@ -337,12 +369,28 @@ export function setDoc( * `DocumentReference`. The update will fail if applied to a document that does * not exist. * + * Note that the returned `Promise` does _not_ resolve until the data is + * successfully written to the remote Firestore backend and, similarly, is not + * rejected until the remote Firestore backend reports an error saving the given + * data. So if the client cannot reach the backend (for example, due to being + * offline) then the returned `Promise` will not resolve for a potentially-long + * time (for example, until the client has gone back online). That being said, + * the given data _will_ be immediately saved to the local cache and will be + * incorporated into future "get" operations as if it had been successfully + * written to the remote Firestore server, a feature of Firestore called + * "latency compensation". The data will _eventually_ be written to the remote + * Firestore backend once a connection can be established. Therefore, it is + * usually undesirable to `await` the `Promise` returned from this function + * because the indefinite amount of time before which the promise resolves or + * rejects can block application logic unnecessarily. + * * @param reference - A reference to the document to update. * @param data - An object containing the fields and values with which to * update the document. Fields can contain dots to reference nested fields * within the document. - * @returns A `Promise` resolved once the data has been successfully written - * to the backend (note that it won't resolve while you're offline). + * @returns A `Promise` that resolves once the data has been successfully + * written to the backend or rejects once the backend reports an error writing + * the data. */ export function updateDoc( reference: DocumentReference, @@ -356,12 +404,28 @@ export function updateDoc( * Nested fields can be updated by providing dot-separated field path * strings or by providing `FieldPath` objects. * + * Note that the returned `Promise` does _not_ resolve until the data is + * successfully written to the remote Firestore backend and, similarly, is not + * rejected until the remote Firestore backend reports an error saving the given + * data. So if the client cannot reach the backend (for example, due to being + * offline) then the returned `Promise` will not resolve for a potentially-long + * time (for example, until the client has gone back online). That being said, + * the given data _will_ be immediately saved to the local cache and will be + * incorporated into future "get" operations as if it had been successfully + * written to the remote Firestore server, a feature of Firestore called + * "latency compensation". The data will _eventually_ be written to the remote + * Firestore backend once a connection can be established. Therefore, it is + * usually undesirable to `await` the `Promise` returned from this function + * because the indefinite amount of time before which the promise resolves or + * rejects can block application logic unnecessarily. + * * @param reference - A reference to the document to update. * @param field - The first field to update. * @param value - The first value. * @param moreFieldsAndValues - Additional key value pairs. - * @returns A `Promise` resolved once the data has been successfully written - * to the backend (note that it won't resolve while you're offline). + * @returns A `Promise` that resolves once the data has been successfully + * written to the backend or rejects once the backend reports an error writing + * the data. */ export function updateDoc( reference: DocumentReference, @@ -416,9 +480,25 @@ export function updateDoc( /** * Deletes the document referred to by the specified `DocumentReference`. * + * Note that the returned `Promise` does _not_ resolve until the document is + * successfully deleted from the remote Firestore backend and, similarly, is not + * rejected until the remote Firestore backend reports an error deleting the given + * document. So if the client cannot reach the backend (for example, due to being + * offline) then the returned `Promise` will not resolve for a potentially-long + * time (for example, until the client has gone back online). That being said, + * the given data _will_ be immediately deleted from the local cache and will be + * reflected in future "get" operations as if it had been successfully + * deleted from the remote Firestore server, a feature of Firestore called + * "latency compensation". The document will _eventually_ be deleted from the remote + * Firestore backend once a connection can be established. Therefore, it is + * usually undesirable to `await` the `Promise` returned from this function + * because the indefinite amount of time before which the promise resolves or + * rejects can block application logic unnecessarily. + * * @param reference - A reference to the document to delete. - * @returns A Promise resolved once the document has been successfully - * deleted from the backend (note that it won't resolve while you're offline). + * @returns A `Promise` that resolves once the document has been successfully + * deleted from the backend or rejects once the backend reports an error + * deleting the document. */ export function deleteDoc( reference: DocumentReference @@ -432,11 +512,26 @@ export function deleteDoc( * Add a new document to specified `CollectionReference` with the given data, * assigning it a document ID automatically. * + * Note that the returned `Promise` does _not_ resolve until the document is + * successfully created to the remote Firestore backend and, similarly, is not + * rejected until the remote Firestore backend reports an error creating the given + * document. So if the client cannot reach the backend (for example, due to being + * offline) then the returned `Promise` will not resolve for a potentially-long + * time (for example, until the client has gone back online). That being said, + * the given document _will_ be immediately created in the local cache and will be + * incorporated into future "get" operations as if it had been successfully + * created in the remote Firestore server, a feature of Firestore called + * "latency compensation". The document will _eventually_ be created in the remote + * Firestore backend once a connection can be established. Therefore, it is + * usually undesirable to `await` the `Promise` returned from this function + * because the indefinite amount of time before which the promise resolves or + * rejects can block application logic unnecessarily. + * * @param reference - A reference to the collection to add this document to. * @param data - An Object containing the data for the new document. - * @returns A `Promise` resolved with a `DocumentReference` pointing to the - * newly created document after it has been written to the backend (Note that it - * won't resolve while you're offline). + * @returns A `Promise` that resolves once the docoument has been successfully + * created in the backend or rejects once the backend reports an error creating + * the document. */ export function addDoc( reference: CollectionReference, From a3837700877822acd1bad82431a051d64f479508 Mon Sep 17 00:00:00 2001 From: Mark Duckworth <1124037+MarkDuckworth@users.noreply.github.com> Date: Fri, 6 Mar 2026 17:52:53 +0000 Subject: [PATCH 097/174] fix: Workaround rollup terser-plugin's inconsistent property naming when using multiple entry points (#9622) * fix: Workaround rollup terser-plugin's inconsistent property naming when using multiple entrypoints * Create spotty-hornets-thank.md * Update rollup.config.lite.js Removed the `-[hash]` from the intermediate builds on the lite pipelines, both for consistency and to limit the amount of extraneous files created. --- .changeset/spotty-hornets-thank.md | 5 ++ packages/firestore/rollup.config.js | 30 +++++++- packages/firestore/rollup.config.lite.js | 41 ++++++++++- packages/firestore/rollup.shared.js | 87 ++++++++---------------- 4 files changed, 101 insertions(+), 62 deletions(-) create mode 100644 .changeset/spotty-hornets-thank.md diff --git a/.changeset/spotty-hornets-thank.md b/.changeset/spotty-hornets-thank.md new file mode 100644 index 0000000000..cbebe8a01b --- /dev/null +++ b/.changeset/spotty-hornets-thank.md @@ -0,0 +1,5 @@ +--- +"@firebase/firestore": patch +--- + +Fixed X is not a function issues observed in server side rendering APIs. diff --git a/packages/firestore/rollup.config.js b/packages/firestore/rollup.config.js index 646ed038f0..ead3882add 100644 --- a/packages/firestore/rollup.config.js +++ b/packages/firestore/rollup.config.js @@ -57,10 +57,33 @@ const browserPlugins = [ transformers: [util.removeAssertAndPrefixInternalTransformer] }), json({ preferConst: true }), - terser(util.manglePrivatePropertiesOptions) + terser(util.manglePrivatePropertiesOptions), + util.cleanupNameCache(util.manglePrivatePropertiesOptions.nameCache) ]; const allBuilds = [ + // Workaround for https://github.com/rollup/plugins/issues/1970 + // We invoke this intermediate browser build twice. The first + // invocation will not properly mangle property names because of the + // rollup/plugin-terser issue #1970, however it will output a nameCache + // mapping all the mangled names to new names. The second invocation + // will use the nameCache from the first, and consistently mangle + // all property names. + // + // This is the first invocation of the intermediate browser build. + // It must run before any other build using `browserPlugins`. + // TODO Remove this build when https://github.com/rollup/plugins/issues/1970 is fixed. + { + input: ['./src/index.ts', './pipelines/pipelines.ts'], + output: { + dir: 'dist/intermediate', + entryFileNames: '[name].js', + chunkFileNames: 'common.js', + format: 'es' + }, + plugins: [alias(util.generateAliasConfig('browser')), ...browserPlugins], + external: util.resolveBrowserExterns + }, // Intermediate Node ESM build without build target reporting // this is an intermediate build used to generate the actual esm and cjs builds // which add build target reporting @@ -134,6 +157,9 @@ const allBuilds = [ moduleSideEffects: false } }, + // This is the second invocation of the intermediate browser build. + // Keep this build when https://github.com/rollup/plugins/issues/1970 is fixed. + // // Intermediate browser build without build target reporting // this is an intermediate build used to generate the actual esm and cjs builds // which add build target reporting @@ -142,7 +168,7 @@ const allBuilds = [ output: { dir: 'dist/intermediate', entryFileNames: '[name].js', - chunkFileNames: 'common-[hash].js', + chunkFileNames: 'common.js', format: 'es', sourcemap: true }, diff --git a/packages/firestore/rollup.config.lite.js b/packages/firestore/rollup.config.lite.js index 6bf9297e4d..403d494cf9 100644 --- a/packages/firestore/rollup.config.lite.js +++ b/packages/firestore/rollup.config.lite.js @@ -48,10 +48,44 @@ const browserPlugins = [ transformers: [util.removeAssertAndPrefixInternalTransformer] }), json({ preferConst: true }), - terser(util.manglePrivatePropertiesOptions) + terser(util.manglePrivatePropertiesOptions), + util.cleanupNameCache(util.manglePrivatePropertiesOptions.nameCache) ]; const allBuilds = [ + // Workaround for https://github.com/rollup/plugins/issues/1970 + // We invoke this intermediate browser build twice. The first + // invocation will not properly mangle property names because of the + // rollup/plugin-terser issue #1970, however it will output a nameCache + // mapping all of the mangled names to new names. The second invocation + // will use the nameCache from the first, and consistently mangle + // all property names. + // + // This is the first invocation of the intermediate browser build. + // It must run before any other build using `browserPlugins`. + // TODO Remove this build when https://github.com/rollup/plugins/issues/1970 is fixed. + { + input: ['./lite/index.ts', './lite/pipelines/pipelines.ts'], + output: { + dir: 'dist/intermediate/lite/', + entryFileNames: '[name].browser.js', + chunkFileNames: 'common.browser.js', + format: 'es', + sourcemap: true + }, + plugins: [ + alias(util.generateAliasConfig('browser_lite')), + ...browserPlugins, + // setting it to empty string because browser is the default env + replace({ + '__RUNTIME_ENV__': '' + }) + ], + external: util.resolveBrowserExterns, + treeshake: { + moduleSideEffects: false + } + }, // Intermediate Node ESM build without build target reporting // this is an intermediate build used to generate the actual esm and cjs builds // which add build target reporting @@ -129,6 +163,9 @@ const allBuilds = [ moduleSideEffects: false } }, + // This is the second invocation of the intermediate browser build. + // Keep this build when https://github.com/rollup/plugins/issues/1970 is fixed. + // // Intermediate browser build without build target reporting // this is an intermediate build used to generate the actual esm and cjs builds // which add build target reporting @@ -137,7 +174,7 @@ const allBuilds = [ output: { dir: 'dist/intermediate/lite/', entryFileNames: '[name].browser.js', - chunkFileNames: 'common-[hash].browser.js', + chunkFileNames: 'common.browser.js', format: 'es', sourcemap: true }, diff --git a/packages/firestore/rollup.shared.js b/packages/firestore/rollup.shared.js index 99adca9096..b7bcba92b5 100644 --- a/packages/firestore/rollup.shared.js +++ b/packages/firestore/rollup.shared.js @@ -138,12 +138,22 @@ exports.removeAssertAndPrefixInternalTransformer = * Terser options that mangle all properties prefixed with __PRIVATE_. */ const manglePrivatePropertiesOptions = { + // Prevent parallelism in minification by terser + // to prevent race conditions when writing the nameCache + maxWorkers: 1, output: { comments: 'all', beautify: true }, keep_fnames: true, keep_classnames: true, + // use a shared name cache across all terser invocations as part of the + // workaround for https://github.com/rollup/plugins/issues/1970. + // The workaround works by populating this nameCache using a throwaway + // build. Then subsequent builds using plugin-terser will use the generated + // name cache to consistently rename properties across chunks. + // TODO remove this when https://github.com/rollup/plugins/issues/1970 is fixed + nameCache: {}, mangle: { // Temporary hack fix for an issue where mangled code causes some downstream // bundlers (Babel?) to confuse the same variable name in different scopes. @@ -240,61 +250,22 @@ exports.applyPrebuilt = function (name = 'prebuilt.js') { }); }; -exports.es2020Plugins = function (platform, mangled = false) { - if (mangled) { - return [ - alias(generateAliasConfig(platform)), - typescriptPlugin({ - typescript, - cacheDir: tmp.dirSync(), - transformers: [removeAssertAndPrefixInternalTransformer] - }), - json({ preferConst: true }), - terser(manglePrivatePropertiesOptions) - ]; - } else { - return [ - alias(generateAliasConfig(platform)), - typescriptPlugin({ - typescript, - cacheDir: tmp.dirSync(), - transformers: [removeAssertTransformer] - }), - json({ preferConst: true }) - ]; - } -}; - -exports.es2020PluginsCompat = function ( - platform, - pathTransformer, - mangled = false -) { - if (mangled) { - return [ - alias(generateAliasConfig(platform)), - typescriptPlugin({ - typescript, - cacheDir: tmp.dirSync(), - abortOnError: true, - transformers: [ - removeAssertAndPrefixInternalTransformer, - pathTransformer - ] - }), - json({ preferConst: true }), - terser(manglePrivatePropertiesOptions) - ]; - } else { - return [ - alias(generateAliasConfig(platform)), - typescriptPlugin({ - typescript, - cacheDir: tmp.dirSync(), - abortOnError: true, - transformers: [removeAssertTransformer, pathTransformer] - }), - json({ preferConst: true }) - ]; - } -}; +// This is part of the workaround for https://github.com/rollup/plugins/issues/1970 +// The workaround requires that a nameCache is supplied as an argument to +// the @rollup/plugin-terser. Only the 'params' property of the nameCache +// is required. If the 'vars' property of the nameCache is persisted through +// builds, this can cause name collisions if running both cjs and esm builds. +// This plugin, deletes 'vars' from a nameCache object, so that nameCache can +// be cleanly shared between esm and cjs builds. +// Make sure this plugin is run after terser in the plugins. +// Example `plugins: [terser({..., nameCache: myNameCache }), cleanUpNameCache(myNameCache)]` +// TODO Remove this when https://github.com/rollup/plugins/issues/1970 is fixed +function cleanupNameCache(nameCache = {}) { + return { + name: 'cleanup-name-cache-plugin', + generateBundle() { + delete nameCache.vars; + } + }; +} +exports.cleanupNameCache = cleanupNameCache; From d7b182645abb63d9f061e90cf86d53ad3abc89ec Mon Sep 17 00:00:00 2001 From: Mark Duckworth <1124037+MarkDuckworth@users.noreply.github.com> Date: Wed, 11 Mar 2026 16:06:59 +0000 Subject: [PATCH 098/174] Fix syntax in Pipeline examples in TSDoc (#9712) --- ...estore_lite_pipelines.booleanexpression.md | 8 ++-- .../firestore_lite_pipelines.expression.md | 11 +++-- docs-devsite/firestore_lite_pipelines.md | 22 +++++----- .../firestore_lite_pipelines.pipeline.md | 40 +++++++++--------- .../firestore_pipelines.booleanexpression.md | 8 ++-- .../firestore_pipelines.expression.md | 11 +++-- docs-devsite/firestore_pipelines.md | 30 +++++++------- packages/firestore/src/api/pipeline_impl.ts | 8 ++-- .../firestore/src/lite-api/expressions.ts | 41 +++++++++---------- packages/firestore/src/lite-api/pipeline.ts | 40 +++++++++--------- 10 files changed, 108 insertions(+), 111 deletions(-) diff --git a/docs-devsite/firestore_lite_pipelines.booleanexpression.md b/docs-devsite/firestore_lite_pipelines.booleanexpression.md index f970712c06..1b4b918bed 100644 --- a/docs-devsite/firestore_lite_pipelines.booleanexpression.md +++ b/docs-devsite/firestore_lite_pipelines.booleanexpression.md @@ -127,7 +127,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create an expression that protects against a divide by zero error // but always returns a boolean expression. -constant(50).divide('length').gt(1).ifError(constant(false)); +constant(50).divide(field('length')).greaterThan(1).ifError(constant(false)); ``` @@ -162,7 +162,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create an expression that protects against a divide by zero error // but always returns a boolean expression. -constant(50).divide('length').gt(1).ifError(false); +constant(50).divide(field('length')).greaterThan(1).ifError(false); ``` @@ -196,7 +196,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create an expression that protects against a divide by zero error. -constant(50).divide('length').gt(1).ifError(constant(0)); +constant(50).divide(field('length')).greaterThan(1).ifError(constant(0)); ``` @@ -230,7 +230,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create an expression that protects against a divide by zero error. -constant(50).divide('length').gt(1).ifError(0); +constant(50).divide(field('length')).greaterThan(1).ifError(0); ``` diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index d838997115..4ad64ca4c8 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -1389,7 +1389,7 @@ A new `Ordering` for ascending sorting. ```typescript // Sort documents by the 'name' field in ascending order -pipeline().collection("users") +firestore.pipeline().collection("users") .sort(field("name").ascending()); ``` @@ -2043,7 +2043,7 @@ A new `Expression` representing the 'IN' comparison. ```typescript // Check if the 'category' field is either "Electronics" or value of field 'primaryType' -field("category").equalAny("Electronics", field("primaryType")); +field("category").equalAny(["Electronics", field("primaryType")]); ``` @@ -2557,7 +2557,6 @@ A new [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpr ```typescript // Check if the field `value` is absent. field("value").isAbsent(); -@example ``` @@ -3038,7 +3037,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Returns the larger value between the 'timestamp' field and the current timestamp. -field("timestamp").logicalMaximum(Function.currentTimestamp()); +field("timestamp").logicalMaximum(currentTimestamp()); ``` @@ -3073,7 +3072,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Returns the smaller value between the 'timestamp' field and the current timestamp. -field("timestamp").logicalMinimum(Function.currentTimestamp()); +field("timestamp").logicalMinimum(currentTimestamp()); ``` @@ -4239,7 +4238,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Split the 'scores' field on delimiter ',' or ':' depending on the stored format -field('scores').split(conditional(field('format').equal('csv'), constant(','), constant(':')) +field('scores').split(conditional(field('format').equal('csv'), constant(','), constant(':'))) ``` diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 39be81e193..106b9b5aa6 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -2024,7 +2024,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create an array value from the input array and reference the 'baz' field value from the input document. -array(['bar', Field.of('baz')]).as('foo'); +array(['bar', field('baz')]).as('foo'); ``` @@ -2058,7 +2058,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create a map from the input object and reference the 'baz' field value from the input document. -map({foo: 'bar', baz: Field.of('baz')}).as('data'); +map({foo: 'bar', baz: field('baz')}).as('data'); ``` @@ -3634,7 +3634,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Split the 'scores' field on delimiter ',' or ':' depending on the stored format -split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':')) +split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':'))) ``` @@ -4086,7 +4086,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Reverse the value of the 'myString' field. -strReverse("myString"); +stringReverse("myString"); ``` @@ -5250,7 +5250,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Get the character length of the 'name' field in UTF-8. -strLength("name"); +charLength("name"); ``` @@ -7527,7 +7527,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Split the 'scores' field on delimiter ',' or ':' depending on the stored format -split('scores', conditional(field('format').equal('csv'), constant(','), constant(':')) +split('scores', conditional(field('format').equal('csv'), constant(','), constant(':'))) ``` @@ -9330,7 +9330,7 @@ A new `Expression` representing the greater than comparison. ```typescript // Check if the 'age' field is greater than 18 -greaterThan(field("age"), Constant(9).add(9)); +greaterThan(field("age"), constant(9).add(9)); ``` @@ -10193,7 +10193,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Get the character length of the 'name' field in UTF-8. -strLength(field("name")); +charLength(field("name")); ``` @@ -10829,7 +10829,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Reverse the value of the 'myString' field. -strReverse(field("myString")); +stringReverse(field("myString")); ``` @@ -10897,7 +10897,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Convert the 'title' field to uppercase -toUppercase(field("title")); +toUpper(field("title")); ``` @@ -11195,7 +11195,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create an expression that protects against a divide by zero error // but always returns a boolean expression. -ifError(constant(50).divide('length').gt(1), constant(false)); +ifError(constant(50).divide(field('length')).greaterThan(1), constant(false)); ``` diff --git a/docs-devsite/firestore_lite_pipelines.pipeline.md b/docs-devsite/firestore_lite_pipelines.pipeline.md index e68ad20767..0936e483bc 100644 --- a/docs-devsite/firestore_lite_pipelines.pipeline.md +++ b/docs-devsite/firestore_lite_pipelines.pipeline.md @@ -120,7 +120,7 @@ A new Pipeline object with this stage appended to the stage list. firestore.pipeline().collection("books") .addFields( field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' - add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' + add(field("quantity"), 5).as("totalCost") // Calculate 'totalCost' ); ``` @@ -165,7 +165,7 @@ A new Pipeline object with this stage appended to the stage list. firestore.pipeline().collection("books") .addFields( field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' - add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' + add(field("quantity"), 5).as("totalCost") // Calculate 'totalCost' ); ``` @@ -207,7 +207,7 @@ A new Pipeline object with this stage appended to the stage list. // Calculate the average rating and the total number of books firestore.pipeline().collection("books") .aggregate( - field("rating").avg().as("averageRating"), + field("rating").average().as("averageRating"), countAll().as("totalBooks") ); @@ -251,7 +251,7 @@ A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with t // Calculate the average rating for each genre. firestore.pipeline().collection("books") .aggregate({ - accumulators: [avg(field("rating")).as("avg_rating")] + accumulators: [average(field("rating")).as("avg_rating")], groups: ["genre"] }); @@ -297,7 +297,7 @@ A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with t ```typescript // Get a list of unique author names in uppercase and genre combinations. firestore.pipeline().collection("books") - .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") + .distinct(toUpper(field("author")).as("authorName"), field("genre"), "publishedAt") .select("authorName"); ``` @@ -341,7 +341,7 @@ A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with t ```typescript // Get a list of unique author names in uppercase and genre combinations. firestore.pipeline().collection("books") - .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") + .distinct(toUpper(field("author")).as("authorName"), field("genre"), "publishedAt") .select("authorName"); ``` @@ -594,7 +594,7 @@ A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with t ```typescript // Assume we don't have a built-in 'where' stage firestore.pipeline().collection('books') - .rawStage('where', [field('published').lt(1900)]) // Custom 'where' stage + .rawStage('where', [field('published').lessThan(1900)]) // Custom 'where' stage .select('title', 'author'); ``` @@ -971,7 +971,7 @@ db.pipeline().collection("books") .select( "firstName", field("lastName"), - field("address").toUppercase().as("upperAddress"), + field("address").toUpper().as("upperAddress"), ); ``` @@ -1017,7 +1017,7 @@ db.pipeline().collection("books") .select( "firstName", field("lastName"), - field("address").toUppercase().as("upperAddress"), + field("address").toUpper().as("upperAddress"), ); ``` @@ -1060,8 +1060,8 @@ A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with t // with the same rating firestore.pipeline().collection("books") .sort( - Ordering.of(field("rating")).descending(), - Ordering.of(field("title")) // Ascending order is the default + field("rating").descending(), + field("title").ascending() ); ``` @@ -1103,8 +1103,8 @@ A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with t // with the same rating firestore.pipeline().collection("books") .sort( - Ordering.of(field("rating")).descending(), - Ordering.of(field("title")) // Ascending order is the default + field("rating").descending(), + field("title").ascending() ); ``` @@ -1328,8 +1328,8 @@ A new Pipeline object with this stage appended to the stage list. firestore.pipeline().collection("books") .where( and( - gt(field("rating"), 4.0), // Filter for ratings greater than 4.0 - field("genre").eq("Science Fiction") // Equivalent to gt("genre", "Science Fiction") + greaterThan(field("rating"), 4.0), // Filter for ratings greater than 4.0 + field("genre").equal("Science Fiction") // Equivalent to equal("genre", "Science Fiction") ) ); @@ -1373,8 +1373,8 @@ A new Pipeline object with this stage appended to the stage list. firestore.pipeline().collection("books") .where( and( - gt(field("rating"), 4.0), // Filter for ratings greater than 4.0 - field("genre").eq("Science Fiction") // Equivalent to gt("genre", "Science Fiction") + greaterThan(field("rating"), 4.0), // Filter for ratings greater than 4.0 + field("genre").equal("Science Fiction") // Equivalent to equal("genre", "Science Fiction") ) ); @@ -1394,13 +1394,13 @@ const results1 = await execute(db.pipeline() // Example 2: Filter documents where 'genre' is "Science Fiction" and 'published' is after 1950 const results2 = await execute(db.pipeline() .collection("books") - .where(and(field("genre").eq("Science Fiction"), field("published").gt(1950)))); + .where(and(field("genre").equal("Science Fiction"), field("published").greaterThan(1950)))); // Example 3: Calculate the average rating of books published after 1980 const results3 = await execute(db.pipeline() .collection("books") - .where(field("published").gt(1980)) - .aggregate(avg(field("rating")).as("averageRating"))); + .where(field("published").greaterThan(1980)) + .aggregate(average(field("rating")).as("averageRating"))); ``` diff --git a/docs-devsite/firestore_pipelines.booleanexpression.md b/docs-devsite/firestore_pipelines.booleanexpression.md index 4717d34e96..a5d0f86f12 100644 --- a/docs-devsite/firestore_pipelines.booleanexpression.md +++ b/docs-devsite/firestore_pipelines.booleanexpression.md @@ -127,7 +127,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create an expression that protects against a divide by zero error // but always returns a boolean expression. -constant(50).divide('length').gt(1).ifError(constant(false)); +constant(50).divide(field('length')).greaterThan(1).ifError(constant(false)); ``` @@ -162,7 +162,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create an expression that protects against a divide by zero error // but always returns a boolean expression. -constant(50).divide('length').gt(1).ifError(false); +constant(50).divide(field('length')).greaterThan(1).ifError(false); ``` @@ -196,7 +196,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create an expression that protects against a divide by zero error. -constant(50).divide('length').gt(1).ifError(constant(0)); +constant(50).divide(field('length')).greaterThan(1).ifError(constant(0)); ``` @@ -230,7 +230,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create an expression that protects against a divide by zero error. -constant(50).divide('length').gt(1).ifError(0); +constant(50).divide(field('length')).greaterThan(1).ifError(0); ``` diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 7e7c510b2a..f0f10abc82 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -1389,7 +1389,7 @@ A new `Ordering` for ascending sorting. ```typescript // Sort documents by the 'name' field in ascending order -pipeline().collection("users") +firestore.pipeline().collection("users") .sort(field("name").ascending()); ``` @@ -2043,7 +2043,7 @@ A new `Expression` representing the 'IN' comparison. ```typescript // Check if the 'category' field is either "Electronics" or value of field 'primaryType' -field("category").equalAny("Electronics", field("primaryType")); +field("category").equalAny(["Electronics", field("primaryType")]); ``` @@ -2557,7 +2557,6 @@ A new [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpr ```typescript // Check if the field `value` is absent. field("value").isAbsent(); -@example ``` @@ -3038,7 +3037,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Returns the larger value between the 'timestamp' field and the current timestamp. -field("timestamp").logicalMaximum(Function.currentTimestamp()); +field("timestamp").logicalMaximum(currentTimestamp()); ``` @@ -3073,7 +3072,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Returns the smaller value between the 'timestamp' field and the current timestamp. -field("timestamp").logicalMinimum(Function.currentTimestamp()); +field("timestamp").logicalMinimum(currentTimestamp()); ``` @@ -4239,7 +4238,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Split the 'scores' field on delimiter ',' or ':' depending on the stored format -field('scores').split(conditional(field('format').equal('csv'), constant(','), constant(':')) +field('scores').split(conditional(field('format').equal('csv'), constant(','), constant(':'))) ``` diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 74a94359da..e94b8d4b1c 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -2030,7 +2030,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create an array value from the input array and reference the 'baz' field value from the input document. -array(['bar', Field.of('baz')]).as('foo'); +array(['bar', field('baz')]).as('foo'); ``` @@ -2064,7 +2064,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create a map from the input object and reference the 'baz' field value from the input document. -map({foo: 'bar', baz: Field.of('baz')}).as('data'); +map({foo: 'bar', baz: field('baz')}).as('data'); ``` @@ -3640,7 +3640,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Split the 'scores' field on delimiter ',' or ':' depending on the stored format -split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':')) +split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':'))) ``` @@ -4092,7 +4092,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Reverse the value of the 'myString' field. -strReverse("myString"); +stringReverse("myString"); ``` @@ -5256,7 +5256,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Get the character length of the 'name' field in UTF-8. -strLength("name"); +charLength("name"); ``` @@ -7533,7 +7533,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Split the 'scores' field on delimiter ',' or ':' depending on the stored format -split('scores', conditional(field('format').equal('csv'), constant(','), constant(':')) +split('scores', conditional(field('format').equal('csv'), constant(','), constant(':'))) ``` @@ -9336,7 +9336,7 @@ A new `Expression` representing the greater than comparison. ```typescript // Check if the 'age' field is greater than 18 -greaterThan(field("age"), Constant(9).add(9)); +greaterThan(field("age"), constant(9).add(9)); ``` @@ -10157,10 +10157,10 @@ A Promise representing the asynchronous pipeline execution. ```typescript const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") - .where(gt(field("rating"), 4.5)) + .where(greaterThan(field("rating"), 4.5)) .select("title", "author", "rating")); -const results: PipelineResults = snapshot.results; +const results: PipelineResult[] = snapshot.results; ``` @@ -10229,10 +10229,10 @@ A Promise representing the asynchronous pipeline execution. ```typescript const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") - .where(gt(field("rating"), 4.5)) + .where(greaterThan(field("rating"), 4.5)) .select("title", "author", "rating")); -const results: PipelineResults = snapshot.results; +const results: PipelineResult[] = snapshot.results; ``` @@ -10268,7 +10268,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Get the character length of the 'name' field in UTF-8. -strLength(field("name")); +charLength(field("name")); ``` @@ -10904,7 +10904,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Reverse the value of the 'myString' field. -strReverse(field("myString")); +stringReverse(field("myString")); ``` @@ -10972,7 +10972,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Convert the 'title' field to uppercase -toUppercase(field("title")); +toUpper(field("title")); ``` @@ -11270,7 +11270,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ```typescript // Create an expression that protects against a divide by zero error // but always returns a boolean expression. -ifError(constant(50).divide('length').gt(1), constant(false)); +ifError(constant(50).divide(field('length')).greaterThan(1), constant(false)); ``` diff --git a/packages/firestore/src/api/pipeline_impl.ts b/packages/firestore/src/api/pipeline_impl.ts index ba4544f407..14ee378506 100644 --- a/packages/firestore/src/api/pipeline_impl.ts +++ b/packages/firestore/src/api/pipeline_impl.ts @@ -77,10 +77,10 @@ declare module './database' { * @example * ```typescript * const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") - * .where(gt(field("rating"), 4.5)) + * .where(greaterThan(field("rating"), 4.5)) * .select("title", "author", "rating")); * - * const results: PipelineResults = snapshot.results; + * const results: PipelineResult[] = snapshot.results; * ``` * * @param pipeline - The pipeline to execute. @@ -112,10 +112,10 @@ export function execute(pipeline: LitePipeline): Promise; * @example * ```typescript * const snapshot: PipelineSnapshot = await execute(firestore.pipeline().collection("books") - * .where(gt(field("rating"), 4.5)) + * .where(greaterThan(field("rating"), 4.5)) * .select("title", "author", "rating")); * - * const results: PipelineResults = snapshot.results; + * const results: PipelineResult[] = snapshot.results; * ``` * * @param options - Specifies the pipeline to execute and other options for execute. diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index f3cb3da30c..c72229f6c7 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -772,7 +772,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @example * ```typescript * // Check if the 'category' field is either "Electronics" or value of field 'primaryType' - * field("category").equalAny("Electronics", field("primaryType")); + * field("category").equalAny(["Electronics", field("primaryType")]); * ``` * * @param values - The values or expressions to check against. @@ -2218,7 +2218,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @example * ```typescript * // Returns the larger value between the 'timestamp' field and the current timestamp. - * field("timestamp").logicalMaximum(Function.currentTimestamp()); + * field("timestamp").logicalMaximum(currentTimestamp()); * ``` * * @param second - The second expression or literal to compare with. @@ -2244,7 +2244,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @example * ```typescript * // Returns the smaller value between the 'timestamp' field and the current timestamp. - * field("timestamp").logicalMinimum(Function.currentTimestamp()); + * field("timestamp").logicalMinimum(currentTimestamp()); * ``` * * @param second - The second expression or literal to compare with. @@ -2796,7 +2796,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * ```typescript * // Check if the field `value` is absent. * field("value").isAbsent(); - * @example * ``` * * @returns A new {@link @firebase/firestore/pipelines#BooleanExpression} representing the 'isAbsent' check. @@ -3237,7 +3236,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @example * ```typescript * // Split the 'scores' field on delimiter ',' or ':' depending on the stored format - * field('scores').split(conditional(field('format').equal('csv'), constant(','), constant(':')) + * field('scores').split(conditional(field('format').equal('csv'), constant(','), constant(':'))) * ``` * * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the split function. @@ -3311,7 +3310,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @example * ```typescript * // Sort documents by the 'name' field in ascending order - * pipeline().collection("users") + * firestore.pipeline().collection("users") * .sort(field("name").ascending()); * ``` * @@ -4029,7 +4028,7 @@ export abstract class BooleanExpression extends Expression { * ```typescript * // Create an expression that protects against a divide by zero error * // but always returns a boolean expression. - * constant(50).divide('length').gt(1).ifError(constant(false)); + * constant(50).divide(field('length')).greaterThan(1).ifError(constant(false)); * ``` * * @param catchValue - The value that will be returned if this expression @@ -4048,7 +4047,7 @@ export abstract class BooleanExpression extends Expression { * ```typescript * // Create an expression that protects against a divide by zero error * // but always returns a boolean expression. - * constant(50).divide('length').gt(1).ifError(false); + * constant(50).divide(field('length')).greaterThan(1).ifError(false); * ``` * * @param catchValue - The value that will be returned if this expression @@ -4066,7 +4065,7 @@ export abstract class BooleanExpression extends Expression { * @example * ```typescript * // Create an expression that protects against a divide by zero error. - * constant(50).divide('length').gt(1).ifError(constant(0)); + * constant(50).divide(field('length')).greaterThan(1).ifError(constant(0)); * ``` * * @param catchValue - The value that will be returned if this expression @@ -4084,7 +4083,7 @@ export abstract class BooleanExpression extends Expression { * @example * ```typescript * // Create an expression that protects against a divide by zero error. - * constant(50).divide('length').gt(1).ifError(0); + * constant(50).divide(field('length')).greaterThan(1).ifError(0); * ``` * * @param catchValue - The value that will be returned if this expression @@ -4283,7 +4282,7 @@ export function isError(value: Expression): BooleanExpression { * ```typescript * // Create an expression that protects against a divide by zero error * // but always returns a boolean expression. - * ifError(constant(50).divide('length').gt(1), constant(false)); + * ifError(constant(50).divide(field('length')).greaterThan(1), constant(false)); * ``` * * @param tryExpr - The try expression. @@ -4991,7 +4990,7 @@ export function mod( * @example * ```typescript * // Create a map from the input object and reference the 'baz' field value from the input document. - * map({foo: 'bar', baz: Field.of('baz')}).as('data'); + * map({foo: 'bar', baz: field('baz')}).as('data'); * ``` * * @param elements - The input map to evaluate in the expression. @@ -5045,7 +5044,7 @@ export function _mapValue(plainObject: Record): MapValue { * @example * ```typescript * // Create an array value from the input array and reference the 'baz' field value from the input document. - * array(['bar', Field.of('baz')]).as('foo'); + * array(['bar', field('baz')]).as('foo'); * ``` * * @param elements - The input array to evaluate in the expression. @@ -5414,7 +5413,7 @@ export function lessThanOrEqual( * @example * ```typescript * // Check if the 'age' field is greater than 18 - * greaterThan(field("age"), Constant(9).add(9)); + * greaterThan(field("age"), constant(9).add(9)); * ``` * * @param left - The first expression to compare. @@ -6572,7 +6571,7 @@ export function countDistinct(expr: Expression | string): AggregateFunction { * @example * ```typescript * // Get the character length of the 'name' field in UTF-8. - * strLength("name"); + * charLength("name"); * ``` * * @param fieldName - The name of the field containing the string. @@ -6588,7 +6587,7 @@ export function charLength(fieldName: string): FunctionExpression; * @example * ```typescript * // Get the character length of the 'name' field in UTF-8. - * strLength(field("name")); + * charLength(field("name")); * ``` * * @param stringExpression - The expression representing the string to calculate the length of. @@ -8028,7 +8027,7 @@ export function toUpper(fieldName: string): FunctionExpression; * @example * ```typescript * // Convert the 'title' field to uppercase - * toUppercase(field("title")); + * toUpper(field("title")); * ``` * * @param stringExpression - The expression representing the string to convert to uppercase. @@ -10340,7 +10339,7 @@ export function sqrt(expr: Expression | string): FunctionExpression { * @example * ```typescript * // Reverse the value of the 'myString' field. - * strReverse(field("myString")); + * stringReverse(field("myString")); * ``` * * @param stringExpression - An expression evaluating to a string value, which will be reversed. @@ -10355,7 +10354,7 @@ export function stringReverse(stringExpression: Expression): FunctionExpression; * @example * ```typescript * // Reverse the value of the 'myString' field. - * strReverse("myString"); + * stringReverse("myString"); * ``` * * @param field - The name of the field representing the string to reverse. @@ -10696,7 +10695,7 @@ export function split(fieldName: string, delimiter: string): FunctionExpression; * @example * ```typescript * // Split the 'scores' field on delimiter ',' or ':' depending on the stored format - * split('scores', conditional(field('format').equal('csv'), constant(','), constant(':')) + * split('scores', conditional(field('format').equal('csv'), constant(','), constant(':'))) * ``` * * @param fieldName - Split the value in this field. @@ -10736,7 +10735,7 @@ export function split( * @example * ```typescript * // Split the 'scores' field on delimiter ',' or ':' depending on the stored format - * split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':')) + * split(field('scores'), conditional(field('format').equal('csv'), constant(','), constant(':'))) * ``` * * @param expression - Split the result of this expression. diff --git a/packages/firestore/src/lite-api/pipeline.ts b/packages/firestore/src/lite-api/pipeline.ts index 2dda90eaa4..23c37ba5d8 100644 --- a/packages/firestore/src/lite-api/pipeline.ts +++ b/packages/firestore/src/lite-api/pipeline.ts @@ -119,13 +119,13 @@ import { AbstractUserDataWriter } from './user_data_writer'; * // Example 2: Filter documents where 'genre' is "Science Fiction" and 'published' is after 1950 * const results2 = await execute(db.pipeline() * .collection("books") - * .where(and(field("genre").eq("Science Fiction"), field("published").gt(1950)))); + * .where(and(field("genre").equal("Science Fiction"), field("published").greaterThan(1950)))); * * // Example 3: Calculate the average rating of books published after 1980 * const results3 = await execute(db.pipeline() * .collection("books") - * .where(field("published").gt(1980)) - * .aggregate(avg(field("rating")).as("averageRating"))); + * .where(field("published").greaterThan(1980)) + * .aggregate(average(field("rating")).as("averageRating"))); * ``` */ export class Pipeline implements ProtoSerializable { @@ -181,7 +181,7 @@ export class Pipeline implements ProtoSerializable { * firestore.pipeline().collection("books") * .addFields( * field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' - * add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' + * add(field("quantity"), 5).as("totalCost") // Calculate 'totalCost' * ); * ``` * @@ -211,7 +211,7 @@ export class Pipeline implements ProtoSerializable { * firestore.pipeline().collection("books") * .addFields( * field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' - * add(5, field("quantity")).as("totalCost") // Calculate 'totalCost' + * add(field("quantity"), 5).as("totalCost") // Calculate 'totalCost' * ); * ``` * @@ -352,7 +352,7 @@ export class Pipeline implements ProtoSerializable { * .select( * "firstName", * field("lastName"), - * field("address").toUppercase().as("upperAddress"), + * field("address").toUpper().as("upperAddress"), * ); * ``` * @@ -391,7 +391,7 @@ export class Pipeline implements ProtoSerializable { * .select( * "firstName", * field("lastName"), - * field("address").toUppercase().as("upperAddress"), + * field("address").toUpper().as("upperAddress"), * ); * ``` * @@ -457,8 +457,8 @@ export class Pipeline implements ProtoSerializable { * firestore.pipeline().collection("books") * .where( * and( - * gt(field("rating"), 4.0), // Filter for ratings greater than 4.0 - * field("genre").eq("Science Fiction") // Equivalent to gt("genre", "Science Fiction") + * greaterThan(field("rating"), 4.0), // Filter for ratings greater than 4.0 + * field("genre").equal("Science Fiction") // Equivalent to equal("genre", "Science Fiction") * ) * ); * ``` @@ -491,8 +491,8 @@ export class Pipeline implements ProtoSerializable { * firestore.pipeline().collection("books") * .where( * and( - * gt(field("rating"), 4.0), // Filter for ratings greater than 4.0 - * field("genre").eq("Science Fiction") // Equivalent to gt("genre", "Science Fiction") + * greaterThan(field("rating"), 4.0), // Filter for ratings greater than 4.0 + * field("genre").equal("Science Fiction") // Equivalent to equal("genre", "Science Fiction") * ) * ); * ``` @@ -694,7 +694,7 @@ export class Pipeline implements ProtoSerializable { * ```typescript * // Get a list of unique author names in uppercase and genre combinations. * firestore.pipeline().collection("books") - * .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") + * .distinct(toUpper(field("author")).as("authorName"), field("genre"), "publishedAt") * .select("authorName"); * ``` * @@ -728,7 +728,7 @@ export class Pipeline implements ProtoSerializable { * ```typescript * // Get a list of unique author names in uppercase and genre combinations. * firestore.pipeline().collection("books") - * .distinct(toUppercase(field("author")).as("authorName"), field("genre"), "publishedAt") + * .distinct(toUpper(field("author")).as("authorName"), field("genre"), "publishedAt") * .select("authorName"); * ``` * @@ -783,7 +783,7 @@ export class Pipeline implements ProtoSerializable { * // Calculate the average rating and the total number of books * firestore.pipeline().collection("books") * .aggregate( - * field("rating").avg().as("averageRating"), + * field("rating").average().as("averageRating"), * countAll().as("totalBooks") * ); * ``` @@ -823,7 +823,7 @@ export class Pipeline implements ProtoSerializable { * // Calculate the average rating for each genre. * firestore.pipeline().collection("books") * .aggregate({ - * accumulators: [avg(field("rating")).as("avg_rating")] + * accumulators: [average(field("rating")).as("avg_rating")], * groups: ["genre"] * }); * ``` @@ -949,8 +949,8 @@ export class Pipeline implements ProtoSerializable { * // with the same rating * firestore.pipeline().collection("books") * .sort( - * Ordering.of(field("rating")).descending(), - * Ordering.of(field("title")) // Ascending order is the default + * field("rating").descending(), + * field("title").ascending() * ); * ``` * @@ -977,8 +977,8 @@ export class Pipeline implements ProtoSerializable { * // with the same rating * firestore.pipeline().collection("books") * .sort( - * Ordering.of(field("rating")).descending(), - * Ordering.of(field("title")) // Ascending order is the default + * field("rating").descending(), + * field("title").ascending() * ); * ``` * @@ -1419,7 +1419,7 @@ export class Pipeline implements ProtoSerializable { * ```typescript * // Assume we don't have a built-in 'where' stage * firestore.pipeline().collection('books') - * .rawStage('where', [field('published').lt(1900)]) // Custom 'where' stage + * .rawStage('where', [field('published').lessThan(1900)]) // Custom 'where' stage * .select('title', 'author'); * ``` * From c44bb9a62b3c3e324677f14b55e6ca8578d4f411 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Wed, 11 Mar 2026 15:52:51 -0400 Subject: [PATCH 099/174] test(firestore): add vscode debug config for enterprise lite (#9621) --- .vscode/launch.json | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 97e3c8c0e3..5b60868f75 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -38,7 +38,8 @@ "--timeout", "5000", "integration/**/*.test.ts", - "--grep", "${input:grepString}", + "--grep", + "${input:grepString}" ], "env": { "TS_NODE_COMPILER_OPTIONS": "{\"module\":\"commonjs\"}" @@ -169,6 +170,29 @@ }, "sourceMaps": true }, + { + "name": "Firestore Enterprise Lite Tests", + "type": "node", + "request": "launch", + "runtimeArgs": ["-r", "ts-node/register"], + "cwd": "${workspaceRoot}/packages/firestore", + "program": "${workspaceRoot}/packages/firestore/scripts/run-tests.ts", + "args": [ + "--platform", + "node_lite", + "--main=lite/index.ts", + "test/lite/**/*.test.ts", + "--grep", + "${input:grepString}" + ], + "env": { + "TS_NODE_COMPILER_OPTIONS": "{\"module\":\"commonjs\"}", + "FIRESTORE_TARGET_BACKEND": "nightly", + "FIRESTORE_TARGET_DB_ID": "enterprise", + "RUN_ENTERPRISE_TESTS": "true" + }, + "sourceMaps": true + }, { "type": "node", "request": "launch", From 54ff05ef922016fee2e9e6f4b8aea30120170da7 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Mon, 16 Mar 2026 11:41:48 -0400 Subject: [PATCH 100/174] fix(firestore): read and write user data on pipeline execute (#9715) --- .changeset/eleven-carrots-relate.md | 5 + .../firestore-lite-pipelines.api.md | 23 ++- common/api-review/firestore-pipelines.api.md | 18 +- packages/firestore/src/api/pipeline.ts | 13 +- packages/firestore/src/api/pipeline_impl.ts | 30 ++-- .../firestore/src/lite-api/pipeline-source.ts | 35 ---- packages/firestore/src/lite-api/pipeline.ts | 161 ++---------------- .../firestore/src/lite-api/pipeline_impl.ts | 33 ++-- packages/firestore/test/lite/pipeline.test.ts | 64 ++++--- 9 files changed, 122 insertions(+), 260 deletions(-) create mode 100644 .changeset/eleven-carrots-relate.md diff --git a/.changeset/eleven-carrots-relate.md b/.changeset/eleven-carrots-relate.md new file mode 100644 index 0000000000..ea39b77b5b --- /dev/null +++ b/.changeset/eleven-carrots-relate.md @@ -0,0 +1,5 @@ +--- +'@firebase/firestore': patch +--- + +**Beta API Breaking change**: Defer pipeline user data validation from initialization to `execute()`. This breaking change is allowed in a non-major release since the Firestore Pipelines API is currently in Public Preview. diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index 1bf77934ab..94d20c4a45 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -1156,11 +1156,6 @@ export class Ordering { // @beta export class Pipeline { - /* Excluded from this release type: _db */ - /* Excluded from this release type: userDataReader */ - /* Excluded from this release type: _userDataWriter */ - /* Excluded from this release type: stages */ - /* Excluded from this release type: __constructor */ addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; addFields(options: AddFieldsStageOptions): Pipeline; aggregate(accumulator: AliasedAggregate, ...additionalAccumulators: AliasedAggregate[]): Pipeline; @@ -1217,15 +1212,31 @@ export class PipelineSnapshot { // @beta export class PipelineSource { collection(collection: string | Query): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ collection(options: CollectionStageOptions): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ collectionGroup(collectionId: string): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ collectionGroup(options: CollectionGroupStageOptions): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ createFrom(query: Query): Pipeline; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ database(): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ database(options: DatabaseStageOptions): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ documents(docs: Array): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ documents(options: DocumentsStageOptions): PipelineType; - } +} // @beta export function pow(base: Expression, exponent: Expression): FunctionExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 1c5044113d..c7127039da 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -1254,15 +1254,31 @@ export class PipelineSnapshot { // @beta export class PipelineSource { collection(collection: string | Query): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ collection(options: CollectionStageOptions): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ collectionGroup(collectionId: string): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ collectionGroup(options: CollectionGroupStageOptions): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ createFrom(query: Query): Pipeline; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ database(): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ database(options: DatabaseStageOptions): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ documents(docs: Array): PipelineType; + /* Excluded from this release type: _createPipeline */ + /* Excluded from this release type: __constructor */ documents(options: DocumentsStageOptions): PipelineType; - } +} // @beta export function pow(base: Expression, exponent: Expression): FunctionExpression; diff --git a/packages/firestore/src/api/pipeline.ts b/packages/firestore/src/api/pipeline.ts index 311c3a59c4..49f0c43c14 100644 --- a/packages/firestore/src/api/pipeline.ts +++ b/packages/firestore/src/api/pipeline.ts @@ -17,8 +17,6 @@ import { Pipeline as LitePipeline } from '../lite-api/pipeline'; import { Stage } from '../lite-api/stage'; -import { UserDataReader } from '../lite-api/user_data_reader'; -import { AbstractUserDataWriter } from '../lite-api/user_data_writer'; import { Firestore } from './database'; @@ -30,18 +28,11 @@ export class Pipeline extends LitePipeline { * @internal * @private * @param db - * @param userDataReader * @param userDataWriter * @param stages - * @param converter * @protected */ - protected newPipeline( - db: Firestore, - userDataReader: UserDataReader, - userDataWriter: AbstractUserDataWriter, - stages: Stage[] - ): Pipeline { - return new Pipeline(db, userDataReader, userDataWriter, stages); + protected newPipeline(db: Firestore, stages: Stage[]): Pipeline { + return new Pipeline(db, stages); } } diff --git a/packages/firestore/src/api/pipeline_impl.ts b/packages/firestore/src/api/pipeline_impl.ts index 14ee378506..c92bd66057 100644 --- a/packages/firestore/src/api/pipeline_impl.ts +++ b/packages/firestore/src/api/pipeline_impl.ts @@ -28,7 +28,6 @@ import { PipelineExecuteOptions } from '../lite-api/pipeline_options'; import { Stage } from '../lite-api/stage'; import { newUserDataReader, - UserDataReader, UserDataSource } from '../lite-api/user_data_reader'; import { cast } from '../util/input_validation'; @@ -140,11 +139,14 @@ export function execute( const firestore = cast(pipeline._db, Firestore); const client = ensureFirestoreConfigured(firestore); - const udr = new UserDataReader( - firestore._databaseId, - /* ignoreUndefinedProperties */ true + const userDataReader = newUserDataReader(firestore); + const context = userDataReader.createContext( + UserDataSource.Argument, + 'execute' ); - const context = udr.createContext(UserDataSource.Argument, 'execute'); + + pipeline._readUserData(context); + const userDataWriter = new ExpUserDataWriter(firestore); const structuredPipelineOptions = new StructuredPipelineOptions( rest, @@ -172,7 +174,7 @@ export function execute( .map( element => new PipelineResult( - pipeline._userDataWriter, + userDataWriter, element.fields!, element.key?.path ? new DocumentReference(firestore, null, element.key) @@ -198,17 +200,7 @@ export function execute( */ // Augment the Firestore class with the pipeline() factory method Firestore.prototype.pipeline = function (): PipelineSource { - const userDataReader = newUserDataReader(this); - return new PipelineSource( - this._databaseId, - userDataReader, - (stages: Stage[]) => { - return new Pipeline( - this, - userDataReader, - new ExpUserDataWriter(this), - stages - ); - } - ); + return new PipelineSource(this._databaseId, (stages: Stage[]) => { + return new Pipeline(this, stages); + }); }; diff --git a/packages/firestore/src/lite-api/pipeline-source.ts b/packages/firestore/src/lite-api/pipeline-source.ts index 87f5a6a882..ee11b9661c 100644 --- a/packages/firestore/src/lite-api/pipeline-source.ts +++ b/packages/firestore/src/lite-api/pipeline-source.ts @@ -40,7 +40,6 @@ import { DatabaseStageOptions, DocumentsStageOptions } from './stage_options'; -import { UserDataReader, UserDataSource } from './user_data_reader'; /** * @beta @@ -55,12 +54,10 @@ export class PipelineSource { * @internal * @private * @param databaseId - * @param userDataReader * @param _createPipeline */ constructor( private databaseId: DatabaseId, - private userDataReader: UserDataReader, /** * @internal * @private @@ -108,14 +105,6 @@ export class PipelineSource { // Create stage object const stage = new CollectionSource(normalizedCollection, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'collection' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._createPipeline([stage]); } @@ -148,14 +137,6 @@ export class PipelineSource { // Create stage object const stage = new CollectionGroupSource(collectionId, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'collectionGroup' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._createPipeline([stage]); } @@ -178,14 +159,6 @@ export class PipelineSource { // Create stage object const stage = new DatabaseSource(options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'database' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._createPipeline([stage]); } @@ -236,14 +209,6 @@ export class PipelineSource { // Create stage object const stage = new DocumentsSource(normalizedDocs, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'documents' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._createPipeline([stage]); } diff --git a/packages/firestore/src/lite-api/pipeline.ts b/packages/firestore/src/lite-api/pipeline.ts index 23c37ba5d8..5d961885e5 100644 --- a/packages/firestore/src/lite-api/pipeline.ts +++ b/packages/firestore/src/lite-api/pipeline.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { ParseContext } from '../api/parse_context'; import { Pipeline as ProtoPipeline, Stage as ProtoStage @@ -85,8 +86,7 @@ import { UnnestStageOptions, WhereStageOptions } from './stage_options'; -import { UserDataReader, UserDataSource } from './user_data_reader'; -import { AbstractUserDataWriter } from './user_data_writer'; +import { UserData } from './user_data_reader'; /** * @beta @@ -128,13 +128,11 @@ import { AbstractUserDataWriter } from './user_data_writer'; * .aggregate(average(field("rating")).as("averageRating"))); * ``` */ -export class Pipeline implements ProtoSerializable { +export class Pipeline implements ProtoSerializable, UserData { /** * @internal * @private * @param _db - * @param userDataReader - * @param _userDataWriter * @param stages */ constructor( @@ -143,16 +141,6 @@ export class Pipeline implements ProtoSerializable { * @private */ public _db: Firestore, - /** - * @internal - * @private - */ - private userDataReader: UserDataReader, - /** - * @internal - * @private - */ - public _userDataWriter: AbstractUserDataWriter, /** * @internal * @private @@ -160,6 +148,15 @@ export class Pipeline implements ProtoSerializable { private stages: Stage[] ) {} + _readUserData(context: ParseContext): void { + this.stages.forEach(stage => { + const subContext = context.contextWith({ + methodName: stage._name + }); + stage._readUserData(subContext); + }); + } + /** * @beta * Adds new fields to outputs from previous stages. @@ -239,14 +236,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new AddFields(normalizedFields, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'addFields' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -317,12 +306,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new RemoveFields(convertedFields, options); - // User data must be read in the context of the API method to - // provide contextual errors - stage._readUserData( - this.userDataReader.createContext(UserDataSource.Argument, 'removeFields') - ); - // Add stage to the pipeline return this._addStage(stage); } @@ -421,14 +404,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new Select(normalizedSelections, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'select' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -511,14 +486,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new Where(condition, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'where' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -584,14 +551,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new Offset(offset, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'offset' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -662,14 +621,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new Limit(limit, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'limit' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -756,14 +707,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new Distinct(convertedGroups, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'distinct' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -860,14 +803,6 @@ export class Pipeline implements ProtoSerializable { options ); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'aggregate' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -919,14 +854,6 @@ export class Pipeline implements ProtoSerializable { internalOptions ); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'addFields' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -999,14 +926,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new Sort(orderings, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'sort' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -1140,14 +1059,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new Replace(mapExpr, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'replaceWith' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -1214,14 +1125,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new Sample(rate, mode, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'sample' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -1282,14 +1185,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new Union(otherPipeline, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'union' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -1393,14 +1288,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new Unnest(alias, expr, options); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'unnest' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -1449,14 +1336,6 @@ export class Pipeline implements ProtoSerializable { // Create stage object const stage = new RawStage(name, expressionParams, options ?? {}); - // User data must be read in the context of the API method to - // provide contextual errors - const parseContext = this.userDataReader.createContext( - UserDataSource.Argument, - 'rawStage' - ); - stage._readUserData(parseContext); - // Add stage to the pipeline return this._addStage(stage); } @@ -1475,12 +1354,7 @@ export class Pipeline implements ProtoSerializable { private _addStage(stage: Stage): Pipeline { const copy = this.stages.map(s => s); copy.push(stage); - return this.newPipeline( - this._db, - this.userDataReader, - this._userDataWriter, - copy - ); + return this.newPipeline(this._db, copy); } /** @@ -1492,13 +1366,8 @@ export class Pipeline implements ProtoSerializable { * @param stages * @protected */ - protected newPipeline( - db: Firestore, - userDataReader: UserDataReader, - userDataWriter: AbstractUserDataWriter, - stages: Stage[] - ): Pipeline { - return new Pipeline(db, userDataReader, userDataWriter, stages); + protected newPipeline(db: Firestore, stages: Stage[]): Pipeline { + return new Pipeline(db, stages); } } diff --git a/packages/firestore/src/lite-api/pipeline_impl.ts b/packages/firestore/src/lite-api/pipeline_impl.ts index fa0d480221..8a1c4553da 100644 --- a/packages/firestore/src/lite-api/pipeline_impl.ts +++ b/packages/firestore/src/lite-api/pipeline_impl.ts @@ -20,6 +20,7 @@ import { StructuredPipelineOptions } from '../core/structured_pipeline'; import { invokeExecutePipeline } from '../remote/datastore'; +import { cast } from '../util/input_validation'; import { getDatastore } from './components'; import { Firestore } from './database'; @@ -29,11 +30,7 @@ import { PipelineSource } from './pipeline-source'; import { DocumentReference } from './reference'; import { LiteUserDataWriter } from './reference_impl'; import { Stage } from './stage'; -import { - newUserDataReader, - UserDataReader, - UserDataSource -} from './user_data_reader'; +import { newUserDataReader, UserDataSource } from './user_data_reader'; declare module './database' { interface Firestore { @@ -86,12 +83,16 @@ declare module './database' { */ export function execute(pipeline: Pipeline): Promise { const datastore = getDatastore(pipeline._db); + const firestore = cast(pipeline._db, Firestore); - const udr = new UserDataReader( - pipeline._db._databaseId, - /* ignoreUndefinedProperties */ true + const userDataReader = newUserDataReader(firestore); + const context = userDataReader.createContext( + UserDataSource.Argument, + 'execute' ); - const context = udr.createContext(UserDataSource.Argument, 'execute'); + + pipeline._readUserData(context); + const userDataWriter = new LiteUserDataWriter(firestore); const structuredPipelineOptions = new StructuredPipelineOptions({}, {}); structuredPipelineOptions._readUserData(context); @@ -115,7 +116,7 @@ export function execute(pipeline: Pipeline): Promise { .map( element => new PipelineResult( - pipeline._userDataWriter, + userDataWriter, element.fields!, element.key?.path ? new DocumentReference(pipeline._db, null, element.key) @@ -139,13 +140,7 @@ export function execute(pipeline: Pipeline): Promise { * ``` */ Firestore.prototype.pipeline = function (): PipelineSource { - const userDataWriter = new LiteUserDataWriter(this); - const userDataReader = newUserDataReader(this); - return new PipelineSource( - this._databaseId, - userDataReader, - (stages: Stage[]) => { - return new Pipeline(this, userDataReader, userDataWriter, stages); - } - ); + return new PipelineSource(this._databaseId, (stages: Stage[]) => { + return new Pipeline(this, stages); + }); }; diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index a1bb9ac137..2097fe1c3d 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -717,32 +717,50 @@ describe.skipClassic('Firestore Pipelines', () => { }); it('throws on undefined in a map', async () => { - expect(() => { - firestore - .pipeline() - .collection(randomCol.path) - .limit(1) - .select( - map({ - 'number': 1, - undefined - }).as('foo') - ); - }).to.throw( - 'Function map() called with invalid data. Unsupported field value: undefined' - ); + try { + await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select( + map({ + 'number': 1, + undefined + }).as('foo') + ) + ); + expect(true, 'should throw').to.be.false; + } catch (e: unknown) { + expect(e instanceof FirebaseError).to.be.true; + const err = e as FirebaseError; + expect(err['code']).to.equal('invalid-argument'); + expect(typeof err['message']).to.equal('string'); + expect(err['message']).to.equal( + 'Function map() called with invalid data. Unsupported field value: undefined' + ); + } }); it('throws on undefined in an array', async () => { - expect(() => { - firestore - .pipeline() - .collection(randomCol.path) - .limit(1) - .select(array([1, undefined]).as('foo')); - }).to.throw( - 'Function array() called with invalid data. Unsupported field value: undefined' - ); + try { + await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(array([1, undefined]).as('foo')) + ); + expect(true, 'should throw').to.be.false; + } catch (e: unknown) { + expect(e instanceof FirebaseError).to.be.true; + const err = e as FirebaseError; + expect(err['code']).to.equal('invalid-argument'); + expect(typeof err['message']).to.equal('string'); + expect(err['message']).to.equal( + 'Function array() called with invalid data. Unsupported field value: undefined' + ); + } }); it('converts arrays and plain objects to functionValues if the customer intent is unspecified', async () => { From 891a0c9d4e7b02dd5ff97ba31d18bab0c07cae21 Mon Sep 17 00:00:00 2001 From: Stephen Rosa <84193009+stephenarosaj@users.noreply.github.com> Date: Tue, 17 Mar 2026 07:15:14 -0700 Subject: [PATCH 101/174] update CODEOWNERs (#9724) --- .github/CODEOWNERS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 1ae328951f..914271bd1c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -11,12 +11,12 @@ * @firebase/jssdk-global-approvers # Database Code -packages/database @maneesht @aashishpatil-g @firebase/jssdk-global-approvers -packages/database-compat @maneesht @aashishpatil-g @firebase/jssdk-global-approvers -packages/database-types @maneesht @aashishpatil-g @firebase/jssdk-global-approvers +packages/database @stephenarosaj @dconeybe @aashishpatil-g @firebase/jssdk-global-approvers +packages/database-compat @stephenarosaj @dconeybe @aashishpatil-g @firebase/jssdk-global-approvers +packages/database-types @stephenarosaj @dconeybe @aashishpatil-g @firebase/jssdk-global-approvers # Data Connect Code -packages/data-connect @maneesht @aashishpatil-g @firebase/jssdk-global-approvers +packages/data-connect @stephenarosaj @dconeybe @aashishpatil-g @firebase/jssdk-global-approvers # Firestore Code packages/firestore @firebase/firestore-js-team @firebase/jssdk-global-approvers From 9d33dd6434dfc70cf835d603c1da09d9663885ec Mon Sep 17 00:00:00 2001 From: Stephen Rosa <84193009+stephenarosaj@users.noreply.github.com> Date: Tue, 17 Mar 2026 07:40:26 -0700 Subject: [PATCH 102/174] feat(data-connect): Add validateArgsWithOptions() (#9614) * update validateArgs to handle new options arguments * add validateArgs unit tests * split functionality into separate functions, add changeset * add hasVars argument to help differentiate first argument * update changelog * export validateArgs * remove vestigial console log * update changeset --- .changeset/funny-apples-pay.md | 6 + common/api-review/data-connect.api.md | 2 +- packages/data-connect/src/api/index.ts | 2 +- .../src/core/query/queryOptions.ts | 4 +- .../data-connect/src/util/validateArgs.ts | 82 +++- .../test/unit/validateArgs.test.ts | 400 ++++++++++++++++++ 6 files changed, 487 insertions(+), 9 deletions(-) create mode 100644 .changeset/funny-apples-pay.md create mode 100644 packages/data-connect/test/unit/validateArgs.test.ts diff --git a/.changeset/funny-apples-pay.md b/.changeset/funny-apples-pay.md new file mode 100644 index 0000000000..33231c4b21 --- /dev/null +++ b/.changeset/funny-apples-pay.md @@ -0,0 +1,6 @@ +--- +'@firebase/data-connect': minor +'firebase': minor +--- + +Add validateArgsWithOptions() to Data Connect (internal change, no need to add to public release notes). \ No newline at end of file diff --git a/common/api-review/data-connect.api.md b/common/api-review/data-connect.api.md index c8f4814764..c1994ade96 100644 --- a/common/api-review/data-connect.api.md +++ b/common/api-review/data-connect.api.md @@ -165,7 +165,7 @@ export function executeMutation(mutationRef: MutationRef(queryRef: QueryRef, options?: ExecuteQueryOptions): QueryPromise; -// @public (undocumented) +// @public export interface ExecuteQueryOptions { // (undocumented) fetchPolicy: QueryFetchPolicy; diff --git a/packages/data-connect/src/api/index.ts b/packages/data-connect/src/api/index.ts index 1140e7ed9f..e6a37314d7 100644 --- a/packages/data-connect/src/api/index.ts +++ b/packages/data-connect/src/api/index.ts @@ -39,7 +39,7 @@ export * from './Reference'; export * from './Mutation'; export * from './query'; export { setLogLevel } from '../logger'; -export { validateArgs } from '../util/validateArgs'; +export { validateArgs, validateArgsWithOptions } from '../util/validateArgs'; export { DataConnectErrorCode, Code, diff --git a/packages/data-connect/src/core/query/queryOptions.ts b/packages/data-connect/src/core/query/queryOptions.ts index 6afb1fe94d..d7cec22e44 100644 --- a/packages/data-connect/src/core/query/queryOptions.ts +++ b/packages/data-connect/src/core/query/queryOptions.ts @@ -23,11 +23,13 @@ export const QueryFetchPolicy = { /* * Represents policy for how executeQuery fetches data - * */ export type QueryFetchPolicy = (typeof QueryFetchPolicy)[keyof typeof QueryFetchPolicy]; +/** + * Options for executing a query. + */ export interface ExecuteQueryOptions { fetchPolicy: QueryFetchPolicy; } diff --git a/packages/data-connect/src/util/validateArgs.ts b/packages/data-connect/src/util/validateArgs.ts index e957786aa4..03304fc426 100644 --- a/packages/data-connect/src/util/validateArgs.ts +++ b/packages/data-connect/src/util/validateArgs.ts @@ -15,24 +15,32 @@ * limitations under the License. */ +import { ExecuteQueryOptions } from '../api'; import { ConnectorConfig, DataConnect, getDataConnect } from '../api/DataConnect'; import { Code, DataConnectError } from '../core/error'; + interface ParsedArgs { dc: DataConnect; vars: Variables; + options?: ExecuteQueryOptions; } /** - * The generated SDK will allow the user to pass in either the variable or the data connect instance with the variable, - * and this function validates the variables and returns back the DataConnect instance and variables based on the arguments passed in. + * The generated SDK will allow the user to pass in either the variables or the data connect instance + * with the variables. This function validates the variables and returns back the DataConnect instance + * and variables based on the arguments passed in. + * + * Generated SDKs generated from versions 3.2.0 and lower of the Data Connect emulator binary are + * NOT concerned with options, and will use this function to validate arguments. + * * @param connectorConfig * @param dcOrVars * @param vars - * @param validateVars + * @param variablesRequired * @returns {DataConnect} and {Variables} instance * @internal */ @@ -40,19 +48,81 @@ export function validateArgs( connectorConfig: ConnectorConfig, dcOrVars?: DataConnect | Variables, vars?: Variables, - validateVars?: boolean + variablesRequired?: boolean ): ParsedArgs { let dcInstance: DataConnect; let realVars: Variables; - if (dcOrVars && 'enableEmulator' in dcOrVars) { + + const dcFirstArg = dcOrVars && 'enableEmulator' in dcOrVars; + + if (dcFirstArg) { dcInstance = dcOrVars as DataConnect; realVars = vars as Variables; } else { dcInstance = getDataConnect(connectorConfig); realVars = dcOrVars as Variables; } - if (!dcInstance || (!realVars && validateVars)) { + + if (!dcInstance || (!realVars && variablesRequired)) { throw new DataConnectError(Code.INVALID_ARGUMENT, 'Variables required.'); } + return { dc: dcInstance, vars: realVars }; } + +/** + * The generated SDK will allow the user to pass in either the variables or the data connect instance + * with the variables, and/or options. This function validates the variables and returns back the + * DataConnect instance and variables, and potentially options, based on the arguments passed in. + * + * Generated SDKs generated from versions 3.2.0 and higher of the Data Connect emulator binary are + * in fact concerned with options, and will use this function to validate arguments. + * + * @param connectorConfig + * @param dcOrVarsOrOptions + * @param varsOrOptions + * @param variablesRequired + * @param options + * @returns {DataConnect} and {Variables} instance, and optionally {ExecuteQueryOptions} + * @internal + */ +export function validateArgsWithOptions( + connectorConfig: ConnectorConfig, + dcOrVarsOrOptions?: DataConnect | Variables | ExecuteQueryOptions, + varsOrOptions?: Variables | ExecuteQueryOptions, + options?: ExecuteQueryOptions, + hasVars?: boolean, + variablesRequired?: boolean +): ParsedArgs { + let dcInstance: DataConnect; + let realVars: Variables; + let realOptions: ExecuteQueryOptions; + + const dcFirstArg = dcOrVarsOrOptions && 'enableEmulator' in dcOrVarsOrOptions; + + if (dcFirstArg) { + dcInstance = dcOrVarsOrOptions as DataConnect; + if (hasVars) { + realVars = varsOrOptions as Variables; + realOptions = options as ExecuteQueryOptions; + } else { + realVars = undefined as unknown as Variables; + realOptions = varsOrOptions as ExecuteQueryOptions; + } + } else { + dcInstance = getDataConnect(connectorConfig); + if (hasVars) { + realVars = dcOrVarsOrOptions as Variables; + realOptions = varsOrOptions as ExecuteQueryOptions; + } else { + realVars = undefined as unknown as Variables; + realOptions = dcOrVarsOrOptions as ExecuteQueryOptions; + } + } + + if (!dcInstance || (!realVars && variablesRequired)) { + throw new DataConnectError(Code.INVALID_ARGUMENT, 'Variables required.'); + } + + return { dc: dcInstance, vars: realVars, options: realOptions }; +} diff --git a/packages/data-connect/test/unit/validateArgs.test.ts b/packages/data-connect/test/unit/validateArgs.test.ts new file mode 100644 index 0000000000..05b66f2431 --- /dev/null +++ b/packages/data-connect/test/unit/validateArgs.test.ts @@ -0,0 +1,400 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai'; +import * as sinon from 'sinon'; + +import * as dataConnectIndex from '../../src/api/DataConnect'; +import { DataConnect, ConnectorConfig } from '../../src/api/DataConnect'; +import { Code, DataConnectError } from '../../src/core/error'; +import { QueryFetchPolicy } from '../../src/core/query/queryOptions'; +import { + validateArgs, + validateArgsWithOptions +} from '../../src/util/validateArgs'; + +interface IdVars { + id: string; +} + +describe('validateArgs()', () => { + let getDataConnectStub: sinon.SinonStub; + + const connectorConfig: ConnectorConfig = { + location: 'us-west2', + service: 'my-service', + connector: 'my-connector' + }; + + const providedDcInstance = { + app: { options: { projectId: 'my-project' } }, + dataConnectOptions: connectorConfig, + source: 'PROVIDED', + enableEmulator: sinon.stub() + } as unknown as DataConnect; + + const variables: IdVars = { id: 'stephenarosaj' }; + const options = { fetchPolicy: QueryFetchPolicy.SERVER_ONLY }; + + const stubDcInstance = { + app: { options: { projectId: 'my-project' } }, + dataConnectOptions: connectorConfig, + source: 'STUB' + } as unknown as DataConnect; + + beforeEach(() => { + getDataConnectStub = sinon + .stub(dataConnectIndex, 'getDataConnect') + .returns(stubDcInstance); + }); + + afterEach(() => { + getDataConnectStub.restore(); + }); + + describe('validateArgs', () => { + describe('should parse arguments properly', () => { + it('when dc and vars are provided', () => { + const { dc: dcInstance, vars: inputVars } = validateArgs( + connectorConfig, + providedDcInstance, + variables + ); + expect(dcInstance).to.deep.equal(providedDcInstance); + expect(inputVars).to.deep.equal(variables); + }); + + it('when only vars are provided (infer dc)', () => { + const { dc: dcInstance, vars: inputVars } = validateArgs( + connectorConfig, + variables + ); + expect(getDataConnectStub.calledOnce).to.be.true; + expect(dcInstance).to.deep.equal(stubDcInstance); + expect(inputVars).to.deep.equal(variables); + }); + + it('when no args are provided (infer dc)', () => { + const { dc: dcInstance, vars: inputVars } = + validateArgs(connectorConfig); + expect(getDataConnectStub.calledOnce).to.be.true; + expect(dcInstance).to.deep.equal(stubDcInstance); + expect(inputVars).to.be.undefined; + }); + }); + + describe('should throw when vars are required but missing', () => { + it('and dc is provided', () => { + expect(() => { + validateArgs( + connectorConfig, + providedDcInstance, + undefined, + /** variablesRequired = */ true + ); + }) + .to.throw(DataConnectError, 'Variables required') + .with.property('code', Code.INVALID_ARGUMENT); + }); + it('and dc is NOT provided', () => { + expect(() => { + validateArgs( + connectorConfig, + undefined, + undefined, + /** variablesRequired = */ true + ); + }) + .to.throw(DataConnectError, 'Variables required') + .with.property('code', Code.INVALID_ARGUMENT); + }); + }); + }); + + describe('validateArgsWithOptions', () => { + describe('should parse arguments properly', () => { + describe('with hasVars = true', () => { + it('when dc, vars, and options are provided', () => { + const { + dc: dcInstance, + vars: inputVars, + options: inputOpts + } = validateArgsWithOptions( + connectorConfig, + providedDcInstance, + variables, + options, + /** hasVars = */ true, + /** variablesRequired = */ false + ); + expect(dcInstance).to.deep.equal(providedDcInstance); + expect(inputVars).to.deep.equal(variables); + expect(inputOpts).to.deep.equal(options); + }); + + it('when vars and options are provided (infer dc)', () => { + const { + dc: dcInstance, + vars: inputVars, + options: inputOpts + } = validateArgsWithOptions( + connectorConfig, + variables, + options, + undefined, + /** hasVars = */ true, + /** variablesRequired = */ false + ); + expect(getDataConnectStub.calledOnce).to.be.true; + expect(dcInstance).to.deep.equal(stubDcInstance); + expect(inputVars).to.deep.equal(variables); + expect(inputOpts).to.deep.equal(options); + }); + + it('when dc and vars are provided (no options)', () => { + const { + dc: dcInstance, + vars: inputVars, + options: inputOpts + } = validateArgsWithOptions( + connectorConfig, + providedDcInstance, + variables, + undefined, + /** hasVars = */ true, + /** variablesRequired = */ false + ); + expect(dcInstance).to.deep.equal(providedDcInstance); + expect(inputVars).to.deep.equal(variables); + expect(inputOpts).to.be.undefined; + }); + + it('when only vars are provided (no options, infer dc)', () => { + const { + dc: dcInstance, + vars: inputVars, + options: inputOpts + } = validateArgsWithOptions( + connectorConfig, + variables, + undefined, + undefined, + /** hasVars = */ true, + /** variablesRequired = */ false + ); + expect(getDataConnectStub.calledOnce).to.be.true; + expect(dcInstance).to.deep.equal(stubDcInstance); + expect(inputVars).to.deep.equal(variables); + expect(inputOpts).to.be.undefined; + }); + + it('when dc and options are provided (optional vars are undefined)', () => { + const { + dc: dcInstance, + vars: inputVars, + options: inputOpts + } = validateArgsWithOptions( + connectorConfig, + providedDcInstance, + undefined, + options, + /** hasVars = */ true, + /** variablesRequired = */ false + ); + expect(dcInstance).to.deep.equal(providedDcInstance); + expect(inputVars).to.be.undefined; + expect(inputOpts).to.deep.equal(options); + }); + + it('when only options is provided (infer dc, optional vars are undefined)', () => { + const { + dc: dcInstance, + vars: inputVars, + options: inputOpts + } = validateArgsWithOptions( + connectorConfig, + undefined, + options, + undefined, + /** hasVars = */ true, + /** variablesRequired = */ false + ); + expect(dcInstance).to.deep.equal(stubDcInstance); + expect(inputVars).to.be.undefined; + expect(inputOpts).to.deep.equal(options); + }); + + it('when no args are provided (infer dc, optional vars are undefined)', () => { + const { + dc: dcInstance, + vars: inputVars, + options: inputOpts + } = validateArgsWithOptions( + connectorConfig, + undefined, + undefined, + undefined, + /** hasVars = */ true, + /** variablesRequired = */ false + ); + expect(getDataConnectStub.calledOnce).to.be.true; + expect(dcInstance).to.deep.equal(stubDcInstance); + expect(inputVars).to.be.undefined; + expect(inputOpts).to.be.undefined; + }); + }); + + describe('with hasVars = false', () => { + it('when dc and options are provided', () => { + const { + dc: dcInstance, + vars: inputVars, + options: inputOpts + } = validateArgsWithOptions( + connectorConfig, + providedDcInstance, + options, + undefined, + /** hasVars = */ false, + /** variablesRequired = */ false + ); + expect(dcInstance).to.deep.equal(providedDcInstance); + expect(inputVars).to.deep.equal(undefined); + expect(inputOpts).to.deep.equal(options); + }); + + it('when only dc is provided (no options)', () => { + const { + dc: dcInstance, + vars: inputVars, + options: inputOpts + } = validateArgsWithOptions( + connectorConfig, + providedDcInstance, + undefined, + undefined, + /** hasVars = */ false, + /** variablesRequired = */ false + ); + expect(dcInstance).to.deep.equal(providedDcInstance); + expect(inputVars).to.deep.equal(undefined); + expect(inputOpts).to.be.undefined; + }); + + it('when only options are provided (infer dc)', () => { + const { + dc: dcInstance, + vars: inputVars, + options: inputOpts + } = validateArgsWithOptions( + connectorConfig, + options, + undefined, + undefined, + /** hasVars = */ false, + /** variablesRequired = */ false + ); + expect(getDataConnectStub.calledOnce).to.be.true; + expect(dcInstance).to.deep.equal(stubDcInstance); + expect(inputVars).to.deep.equal(undefined); + expect(inputOpts).to.deep.equal(options); + }); + + it('when no args are provided (infer dc)', () => { + const { + dc: dcInstance, + vars: inputVars, + options: inputOpts + } = validateArgsWithOptions( + connectorConfig, + undefined, + undefined, + undefined, + /** hasVars = */ false, + /** variablesRequired = */ false + ); + expect(getDataConnectStub.calledOnce).to.be.true; + expect(dcInstance).to.deep.equal(stubDcInstance); + expect(inputVars).to.be.undefined; + expect(inputOpts).to.be.undefined; + }); + }); + }); + + describe('should throw when vars are required but missing', () => { + it('and only dc is provided', () => { + expect(() => { + validateArgsWithOptions( + connectorConfig, + providedDcInstance, + undefined, + undefined, + /** hasVars = */ true, + /** variablesRequired = */ true + ); + }) + .to.throw(DataConnectError, 'Variables required') + .with.property('code', Code.INVALID_ARGUMENT); + }); + + it('and only options is provided', () => { + expect(() => { + validateArgsWithOptions( + connectorConfig, + undefined, + options, + undefined, + /** hasVars = */ true, + /** variablesRequired = */ true + ); + }) + .to.throw(DataConnectError, 'Variables required') + .with.property('code', Code.INVALID_ARGUMENT); + }); + + it('and dc and options is provided', () => { + expect(() => { + validateArgsWithOptions( + connectorConfig, + providedDcInstance, + undefined, + options, + /** hasVars = */ true, + /** variablesRequired = */ true + ); + }) + .to.throw(DataConnectError, 'Variables required') + .with.property('code', Code.INVALID_ARGUMENT); + }); + + it('and nothing is provided', () => { + expect(() => { + validateArgsWithOptions( + connectorConfig, + undefined, + undefined, + undefined, + /** hasVars = */ true, + /** variablesRequired = */ true + ); + }) + .to.throw(DataConnectError, 'Variables required') + .with.property('code', Code.INVALID_ARGUMENT); + }); + }); + }); +}); From 843a8d7892beb27e6bb62bb6331fe03aef97c57e Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 17 Mar 2026 07:49:44 -0700 Subject: [PATCH 103/174] feat(ai): Add responseJsonSchema (#9693) Adds `responseJsonSchema` field, which takes an object in JSON Schema format. Gemini docs examples show how to use the zod library to easily generate this object (https://ai.google.dev/gemini-api/docs/structured-output?example=recipe), and we should follow this with an example of how to do the same, somewhere in the Firebase guides. Maybe this page? https://firebase.google.com/docs/ai-logic/generate-structured-output?api=dev Tested manually with Developer API and Vertex and both work. Doc changes: Added text for `responseJsonSchema` and used `@remarks` to remove bulk of text of both `responseSchema` and `responseJsonSchema` from table of contents (full text is still in the section below). Fixes #9625 --- .changeset/sharp-kiwis-push.md | 6 ++++++ common/api-review/ai.api.md | 3 +++ docs-devsite/ai.generationconfig.md | 15 +++++++++++++++ packages/ai/src/models/generative-model.ts | 20 ++++++++++++++++++++ packages/ai/src/types/requests.ts | 8 ++++++++ 5 files changed, 52 insertions(+) create mode 100644 .changeset/sharp-kiwis-push.md diff --git a/.changeset/sharp-kiwis-push.md b/.changeset/sharp-kiwis-push.md new file mode 100644 index 0000000000..48ccf8212c --- /dev/null +++ b/.changeset/sharp-kiwis-push.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +Added `responseJsonSchema` to `GenerationConfig`. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 8f6ee39ed0..59fdd75113 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -520,6 +520,9 @@ export interface GenerationConfig { maxOutputTokens?: number; // (undocumented) presencePenalty?: number; + responseJsonSchema?: { + [key: string]: unknown; + }; responseMimeType?: string; // @beta responseModalities?: ResponseModality[]; diff --git a/docs-devsite/ai.generationconfig.md b/docs-devsite/ai.generationconfig.md index 7330b8e699..fbf39f1f15 100644 --- a/docs-devsite/ai.generationconfig.md +++ b/docs-devsite/ai.generationconfig.md @@ -26,6 +26,7 @@ export interface GenerationConfig | [frequencyPenalty](./ai.generationconfig.md#generationconfigfrequencypenalty) | number | | | [maxOutputTokens](./ai.generationconfig.md#generationconfigmaxoutputtokens) | number | | | [presencePenalty](./ai.generationconfig.md#generationconfigpresencepenalty) | number | | +| [responseJsonSchema](./ai.generationconfig.md#generationconfigresponsejsonschema) | { \[key: string\]: unknown; } | Output schema of the generated response. This is an alternative to responseSchema that accepts \[JSON Schema\](https://json-schema.org/).If set, responseSchema must be omitted, but responseMimeType is required and must be set to application/json. | | [responseMimeType](./ai.generationconfig.md#generationconfigresponsemimetype) | string | Output response MIME type of the generated candidate text. Supported MIME types are text/plain (default, text output), application/json (JSON response in the candidates), and text/x.enum. | | [responseModalities](./ai.generationconfig.md#generationconfigresponsemodalities) | [ResponseModality](./ai.md#responsemodality)\[\] | (Public Preview) Generation modalities to be returned in generation responses. | | [responseSchema](./ai.generationconfig.md#generationconfigresponseschema) | [TypedSchema](./ai.md#typedschema) \| [SchemaRequest](./ai.schemarequest.md#schemarequest_interface) | Output response schema of the generated candidate text. This value can be a class generated with a [Schema](./ai.schema.md#schema_class) static method like Schema.string() or Schema.object() or it can be a plain JS object matching the [SchemaRequest](./ai.schemarequest.md#schemarequest_interface) interface.
    Note: This only applies when the specified responseMimeType supports a schema; currently this is limited to application/json and text/x.enum. | @@ -67,6 +68,20 @@ maxOutputTokens?: number; presencePenalty?: number; ``` +## GenerationConfig.responseJsonSchema + +Output schema of the generated response. This is an alternative to `responseSchema` that accepts \[JSON Schema\](https://json-schema.org/). + +If set, `responseSchema` must be omitted, but `responseMimeType` is required and must be set to `application/json`. + +Signature: + +```typescript +responseJsonSchema?: { + [key: string]: unknown; + }; +``` + ## GenerationConfig.responseMimeType Output response MIME type of the generated candidate text. Supported MIME types are `text/plain` (default, text output), `application/json` (JSON response in the candidates), and `text/x.enum`. diff --git a/packages/ai/src/models/generative-model.ts b/packages/ai/src/models/generative-model.ts index 20922f0004..5a76b62918 100644 --- a/packages/ai/src/models/generative-model.ts +++ b/packages/ai/src/models/generative-model.ts @@ -201,4 +201,24 @@ function validateGenerationConfig(generationConfig: GenerationConfig): void { `Cannot set both thinkingBudget and thinkingLevel in a config.` ); } + if ( + // != allows for null and undefined. + generationConfig.responseSchema != null && + generationConfig.responseJsonSchema != null + ) { + throw new AIError( + AIErrorCode.UNSUPPORTED, + `Cannot set both responseSchema and responseJsonSchema in a config.` + ); + } + if ( + (generationConfig.responseSchema != null || + generationConfig.responseJsonSchema != null) && + generationConfig.responseMimeType + ) { + throw new AIError( + AIErrorCode.UNSUPPORTED, + `responseMimeType must be set if responseSchema or responseJsonSchema are set.` + ); + } } diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index c4d7b24d2c..cee42fc5a1 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -120,6 +120,14 @@ export interface GenerationConfig { * this is limited to `application/json` and `text/x.enum`. */ responseSchema?: TypedSchema | SchemaRequest; + /** + * Output schema of the generated response. This is an alternative to + * `responseSchema` that accepts [JSON Schema](https://json-schema.org/). + * + * If set, `responseSchema` must be omitted, but `responseMimeType` + * is required and must be set to `application/json`. + */ + responseJsonSchema?: { [key: string]: unknown }; /** * Generation modalities to be returned in generation responses. * From 852957b27d1a186ef6f4394d30f1f93dc1c316ea Mon Sep 17 00:00:00 2001 From: Google Open Source Bot Date: Thu, 19 Mar 2026 05:41:00 -0700 Subject: [PATCH 104/174] Version Packages (#9727) Release v12.11.0 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/eleven-carrots-relate.md | 5 -- .changeset/funny-apples-pay.md | 6 --- .changeset/sharp-kiwis-push.md | 6 --- .changeset/spotty-hornets-thank.md | 5 -- .changeset/spotty-rocks-sin.md | 6 --- .changeset/yellow-poets-teach.md | 11 ----- integration/compat-interop/package.json | 28 +++++------ integration/firestore/package.json | 4 +- integration/messaging/package.json | 2 +- packages/ai/CHANGELOG.md | 12 +++++ packages/ai/package.json | 8 ++-- packages/analytics-compat/CHANGELOG.md | 9 ++++ packages/analytics-compat/package.json | 10 ++-- packages/analytics/CHANGELOG.md | 9 ++++ packages/analytics/package.json | 10 ++-- packages/app-check-compat/CHANGELOG.md | 9 ++++ packages/app-check-compat/package.json | 10 ++-- packages/app-check/CHANGELOG.md | 8 ++++ packages/app-check/package.json | 8 ++-- packages/app-compat/CHANGELOG.md | 9 ++++ packages/app-compat/package.json | 8 ++-- packages/app/CHANGELOG.md | 10 ++++ packages/app/package.json | 6 +-- packages/auth-compat/CHANGELOG.md | 9 ++++ packages/auth-compat/package.json | 10 ++-- packages/auth/CHANGELOG.md | 10 ++++ packages/auth/package.json | 8 ++-- packages/component/CHANGELOG.md | 7 +++ packages/component/package.json | 4 +- packages/data-connect/CHANGELOG.md | 14 ++++++ packages/data-connect/package.json | 8 ++-- packages/database-compat/CHANGELOG.md | 10 ++++ packages/database-compat/package.json | 12 ++--- packages/database-types/CHANGELOG.md | 7 +++ packages/database-types/package.json | 4 +- packages/database/CHANGELOG.md | 10 ++++ packages/database/package.json | 8 ++-- packages/firebase/CHANGELOG.md | 41 ++++++++++++++++ packages/firebase/package.json | 56 +++++++++++----------- packages/firestore-compat/CHANGELOG.md | 9 ++++ packages/firestore-compat/package.json | 10 ++-- packages/firestore/CHANGELOG.md | 18 +++++++ packages/firestore/package.json | 12 ++--- packages/functions-compat/CHANGELOG.md | 9 ++++ packages/functions-compat/package.json | 10 ++-- packages/functions/CHANGELOG.md | 10 ++++ packages/functions/package.json | 8 ++-- packages/installations-compat/CHANGELOG.md | 9 ++++ packages/installations-compat/package.json | 10 ++-- packages/installations/CHANGELOG.md | 8 ++++ packages/installations/package.json | 8 ++-- packages/messaging-compat/CHANGELOG.md | 9 ++++ packages/messaging-compat/package.json | 10 ++-- packages/messaging/CHANGELOG.md | 9 ++++ packages/messaging/package.json | 10 ++-- packages/performance-compat/CHANGELOG.md | 9 ++++ packages/performance-compat/package.json | 10 ++-- packages/performance/CHANGELOG.md | 9 ++++ packages/performance/package.json | 10 ++-- packages/remote-config-compat/CHANGELOG.md | 9 ++++ packages/remote-config-compat/package.json | 10 ++-- packages/remote-config/CHANGELOG.md | 9 ++++ packages/remote-config/package.json | 10 ++-- packages/storage-compat/CHANGELOG.md | 9 ++++ packages/storage-compat/package.json | 12 ++--- packages/storage/CHANGELOG.md | 10 ++++ packages/storage/package.json | 10 ++-- packages/template/package.json | 2 +- packages/util/CHANGELOG.md | 6 +++ packages/util/package.json | 2 +- repo-scripts/size-analysis/package.json | 4 +- 71 files changed, 492 insertions(+), 215 deletions(-) delete mode 100644 .changeset/eleven-carrots-relate.md delete mode 100644 .changeset/funny-apples-pay.md delete mode 100644 .changeset/sharp-kiwis-push.md delete mode 100644 .changeset/spotty-hornets-thank.md delete mode 100644 .changeset/spotty-rocks-sin.md delete mode 100644 .changeset/yellow-poets-teach.md diff --git a/.changeset/eleven-carrots-relate.md b/.changeset/eleven-carrots-relate.md deleted file mode 100644 index ea39b77b5b..0000000000 --- a/.changeset/eleven-carrots-relate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/firestore': patch ---- - -**Beta API Breaking change**: Defer pipeline user data validation from initialization to `execute()`. This breaking change is allowed in a non-major release since the Firestore Pipelines API is currently in Public Preview. diff --git a/.changeset/funny-apples-pay.md b/.changeset/funny-apples-pay.md deleted file mode 100644 index 33231c4b21..0000000000 --- a/.changeset/funny-apples-pay.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/data-connect': minor -'firebase': minor ---- - -Add validateArgsWithOptions() to Data Connect (internal change, no need to add to public release notes). \ No newline at end of file diff --git a/.changeset/sharp-kiwis-push.md b/.changeset/sharp-kiwis-push.md deleted file mode 100644 index 48ccf8212c..0000000000 --- a/.changeset/sharp-kiwis-push.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -Added `responseJsonSchema` to `GenerationConfig`. diff --git a/.changeset/spotty-hornets-thank.md b/.changeset/spotty-hornets-thank.md deleted file mode 100644 index cbebe8a01b..0000000000 --- a/.changeset/spotty-hornets-thank.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@firebase/firestore": patch ---- - -Fixed X is not a function issues observed in server side rendering APIs. diff --git a/.changeset/spotty-rocks-sin.md b/.changeset/spotty-rocks-sin.md deleted file mode 100644 index 572877ff25..0000000000 --- a/.changeset/spotty-rocks-sin.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/firestore': minor ---- - -Add support for array expressions `arrayFirst`, `arrayFirstN`,`arrayLast`,`arrayLastN`,`arrayMinimum`,`arrayMinimumN`,`arrayMaximum`,`arrayMaximumN`,`arrayIndexOf`, `arrayLastIndexOf` and `arrayIndexOfAll` diff --git a/.changeset/yellow-poets-teach.md b/.changeset/yellow-poets-teach.md deleted file mode 100644 index ff7cda7d43..0000000000 --- a/.changeset/yellow-poets-teach.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@firebase/data-connect': patch -'@firebase/firestore': patch -'@firebase/functions': patch -'@firebase/database': patch -'@firebase/storage': patch -'@firebase/auth': patch -'@firebase/util': minor ---- - -Remove `updateEmulatorBanner()`. (No release note needed.) diff --git a/integration/compat-interop/package.json b/integration/compat-interop/package.json index 0a82152099..ea55aaf2c9 100644 --- a/integration/compat-interop/package.json +++ b/integration/compat-interop/package.json @@ -8,20 +8,20 @@ "test:debug": "karma start --browsers Chrome --auto-watch" }, "dependencies": { - "@firebase/app": "0.14.9", - "@firebase/app-compat": "0.5.9", - "@firebase/analytics": "0.10.20", - "@firebase/analytics-compat": "0.2.26", - "@firebase/auth": "1.12.1", - "@firebase/auth-compat": "0.6.3", - "@firebase/functions": "0.13.2", - "@firebase/functions-compat": "0.4.2", - "@firebase/messaging": "0.12.24", - "@firebase/messaging-compat": "0.2.24", - "@firebase/performance": "0.7.10", - "@firebase/performance-compat": "0.2.23", - "@firebase/remote-config": "0.8.1", - "@firebase/remote-config-compat": "0.2.22" + "@firebase/app": "0.14.10", + "@firebase/app-compat": "0.5.10", + "@firebase/analytics": "0.10.21", + "@firebase/analytics-compat": "0.2.27", + "@firebase/auth": "1.12.2", + "@firebase/auth-compat": "0.6.4", + "@firebase/functions": "0.13.3", + "@firebase/functions-compat": "0.4.3", + "@firebase/messaging": "0.12.25", + "@firebase/messaging-compat": "0.2.25", + "@firebase/performance": "0.7.11", + "@firebase/performance-compat": "0.2.24", + "@firebase/remote-config": "0.8.2", + "@firebase/remote-config-compat": "0.2.23" }, "devDependencies": { "typescript": "5.5.4" diff --git a/integration/firestore/package.json b/integration/firestore/package.json index 2233e43af8..e97286e55c 100644 --- a/integration/firestore/package.json +++ b/integration/firestore/package.json @@ -15,8 +15,8 @@ "test:memory:debug": "yarn build:memory; karma start --auto-watch --browsers Chrome" }, "dependencies": { - "@firebase/app": "0.14.9", - "@firebase/firestore": "4.12.0" + "@firebase/app": "0.14.10", + "@firebase/firestore": "4.13.0" }, "devDependencies": { "@types/mocha": "9.1.1", diff --git a/integration/messaging/package.json b/integration/messaging/package.json index c06e785902..df15118987 100644 --- a/integration/messaging/package.json +++ b/integration/messaging/package.json @@ -9,7 +9,7 @@ "test:manual": "mocha --exit" }, "devDependencies": { - "firebase": "12.10.0", + "firebase": "12.11.0", "chai": "4.5.0", "chromedriver": "119.0.1", "express": "4.21.2", diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 08493eccd3..670d2fe498 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/ai +## 2.10.0 + +### Minor Changes + +- [`843a8d7`](https://github.com/firebase/firebase-js-sdk/commit/843a8d7892beb27e6bb62bb6331fe03aef97c57e) [#9693](https://github.com/firebase/firebase-js-sdk/pull/9693) (fixes [#9625](https://github.com/firebase/firebase-js-sdk/issues/9625)) - Added `responseJsonSchema` to `GenerationConfig`. + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 2.9.0 ### Minor Changes diff --git a/packages/ai/package.json b/packages/ai/package.json index a9534d657d..4c0b0ba525 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/ai", - "version": "2.9.0", + "version": "2.10.0", "description": "The Firebase AI SDK", "author": "Firebase (https://firebase.google.com/)", "engines": { @@ -53,14 +53,14 @@ }, "dependencies": { "@firebase/app-check-interop-types": "0.3.3", - "@firebase/component": "0.7.1", + "@firebase/component": "0.7.2", "@firebase/logger": "0.5.0", - "@firebase/util": "1.14.0", + "@firebase/util": "1.15.0", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/analytics-compat/CHANGELOG.md b/packages/analytics-compat/CHANGELOG.md index e2a573eef3..f4b960e418 100644 --- a/packages/analytics-compat/CHANGELOG.md +++ b/packages/analytics-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/analytics-compat +## 0.2.27 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/analytics@0.10.21 + - @firebase/component@0.7.2 + ## 0.2.26 ### Patch Changes diff --git a/packages/analytics-compat/package.json b/packages/analytics-compat/package.json index 114acb35d2..3c6bc734ff 100644 --- a/packages/analytics-compat/package.json +++ b/packages/analytics-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/analytics-compat", - "version": "0.2.26", + "version": "0.2.27", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -22,7 +22,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.9", + "@firebase/app-compat": "0.5.10", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", @@ -52,10 +52,10 @@ }, "typings": "dist/src/index.d.ts", "dependencies": { - "@firebase/component": "0.7.1", - "@firebase/analytics": "0.10.20", + "@firebase/component": "0.7.2", + "@firebase/analytics": "0.10.21", "@firebase/analytics-types": "0.8.3", - "@firebase/util": "1.14.0", + "@firebase/util": "1.15.0", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/analytics/CHANGELOG.md b/packages/analytics/CHANGELOG.md index 789a88717e..43e7f207db 100644 --- a/packages/analytics/CHANGELOG.md +++ b/packages/analytics/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/analytics +## 0.10.21 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/installations@0.6.21 + - @firebase/component@0.7.2 + ## 0.10.20 ### Patch Changes diff --git a/packages/analytics/package.json b/packages/analytics/package.json index 75350bf020..4cce969cd4 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/analytics", - "version": "0.10.20", + "version": "0.10.21", "description": "A analytics package for new firebase packages", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -39,15 +39,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.20", + "@firebase/installations": "0.6.21", "@firebase/logger": "0.5.0", - "@firebase/util": "1.14.0", - "@firebase/component": "0.7.1", + "@firebase/util": "1.15.0", + "@firebase/component": "0.7.2", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "@rollup/plugin-commonjs": "21.1.0", diff --git a/packages/app-check-compat/CHANGELOG.md b/packages/app-check-compat/CHANGELOG.md index a081ae457c..38bcb741a1 100644 --- a/packages/app-check-compat/CHANGELOG.md +++ b/packages/app-check-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/app-check-compat +## 0.4.2 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/app-check@0.11.2 + - @firebase/component@0.7.2 + ## 0.4.1 ### Patch Changes diff --git a/packages/app-check-compat/package.json b/packages/app-check-compat/package.json index 6ae047d53b..1d8a31a447 100644 --- a/packages/app-check-compat/package.json +++ b/packages/app-check-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-check-compat", - "version": "0.4.1", + "version": "0.4.2", "description": "A compat App Check package for new firebase packages", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -34,16 +34,16 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/app-check": "0.11.1", + "@firebase/app-check": "0.11.2", "@firebase/app-check-types": "0.5.3", "@firebase/logger": "0.5.0", - "@firebase/util": "1.14.0", - "@firebase/component": "0.7.1", + "@firebase/util": "1.15.0", + "@firebase/component": "0.7.2", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.9", + "@firebase/app-compat": "0.5.10", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-check/CHANGELOG.md b/packages/app-check/CHANGELOG.md index aae45703c6..1d12dd4297 100644 --- a/packages/app-check/CHANGELOG.md +++ b/packages/app-check/CHANGELOG.md @@ -1,5 +1,13 @@ # @firebase/app-check +## 0.11.2 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 0.11.1 ### Patch Changes diff --git a/packages/app-check/package.json b/packages/app-check/package.json index a2ebeff2db..504f003ad3 100644 --- a/packages/app-check/package.json +++ b/packages/app-check/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-check", - "version": "0.11.1", + "version": "0.11.2", "description": "The App Check component of the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,14 +37,14 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/util": "1.14.0", - "@firebase/component": "0.7.1", + "@firebase/util": "1.15.0", + "@firebase/component": "0.7.2", "@firebase/logger": "0.5.0", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-compat/CHANGELOG.md b/packages/app-compat/CHANGELOG.md index 2f30cf04eb..a6adc07872 100644 --- a/packages/app-compat/CHANGELOG.md +++ b/packages/app-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/app-compat +## 0.5.10 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/app@0.14.10 + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 0.5.9 ### Patch Changes diff --git a/packages/app-compat/package.json b/packages/app-compat/package.json index 8a0693ed07..116343627e 100644 --- a/packages/app-compat/package.json +++ b/packages/app-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-compat", - "version": "0.5.9", + "version": "0.5.10", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,10 +37,10 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/app": "0.14.9", - "@firebase/util": "1.14.0", + "@firebase/app": "0.14.10", + "@firebase/util": "1.15.0", "@firebase/logger": "0.5.0", - "@firebase/component": "0.7.1", + "@firebase/component": "0.7.2", "tslib": "^2.1.0" }, "devDependencies": { diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 996b20099a..9293be09ee 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,15 @@ # @firebase/app +## 0.14.10 + +### Patch Changes + +- Update SDK_VERSION. + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 0.14.9 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 256aea0f79..264677f2db 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app", - "version": "0.14.9", + "version": "0.14.10", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -39,9 +39,9 @@ "typings:internal": "node ../../scripts/build/use_typings.js ./dist/app.d.ts" }, "dependencies": { - "@firebase/util": "1.14.0", + "@firebase/util": "1.15.0", "@firebase/logger": "0.5.0", - "@firebase/component": "0.7.1", + "@firebase/component": "0.7.2", "idb": "7.1.1", "tslib": "^2.1.0" }, diff --git a/packages/auth-compat/CHANGELOG.md b/packages/auth-compat/CHANGELOG.md index 152f7a1cd8..b3a505c481 100644 --- a/packages/auth-compat/CHANGELOG.md +++ b/packages/auth-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/auth-compat +## 0.6.4 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/auth@1.12.2 + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 0.6.3 ### Patch Changes diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index 051a874eed..2ced0e34b8 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth-compat", - "version": "0.6.3", + "version": "0.6.4", "description": "FirebaseAuth compatibility package that uses API style compatible with Firebase@8 and prior versions", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -49,15 +49,15 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/auth": "1.12.1", + "@firebase/auth": "1.12.2", "@firebase/auth-types": "0.13.0", - "@firebase/component": "0.7.1", - "@firebase/util": "1.14.0", + "@firebase/component": "0.7.2", + "@firebase/util": "1.15.0", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.9", + "@firebase/app-compat": "0.5.10", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/auth/CHANGELOG.md b/packages/auth/CHANGELOG.md index 3b475e84c0..3301b964b2 100644 --- a/packages/auth/CHANGELOG.md +++ b/packages/auth/CHANGELOG.md @@ -1,5 +1,15 @@ # @firebase/auth +## 1.12.2 + +### Patch Changes + +- [`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752) [#9608](https://github.com/firebase/firebase-js-sdk/pull/9608) - Remove `updateEmulatorBanner()`. (No release note needed.) + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 1.12.1 ### Patch Changes diff --git a/packages/auth/package.json b/packages/auth/package.json index df29557a63..3af41f4100 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth", - "version": "1.12.1", + "version": "1.12.2", "description": "The Firebase Authenticaton component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/node/index.js", @@ -124,14 +124,14 @@ } }, "dependencies": { - "@firebase/component": "0.7.1", + "@firebase/component": "0.7.2", "@firebase/logger": "0.5.0", - "@firebase/util": "1.14.0", + "@firebase/util": "1.15.0", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-strip": "3.0.4", "@types/express": "4.17.21", diff --git a/packages/component/CHANGELOG.md b/packages/component/CHANGELOG.md index de0ee0660c..b12325b41b 100644 --- a/packages/component/CHANGELOG.md +++ b/packages/component/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/component +## 0.7.2 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + ## 0.7.1 ### Patch Changes diff --git a/packages/component/package.json b/packages/component/package.json index 061f3367ba..756501e1ac 100644 --- a/packages/component/package.json +++ b/packages/component/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/component", - "version": "0.7.1", + "version": "0.7.2", "description": "Firebase Component Platform", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -31,7 +31,7 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/util": "1.14.0", + "@firebase/util": "1.15.0", "tslib": "^2.1.0" }, "license": "Apache-2.0", diff --git a/packages/data-connect/CHANGELOG.md b/packages/data-connect/CHANGELOG.md index 21fbb03304..3d144028a6 100644 --- a/packages/data-connect/CHANGELOG.md +++ b/packages/data-connect/CHANGELOG.md @@ -1,5 +1,19 @@ ## Unreleased +## 0.5.0 + +### Minor Changes + +- [`9d33dd6`](https://github.com/firebase/firebase-js-sdk/commit/9d33dd6434dfc70cf835d603c1da09d9663885ec) [#9614](https://github.com/firebase/firebase-js-sdk/pull/9614) - Add validateArgsWithOptions() to Data Connect (internal change, no need to add to public release notes). + +### Patch Changes + +- [`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752) [#9608](https://github.com/firebase/firebase-js-sdk/pull/9608) - Remove `updateEmulatorBanner()`. (No release note needed.) + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 0.4.0 ### Minor Changes diff --git a/packages/data-connect/package.json b/packages/data-connect/package.json index 1370e46a83..402dafdba9 100644 --- a/packages/data-connect/package.json +++ b/packages/data-connect/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/data-connect", - "version": "0.4.0", + "version": "0.5.0", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -49,13 +49,13 @@ }, "dependencies": { "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.7.1", + "@firebase/component": "0.7.2", "@firebase/logger": "0.5.0", - "@firebase/util": "1.14.0", + "@firebase/util": "1.15.0", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/database-compat/CHANGELOG.md b/packages/database-compat/CHANGELOG.md index c4aebb6163..b72097f612 100644 --- a/packages/database-compat/CHANGELOG.md +++ b/packages/database-compat/CHANGELOG.md @@ -1,5 +1,15 @@ # @firebase/database-compat +## 2.1.2 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/database@1.1.2 + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + - @firebase/database-types@1.0.18 + ## 2.1.1 ### Patch Changes diff --git a/packages/database-compat/package.json b/packages/database-compat/package.json index 648986b1bd..ef63bc25e6 100644 --- a/packages/database-compat/package.json +++ b/packages/database-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database-compat", - "version": "2.1.1", + "version": "2.1.2", "description": "The Realtime Database component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.js", @@ -49,15 +49,15 @@ "add-compat-overloads": "ts-node-script ../../scripts/build/create-overloads.ts -i ../database/dist/public.d.ts -o dist/database-compat/src/index.d.ts -a -r Database:types.FirebaseDatabase -r Query:types.Query -r DatabaseReference:types.Reference -r FirebaseApp:FirebaseAppCompat --moduleToEnhance @firebase/database" }, "dependencies": { - "@firebase/database": "1.1.1", - "@firebase/database-types": "1.0.17", + "@firebase/database": "1.1.2", + "@firebase/database-types": "1.0.18", "@firebase/logger": "0.5.0", - "@firebase/util": "1.14.0", - "@firebase/component": "0.7.1", + "@firebase/util": "1.15.0", + "@firebase/component": "0.7.2", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.9", + "@firebase/app-compat": "0.5.10", "typescript": "5.5.4" }, "repository": { diff --git a/packages/database-types/CHANGELOG.md b/packages/database-types/CHANGELOG.md index 18a6a3226a..4a22c0f0e5 100644 --- a/packages/database-types/CHANGELOG.md +++ b/packages/database-types/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/database-types +## 1.0.18 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + ## 1.0.17 ### Patch Changes diff --git a/packages/database-types/package.json b/packages/database-types/package.json index 967642d5c7..4e0bc17b05 100644 --- a/packages/database-types/package.json +++ b/packages/database-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database-types", - "version": "1.0.17", + "version": "1.0.18", "description": "@firebase/database Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -13,7 +13,7 @@ ], "dependencies": { "@firebase/app-types": "0.9.3", - "@firebase/util": "1.14.0" + "@firebase/util": "1.15.0" }, "repository": { "directory": "packages/database-types", diff --git a/packages/database/CHANGELOG.md b/packages/database/CHANGELOG.md index bef7ecefb3..b84061f3bd 100644 --- a/packages/database/CHANGELOG.md +++ b/packages/database/CHANGELOG.md @@ -1,5 +1,15 @@ # Unreleased +## 1.1.2 + +### Patch Changes + +- [`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752) [#9608](https://github.com/firebase/firebase-js-sdk/pull/9608) - Remove `updateEmulatorBanner()`. (No release note needed.) + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 1.1.1 ### Patch Changes diff --git a/packages/database/package.json b/packages/database/package.json index a3d2d98ed4..0cb83dbe84 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database", - "version": "1.1.1", + "version": "1.1.2", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -49,15 +49,15 @@ "peerDependencies": {}, "dependencies": { "@firebase/logger": "0.5.0", - "@firebase/util": "1.14.0", - "@firebase/component": "0.7.1", + "@firebase/util": "1.15.0", + "@firebase/component": "0.7.2", "@firebase/app-check-interop-types": "0.3.3", "@firebase/auth-interop-types": "0.2.4", "faye-websocket": "0.11.4", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/firebase/CHANGELOG.md b/packages/firebase/CHANGELOG.md index b941c52bc8..b55fed5117 100644 --- a/packages/firebase/CHANGELOG.md +++ b/packages/firebase/CHANGELOG.md @@ -1,5 +1,46 @@ # firebase +## 12.11.0 + +### Minor Changes + +- [`9d33dd6`](https://github.com/firebase/firebase-js-sdk/commit/9d33dd6434dfc70cf835d603c1da09d9663885ec) [#9614](https://github.com/firebase/firebase-js-sdk/pull/9614) - Add validateArgsWithOptions() to Data Connect (internal change, no need to add to public release notes). + +- [`843a8d7`](https://github.com/firebase/firebase-js-sdk/commit/843a8d7892beb27e6bb62bb6331fe03aef97c57e) [#9693](https://github.com/firebase/firebase-js-sdk/pull/9693) (fixes [#9625](https://github.com/firebase/firebase-js-sdk/issues/9625)) - Added `responseJsonSchema` to `GenerationConfig`. + +- [`78384d3`](https://github.com/firebase/firebase-js-sdk/commit/78384d32c5352bd25cdc3d12fc8f2f4b5d48a440) [#9492](https://github.com/firebase/firebase-js-sdk/pull/9492) - Add support for array expressions `arrayFirst`, `arrayFirstN`,`arrayLast`,`arrayLastN`,`arrayMinimum`,`arrayMinimumN`,`arrayMaximum`,`arrayMaximumN`,`arrayIndexOf`, `arrayLastIndexOf` and `arrayIndexOfAll` + +### Patch Changes + +- Updated dependencies [[`54ff05e`](https://github.com/firebase/firebase-js-sdk/commit/54ff05ef922016fee2e9e6f4b8aea30120170da7), [`9d33dd6`](https://github.com/firebase/firebase-js-sdk/commit/9d33dd6434dfc70cf835d603c1da09d9663885ec), [`843a8d7`](https://github.com/firebase/firebase-js-sdk/commit/843a8d7892beb27e6bb62bb6331fe03aef97c57e), [`a383770`](https://github.com/firebase/firebase-js-sdk/commit/a3837700877822acd1bad82431a051d64f479508), [`78384d3`](https://github.com/firebase/firebase-js-sdk/commit/78384d32c5352bd25cdc3d12fc8f2f4b5d48a440), [`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/app@0.14.10 + - @firebase/firestore@4.13.0 + - @firebase/data-connect@0.5.0 + - @firebase/ai@2.10.0 + - @firebase/functions@0.13.3 + - @firebase/database@1.1.2 + - @firebase/storage@0.14.2 + - @firebase/auth@1.12.2 + - @firebase/util@1.15.0 + - @firebase/analytics@0.10.21 + - @firebase/app-check@0.11.2 + - @firebase/app-compat@0.5.10 + - @firebase/installations@0.6.21 + - @firebase/messaging@0.12.25 + - @firebase/performance@0.7.11 + - @firebase/remote-config@0.8.2 + - @firebase/firestore-compat@0.4.7 + - @firebase/functions-compat@0.4.3 + - @firebase/database-compat@2.1.2 + - @firebase/storage-compat@0.4.2 + - @firebase/auth-compat@0.6.4 + - @firebase/analytics-compat@0.2.27 + - @firebase/app-check-compat@0.4.2 + - @firebase/installations-compat@0.2.21 + - @firebase/messaging-compat@0.2.25 + - @firebase/performance-compat@0.2.24 + - @firebase/remote-config-compat@0.2.23 + ## 12.10.0 ### Minor Changes diff --git a/packages/firebase/package.json b/packages/firebase/package.json index 30e7953033..f8be1a2bd9 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -1,6 +1,6 @@ { "name": "firebase", - "version": "12.10.0", + "version": "12.11.0", "description": "Firebase JavaScript library for web and Node.js", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -423,34 +423,34 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/ai": "2.9.0", - "@firebase/app": "0.14.9", - "@firebase/app-compat": "0.5.9", + "@firebase/ai": "2.10.0", + "@firebase/app": "0.14.10", + "@firebase/app-compat": "0.5.10", "@firebase/app-types": "0.9.3", - "@firebase/auth": "1.12.1", - "@firebase/auth-compat": "0.6.3", - "@firebase/data-connect": "0.4.0", - "@firebase/database": "1.1.1", - "@firebase/database-compat": "2.1.1", - "@firebase/firestore": "4.12.0", - "@firebase/firestore-compat": "0.4.6", - "@firebase/functions": "0.13.2", - "@firebase/functions-compat": "0.4.2", - "@firebase/installations": "0.6.20", - "@firebase/installations-compat": "0.2.20", - "@firebase/messaging": "0.12.24", - "@firebase/messaging-compat": "0.2.24", - "@firebase/storage": "0.14.1", - "@firebase/storage-compat": "0.4.1", - "@firebase/performance": "0.7.10", - "@firebase/performance-compat": "0.2.23", - "@firebase/remote-config": "0.8.1", - "@firebase/remote-config-compat": "0.2.22", - "@firebase/analytics": "0.10.20", - "@firebase/analytics-compat": "0.2.26", - "@firebase/app-check": "0.11.1", - "@firebase/app-check-compat": "0.4.1", - "@firebase/util": "1.14.0" + "@firebase/auth": "1.12.2", + "@firebase/auth-compat": "0.6.4", + "@firebase/data-connect": "0.5.0", + "@firebase/database": "1.1.2", + "@firebase/database-compat": "2.1.2", + "@firebase/firestore": "4.13.0", + "@firebase/firestore-compat": "0.4.7", + "@firebase/functions": "0.13.3", + "@firebase/functions-compat": "0.4.3", + "@firebase/installations": "0.6.21", + "@firebase/installations-compat": "0.2.21", + "@firebase/messaging": "0.12.25", + "@firebase/messaging-compat": "0.2.25", + "@firebase/storage": "0.14.2", + "@firebase/storage-compat": "0.4.2", + "@firebase/performance": "0.7.11", + "@firebase/performance-compat": "0.2.24", + "@firebase/remote-config": "0.8.2", + "@firebase/remote-config-compat": "0.2.23", + "@firebase/analytics": "0.10.21", + "@firebase/analytics-compat": "0.2.27", + "@firebase/app-check": "0.11.2", + "@firebase/app-check-compat": "0.4.2", + "@firebase/util": "1.15.0" }, "devDependencies": { "rollup": "2.79.2", diff --git a/packages/firestore-compat/CHANGELOG.md b/packages/firestore-compat/CHANGELOG.md index 87e4aac3b0..d65b76cdd9 100644 --- a/packages/firestore-compat/CHANGELOG.md +++ b/packages/firestore-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/firestore-compat +## 0.4.7 + +### Patch Changes + +- Updated dependencies [[`54ff05e`](https://github.com/firebase/firebase-js-sdk/commit/54ff05ef922016fee2e9e6f4b8aea30120170da7), [`a383770`](https://github.com/firebase/firebase-js-sdk/commit/a3837700877822acd1bad82431a051d64f479508), [`78384d3`](https://github.com/firebase/firebase-js-sdk/commit/78384d32c5352bd25cdc3d12fc8f2f4b5d48a440), [`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/firestore@4.13.0 + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 0.4.6 ### Patch Changes diff --git a/packages/firestore-compat/package.json b/packages/firestore-compat/package.json index bc7bd40355..8866dea9ee 100644 --- a/packages/firestore-compat/package.json +++ b/packages/firestore-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore-compat", - "version": "0.4.6", + "version": "0.4.7", "description": "The Cloud Firestore component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -46,14 +46,14 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/component": "0.7.1", - "@firebase/firestore": "4.12.0", - "@firebase/util": "1.14.0", + "@firebase/component": "0.7.2", + "@firebase/firestore": "4.13.0", + "@firebase/util": "1.15.0", "@firebase/firestore-types": "3.0.3", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.9", + "@firebase/app-compat": "0.5.10", "@types/eslint": "7.29.0", "rollup": "2.79.2", "rollup-plugin-sourcemaps": "0.6.3", diff --git a/packages/firestore/CHANGELOG.md b/packages/firestore/CHANGELOG.md index e1d1f14b1f..c2bbbeae06 100644 --- a/packages/firestore/CHANGELOG.md +++ b/packages/firestore/CHANGELOG.md @@ -1,5 +1,23 @@ # @firebase/firestore +## 4.13.0 + +### Minor Changes + +- [`78384d3`](https://github.com/firebase/firebase-js-sdk/commit/78384d32c5352bd25cdc3d12fc8f2f4b5d48a440) [#9492](https://github.com/firebase/firebase-js-sdk/pull/9492) - Add support for array expressions `arrayFirst`, `arrayFirstN`,`arrayLast`,`arrayLastN`,`arrayMinimum`,`arrayMinimumN`,`arrayMaximum`,`arrayMaximumN`,`arrayIndexOf`, `arrayLastIndexOf` and `arrayIndexOfAll` + +### Patch Changes + +- [`54ff05e`](https://github.com/firebase/firebase-js-sdk/commit/54ff05ef922016fee2e9e6f4b8aea30120170da7) [#9715](https://github.com/firebase/firebase-js-sdk/pull/9715) - **Beta API Breaking change**: Defer pipeline user data validation from initialization to `execute()`. This breaking change is allowed in a non-major release since the Firestore Pipelines API is currently in Public Preview. + +- [`a383770`](https://github.com/firebase/firebase-js-sdk/commit/a3837700877822acd1bad82431a051d64f479508) [#9622](https://github.com/firebase/firebase-js-sdk/pull/9622) - Fixed X is not a function issues observed in server side rendering APIs. + +- [`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752) [#9608](https://github.com/firebase/firebase-js-sdk/pull/9608) - Remove `updateEmulatorBanner()`. (No release note needed.) + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 4.12.0 ### Minor Changes diff --git a/packages/firestore/package.json b/packages/firestore/package.json index c8d69962e4..6812380ce1 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore", - "version": "4.12.0", + "version": "4.13.0", "engines": { "node": ">=20.0.0" }, @@ -133,9 +133,9 @@ "lite/pipelines/pipelines.d.ts" ], "dependencies": { - "@firebase/component": "0.7.1", + "@firebase/component": "0.7.2", "@firebase/logger": "0.5.0", - "@firebase/util": "1.14.0", + "@firebase/util": "1.15.0", "@firebase/webchannel-wrapper": "1.0.5", "@grpc/grpc-js": "~1.9.0", "@grpc/proto-loader": "^0.7.8", @@ -145,9 +145,9 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.9", - "@firebase/app-compat": "0.5.9", - "@firebase/auth": "1.12.1", + "@firebase/app": "0.14.10", + "@firebase/app-compat": "0.5.10", + "@firebase/auth": "1.12.2", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", "@types/eslint": "7.29.0", diff --git a/packages/functions-compat/CHANGELOG.md b/packages/functions-compat/CHANGELOG.md index d88ab9c0b5..363f1e201a 100644 --- a/packages/functions-compat/CHANGELOG.md +++ b/packages/functions-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/functions-compat +## 0.4.3 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/functions@0.13.3 + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 0.4.2 ### Patch Changes diff --git a/packages/functions-compat/package.json b/packages/functions-compat/package.json index dd3213c263..ae7b07b3f0 100644 --- a/packages/functions-compat/package.json +++ b/packages/functions-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/functions-compat", - "version": "0.4.2", + "version": "0.4.3", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -29,7 +29,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.9", + "@firebase/app-compat": "0.5.10", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", @@ -62,10 +62,10 @@ }, "typings": "dist/src/index.d.ts", "dependencies": { - "@firebase/component": "0.7.1", - "@firebase/functions": "0.13.2", + "@firebase/component": "0.7.2", + "@firebase/functions": "0.13.3", "@firebase/functions-types": "0.6.3", - "@firebase/util": "1.14.0", + "@firebase/util": "1.15.0", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/functions/CHANGELOG.md b/packages/functions/CHANGELOG.md index 1fbc6ded0a..6846f19075 100644 --- a/packages/functions/CHANGELOG.md +++ b/packages/functions/CHANGELOG.md @@ -1,5 +1,15 @@ # @firebase/functions +## 0.13.3 + +### Patch Changes + +- [`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752) [#9608](https://github.com/firebase/firebase-js-sdk/pull/9608) - Remove `updateEmulatorBanner()`. (No release note needed.) + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 0.13.2 ### Patch Changes diff --git a/packages/functions/package.json b/packages/functions/package.json index 479deeb3de..144f9e901b 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/functions", - "version": "0.13.2", + "version": "0.13.3", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -49,7 +49,7 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", @@ -65,11 +65,11 @@ }, "typings": "dist/src/index.d.ts", "dependencies": { - "@firebase/component": "0.7.1", + "@firebase/component": "0.7.2", "@firebase/messaging-interop-types": "0.2.3", "@firebase/auth-interop-types": "0.2.4", "@firebase/app-check-interop-types": "0.3.3", - "@firebase/util": "1.14.0", + "@firebase/util": "1.15.0", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/installations-compat/CHANGELOG.md b/packages/installations-compat/CHANGELOG.md index 387599ea01..966bc638e3 100644 --- a/packages/installations-compat/CHANGELOG.md +++ b/packages/installations-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/installations-compat +## 0.2.21 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/installations@0.6.21 + - @firebase/component@0.7.2 + ## 0.2.20 ### Patch Changes diff --git a/packages/installations-compat/package.json b/packages/installations-compat/package.json index f56c83c8ce..1691e4b915 100644 --- a/packages/installations-compat/package.json +++ b/packages/installations-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/installations-compat", - "version": "0.2.20", + "version": "0.2.21", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", "module": "dist/esm/index.esm.js", @@ -44,7 +44,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app-compat": "0.5.9", + "@firebase/app-compat": "0.5.10", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", @@ -57,10 +57,10 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.20", + "@firebase/installations": "0.6.21", "@firebase/installations-types": "0.5.3", - "@firebase/util": "1.14.0", - "@firebase/component": "0.7.1", + "@firebase/util": "1.15.0", + "@firebase/component": "0.7.2", "tslib": "^2.1.0" } } diff --git a/packages/installations/CHANGELOG.md b/packages/installations/CHANGELOG.md index f18c606587..77efe69228 100644 --- a/packages/installations/CHANGELOG.md +++ b/packages/installations/CHANGELOG.md @@ -1,5 +1,13 @@ # @firebase/installations +## 0.6.21 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 0.6.20 ### Patch Changes diff --git a/packages/installations/package.json b/packages/installations/package.json index 4658439941..75a37e6b99 100644 --- a/packages/installations/package.json +++ b/packages/installations/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/installations", - "version": "0.6.20", + "version": "0.6.21", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", "module": "dist/esm/index.esm.js", @@ -49,7 +49,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", @@ -62,8 +62,8 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/util": "1.14.0", - "@firebase/component": "0.7.1", + "@firebase/util": "1.15.0", + "@firebase/component": "0.7.2", "idb": "7.1.1", "tslib": "^2.1.0" } diff --git a/packages/messaging-compat/CHANGELOG.md b/packages/messaging-compat/CHANGELOG.md index 2059809d5c..f41ff0b934 100644 --- a/packages/messaging-compat/CHANGELOG.md +++ b/packages/messaging-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/messaging-compat +## 0.2.25 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/messaging@0.12.25 + - @firebase/component@0.7.2 + ## 0.2.24 ### Patch Changes diff --git a/packages/messaging-compat/package.json b/packages/messaging-compat/package.json index 622379d8c0..553d72d493 100644 --- a/packages/messaging-compat/package.json +++ b/packages/messaging-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/messaging-compat", - "version": "0.2.24", + "version": "0.2.25", "license": "Apache-2.0", "description": "", "author": "Firebase (https://firebase.google.com/)", @@ -38,13 +38,13 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/messaging": "0.12.24", - "@firebase/component": "0.7.1", - "@firebase/util": "1.14.0", + "@firebase/messaging": "0.12.25", + "@firebase/component": "0.7.2", + "@firebase/util": "1.15.0", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.9", + "@firebase/app-compat": "0.5.10", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", "ts-essentials": "9.4.2", diff --git a/packages/messaging/CHANGELOG.md b/packages/messaging/CHANGELOG.md index 4def7d21c4..9aa0717d5d 100644 --- a/packages/messaging/CHANGELOG.md +++ b/packages/messaging/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/messaging +## 0.12.25 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/installations@0.6.21 + - @firebase/component@0.7.2 + ## 0.12.24 ### Patch Changes diff --git a/packages/messaging/package.json b/packages/messaging/package.json index 79823aac17..444067db84 100644 --- a/packages/messaging/package.json +++ b/packages/messaging/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/messaging", - "version": "0.12.24", + "version": "0.12.25", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -52,15 +52,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.20", + "@firebase/installations": "0.6.21", "@firebase/messaging-interop-types": "0.2.3", - "@firebase/util": "1.14.0", - "@firebase/component": "0.7.1", + "@firebase/util": "1.15.0", + "@firebase/component": "0.7.2", "idb": "7.1.1", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/performance-compat/CHANGELOG.md b/packages/performance-compat/CHANGELOG.md index 9b5392d771..be7f43651c 100644 --- a/packages/performance-compat/CHANGELOG.md +++ b/packages/performance-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/performance-compat +## 0.2.24 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/performance@0.7.11 + - @firebase/component@0.7.2 + ## 0.2.23 ### Patch Changes diff --git a/packages/performance-compat/package.json b/packages/performance-compat/package.json index d7ff76409b..af5b6fde6b 100644 --- a/packages/performance-compat/package.json +++ b/packages/performance-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/performance-compat", - "version": "0.2.23", + "version": "0.2.24", "description": "The compatibility package of Firebase Performance", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -38,11 +38,11 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/performance": "0.7.10", + "@firebase/performance": "0.7.11", "@firebase/performance-types": "0.2.3", - "@firebase/util": "1.14.0", + "@firebase/util": "1.15.0", "@firebase/logger": "0.5.0", - "@firebase/component": "0.7.1", + "@firebase/component": "0.7.2", "tslib": "^2.1.0" }, "devDependencies": { @@ -51,7 +51,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.9" + "@firebase/app-compat": "0.5.10" }, "repository": { "directory": "packages/performance-compat", diff --git a/packages/performance/CHANGELOG.md b/packages/performance/CHANGELOG.md index 5adf2d4037..ad80837bf8 100644 --- a/packages/performance/CHANGELOG.md +++ b/packages/performance/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/performance +## 0.7.11 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/installations@0.6.21 + - @firebase/component@0.7.2 + ## 0.7.10 ### Patch Changes diff --git a/packages/performance/package.json b/packages/performance/package.json index 3c29a2a9bb..e07b7f645b 100644 --- a/packages/performance/package.json +++ b/packages/performance/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/performance", - "version": "0.7.10", + "version": "0.7.11", "description": "Firebase performance for web", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -39,15 +39,15 @@ }, "dependencies": { "@firebase/logger": "0.5.0", - "@firebase/installations": "0.6.20", - "@firebase/util": "1.14.0", - "@firebase/component": "0.7.1", + "@firebase/installations": "0.6.21", + "@firebase/util": "1.15.0", + "@firebase/component": "0.7.2", "tslib": "^2.1.0", "web-vitals": "^4.2.4" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/remote-config-compat/CHANGELOG.md b/packages/remote-config-compat/CHANGELOG.md index 424897ed3f..cd1dcbbbc1 100644 --- a/packages/remote-config-compat/CHANGELOG.md +++ b/packages/remote-config-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/remote-config-compat +## 0.2.23 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/remote-config@0.8.2 + - @firebase/component@0.7.2 + ## 0.2.22 ### Patch Changes diff --git a/packages/remote-config-compat/package.json b/packages/remote-config-compat/package.json index ed628b20fe..4d526e1098 100644 --- a/packages/remote-config-compat/package.json +++ b/packages/remote-config-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/remote-config-compat", - "version": "0.2.22", + "version": "0.2.23", "description": "The compatibility package of Remote Config", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,11 +37,11 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/remote-config": "0.8.1", + "@firebase/remote-config": "0.8.2", "@firebase/remote-config-types": "0.5.0", - "@firebase/util": "1.14.0", + "@firebase/util": "1.15.0", "@firebase/logger": "0.5.0", - "@firebase/component": "0.7.1", + "@firebase/component": "0.7.2", "tslib": "^2.1.0" }, "devDependencies": { @@ -50,7 +50,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.9" + "@firebase/app-compat": "0.5.10" }, "repository": { "directory": "packages/remote-config-compat", diff --git a/packages/remote-config/CHANGELOG.md b/packages/remote-config/CHANGELOG.md index d7e9fe23d3..a6305dae75 100644 --- a/packages/remote-config/CHANGELOG.md +++ b/packages/remote-config/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/remote-config +## 0.8.2 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/installations@0.6.21 + - @firebase/component@0.7.2 + ## 0.8.1 ### Patch Changes diff --git a/packages/remote-config/package.json b/packages/remote-config/package.json index da09d5165f..6fb62ed71e 100644 --- a/packages/remote-config/package.json +++ b/packages/remote-config/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/remote-config", - "version": "0.8.1", + "version": "0.8.2", "description": "The Remote Config package of the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -40,15 +40,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.20", + "@firebase/installations": "0.6.21", "@firebase/logger": "0.5.0", - "@firebase/util": "1.14.0", - "@firebase/component": "0.7.1", + "@firebase/util": "1.15.0", + "@firebase/component": "0.7.2", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/storage-compat/CHANGELOG.md b/packages/storage-compat/CHANGELOG.md index 1733f49979..e6d8a43ad4 100644 --- a/packages/storage-compat/CHANGELOG.md +++ b/packages/storage-compat/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/storage-compat +## 0.4.2 + +### Patch Changes + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/storage@0.14.2 + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 0.4.1 ### Patch Changes diff --git a/packages/storage-compat/package.json b/packages/storage-compat/package.json index 4d80898948..60ce914b8c 100644 --- a/packages/storage-compat/package.json +++ b/packages/storage-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/storage-compat", - "version": "0.4.1", + "version": "0.4.2", "description": "The Firebase Firestore compatibility package", "author": "Firebase (https://firebase.google.com/)", "main": "./dist/index.cjs.js", @@ -37,15 +37,15 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/storage": "0.14.1", + "@firebase/storage": "0.14.2", "@firebase/storage-types": "0.8.3", - "@firebase/util": "1.14.0", - "@firebase/component": "0.7.1", + "@firebase/util": "1.15.0", + "@firebase/component": "0.7.2", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.9", - "@firebase/auth-compat": "0.6.3", + "@firebase/app-compat": "0.5.10", + "@firebase/auth-compat": "0.6.4", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/storage/CHANGELOG.md b/packages/storage/CHANGELOG.md index a0c2376aea..00619174a3 100644 --- a/packages/storage/CHANGELOG.md +++ b/packages/storage/CHANGELOG.md @@ -1,5 +1,15 @@ #Unreleased +## 0.14.2 + +### Patch Changes + +- [`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752) [#9608](https://github.com/firebase/firebase-js-sdk/pull/9608) - Remove `updateEmulatorBanner()`. (No release note needed.) + +- Updated dependencies [[`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752)]: + - @firebase/util@1.15.0 + - @firebase/component@0.7.2 + ## 0.14.1 ### Patch Changes diff --git a/packages/storage/package.json b/packages/storage/package.json index 379f804fe7..0631f0e860 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/storage", - "version": "0.14.1", + "version": "0.14.2", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -46,16 +46,16 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/util": "1.14.0", - "@firebase/component": "0.7.1", + "@firebase/util": "1.15.0", + "@firebase/component": "0.7.2", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.9", - "@firebase/auth": "1.12.1", + "@firebase/app": "0.14.10", + "@firebase/auth": "1.12.2", "rollup": "2.79.2", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", diff --git a/packages/template/package.json b/packages/template/package.json index d1764b4350..f0512848fa 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -48,7 +48,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/util/CHANGELOG.md b/packages/util/CHANGELOG.md index 48a4897bd2..8d7468a327 100644 --- a/packages/util/CHANGELOG.md +++ b/packages/util/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/util +## 1.15.0 + +### Minor Changes + +- [`2f7f426`](https://github.com/firebase/firebase-js-sdk/commit/2f7f426dec37efd75bad8dcc87cdd769ed4f7752) [#9608](https://github.com/firebase/firebase-js-sdk/pull/9608) - Remove `updateEmulatorBanner()`. (No release note needed.) + ## 1.14.0 ### Minor Changes diff --git a/packages/util/package.json b/packages/util/package.json index a3982578bb..4ac6664275 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/util", - "version": "1.14.0", + "version": "1.15.0", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index dc2823cdea..0c246b32be 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -20,7 +20,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/util": "1.14.0", + "@firebase/util": "1.15.0", "child-process-promise": "2.2.1", "glob": "7.2.3", "tmp": "0.2.3", @@ -40,7 +40,7 @@ "yargs": "17.7.2" }, "devDependencies": { - "@firebase/app": "0.14.9", + "@firebase/app": "0.14.10", "@firebase/logger": "0.5.0", "@types/webpack": "5.28.5" }, From 403c6de94f2e7eeda62cbe1c4b631f52df3d7f8e Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Fri, 20 Mar 2026 10:56:23 -0400 Subject: [PATCH 105/174] chore(ci): E2E cloud functions, add continue-on-error: true (#9733) Current project policy prohibits the update of our test cloud function. Ignore this failure for now until we can get an exception. This shouldn't be a problem since the cloud function signature / behavior hasn't changed recently. --- .github/workflows/e2e-test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 7f7c245f79..5fc9c710ec 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -67,6 +67,7 @@ jobs: env: GITHUB_EVENT_CLIENT_PAYLOAD_VERSIONORTAG: ${{ github.event.client_payload.versionOrTag }} - name: Deploy "callTest" cloud function + continue-on-error: true run: | pushd functions npm install From ba0bc39bb70d087e28755c194eeedefcb1e890ec Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 20 Mar 2026 13:05:54 -0700 Subject: [PATCH 106/174] Update the version of firebase to use (#9737) --- e2e/data-connect/package.json | 2 +- e2e/data-connect/yarn.lock | 656 +++++++++++++++++----------------- 2 files changed, 323 insertions(+), 335 deletions(-) diff --git a/e2e/data-connect/package.json b/e2e/data-connect/package.json index d9d1f234ab..277f151acf 100644 --- a/e2e/data-connect/package.json +++ b/e2e/data-connect/package.json @@ -16,6 +16,6 @@ "typescript": "5.5.4" }, "dependencies": { - "firebase": "11.8.1" + "firebase": "latest" } } diff --git a/e2e/data-connect/yarn.lock b/e2e/data-connect/yarn.lock index d8d5a981fe..d1ba5c4c26 100644 --- a/e2e/data-connect/yarn.lock +++ b/e2e/data-connect/yarn.lock @@ -4,405 +4,405 @@ "@cspotcode/source-map-support@^0.8.0": version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@firebase/ai@1.3.0": - version "1.3.0" - resolved "https://registry.npmjs.org/@firebase/ai/-/ai-1.3.0.tgz#66b8edaa32d8e5d46c99be0efc337cbf034dffb7" - integrity sha512-qBxJTtl9hpgZr050kVFTRADX6I0Ss6mEQyp/JEkBgKwwxixKnaRNqEDGFba4OKNL7K8E4Y7LlA/ZW6L8aCKH4A== +"@firebase/ai@2.10.0": + version "2.10.0" + resolved "https://registry.npmjs.org/@firebase/ai/-/ai-2.10.0.tgz" + integrity sha512-1lI6HomyoO/8RSJb6ItyHLpHnB2z27m5F4aX/Vpi1nhwWoxdNjkq+6UQOykHyCE0KairojOE5qQ20i1tnF0nNA== dependencies: "@firebase/app-check-interop-types" "0.3.3" - "@firebase/component" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" -"@firebase/analytics-compat@0.2.22": - version "0.2.22" - resolved "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.22.tgz#5ec880cf719642c233742ad805ba95e5b4dad999" - integrity sha512-VogWHgwkdYhjWKh8O1XU04uPrRaiDihkWvE/EMMmtWtaUtVALnpLnUurc3QtSKdPnvTz5uaIGKlW84DGtSPFbw== +"@firebase/analytics-compat@0.2.27": + version "0.2.27" + resolved "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.27.tgz" + integrity sha512-ZObpYpAxL6JfgH7GnvlDD0sbzGZ0o4nijV8skatV9ZX49hJtCYbFqaEcPYptT94rgX1KUoKEderC7/fa7hybtw== dependencies: - "@firebase/analytics" "0.10.16" + "@firebase/analytics" "0.10.21" "@firebase/analytics-types" "0.8.3" - "@firebase/component" "0.6.17" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/util" "1.15.0" tslib "^2.1.0" "@firebase/analytics-types@0.8.3": version "0.8.3" - resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.8.3.tgz#d08cd39a6209693ca2039ba7a81570dfa6c1518f" + resolved "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz" integrity sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg== -"@firebase/analytics@0.10.16": - version "0.10.16" - resolved "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.16.tgz#516f211465060008538fed46c7f78f0ea14dd549" - integrity sha512-cMtp19He7Fd6uaj/nDEul+8JwvJsN8aRSJyuA1QN3QrKvfDDp+efjVurJO61sJpkVftw9O9nNMdhFbRcTmTfRQ== +"@firebase/analytics@0.10.21": + version "0.10.21" + resolved "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.21.tgz" + integrity sha512-j2y2q65BlgLGB5Pwjhv/Jopw2X/TBTzvAtI5z/DSp56U4wBj7LfhBfzbdCtFPges+Wz0g55GdoawXibOH5jGng== dependencies: - "@firebase/component" "0.6.17" - "@firebase/installations" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/installations" "0.6.21" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" -"@firebase/app-check-compat@0.3.25": - version "0.3.25" - resolved "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.25.tgz#03d1941dba78626bdacf544f9d1d48b451dbb49c" - integrity sha512-3zrsPZWAKfV7DVC20T2dgfjzjtQnSJS65OfMOiddMUtJL1S5i0nAZKsdX0bOEvvrd0SBIL8jYnfpfDeQRnhV3w== +"@firebase/app-check-compat@0.4.2": + version "0.4.2" + resolved "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.4.2.tgz" + integrity sha512-M91NhxqbSkI0ChkJWy69blC+rPr6HEgaeRllddSaU1pQ/7IiegeCQM9pPDIgvWnwnBSzKhUHpe6ro/jhJ+cvzw== dependencies: - "@firebase/app-check" "0.10.0" + "@firebase/app-check" "0.11.2" "@firebase/app-check-types" "0.5.3" - "@firebase/component" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" "@firebase/app-check-interop-types@0.3.3": version "0.3.3" - resolved "https://registry.yarnpkg.com/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz#ed9c4a4f48d1395ef378f007476db3940aa5351a" + resolved "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz" integrity sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A== "@firebase/app-check-types@0.5.3": version "0.5.3" - resolved "https://registry.yarnpkg.com/@firebase/app-check-types/-/app-check-types-0.5.3.tgz#38ba954acf4bffe451581a32fffa20337f11d8e5" + resolved "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz" integrity sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng== -"@firebase/app-check@0.10.0": - version "0.10.0" - resolved "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.10.0.tgz#dc833ead2b31930eee13b5c9eb028091c630d21b" - integrity sha512-AZlRlVWKcu8BH4Yf8B5EI8sOi2UNGTS8oMuthV45tbt6OVUTSQwFPIEboZzhNJNKY+fPsg7hH8vixUWFZ3lrhw== +"@firebase/app-check@0.11.2": + version "0.11.2" + resolved "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.11.2.tgz" + integrity sha512-jcXQVMHAQ5AEKzVD5C7s5fmAYeFOuN6lAJeNTgZK2B9aLnofWaJt8u1A8Idm8gpsBBYSaY3cVyeH5SWMOVPBLQ== dependencies: - "@firebase/component" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" -"@firebase/app-compat@0.4.0": - version "0.4.0" - resolved "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.4.0.tgz#4c908115b2a68756e4944ee8f9bc7042d8715f92" - integrity sha512-LjLUrzbUgTa/sCtPoLKT2C7KShvLVHS3crnU1Du02YxnGVLE0CUBGY/NxgfR/Zg84mEbj1q08/dgesojxjn0dA== +"@firebase/app-compat@0.5.10", "@firebase/app-compat@0.x": + version "0.5.10" + resolved "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.10.tgz" + integrity sha512-tFmBuZL0/v1h6eyKRgWI58ucft6dEJmAi9nhPUXoAW4ZbPSTlnsh31AuEwUoRTz+wwRk9gmgss9GZV05ZM9Kug== dependencies: - "@firebase/app" "0.13.0" - "@firebase/component" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/app" "0.14.10" + "@firebase/component" "0.7.2" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" -"@firebase/app-types@0.9.3": +"@firebase/app-types@0.9.3", "@firebase/app-types@0.x": version "0.9.3" - resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.9.3.tgz#8408219eae9b1fb74f86c24e7150a148460414ad" + resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz" integrity sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw== -"@firebase/app@0.13.0": - version "0.13.0" - resolved "https://registry.npmjs.org/@firebase/app/-/app-0.13.0.tgz#ef67c7e5dc3f47efb430157f9de969a67abd53a7" - integrity sha512-Vj3MST245nq+V5UmmfEkB3isIgPouyUr8yGJlFeL9Trg/umG5ogAvrjAYvQ8gV7daKDoQSRnJKWI2JFpQqRsuQ== +"@firebase/app@0.14.10", "@firebase/app@0.x": + version "0.14.10" + resolved "https://registry.npmjs.org/@firebase/app/-/app-0.14.10.tgz" + integrity sha512-PlPhdtjgWUra+LImQTnXOUqUa/jcufZhizdR93ZjlQSS3ahCtDTG6pJw7j0OwFal18DQjICXfeVNsUUrcNisfA== dependencies: - "@firebase/component" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" idb "7.1.1" tslib "^2.1.0" -"@firebase/auth-compat@0.5.26": - version "0.5.26" - resolved "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.26.tgz#ff795ad7dd43077dc603a8576bf92e756c6a2064" - integrity sha512-4baB7tR0KukyGzrlD25aeO4t0ChLifwvDQXTBiVJE9WWwJEOjkZpHmoU9Iww0+Vdalsq4sZ3abp6YTNjHyB1dA== +"@firebase/auth-compat@0.6.4": + version "0.6.4" + resolved "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.6.4.tgz" + integrity sha512-2pj8m/hnqXvMLfC0Mk+fORVTM5DQPkS6l8JpMgtoAWGVgCmYnoWdFMaNWtKbmCxBEyvMA3FlnCJyzrUSMWTfuA== dependencies: - "@firebase/auth" "1.10.6" + "@firebase/auth" "1.12.2" "@firebase/auth-types" "0.13.0" - "@firebase/component" "0.6.17" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/util" "1.15.0" tslib "^2.1.0" "@firebase/auth-interop-types@0.2.4": version "0.2.4" - resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz#176a08686b0685596ff03d7879b7e4115af53de0" + resolved "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz" integrity sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA== "@firebase/auth-types@0.13.0": version "0.13.0" - resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.13.0.tgz#ae6e0015e3bd4bfe18edd0942b48a0a118a098d9" + resolved "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.13.0.tgz" integrity sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg== -"@firebase/auth@1.10.6": - version "1.10.6" - resolved "https://registry.npmjs.org/@firebase/auth/-/auth-1.10.6.tgz#2403e92e382034367f7fefd6715f992e061c3e59" - integrity sha512-cFbo2FymQltog4atI9cKTO6CxKxS0dOMXslTQrlNZRH7qhDG44/d7QeI6GXLweFZtrnlecf52ESnNz1DU6ek8w== +"@firebase/auth@1.12.2": + version "1.12.2" + resolved "https://registry.npmjs.org/@firebase/auth/-/auth-1.12.2.tgz" + integrity sha512-CZJL8V10Vzibs+pDTXdQF+hot1IigIoqF4a4lA/qr5Deo1srcefiyIfgg28B67Lk7IxZhwfJMuI+1bu2xBmV0A== dependencies: - "@firebase/component" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" -"@firebase/component@0.6.17": - version "0.6.17" - resolved "https://registry.npmjs.org/@firebase/component/-/component-0.6.17.tgz#6cef28dbe6de80ce393f97147bf3f1ea0a5453ec" - integrity sha512-M6DOg7OySrKEFS8kxA3MU5/xc37fiOpKPMz6cTsMUcsuKB6CiZxxNAvgFta8HGRgEpZbi8WjGIj6Uf+TpOhyzg== +"@firebase/component@0.7.2": + version "0.7.2" + resolved "https://registry.npmjs.org/@firebase/component/-/component-0.7.2.tgz" + integrity sha512-iyVDGc6Vjx7Rm0cAdccLH/NG6fADsgJak/XW9IA2lPf8AjIlsemOpFGKczYyPHxm4rnKdR8z6sK4+KEC7NwmEg== dependencies: - "@firebase/util" "1.12.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" -"@firebase/data-connect@0.3.9": - version "0.3.9" - resolved "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.3.9.tgz#9fe2f30d73c4013367b8ddd7ad57387d0438dce1" - integrity sha512-B5tGEh5uQrQeH0i7RvlU8kbZrKOJUmoyxVIX4zLA8qQJIN6A7D+kfBlGXtSwbPdrvyaejcRPcbOtqsDQ9HPJKw== +"@firebase/data-connect@0.5.0": + version "0.5.0" + resolved "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.5.0.tgz" + integrity sha512-G3GYHpWNJJ95502RQLApzw0jaG3pScHl+J/2MdxIuB51xtHnkRL6KvIAP3fFF1drUewWJHOnDA1U+q4Evf3KSw== dependencies: "@firebase/auth-interop-types" "0.2.4" - "@firebase/component" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" -"@firebase/database-compat@2.0.10": - version "2.0.10" - resolved "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.10.tgz#5cfe487b5fdb68752ded5ad17dabd99e763ba152" - integrity sha512-3sjl6oGaDDYJw/Ny0E5bO6v+KM3KoD4Qo/sAfHGdRFmcJ4QnfxOX9RbG9+ce/evI3m64mkPr24LlmTDduqMpog== +"@firebase/database-compat@2.1.2": + version "2.1.2" + resolved "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.1.2.tgz" + integrity sha512-j4A6IhVZbgxAzT6gJJC2PfOxYCK9SrDrUO7nTM4EscTYtKkAkzsbKoCnDdjFapQfnsncvPWjqVTr/0PffUwg3g== dependencies: - "@firebase/component" "0.6.17" - "@firebase/database" "1.0.19" - "@firebase/database-types" "1.0.14" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/database" "1.1.2" + "@firebase/database-types" "1.0.18" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" -"@firebase/database-types@1.0.14": - version "1.0.14" - resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.14.tgz#454a33f55da46c243302d6b420b8b319ab80c6ce" - integrity sha512-8a0Q1GrxM0akgF0RiQHliinhmZd+UQPrxEmUv7MnQBYfVFiLtKOgs3g6ghRt/WEGJHyQNslZ+0PocIwNfoDwKw== +"@firebase/database-types@1.0.18": + version "1.0.18" + resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.18.tgz" + integrity sha512-yOY8IC2go9lfbVDMiy2ATun4EB2AFwocPaQADwMN/RHRUAZSM4rlAV7PGbWPSG/YhkJ2A9xQAiAENgSua9G5Fg== dependencies: "@firebase/app-types" "0.9.3" - "@firebase/util" "1.12.0" + "@firebase/util" "1.15.0" -"@firebase/database@1.0.19": - version "1.0.19" - resolved "https://registry.npmjs.org/@firebase/database/-/database-1.0.19.tgz#2d52e731407431bdc1581990d99b533784700fc6" - integrity sha512-khE+MIYK+XlIndVn/7mAQ9F1fwG5JHrGKaG72hblCC6JAlUBDd3SirICH6SMCf2PQ0iYkruTECth+cRhauacyQ== +"@firebase/database@1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@firebase/database/-/database-1.1.2.tgz" + integrity sha512-lP96CMjMPy/+d1d9qaaHjHHdzdwvEOuyyLq9ehX89e2XMKwS1jHNzYBO+42bdSumuj5ukPbmnFtViZu8YOMT+w== dependencies: "@firebase/app-check-interop-types" "0.3.3" "@firebase/auth-interop-types" "0.2.4" - "@firebase/component" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" faye-websocket "0.11.4" tslib "^2.1.0" -"@firebase/firestore-compat@0.3.51": - version "0.3.51" - resolved "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.51.tgz#46ecebe9de16b60febf27d5014c9f21298064703" - integrity sha512-E5iubPhS6aAM7oSsHMx/FGBwfA2nbEHaK/hCs+MD3l3N7rHKnq4SYCGmVu/AraSJaMndZR1I37N9A/BH7aCq5A== +"@firebase/firestore-compat@0.4.7": + version "0.4.7" + resolved "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.4.7.tgz" + integrity sha512-Et4XxtGnjp0Q9tmaEMETnY5GHJ8gQ9+RN6sSTT4ETWKmym2d6gIjarw0rCQcx+7BrWVYLEIOAXSXysl0b3xnUA== dependencies: - "@firebase/component" "0.6.17" - "@firebase/firestore" "4.7.16" + "@firebase/component" "0.7.2" + "@firebase/firestore" "4.13.0" "@firebase/firestore-types" "3.0.3" - "@firebase/util" "1.12.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" "@firebase/firestore-types@3.0.3": version "3.0.3" - resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-3.0.3.tgz#7d0c3dd8850c0193d8f5ee0cc8f11961407742c1" + resolved "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz" integrity sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q== -"@firebase/firestore@4.7.16": - version "4.7.16" - resolved "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.16.tgz#9807d3355965406da106a098ce15d9950585ac51" - integrity sha512-5OpvlwYVUTLEnqewOlXmtIpH8t2ISlZHDW0NDbKROM2D0ATMqFkMHdvl+/wz9zOAcb8GMQYlhCihOnVAliUbpQ== +"@firebase/firestore@4.13.0": + version "4.13.0" + resolved "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.13.0.tgz" + integrity sha512-7i4cVNJXTMim7/P7UsNim0DwyLPk4QQ3y1oSNzv4l0ykJOKYCiFMOuEeUxUYvrReXDJxWHrT/4XMeVQm+13rRw== dependencies: - "@firebase/component" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" - "@firebase/webchannel-wrapper" "1.0.3" + "@firebase/component" "0.7.2" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" + "@firebase/webchannel-wrapper" "1.0.5" "@grpc/grpc-js" "~1.9.0" "@grpc/proto-loader" "^0.7.8" tslib "^2.1.0" -"@firebase/functions-compat@0.3.25": - version "0.3.25" - resolved "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.25.tgz#9022df60d7471c7111766789f05991966ab692f0" - integrity sha512-V0JKUw5W/7aznXf9BQ8LIYHCX6zVCM8Hdw7XUQ/LU1Y9TVP8WKRCnPB/qdPJ0xGjWWn7fhtwIYbgEw/syH4yTQ== +"@firebase/functions-compat@0.4.3": + version "0.4.3" + resolved "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.4.3.tgz" + integrity sha512-BxkEwWgx1of0tKaao/r2VR6WBLk/RAiyztatiONPrPE8gkitFkOnOCxf8i9cUyA5hX5RGt5H30uNn25Q6QNEmQ== dependencies: - "@firebase/component" "0.6.17" - "@firebase/functions" "0.12.8" + "@firebase/component" "0.7.2" + "@firebase/functions" "0.13.3" "@firebase/functions-types" "0.6.3" - "@firebase/util" "1.12.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" "@firebase/functions-types@0.6.3": version "0.6.3" - resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.6.3.tgz#f5faf770248b13f45d256f614230da6a11bfb654" + resolved "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz" integrity sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg== -"@firebase/functions@0.12.8": - version "0.12.8" - resolved "https://registry.npmjs.org/@firebase/functions/-/functions-0.12.8.tgz#c2e42b4ba82746142c9fe1e120c3f71f0464aa3d" - integrity sha512-p+ft6dQW0CJ3BLLxeDb5Hwk9ARw01kHTZjLqiUdPRzycR6w7Z75ThkegNmL6gCss3S0JEpldgvehgZ3kHybVhA== +"@firebase/functions@0.13.3": + version "0.13.3" + resolved "https://registry.npmjs.org/@firebase/functions/-/functions-0.13.3.tgz" + integrity sha512-csO7ckK3SSs+NUZW1nms9EK7ckHe/1QOjiP8uAkCYa7ND18s44vjE9g3KxEeIUpyEPqZaX1EhJuFyZjHigAcYw== dependencies: "@firebase/app-check-interop-types" "0.3.3" "@firebase/auth-interop-types" "0.2.4" - "@firebase/component" "0.6.17" + "@firebase/component" "0.7.2" "@firebase/messaging-interop-types" "0.2.3" - "@firebase/util" "1.12.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" -"@firebase/installations-compat@0.2.17": - version "0.2.17" - resolved "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.17.tgz#5d61fb652658432e43ca82b8f91a17d5d21a459b" - integrity sha512-J7afeCXB7yq25FrrJAgbx8mn1nG1lZEubOLvYgG7ZHvyoOCK00sis5rj7TgDrLYJgdj/SJiGaO1BD3BAp55TeA== +"@firebase/installations-compat@0.2.21": + version "0.2.21" + resolved "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.21.tgz" + integrity sha512-zahIUkaVKbR8zmTeBHkdfaVl6JGWlhVoSjF7CVH33nFqD3SlPEpEEegn2GNT5iAfsVdtlCyJJ9GW4YKjq+RJKQ== dependencies: - "@firebase/component" "0.6.17" - "@firebase/installations" "0.6.17" + "@firebase/component" "0.7.2" + "@firebase/installations" "0.6.21" "@firebase/installations-types" "0.5.3" - "@firebase/util" "1.12.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" "@firebase/installations-types@0.5.3": version "0.5.3" - resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.5.3.tgz#cac8a14dd49f09174da9df8ae453f9b359c3ef2f" + resolved "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz" integrity sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA== -"@firebase/installations@0.6.17": - version "0.6.17" - resolved "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.17.tgz#f184e49fcf3053ba25015b0509d9de28db99db77" - integrity sha512-zfhqCNJZRe12KyADtRrtOj+SeSbD1H/K8J24oQAJVv/u02eQajEGlhZtcx9Qk7vhGWF5z9dvIygVDYqLL4o1XQ== +"@firebase/installations@0.6.21": + version "0.6.21" + resolved "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.21.tgz" + integrity sha512-xGFGTeICJZ5vhrmmDukeczIcFULFXybojML2+QSDFoKj5A7zbGN7KzFGSKNhDkIxpjzsYG9IleJyUebuAcmqWA== dependencies: - "@firebase/component" "0.6.17" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/util" "1.15.0" idb "7.1.1" tslib "^2.1.0" -"@firebase/logger@0.4.4": - version "0.4.4" - resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.4.4.tgz#29e8379d20fd1149349a195ee6deee4573a86f48" - integrity sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g== +"@firebase/logger@0.5.0": + version "0.5.0" + resolved "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz" + integrity sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g== dependencies: tslib "^2.1.0" -"@firebase/messaging-compat@0.2.21": - version "0.2.21" - resolved "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.21.tgz#8d4c5b9557ed9890a774fba2ea7e5459860a901b" - integrity sha512-1yMne+4BGLbHbtyu/VyXWcLiefUE1+K3ZGfVTyKM4BH4ZwDFRGoWUGhhx+tKRX4Tu9z7+8JN67SjnwacyNWK5g== +"@firebase/messaging-compat@0.2.25": + version "0.2.25" + resolved "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.25.tgz" + integrity sha512-eoOQqGLtRlseTdiemTN44LlHZpltK5gnhq8XVUuLgtIOG+odtDzrz2UoTpcJWSzaJQVxNLb/x9f39tHdDM4N4w== dependencies: - "@firebase/component" "0.6.17" - "@firebase/messaging" "0.12.21" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/messaging" "0.12.25" + "@firebase/util" "1.15.0" tslib "^2.1.0" "@firebase/messaging-interop-types@0.2.3": version "0.2.3" - resolved "https://registry.yarnpkg.com/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz#e647c9cd1beecfe6a6e82018a6eec37555e4da3e" + resolved "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz" integrity sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q== -"@firebase/messaging@0.12.21": - version "0.12.21" - resolved "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.21.tgz#05d76039133c3d2a33208416699a3d3ebd2c0012" - integrity sha512-bYJ2Evj167Z+lJ1ach6UglXz5dUKY1zrJZd15GagBUJSR7d9KfiM1W8dsyL0lDxcmhmA/sLaBYAAhF1uilwN0g== +"@firebase/messaging@0.12.25": + version "0.12.25" + resolved "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.25.tgz" + integrity sha512-7RhDwoDHlOK1/ou0/LeubxmjcngsTjDdrY/ssg2vwAVpUuVAhQzQvuCAOYxcX5wNC1zCgQ54AP1vdngBwbCmOQ== dependencies: - "@firebase/component" "0.6.17" - "@firebase/installations" "0.6.17" + "@firebase/component" "0.7.2" + "@firebase/installations" "0.6.21" "@firebase/messaging-interop-types" "0.2.3" - "@firebase/util" "1.12.0" + "@firebase/util" "1.15.0" idb "7.1.1" tslib "^2.1.0" -"@firebase/performance-compat@0.2.19": - version "0.2.19" - resolved "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.19.tgz#f817a82037285b2240c4c55cc03eb1943ae932d6" - integrity sha512-4cU0T0BJ+LZK/E/UwFcvpBCVdkStgBMQwBztM9fJPT6udrEUk3ugF5/HT+E2Z22FCXtIaXDukJbYkE/c3c6IHw== +"@firebase/performance-compat@0.2.24": + version "0.2.24" + resolved "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.24.tgz" + integrity sha512-YRlejH8wLt7ThWao+HXoKUHUrZKGYq+otxkPS+8nuE5PeN1cBXX7NAJl9ueuUkBwMIrnKdnDqL/voHXxDAAt3g== dependencies: - "@firebase/component" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/performance" "0.7.6" + "@firebase/component" "0.7.2" + "@firebase/logger" "0.5.0" + "@firebase/performance" "0.7.11" "@firebase/performance-types" "0.2.3" - "@firebase/util" "1.12.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" "@firebase/performance-types@0.2.3": version "0.2.3" - resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.2.3.tgz#5ce64e90fa20ab5561f8b62a305010cf9fab86fb" + resolved "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz" integrity sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ== -"@firebase/performance@0.7.6": - version "0.7.6" - resolved "https://registry.npmjs.org/@firebase/performance/-/performance-0.7.6.tgz#36376130c725d8f6df492be4da32c1d1f9a605f8" - integrity sha512-AsOz74dSTlyQGlnnbLWXiHFAsrxhpssPOsFFi4HgOJ5DjzkK7ZdZ/E9uMPrwFoXJyMVoybGRuqsL/wkIbFITsA== +"@firebase/performance@0.7.11": + version "0.7.11" + resolved "https://registry.npmjs.org/@firebase/performance/-/performance-0.7.11.tgz" + integrity sha512-V3uAhrz7IYJuji+OgT3qYTGKxpek/TViXti9OSsUJ4AexZ3jQjYH5Yrn7JvBxk8MGiSLsC872hh+BxQiPZsm7g== dependencies: - "@firebase/component" "0.6.17" - "@firebase/installations" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/installations" "0.6.21" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" web-vitals "^4.2.4" -"@firebase/remote-config-compat@0.2.17": - version "0.2.17" - resolved "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.17.tgz#d91583dfdd85ddb3e8cdd9c0e433d38f02095f1e" - integrity sha512-KelsBD0sXSC0u3esr/r6sJYGRN6pzn3bYuI/6pTvvmZbjBlxQkRabHAVH6d+YhLcjUXKIAYIjZszczd1QJtOyA== +"@firebase/remote-config-compat@0.2.23": + version "0.2.23" + resolved "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.23.tgz" + integrity sha512-4+KqRRHEUUmKT6tFmnpWATOsaFfmSuBs1jXH8JzVtMLEYqq/WS9IDM92OdefFDSrAA2xGd0WN004z8mKeIIscw== dependencies: - "@firebase/component" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/remote-config" "0.6.4" - "@firebase/remote-config-types" "0.4.0" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/logger" "0.5.0" + "@firebase/remote-config" "0.8.2" + "@firebase/remote-config-types" "0.5.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" -"@firebase/remote-config-types@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.4.0.tgz#91b9a836d5ca30ced68c1516163b281fbb544537" - integrity sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg== +"@firebase/remote-config-types@0.5.0": + version "0.5.0" + resolved "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.5.0.tgz" + integrity sha512-vI3bqLoF14L/GchtgayMiFpZJF+Ao3uR8WCde0XpYNkSokDpAKca2DxvcfeZv7lZUqkUwQPL2wD83d3vQ4vvrg== -"@firebase/remote-config@0.6.4": - version "0.6.4" - resolved "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.6.4.tgz#30610bf52452639a127f1b40a94de096ac6cf43a" - integrity sha512-ZyLJRT46wtycyz2+opEkGaoFUOqRQjt/0NX1WfUISOMCI/PuVoyDjqGpq24uK+e8D5NknyTpiXCVq5dowhScmg== +"@firebase/remote-config@0.8.2": + version "0.8.2" + resolved "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.8.2.tgz" + integrity sha512-5EXqOThV4upjK9D38d/qOSVwOqRhemlaOFk9vCkMNNALeIlwr+4pLjtLNo4qoY8etQmU/1q4aIATE9N8PFqg0g== dependencies: - "@firebase/component" "0.6.17" - "@firebase/installations" "0.6.17" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/installations" "0.6.21" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" -"@firebase/storage-compat@0.3.22": - version "0.3.22" - resolved "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.22.tgz#8d5b95b5583d2acac2183e8e3cc302c66c2c3902" - integrity sha512-29j6JgXTjQ76sOIkxmTNHQfYA/hDTeV9qGbn0jolynPXSg/AmzCB0CpCoCYrS0ja0Flgmy1hkA3XYDZ/eiV1Cg== +"@firebase/storage-compat@0.4.2": + version "0.4.2" + resolved "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.4.2.tgz" + integrity sha512-R+aB38wxCH5zjIO/xu9KznI7fgiPuZAG98uVm1NcidHyyupGgIDLKigGmRGBZMnxibe/m2oxNKoZpfEbUX2aQQ== dependencies: - "@firebase/component" "0.6.17" - "@firebase/storage" "0.13.12" + "@firebase/component" "0.7.2" + "@firebase/storage" "0.14.2" "@firebase/storage-types" "0.8.3" - "@firebase/util" "1.12.0" + "@firebase/util" "1.15.0" tslib "^2.1.0" "@firebase/storage-types@0.8.3": version "0.8.3" - resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.8.3.tgz#2531ef593a3452fc12c59117195d6485c6632d3d" + resolved "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz" integrity sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg== -"@firebase/storage@0.13.12": - version "0.13.12" - resolved "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.12.tgz#213c5e7832b77b361e0c454ff8b787437686c45c" - integrity sha512-5JmoFS01MYjW1XMQa5F5rD/kvMwBN10QF03bmcuJWq4lg+BJ3nRgL3sscWnyJPhwM/ZCyv2eRwcfzESVmsYkdQ== +"@firebase/storage@0.14.2": + version "0.14.2" + resolved "https://registry.npmjs.org/@firebase/storage/-/storage-0.14.2.tgz" + integrity sha512-o/culaTeJ8GRpKXRJov21rux/n9dRaSOWLebyatFP2sqEdCxQPjVA1H9Z2fzYwQxMIU0JVmC7SPPmU11v7L6vQ== dependencies: - "@firebase/component" "0.6.17" - "@firebase/util" "1.12.0" + "@firebase/component" "0.7.2" + "@firebase/util" "1.15.0" tslib "^2.1.0" -"@firebase/util@1.12.0": - version "1.12.0" - resolved "https://registry.npmjs.org/@firebase/util/-/util-1.12.0.tgz#202e96cfd832f8dde551232e4868861681b8b89a" - integrity sha512-Z4rK23xBCwgKDqmzGVMef+Vb4xso2j5Q8OG0vVL4m4fA5ZjPMYQazu8OJJC3vtQRC3SQ/Pgx/6TPNVsCd70QRw== +"@firebase/util@1.15.0", "@firebase/util@1.x": + version "1.15.0" + resolved "https://registry.npmjs.org/@firebase/util/-/util-1.15.0.tgz" + integrity sha512-AmWf3cHAOMbrCPG4xdPKQaj5iHnyYfyLKZxwz+Xf55bqKbpAmcYifB4jQinT2W9XhDRHISOoPyBOariJpCG6FA== dependencies: tslib "^2.1.0" -"@firebase/webchannel-wrapper@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz#a73bab8eb491d7b8b7be2f0e6c310647835afe83" - integrity sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ== +"@firebase/webchannel-wrapper@1.0.5": + version "1.0.5" + resolved "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.5.tgz" + integrity sha512-+uGNN7rkfn41HLO0vekTFhTxk61eKa8mTpRGLO0QSqlQdKvIoGAvLp3ppdVIWbTGYJWM6Kp0iN+PjMIOcnVqTw== "@grpc/grpc-js@~1.9.0": version "1.9.15" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.15.tgz#433d7ac19b1754af690ea650ab72190bd700739b" + resolved "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz" integrity sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ== dependencies: "@grpc/proto-loader" "^0.7.8" @@ -410,7 +410,7 @@ "@grpc/proto-loader@^0.7.8": version "0.7.13" - resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.13.tgz#f6a44b2b7c9f7b609f5748c6eac2d420e37670cf" + resolved "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz" integrity sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw== dependencies: lodash.camelcase "^4.3.0" @@ -420,17 +420,17 @@ "@jridgewell/resolve-uri@^3.0.3": version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== "@jridgewell/sourcemap-codec@^1.4.10": version "1.5.0" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== dependencies: "@jridgewell/resolve-uri" "^3.0.3" @@ -438,27 +438,27 @@ "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + resolved "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz" integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== "@protobufjs/base64@^1.1.2": version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + resolved "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz" integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== "@protobufjs/codegen@^2.0.4": version "2.0.4" - resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + resolved "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz" integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== "@protobufjs/eventemitter@^1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + resolved "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz" integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== "@protobufjs/fetch@^1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + resolved "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz" integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== dependencies: "@protobufjs/aspromise" "^1.1.1" @@ -466,95 +466,88 @@ "@protobufjs/float@^1.0.2": version "1.0.2" - resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + resolved "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz" integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== "@protobufjs/inquire@^1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + resolved "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz" integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== "@protobufjs/path@^1.1.2": version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + resolved "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz" integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== "@protobufjs/pool@^1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + resolved "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz" integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== "@protobufjs/utf8@^1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz" integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== "@tsconfig/node10@^1.0.7": version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz" integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== "@tsconfig/node12@^1.0.7": version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== "@tsconfig/node14@^1.0.0": version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": version "1.0.4" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== -"@types/node@18.19.83": +"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@18.19.83": version "18.19.83" - resolved "https://registry.npmjs.org/@types/node/-/node-18.19.83.tgz#44d302cd09364640bdd45d001bc75e596f7da920" + resolved "https://registry.npmjs.org/@types/node/-/node-18.19.83.tgz" integrity sha512-D69JeR5SfFS5H6FLbUaS0vE4r1dGhmMBbG4Ed6BNS4wkDK8GZjsdCShT5LCN59vOHEUHnFCY9J4aclXlIphMkA== dependencies: undici-types "~5.26.4" -"@types/node@>=12.12.47", "@types/node@>=13.7.0": - version "22.14.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.14.0.tgz#d3bfa3936fef0dbacd79ea3eb17d521c628bb47e" - integrity sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA== - dependencies: - undici-types "~6.21.0" - acorn-walk@^8.1.1: version "8.3.4" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz" integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== dependencies: acorn "^8.11.0" acorn@^8.11.0, acorn@^8.4.1: version "8.14.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz" integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-styles@^4.0.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" arg@^4.1.0: version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== cliui@^8.0.1: version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" @@ -563,115 +556,115 @@ cliui@^8.0.1: color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@~1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== create-require@^1.1.0: version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== diff@^4.0.1: version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== escalade@^3.1.1: version "3.2.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz" integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== faye-websocket@0.11.4: version "0.11.4" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + resolved "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz" integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== dependencies: websocket-driver ">=0.5.1" -firebase@11.8.1: - version "11.8.1" - resolved "https://registry.npmjs.org/firebase/-/firebase-11.8.1.tgz#7658c4fed6c10102d8a2b00de576b903af78d767" - integrity sha512-oetXhPCvJZM4DVL/n/06442emMU+KzM0JLZjszpwlU6mqdFZqBwumBxn6hQkLukJyU5wsjihZHUY8HEAE2micg== - dependencies: - "@firebase/ai" "1.3.0" - "@firebase/analytics" "0.10.16" - "@firebase/analytics-compat" "0.2.22" - "@firebase/app" "0.13.0" - "@firebase/app-check" "0.10.0" - "@firebase/app-check-compat" "0.3.25" - "@firebase/app-compat" "0.4.0" +firebase@latest: + version "12.11.0" + resolved "https://registry.npmjs.org/firebase/-/firebase-12.11.0.tgz" + integrity sha512-W9f3Y+cgQYgF9gvCGxt0upec8zwAtiQVcHuU8MfzUIgVU/9fRQWtu48Geiv1lsigtBz9QHML++Km9xAKO5GB5Q== + dependencies: + "@firebase/ai" "2.10.0" + "@firebase/analytics" "0.10.21" + "@firebase/analytics-compat" "0.2.27" + "@firebase/app" "0.14.10" + "@firebase/app-check" "0.11.2" + "@firebase/app-check-compat" "0.4.2" + "@firebase/app-compat" "0.5.10" "@firebase/app-types" "0.9.3" - "@firebase/auth" "1.10.6" - "@firebase/auth-compat" "0.5.26" - "@firebase/data-connect" "0.3.9" - "@firebase/database" "1.0.19" - "@firebase/database-compat" "2.0.10" - "@firebase/firestore" "4.7.16" - "@firebase/firestore-compat" "0.3.51" - "@firebase/functions" "0.12.8" - "@firebase/functions-compat" "0.3.25" - "@firebase/installations" "0.6.17" - "@firebase/installations-compat" "0.2.17" - "@firebase/messaging" "0.12.21" - "@firebase/messaging-compat" "0.2.21" - "@firebase/performance" "0.7.6" - "@firebase/performance-compat" "0.2.19" - "@firebase/remote-config" "0.6.4" - "@firebase/remote-config-compat" "0.2.17" - "@firebase/storage" "0.13.12" - "@firebase/storage-compat" "0.3.22" - "@firebase/util" "1.12.0" + "@firebase/auth" "1.12.2" + "@firebase/auth-compat" "0.6.4" + "@firebase/data-connect" "0.5.0" + "@firebase/database" "1.1.2" + "@firebase/database-compat" "2.1.2" + "@firebase/firestore" "4.13.0" + "@firebase/firestore-compat" "0.4.7" + "@firebase/functions" "0.13.3" + "@firebase/functions-compat" "0.4.3" + "@firebase/installations" "0.6.21" + "@firebase/installations-compat" "0.2.21" + "@firebase/messaging" "0.12.25" + "@firebase/messaging-compat" "0.2.25" + "@firebase/performance" "0.7.11" + "@firebase/performance-compat" "0.2.24" + "@firebase/remote-config" "0.8.2" + "@firebase/remote-config-compat" "0.2.23" + "@firebase/storage" "0.14.2" + "@firebase/storage-compat" "0.4.2" + "@firebase/util" "1.15.0" get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== http-parser-js@>=0.5.1: version "0.5.9" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.9.tgz#b817b3ca0edea6236225000d795378707c169cec" + resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz" integrity sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw== idb@7.1.1: version "7.1.1" - resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" + resolved "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz" integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== lodash.camelcase@^4.3.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz" integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== long@^5.0.0: version "5.3.1" - resolved "https://registry.yarnpkg.com/long/-/long-5.3.1.tgz#9d4222d3213f38a5ec809674834e0f0ab21abe96" + resolved "https://registry.npmjs.org/long/-/long-5.3.1.tgz" integrity sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng== make-error@^1.1.1: version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== protobufjs@^7.2.5: version "7.4.0" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.4.0.tgz#7efe324ce9b3b61c82aae5de810d287bc08a248a" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz" integrity sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw== dependencies: "@protobufjs/aspromise" "^1.1.2" @@ -689,17 +682,17 @@ protobufjs@^7.2.5: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== safe-buffer@>=5.1.0: version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -708,14 +701,14 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" ts-node@^10.9.2: version "10.9.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz" integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== dependencies: "@cspotcode/source-map-support" "^0.8.0" @@ -734,37 +727,32 @@ ts-node@^10.9.2: tslib@^2.1.0: version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== -typescript@5.5.4: +typescript@>=2.7, typescript@5.5.4: version "5.5.4" - resolved "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz" integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== undici-types@~5.26.4: version "5.26.5" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -undici-types@~6.21.0: - version "6.21.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" - integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== - v8-compile-cache-lib@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== web-vitals@^4.2.4: version "4.2.4" - resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.4.tgz#1d20bc8590a37769bd0902b289550936069184b7" + resolved "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz" integrity sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw== websocket-driver@>=0.5.1: version "0.7.4" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + resolved "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz" integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== dependencies: http-parser-js ">=0.5.1" @@ -773,12 +761,12 @@ websocket-driver@>=0.5.1: websocket-extensions@>=0.1.1: version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + resolved "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -787,17 +775,17 @@ wrap-ansi@^7.0.0: y18n@^5.0.5: version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yargs-parser@^21.1.1: version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs@^17.7.2: version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" @@ -810,5 +798,5 @@ yargs@^17.7.2: yn@3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From f4e0086e3fa5299422005d46b11a77c3a77867d9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 23 Mar 2026 10:30:31 -0700 Subject: [PATCH 107/174] fix(deps): update dependency tmp to v0.2.4 [security] (#9619) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- repo-scripts/size-analysis/package.json | 2 +- yarn.lock | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index 0c246b32be..8b3af13d01 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -23,7 +23,7 @@ "@firebase/util": "1.15.0", "child-process-promise": "2.2.1", "glob": "7.2.3", - "tmp": "0.2.3", + "tmp": "0.2.4", "gzip-size": "6.0.0", "memfs": "3.5.3", "terser": "5.37.0", diff --git a/yarn.lock b/yarn.lock index ad913eb48b..b990c9a35e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15925,10 +15925,10 @@ tmp@0.0.30: dependencies: os-tmpdir "~1.0.1" -tmp@0.2.3, tmp@^0.2.1, tmp@^0.2.3: - version "0.2.3" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" - integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== +tmp@0.2.4: + version "0.2.4" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz#c6db987a2ccc97f812f17137b36af2b6521b0d13" + integrity sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ== tmp@^0.0.33: version "0.0.33" @@ -15937,6 +15937,11 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmp@^0.2.1, tmp@^0.2.3: + version "0.2.3" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== + tmpl@1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" From 44ad4cc2e54c6720d34fff4c2773f8887473b935 Mon Sep 17 00:00:00 2001 From: Mila <107142260+milaGGL@users.noreply.github.com> Date: Wed, 25 Mar 2026 11:56:28 -0400 Subject: [PATCH 108/174] feat(firestore): Add logical expressions (#9702) --- .changeset/orange-worms-juggle.md | 6 + .../firestore-lite-pipelines.api.md | 6 + common/api-review/firestore-pipelines.api.md | 6 + docs-devsite/firestore_lite_pipelines.md | 84 ++++++++++++ docs-devsite/firestore_pipelines.md | 84 ++++++++++++ .../firestore/lite/pipelines/pipelines.ts | 2 + packages/firestore/src/api_pipelines.ts | 4 +- .../firestore/src/lite-api/expressions.ts | 73 ++++++++++ .../test/integration/api/pipeline.test.ts | 128 +++++++++++++++++ packages/firestore/test/lite/pipeline.test.ts | 129 ++++++++++++++++++ 10 files changed, 521 insertions(+), 1 deletion(-) create mode 100644 .changeset/orange-worms-juggle.md diff --git a/.changeset/orange-worms-juggle.md b/.changeset/orange-worms-juggle.md new file mode 100644 index 0000000000..8cdd22ce70 --- /dev/null +++ b/.changeset/orange-worms-juggle.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/firestore': minor +--- + +Add support for logical expressions `nor` and `switchOn`. diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index 94d20c4a45..fb0bda529d 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -1103,6 +1103,9 @@ export function multiply(first: Expression, second: Expression | unknown): Funct // @beta export function multiply(fieldName: string, second: Expression | unknown): FunctionExpression; +// @beta +export function nor(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; + // @beta export function not(booleanExpr: BooleanExpression): BooleanExpression; @@ -1472,6 +1475,9 @@ export function sum(expression: Expression): AggregateFunction; // @beta export function sum(fieldName: string): AggregateFunction; +// @beta +export function switchOn(condition: BooleanExpression, result: Expression, ...others: Array): FunctionExpression; + // @beta export type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index c7127039da..9182c27043 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -1106,6 +1106,9 @@ export function multiply(first: Expression, second: Expression | unknown): Funct // @beta export function multiply(fieldName: string, second: Expression | unknown): FunctionExpression; +// @beta +export function nor(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; + // @beta export function not(booleanExpr: BooleanExpression): BooleanExpression; @@ -1514,6 +1517,9 @@ export function sum(expression: Expression): AggregateFunction; // @beta export function sum(fieldName: string): AggregateFunction; +// @beta +export function switchOn(condition: BooleanExpression, result: Expression, ...others: Array): FunctionExpression; + // @beta export type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 106b9b5aa6..9aebc09896 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -63,6 +63,7 @@ https://github.com/firebase/firebase-js-sdk | [not(booleanExpr)](./firestore_lite_pipelines.md#not_c5b8fb1) | (Public Preview) Creates an expression that negates a filter condition. | | function(condition, ...) | | [conditional(condition, thenExpr, elseExpr)](./firestore_lite_pipelines.md#conditional_07a206d) | (Public Preview) Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. | +| [switchOn(condition, result, others)](./firestore_lite_pipelines.md#switchon_02b8caf) | (Public Preview) Creates an expression that evaluates to the result corresponding to the first true condition. | | function(documentPath, ...) | | [documentId(documentPath)](./firestore_lite_pipelines.md#documentid_cef293c) | (Public Preview) Creates an expression that returns the document ID from a path. | | function(documentPathExpr, ...) | @@ -272,6 +273,7 @@ https://github.com/firebase/firebase-js-sdk | [logicalMaximum(first, second, others)](./firestore_lite_pipelines.md#logicalmaximum_83be015) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | | [logicalMinimum(first, second, others)](./firestore_lite_pipelines.md#logicalminimum_83be015) | (Public Preview) Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. | | [multiply(first, second)](./firestore_lite_pipelines.md#multiply_846ca1b) | (Public Preview) Creates an expression that multiplies two expressions together. | +| [nor(first, second, more)](./firestore_lite_pipelines.md#nor_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'NOR' operation on multiple filter conditions. | | [or(first, second, more)](./firestore_lite_pipelines.md#or_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'OR' operation on multiple filter conditions. | | [xor(first, second, additionalConditions)](./firestore_lite_pipelines.md#xor_8197113) | (Public Preview) Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. | | function(firstArray, ...) | @@ -1848,6 +1850,49 @@ conditional( ``` +### switchOn(condition, result, others) {:#switchon_02b8caf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to the result corresponding to the first true condition. + +This function behaves like a `switch` statement. It accepts an alternating sequence of conditions and their corresponding results. If an odd number of arguments is provided, the final argument serves as a default fallback result. If no default is provided and no condition evaluates to true, it throws an error. + +Signature: + +```typescript +export declare function switchOn(condition: BooleanExpression, result: Expression, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| condition | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The first condition to check. | +| result | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The result if the first condition is true. | +| others | Array<[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) \| [Expression](./firestore_lite_pipelines.expression.md#expression_class)> | Additional conditions and results, and optionally a default value. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new Expression representing the switch operation. + +### Example + + +```typescript +// Return "Active" if field "status" is 1, "Pending" if field "status" is 2, +// and default to "Unknown" if none of the conditions are true. +switchOn( + equal(field("status"), 1), constant("Active"), + equal(field("status"), 2), constant("Pending"), + constant("Unknown") +) + +``` + ## function(documentPath, ...) ### documentId(documentPath) {:#documentid_cef293c} @@ -8799,6 +8844,45 @@ multiply(field("quantity"), field("price")); ``` +### nor(first, second, more) {:#nor_e0c48bd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'NOR' operation on multiple filter conditions. + +Signature: + +```typescript +export declare function nor(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The first filter condition. | +| second | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The second filter condition. | +| more | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'NOR' together. | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +A new [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) representing the logical 'NOR' operation. + +### Example + + +```typescript +// Check if neither the 'age' field is greater than 18 nor the 'city' field is "London" +const condition = nor( + greaterThan("age", 18), + equal("city", "London") +); + +``` + ### or(first, second, more) {:#or_e0c48bd} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index e94b8d4b1c..6f51fe0d2e 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -63,6 +63,7 @@ https://github.com/firebase/firebase-js-sdk | [not(booleanExpr)](./firestore_pipelines.md#not_c5b8fb1) | (Public Preview) Creates an expression that negates a filter condition. | | function(condition, ...) | | [conditional(condition, thenExpr, elseExpr)](./firestore_pipelines.md#conditional_07a206d) | (Public Preview) Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. | +| [switchOn(condition, result, others)](./firestore_pipelines.md#switchon_02b8caf) | (Public Preview) Creates an expression that evaluates to the result corresponding to the first true condition. | | function(documentPath, ...) | | [documentId(documentPath)](./firestore_pipelines.md#documentid_cef293c) | (Public Preview) Creates an expression that returns the document ID from a path. | | function(documentPathExpr, ...) | @@ -272,6 +273,7 @@ https://github.com/firebase/firebase-js-sdk | [logicalMaximum(first, second, others)](./firestore_pipelines.md#logicalmaximum_83be015) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | | [logicalMinimum(first, second, others)](./firestore_pipelines.md#logicalminimum_83be015) | (Public Preview) Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. | | [multiply(first, second)](./firestore_pipelines.md#multiply_846ca1b) | (Public Preview) Creates an expression that multiplies two expressions together. | +| [nor(first, second, more)](./firestore_pipelines.md#nor_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'NOR' operation on multiple filter conditions. | | [or(first, second, more)](./firestore_pipelines.md#or_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'OR' operation on multiple filter conditions. | | [xor(first, second, additionalConditions)](./firestore_pipelines.md#xor_8197113) | (Public Preview) Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. | | function(firstArray, ...) | @@ -1854,6 +1856,49 @@ conditional( ``` +### switchOn(condition, result, others) {:#switchon_02b8caf} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that evaluates to the result corresponding to the first true condition. + +This function behaves like a `switch` statement. It accepts an alternating sequence of conditions and their corresponding results. If an odd number of arguments is provided, the final argument serves as a default fallback result. If no default is provided and no condition evaluates to true, it throws an error. + +Signature: + +```typescript +export declare function switchOn(condition: BooleanExpression, result: Expression, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| condition | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The first condition to check. | +| result | [Expression](./firestore_pipelines.expression.md#expression_class) | The result if the first condition is true. | +| others | Array<[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) \| [Expression](./firestore_pipelines.expression.md#expression_class)> | Additional conditions and results, and optionally a default value. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new Expression representing the switch operation. + +### Example + + +```typescript +// Return "Active" if field "status" is 1, "Pending" if field "status" is 2, +// and default to "Unknown" if none of the conditions are true. +switchOn( + equal(field("status"), 1), constant("Active"), + equal(field("status"), 2), constant("Pending"), + constant("Unknown") +) + +``` + ## function(documentPath, ...) ### documentId(documentPath) {:#documentid_cef293c} @@ -8805,6 +8850,45 @@ multiply(field("quantity"), field("price")); ``` +### nor(first, second, more) {:#nor_e0c48bd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that performs a logical 'NOR' operation on multiple filter conditions. + +Signature: + +```typescript +export declare function nor(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| first | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The first filter condition. | +| second | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The second filter condition. | +| more | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class)\[\] | Additional filter conditions to 'NOR' together. | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +A new [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) representing the logical 'NOR' operation. + +### Example + + +```typescript +// Check if neither the 'age' field is greater than 18 nor the 'city' field is "London" +const condition = nor( + greaterThan("age", 18), + equal("city", "London") +); + +``` + ### or(first, second, more) {:#or_e0c48bd} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index 8f99754be7..88a4e7f242 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -132,6 +132,8 @@ export { equalAny, notEqualAny, xor, + nor, + switchOn, conditional, not, logicalMaximum, diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index f9b1e7ec5d..411a9e81e7 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -54,12 +54,12 @@ export { } from './lite-api/stage_options'; export { - field, constant, add, subtract, multiply, divide, + field, mod, equal, notEqual, @@ -88,6 +88,8 @@ export { equalAny, notEqualAny, xor, + nor, + switchOn, conditional, not, logicalMaximum, diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index c72229f6c7..a0629c254a 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -9879,6 +9879,37 @@ export function or( ).asBoolean(); } +/** + * @beta + * + * Creates an expression that performs a logical 'NOR' operation on multiple filter conditions. + * + * @example + * ```typescript + * // Check if neither the 'age' field is greater than 18 nor the 'city' field is "London" + * const condition = nor( + * greaterThan("age", 18), + * equal("city", "London") + * ); + * ``` + * + * @param first - The first filter condition. + * @param second - The second filter condition. + * @param more - Additional filter conditions to 'NOR' together. + * @returns A new {@link @firebase/firestore/pipelines#BooleanExpression} representing the logical 'NOR' operation. + */ +export function nor( + first: BooleanExpression, + second: BooleanExpression, + ...more: BooleanExpression[] +): BooleanExpression { + return new FunctionExpression( + 'nor', + [first, second, ...more], + 'nor' + ).asBoolean(); +} + /** * @beta * Creates an expression that returns the value of the base expression raised to the power of the exponent expression. @@ -10524,6 +10555,48 @@ export function ifAbsent( ); } +/** + * @beta + * Creates an expression that evaluates to the result corresponding to the first true condition. + * + * @remarks + * This function behaves like a `switch` statement. It accepts an alternating sequence of conditions + * and their corresponding results. + * If an odd number of arguments is provided, the final argument serves as a default fallback result. + * If no default is provided and no condition evaluates to true, it throws an error. + * + * @example + * ```typescript + * // Return "Active" if field "status" is 1, "Pending" if field "status" is 2, + * // and default to "Unknown" if none of the conditions are true. + * switchOn( + * equal(field("status"), 1), constant("Active"), + * equal(field("status"), 2), constant("Pending"), + * constant("Unknown") + * ) + * ``` + * + * @param condition - The first condition to check. + * @param result - The result if the first condition is true. + * @param others - Additional conditions and results, and optionally a default value. + * @returns A new Expression representing the switch operation. + */ +export function switchOn( + condition: BooleanExpression, + result: Expression, + ...others: Array +): FunctionExpression { + return new FunctionExpression( + 'switch_on', + [ + valueToDefaultExpr(condition), + valueToDefaultExpr(result), + ...others.map(valueToDefaultExpr) + ], + 'switchOn' + ); +} + /** * @beta * Creates an expression that joins the elements of an array into a string. diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index efe414a71a..fe8c5e5051 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -120,6 +120,8 @@ import { documentId, substring, xor, + nor, + switchOn, field, constant, FindNearestStageOptions, @@ -1541,6 +1543,27 @@ apiDescribe.skipClassic('Pipelines', persistence => { ); }); + it('where with nor', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + nor( + equal('genre', 'Romance'), + equal('genre', 'Dystopian'), + equal('genre', 'Fantasy'), + greaterThan('published', 1949) + ) + ) + .select('title') + ); + expectResults( + snapshot, + { title: 'Crime and Punishment' }, + { title: 'The Great Gatsby' } + ); + }); it('supports options', async () => { const snapshot = await execute( firestore @@ -5292,6 +5315,111 @@ apiDescribe.skipClassic('Pipelines', persistence => { }); }); + it('supports nor', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + a: false, + b: false, + c: true, + d: null + }) + ) + .select( + nor(field('a').asBoolean(), field('b').asBoolean()).as( + 'twoConditions' + ), + nor( + field('a').asBoolean(), + field('b').asBoolean(), + field('c').asBoolean() + ).as('threeConditions'), + nor( + field('a').asBoolean(), + field('b').asBoolean(), + field('d').asBoolean() + ).as('threeConditionsWithNull') + ) + ); + + expectResults(snapshot, { + twoConditions: true, + threeConditions: false, + threeConditionsWithNull: null + }); + }); + + describe('switchOn', () => { + it('supports basic switch', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ value: 1 })) + .select( + switchOn( + equal(field('value'), 1), + constant('one'), + constant('NA') + ).as('result1'), + switchOn( + equal(field('value'), 2), + constant('two'), + constant('NA') + ).as('result2') + ) + ); + expectResults(snapshot, { result1: 'one', result2: 'NA' }); + }); + + it('supports multi-branch switch', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ value: 2 })) + .select( + switchOn( + equal(field('value'), 1), + constant('one'), + equal(field('value'), 2), + constant('two'), + equal(field('value'), 3), + constant('three'), + constant('default') + ).as('result') + ) + ); + expectResults(snapshot, { result: 'two' }); + }); + + it('throws if no match and no default', async () => { + await expect( + execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ value: 5 })) + .select( + switchOn( + equal(field('value'), 1), + constant('one'), + equal(field('value'), 2), + constant('two') + ).as('result') + ) + ) + ).to.be.rejectedWith(/all switch cases evaluate to false/); + }); + }); + // TODO(new-expression): Add new expression tests above this line }); diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 2097fe1c3d..9372ff04b2 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -83,6 +83,8 @@ import { equalAny, notEqualAny, xor, + nor, + switchOn, conditional, logicalMaximum, logicalMinimum, @@ -1527,6 +1529,28 @@ describe.skipClassic('Firestore Pipelines', () => { ); }); + it('where with nor', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + nor( + equal('genre', 'Romance'), + equal('genre', 'Dystopian'), + equal('genre', 'Fantasy'), + greaterThan('published', 1949) + ) + ) + .select('title') + ); + expectResults( + snapshot, + { title: 'Crime and Punishment' }, + { title: 'The Great Gatsby' } + ); + }); + it('supports options', async () => { const snapshot = await execute( firestore @@ -5114,6 +5138,111 @@ describe.skipClassic('Firestore Pipelines', () => { }); }); + it('supports nor', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + a: false, + b: false, + c: true, + d: null + }) + ) + .select( + nor(field('a').asBoolean(), field('b').asBoolean()).as( + 'twoConditions' + ), + nor( + field('a').asBoolean(), + field('b').asBoolean(), + field('c').asBoolean() + ).as('threeConditions'), + nor( + field('a').asBoolean(), + field('b').asBoolean(), + field('d').asBoolean() + ).as('threeConditionsWithNull') + ) + ); + + expectResults(snapshot, { + twoConditions: true, + threeConditions: false, + threeConditionsWithNull: null + }); + }); + + describe('switchOn', () => { + it('supports basic switch', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ value: 1 })) + .select( + switchOn( + equal(field('value'), 1), + constant('one'), + constant('NA') + ).as('result1'), + switchOn( + equal(field('value'), 2), + constant('two'), + constant('NA') + ).as('result2') + ) + ); + expectResults(snapshot, { result1: 'one', result2: 'NA' }); + }); + + it('supports multi-branch switch', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ value: 2 })) + .select( + switchOn( + equal(field('value'), 1), + constant('one'), + equal(field('value'), 2), + constant('two'), + equal(field('value'), 3), + constant('three'), + constant('default') + ).as('result') + ) + ); + expectResults(snapshot, { result: 'two' }); + }); + + it('throws if no match and no default', async () => { + await expect( + execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ value: 5 })) + .select( + switchOn( + equal(field('value'), 1), + constant('one'), + equal(field('value'), 2), + constant('two') + ).as('result') + ) + ) + ).to.be.rejectedWith(/all switch cases evaluate to false/); + }); + }); + // TODO(new-expression): Add new expression tests above this line }); From 5cd6509bdb1eedc9a37ed6ce7677450f574a7e9d Mon Sep 17 00:00:00 2001 From: Yvonne Pan <103622026+yvonnep165@users.noreply.github.com> Date: Wed, 25 Mar 2026 12:19:17 -0400 Subject: [PATCH 109/174] feat(firestore): add timestamp expressions (#9728) * Add timestampTrunc, timestampDiff and timestampExtract expressions * Add changeset * Fix formatting * Fix variable names to follow camelCase * Generate documentation * Fix the int64 documentation error * Fix formatting * Add a test for isoWeek for timestampTruncate --- .changeset/cool-dragons-compete.md | 6 + .../firestore-lite-pipelines.api.md | 35 ++ common/api-review/firestore-pipelines.api.md | 35 ++ .../firestore_lite_pipelines.expression.md | 144 ++++++++ docs-devsite/firestore_lite_pipelines.md | 324 +++++++++++++++- .../firestore_pipelines.expression.md | 144 ++++++++ docs-devsite/firestore_pipelines.md | 324 +++++++++++++++- .../firestore/lite/pipelines/pipelines.ts | 3 + packages/firestore/src/api_pipelines.ts | 3 + .../firestore/src/lite-api/expressions.ts | 348 +++++++++++++++++- .../test/integration/api/pipeline.test.ts | 69 ++++ packages/firestore/test/lite/pipeline.test.ts | 124 +++++++ 12 files changed, 1547 insertions(+), 12 deletions(-) create mode 100644 .changeset/cool-dragons-compete.md diff --git a/.changeset/cool-dragons-compete.md b/.changeset/cool-dragons-compete.md new file mode 100644 index 0000000000..b8405e7758 --- /dev/null +++ b/.changeset/cool-dragons-compete.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/firestore': minor +--- + +Add support for timestamp_trunc, timestamp_diff and timestamp_extract expressions diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index fb0bda529d..dd54c9c827 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -764,6 +764,14 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ timestampAdd(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; /* Excluded from this release type: _readUserData */ + timestampDiff(start: Expression, unit: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampDiff(start: string | Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampExtract(part: TimePart, timezone?: string | Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampExtract(part: Expression, timezone?: string | Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ timestampSubtract(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; @@ -1481,6 +1489,9 @@ export function switchOn(condition: BooleanExpression, result: Expression, ...ot // @beta export type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; +// @beta +export type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; + // @beta export function timestampAdd(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; @@ -1490,6 +1501,30 @@ export function timestampAdd(timestamp: Expression, unit: 'microsecond' | 'milli // @beta export function timestampAdd(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +// @beta +export function timestampDiff(endFieldName: string, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; + +// @beta +export function timestampDiff(endFieldName: string, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; + +// @beta +export function timestampDiff(endExpression: Expression, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; + +// @beta +export function timestampDiff(endExpression: Expression, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; + +// @beta +export function timestampExtract(fieldName: string, part: TimePart, timezone?: string | Expression): FunctionExpression; + +// @beta +export function timestampExtract(fieldName: string, part: Expression, timezone?: string | Expression): FunctionExpression; + +// @beta +export function timestampExtract(timestampExpression: Expression, part: TimePart, timezone?: string | Expression): FunctionExpression; + +// @beta +export function timestampExtract(timestampExpression: Expression, part: Expression, timezone?: string | Expression): FunctionExpression; + // @beta export function timestampSubtract(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 9182c27043..3a2de9e77a 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -767,6 +767,14 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ timestampAdd(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; /* Excluded from this release type: _readUserData */ + timestampDiff(start: Expression, unit: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampDiff(start: string | Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampExtract(part: TimePart, timezone?: string | Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + timestampExtract(part: Expression, timezone?: string | Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ timestampSubtract(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; @@ -1523,6 +1531,9 @@ export function switchOn(condition: BooleanExpression, result: Expression, ...ot // @beta export type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; +// @beta +export type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; + // @beta export function timestampAdd(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; @@ -1532,6 +1543,30 @@ export function timestampAdd(timestamp: Expression, unit: 'microsecond' | 'milli // @beta export function timestampAdd(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +// @beta +export function timestampDiff(endFieldName: string, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; + +// @beta +export function timestampDiff(endFieldName: string, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; + +// @beta +export function timestampDiff(endExpression: Expression, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; + +// @beta +export function timestampDiff(endExpression: Expression, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; + +// @beta +export function timestampExtract(fieldName: string, part: TimePart, timezone?: string | Expression): FunctionExpression; + +// @beta +export function timestampExtract(fieldName: string, part: Expression, timezone?: string | Expression): FunctionExpression; + +// @beta +export function timestampExtract(timestampExpression: Expression, part: TimePart, timezone?: string | Expression): FunctionExpression; + +// @beta +export function timestampExtract(timestampExpression: Expression, part: Expression, timezone?: string | Expression): FunctionExpression; + // @beta export function timestampSubtract(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index 4ad64ca4c8..3e4c060e9c 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -180,6 +180,10 @@ export declare abstract class Expression | [sum()](./firestore_lite_pipelines.expression.md#expressionsum) | | (Public Preview) Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. | | [timestampAdd(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. | | [timestampAdd(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. | +| [timestampDiff(start, unit)](./firestore_lite_pipelines.expression.md#expressiontimestampdiff) | | (Public Preview) Creates an expression that calculates the difference between this timestamp and another timestamp. | +| [timestampDiff(start, unit)](./firestore_lite_pipelines.expression.md#expressiontimestampdiff) | | (Public Preview) Creates an expression that calculates the difference between this timestamp and another timestamp. | +| [timestampExtract(part, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestampextract) | | (Public Preview) Creates an expression that extracts a specified part from this timestamp expression. | +| [timestampExtract(part, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestampextract) | | (Public Preview) Creates an expression that extracts a specified part from this timestamp expression. | | [timestampSubtract(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. | | [timestampSubtract(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. | | [timestampToUnixMicros()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixmicros) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | @@ -4818,6 +4822,146 @@ field("timestamp").timestampAdd("day", 1); ``` +## Expression.timestampDiff() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the difference between this timestamp and another timestamp. + +Signature: + +```typescript +timestampDiff(start: Expression, unit: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| start | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluating to the starting timestamp. | +| unit | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluates to a unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the difference as an integer. + +### Example + + +```typescript +// Calculate the difference determined by fields 'startTime' and 'unit'. +field("endTime").timestampDiff(field("startTime"), field("unit")); + +``` + +## Expression.timestampDiff() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the difference between this timestamp and another timestamp. + +Signature: + +```typescript +timestampDiff(start: string | Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| start | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The field name of the starting timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time for the difference (e.g., "day", "hour"). | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the difference as an integer. + +### Example + + +```typescript +// Calculate the difference in days between 'endTime' and 'startTime' fields. +field("endTime").timestampDiff("startTime", "day"); + +``` + +## Expression.timestampExtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that extracts a specified part from this timestamp expression. + +Signature: + +```typescript +timestampExtract(part: TimePart, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| part | [TimePart](./firestore_lite_pipelines.md#timepart) | The part to extract from the timestamp (e.g., "year", "month", "day"). | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for extraction. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1." | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the extracted part as an integer. + +### Example + + +```typescript +// Extract the year from the 'createdAt' field. +field('createdAt').timestampExtract('year') + +``` + +## Expression.timestampExtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that extracts a specified part from this timestamp expression. + +Signature: + +```typescript +timestampExtract(part: Expression, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| part | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluating to the part to extract. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for extraction. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1." | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the extracted part as an integer. + +### Example + + +```typescript +// Extract the part specified by the field 'extractionPart' from 'createdAt'. +field('createdAt').timestampExtract(field('extractionPart')) + +``` + ## Expression.timestampSubtract() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 9aebc09896..4cb6c81bd1 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -74,6 +74,12 @@ https://github.com/firebase/firebase-js-sdk | function(elements, ...) | | [array(elements)](./firestore_lite_pipelines.md#array_7d853aa) | (Public Preview) Creates an expression that creates a Firestore array value from an input array. | | [map(elements)](./firestore_lite_pipelines.md#map_ce5dee1) | (Public Preview) Creates an expression that creates a Firestore map value from an input object. | +| function(endExpression, ...) | +| [timestampDiff(endExpression, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_8cb2a38) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endExpression, startExpression, unit)](./firestore_lite_pipelines.md#timestampdiff_33aecb4) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| function(endFieldName, ...) | +| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_c062afd) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endFieldName, startExpression, unit)](./firestore_lite_pipelines.md#timestampdiff_8244545) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | | function(expr, ...) | | [abs(expr)](./firestore_lite_pipelines.md#abs_005f3d4) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | | [ascending(expr)](./firestore_lite_pipelines.md#ascending_005f3d4) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. | @@ -250,6 +256,8 @@ https://github.com/firebase/firebase-js-sdk | [subtract(fieldName, value)](./firestore_lite_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. | | [sum(fieldName)](./firestore_lite_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. | | [timestampAdd(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampadd_341fe7d) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. | +| [timestampExtract(fieldName, part, timezone)](./firestore_lite_pipelines.md#timestampextract_a51c205) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | +| [timestampExtract(fieldName, part, timezone)](./firestore_lite_pipelines.md#timestampextract_2d51eac) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | | [timestampSubtract(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_341fe7d) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. | | [timestampToUnixMicros(fieldName)](./firestore_lite_pipelines.md#timestamptounixmicros_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | | [timestampToUnixMillis(fieldName)](./firestore_lite_pipelines.md#timestamptounixmillis_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | @@ -355,6 +363,8 @@ https://github.com/firebase/firebase-js-sdk | [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_98418f9) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | | [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_ffe8e57) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | | function(timestampExpression, ...) | +| [timestampExtract(timestampExpression, part, timezone)](./firestore_lite_pipelines.md#timestampextract_b2f8f48) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | +| [timestampExtract(timestampExpression, part, timezone)](./firestore_lite_pipelines.md#timestampextract_73e0311) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | | [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_ad5d843) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | | [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_d6ab2a4) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | | function(tryExpr, ...) | @@ -447,6 +457,7 @@ https://github.com/firebase/firebase-js-sdk | [SetOptions](./firestore_lite_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | | [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | (Public Preview) Specify time granularity for expressions. | +| [TimePart](./firestore_lite_pipelines.md#timepart) | (Public Preview) Specify time parts for timestampExtract expressions. | | [Type](./firestore_lite_pipelines.md#type) | (Public Preview) An enumeration of the different types generated by the Firestore backend.
    • Numerics evaluate directly to backend representation (int64 or float64), not JS number.
    • JavaScript Date and firestore Timestamp objects strictly evaluate to 'timestamp'.
    • Advanced configurations parsing backend types (such as decimal128, max_key or min_key from BSON) are also incorporated in this union string type. Note that decimal128 is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    | | [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | | [UnnestStageOptions](./firestore_lite_pipelines.md#unneststageoptions) | (Public Preview) Represents the specific options available for configuring an UnnestStage within a pipeline. | @@ -2107,6 +2118,154 @@ map({foo: 'bar', baz: field('baz')}).as('data'); ``` +## function(endExpression, ...) + +### timestampDiff(endExpression, startFieldName, unit) {:#timestampdiff_8cb2a38} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the difference between two timestamps. + +Signature: + +```typescript +export declare function timestampDiff(endExpression: Expression, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| endExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The ending timestamp for the difference calculation. | +| startFieldName | string | The name of the field representing the starting timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the difference as an integer. + +### Example + + +```typescript +// Calculate the difference in days between an ending timestamp expression and 'startTime' field. +timestampDiff(field('endTime'), 'startTime', 'day') + +``` + +### timestampDiff(endExpression, startExpression, unit) {:#timestampdiff_33aecb4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the difference between two timestamps. + +Signature: + +```typescript +export declare function timestampDiff(endExpression: Expression, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| endExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The ending timestamp for the difference calculation. | +| startExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The starting timestamp for the difference calculation. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the difference as an integer. + +### Example + + +```typescript +// Calculate the difference in days between two timestamp expressions. +timestampDiff(field('endTime'), field('startTime'), 'day') + +``` + +## function(endFieldName, ...) + +### timestampDiff(endFieldName, startFieldName, unit) {:#timestampdiff_c062afd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the difference between two timestamps. + +Signature: + +```typescript +export declare function timestampDiff(endFieldName: string, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| endFieldName | string | The name of the field representing the ending timestamp. | +| startFieldName | string | The name of the field representing the starting timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the difference as an integer. + +### Example + + +```typescript +// Calculate the difference in days between 'endTime' and 'startTime' fields. +timestampDiff('endTime', 'startTime', 'day') + +``` + +### timestampDiff(endFieldName, startExpression, unit) {:#timestampdiff_8244545} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the difference between two timestamps. + +Signature: + +```typescript +export declare function timestampDiff(endFieldName: string, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| endFieldName | string | The name of the field representing the ending timestamp. | +| startExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The starting timestamp for the difference calculation. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the difference as an integer. + +### Example + + +```typescript +// Calculate the difference in days between 'endTime' field and a starting timestamp expression. +timestampDiff('endTime', field('startTime'), 'day') + +``` + ## function(expr, ...) ### abs(expr) {:#abs_005f3d4} @@ -8068,6 +8227,78 @@ timestampAdd("timestamp", "day", 1); ``` +### timestampExtract(fieldName, part, timezone) {:#timestampextract_a51c205} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that extracts a specified part from a timestamp. + +Signature: + +```typescript +export declare function timestampExtract(fieldName: string, part: TimePart, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. | +| part | [TimePart](./firestore_lite_pipelines.md#timepart) | The part to extract from the timestamp (e.g., "year", "month", "day"). | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for extraction. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1." | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the extracted part as an integer. + +### Example + + +```typescript +// Extract the year from the 'createdAt' timestamp. +timestampExtract('createdAt', 'year') + +``` + +### timestampExtract(fieldName, part, timezone) {:#timestampextract_2d51eac} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that extracts a specified part from a timestamp. + +Signature: + +```typescript +export declare function timestampExtract(fieldName: string, part: Expression, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. | +| part | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluating to the part to extract. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for extraction. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1." | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the extracted part as an integer. + +### Example + + +```typescript +// Extract the part specified by the field 'part' from 'createdAt'. +timestampExtract('createdAt', field('part')) + +``` + ### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_341fe7d} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -8238,7 +8469,7 @@ A new `Expression` representing the truncated timestamp. ```typescript // Truncate the 'createdAt' timestamp to the beginning of the day. -field('createdAt').timestampTruncate('day') +timestampTruncate('createdAt', 'day') ``` @@ -8274,7 +8505,7 @@ A new `Expression` representing the truncated timestamp. ```typescript // Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. -field('createdAt').timestampTruncate(field('granularity')) +timestampTruncate('createdAt', field('granularity')) ``` @@ -11171,6 +11402,78 @@ timestampSubtract(field("timestamp"), "day", 1); ## function(timestampExpression, ...) +### timestampExtract(timestampExpression, part, timezone) {:#timestampextract_b2f8f48} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that extracts a specified part from a timestamp. + +Signature: + +```typescript +export declare function timestampExtract(timestampExpression: Expression, part: TimePart, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestampExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluating to the timestamp. | +| part | [TimePart](./firestore_lite_pipelines.md#timepart) | The part to extract from the timestamp (e.g., "year", "month", "day"). | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for extraction. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1." | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the extracted part as an integer. + +### Example + + +```typescript +// Extract the year from the timestamp returned by the expression. +timestampExtract(field('createdAt'), 'year') + +``` + +### timestampExtract(timestampExpression, part, timezone) {:#timestampextract_73e0311} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that extracts a specified part from a timestamp. + +Signature: + +```typescript +export declare function timestampExtract(timestampExpression: Expression, part: Expression, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestampExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluating to the timestamp. | +| part | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression evaluating to the part to extract. | +| timezone | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The timezone to use for extraction. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1." | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the extracted part as an integer. + +### Example + + +```typescript +// Extract the part specified by the field 'part' from the timestamp. +timestampExtract(field('createdAt'), field('part')) + +``` + ### timestampTruncate(timestampExpression, granularity, timezone) {:#timestamptruncate_ad5d843} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -11203,7 +11506,7 @@ A new `Expression` representing the truncated timestamp. ```typescript // Truncate the 'createdAt' timestamp to the beginning of the day. -field('createdAt').timestampTruncate('day') +timestampTruncate(field('createdAt'), 'day') ``` @@ -11239,7 +11542,7 @@ A new `Expression` representing the truncated timestamp. ```typescript // Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. -field('createdAt').timestampTruncate(field('granularity')) +timestampTruncate(field('createdAt'), field('granularity')) ``` @@ -12281,6 +12584,19 @@ Specify time granularity for expressions. export declare type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; ``` +## TimePart + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Specify time parts for `timestampExtract` expressions. + +Signature: + +```typescript +export declare type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; +``` + ## Type > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index f0f10abc82..c4cc20b192 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -180,6 +180,10 @@ export declare abstract class Expression | [sum()](./firestore_pipelines.expression.md#expressionsum) | | (Public Preview) Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. | | [timestampAdd(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. | | [timestampAdd(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. | +| [timestampDiff(start, unit)](./firestore_pipelines.expression.md#expressiontimestampdiff) | | (Public Preview) Creates an expression that calculates the difference between this timestamp and another timestamp. | +| [timestampDiff(start, unit)](./firestore_pipelines.expression.md#expressiontimestampdiff) | | (Public Preview) Creates an expression that calculates the difference between this timestamp and another timestamp. | +| [timestampExtract(part, timezone)](./firestore_pipelines.expression.md#expressiontimestampextract) | | (Public Preview) Creates an expression that extracts a specified part from this timestamp expression. | +| [timestampExtract(part, timezone)](./firestore_pipelines.expression.md#expressiontimestampextract) | | (Public Preview) Creates an expression that extracts a specified part from this timestamp expression. | | [timestampSubtract(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. | | [timestampSubtract(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. | | [timestampToUnixMicros()](./firestore_pipelines.expression.md#expressiontimestamptounixmicros) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | @@ -4818,6 +4822,146 @@ field("timestamp").timestampAdd("day", 1); ``` +## Expression.timestampDiff() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the difference between this timestamp and another timestamp. + +Signature: + +```typescript +timestampDiff(start: Expression, unit: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| start | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluating to the starting timestamp. | +| unit | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluates to a unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the difference as an integer. + +### Example + + +```typescript +// Calculate the difference determined by fields 'startTime' and 'unit'. +field("endTime").timestampDiff(field("startTime"), field("unit")); + +``` + +## Expression.timestampDiff() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the difference between this timestamp and another timestamp. + +Signature: + +```typescript +timestampDiff(start: string | Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| start | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The field name of the starting timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time for the difference (e.g., "day", "hour"). | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the difference as an integer. + +### Example + + +```typescript +// Calculate the difference in days between 'endTime' and 'startTime' fields. +field("endTime").timestampDiff("startTime", "day"); + +``` + +## Expression.timestampExtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that extracts a specified part from this timestamp expression. + +Signature: + +```typescript +timestampExtract(part: TimePart, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| part | [TimePart](./firestore_pipelines.md#timepart) | The part to extract from the timestamp (e.g., "year", "month", "day"). | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for extraction. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1." | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the extracted part as an integer. + +### Example + + +```typescript +// Extract the year from the 'createdAt' field. +field('createdAt').timestampExtract('year') + +``` + +## Expression.timestampExtract() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that extracts a specified part from this timestamp expression. + +Signature: + +```typescript +timestampExtract(part: Expression, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| part | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluating to the part to extract. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for extraction. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1." | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the extracted part as an integer. + +### Example + + +```typescript +// Extract the part specified by the field 'extractionPart' from 'createdAt'. +field('createdAt').timestampExtract(field('extractionPart')) + +``` + ## Expression.timestampSubtract() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 6f51fe0d2e..f9e1c381e1 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -74,6 +74,12 @@ https://github.com/firebase/firebase-js-sdk | function(elements, ...) | | [array(elements)](./firestore_pipelines.md#array_7d853aa) | (Public Preview) Creates an expression that creates a Firestore array value from an input array. | | [map(elements)](./firestore_pipelines.md#map_ce5dee1) | (Public Preview) Creates an expression that creates a Firestore map value from an input object. | +| function(endExpression, ...) | +| [timestampDiff(endExpression, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_8cb2a38) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endExpression, startExpression, unit)](./firestore_pipelines.md#timestampdiff_33aecb4) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| function(endFieldName, ...) | +| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_c062afd) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endFieldName, startExpression, unit)](./firestore_pipelines.md#timestampdiff_8244545) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | | function(expr, ...) | | [abs(expr)](./firestore_pipelines.md#abs_005f3d4) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | | [ascending(expr)](./firestore_pipelines.md#ascending_005f3d4) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. | @@ -250,6 +256,8 @@ https://github.com/firebase/firebase-js-sdk | [subtract(fieldName, value)](./firestore_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. | | [sum(fieldName)](./firestore_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. | | [timestampAdd(fieldName, unit, amount)](./firestore_pipelines.md#timestampadd_341fe7d) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. | +| [timestampExtract(fieldName, part, timezone)](./firestore_pipelines.md#timestampextract_a51c205) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | +| [timestampExtract(fieldName, part, timezone)](./firestore_pipelines.md#timestampextract_2d51eac) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | | [timestampSubtract(fieldName, unit, amount)](./firestore_pipelines.md#timestampsubtract_341fe7d) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. | | [timestampToUnixMicros(fieldName)](./firestore_pipelines.md#timestamptounixmicros_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | | [timestampToUnixMillis(fieldName)](./firestore_pipelines.md#timestamptounixmillis_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | @@ -358,6 +366,8 @@ https://github.com/firebase/firebase-js-sdk | [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_98418f9) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | | [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_ffe8e57) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | | function(timestampExpression, ...) | +| [timestampExtract(timestampExpression, part, timezone)](./firestore_pipelines.md#timestampextract_b2f8f48) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | +| [timestampExtract(timestampExpression, part, timezone)](./firestore_pipelines.md#timestampextract_73e0311) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | | [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_ad5d843) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | | [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_d6ab2a4) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | | function(tryExpr, ...) | @@ -453,6 +463,7 @@ https://github.com/firebase/firebase-js-sdk | [SetOptions](./firestore_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | | [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | | [TimeGranularity](./firestore_pipelines.md#timegranularity) | (Public Preview) Specify time granularity for expressions. | +| [TimePart](./firestore_pipelines.md#timepart) | (Public Preview) Specify time parts for timestampExtract expressions. | | [Type](./firestore_pipelines.md#type) | (Public Preview) An enumeration of the different types generated by the Firestore backend.
    • Numerics evaluate directly to backend representation (int64 or float64), not JS number.
    • JavaScript Date and firestore Timestamp objects strictly evaluate to 'timestamp'.
    • Advanced configurations parsing backend types (such as decimal128, max_key or min_key from BSON) are also incorporated in this union string type. Note that decimal128 is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    | | [UnionStageOptions](./firestore_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | | [UnnestStageOptions](./firestore_pipelines.md#unneststageoptions) | (Public Preview) Represents the specific options available for configuring an UnnestStage within a pipeline. | @@ -2113,6 +2124,154 @@ map({foo: 'bar', baz: field('baz')}).as('data'); ``` +## function(endExpression, ...) + +### timestampDiff(endExpression, startFieldName, unit) {:#timestampdiff_8cb2a38} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the difference between two timestamps. + +Signature: + +```typescript +export declare function timestampDiff(endExpression: Expression, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| endExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The ending timestamp for the difference calculation. | +| startFieldName | string | The name of the field representing the starting timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the difference as an integer. + +### Example + + +```typescript +// Calculate the difference in days between an ending timestamp expression and 'startTime' field. +timestampDiff(field('endTime'), 'startTime', 'day') + +``` + +### timestampDiff(endExpression, startExpression, unit) {:#timestampdiff_33aecb4} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the difference between two timestamps. + +Signature: + +```typescript +export declare function timestampDiff(endExpression: Expression, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| endExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The ending timestamp for the difference calculation. | +| startExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The starting timestamp for the difference calculation. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the difference as an integer. + +### Example + + +```typescript +// Calculate the difference in days between two timestamp expressions. +timestampDiff(field('endTime'), field('startTime'), 'day') + +``` + +## function(endFieldName, ...) + +### timestampDiff(endFieldName, startFieldName, unit) {:#timestampdiff_c062afd} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the difference between two timestamps. + +Signature: + +```typescript +export declare function timestampDiff(endFieldName: string, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| endFieldName | string | The name of the field representing the ending timestamp. | +| startFieldName | string | The name of the field representing the starting timestamp. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the difference as an integer. + +### Example + + +```typescript +// Calculate the difference in days between 'endTime' and 'startTime' fields. +timestampDiff('endTime', 'startTime', 'day') + +``` + +### timestampDiff(endFieldName, startExpression, unit) {:#timestampdiff_8244545} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that calculates the difference between two timestamps. + +Signature: + +```typescript +export declare function timestampDiff(endFieldName: string, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| endFieldName | string | The name of the field representing the ending timestamp. | +| startExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The starting timestamp for the difference calculation. | +| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the difference as an integer. + +### Example + + +```typescript +// Calculate the difference in days between 'endTime' field and a starting timestamp expression. +timestampDiff('endTime', field('startTime'), 'day') + +``` + ## function(expr, ...) ### abs(expr) {:#abs_005f3d4} @@ -8074,6 +8233,78 @@ timestampAdd("timestamp", "day", 1); ``` +### timestampExtract(fieldName, part, timezone) {:#timestampextract_a51c205} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that extracts a specified part from a timestamp. + +Signature: + +```typescript +export declare function timestampExtract(fieldName: string, part: TimePart, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. | +| part | [TimePart](./firestore_pipelines.md#timepart) | The part to extract from the timestamp (e.g., "year", "month", "day"). | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for extraction. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1." | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the extracted part as an integer. + +### Example + + +```typescript +// Extract the year from the 'createdAt' timestamp. +timestampExtract('createdAt', 'year') + +``` + +### timestampExtract(fieldName, part, timezone) {:#timestampextract_2d51eac} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that extracts a specified part from a timestamp. + +Signature: + +```typescript +export declare function timestampExtract(fieldName: string, part: Expression, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field representing the timestamp. | +| part | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluating to the part to extract. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for extraction. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1." | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the extracted part as an integer. + +### Example + + +```typescript +// Extract the part specified by the field 'part' from 'createdAt'. +timestampExtract('createdAt', field('part')) + +``` + ### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_341fe7d} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -8244,7 +8475,7 @@ A new `Expression` representing the truncated timestamp. ```typescript // Truncate the 'createdAt' timestamp to the beginning of the day. -field('createdAt').timestampTruncate('day') +timestampTruncate('createdAt', 'day') ``` @@ -8280,7 +8511,7 @@ A new `Expression` representing the truncated timestamp. ```typescript // Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. -field('createdAt').timestampTruncate(field('granularity')) +timestampTruncate('createdAt', field('granularity')) ``` @@ -11246,6 +11477,78 @@ timestampSubtract(field("timestamp"), "day", 1); ## function(timestampExpression, ...) +### timestampExtract(timestampExpression, part, timezone) {:#timestampextract_b2f8f48} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that extracts a specified part from a timestamp. + +Signature: + +```typescript +export declare function timestampExtract(timestampExpression: Expression, part: TimePart, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestampExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluating to the timestamp. | +| part | [TimePart](./firestore_pipelines.md#timepart) | The part to extract from the timestamp (e.g., "year", "month", "day"). | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for extraction. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1." | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the extracted part as an integer. + +### Example + + +```typescript +// Extract the year from the timestamp returned by the expression. +timestampExtract(field('createdAt'), 'year') + +``` + +### timestampExtract(timestampExpression, part, timezone) {:#timestampextract_73e0311} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that extracts a specified part from a timestamp. + +Signature: + +```typescript +export declare function timestampExtract(timestampExpression: Expression, part: Expression, timezone?: string | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| timestampExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluating to the timestamp. | +| part | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression evaluating to the part to extract. | +| timezone | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The timezone to use for extraction. Valid values are from the TZ database (e.g., "America/Los\_Angeles") or in the format "Etc/GMT-1." | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the extracted part as an integer. + +### Example + + +```typescript +// Extract the part specified by the field 'part' from the timestamp. +timestampExtract(field('createdAt'), field('part')) + +``` + ### timestampTruncate(timestampExpression, granularity, timezone) {:#timestamptruncate_ad5d843} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -11278,7 +11581,7 @@ A new `Expression` representing the truncated timestamp. ```typescript // Truncate the 'createdAt' timestamp to the beginning of the day. -field('createdAt').timestampTruncate('day') +timestampTruncate(field('createdAt'), 'day') ``` @@ -11314,7 +11617,7 @@ A new `Expression` representing the truncated timestamp. ```typescript // Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. -field('createdAt').timestampTruncate(field('granularity')) +timestampTruncate(field('createdAt'), field('granularity')) ``` @@ -12356,6 +12659,19 @@ Specify time granularity for expressions. export declare type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; ``` +## TimePart + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Specify time parts for `timestampExtract` expressions. + +Signature: + +```typescript +export declare type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; +``` + ## Type > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index 88a4e7f242..db02745c84 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -186,6 +186,7 @@ export { timestampToUnixSeconds, timestampAdd, timestampSubtract, + timestampDiff, ascending, descending, abs, @@ -212,6 +213,7 @@ export { arraySum, split, timestampTruncate, + timestampExtract, AliasedExpression, Field, Constant, @@ -223,5 +225,6 @@ export { BooleanExpression, AggregateFunction, TimeGranularity, + TimePart, Type } from '../../src/lite-api/expressions'; diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index 411a9e81e7..5c6dd9baf7 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -147,6 +147,7 @@ export { timestampToUnixSeconds, timestampAdd, timestampSubtract, + timestampDiff, ascending, descending, countIf, @@ -180,6 +181,7 @@ export { log10, arraySum, timestampTruncate, + timestampExtract, split, Expression, AliasedExpression, @@ -192,6 +194,7 @@ export { AliasedAggregate, Selectable, TimeGranularity, + TimePart, Type } from './lite-api/expressions'; diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index a0629c254a..459d8e2310 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -2620,6 +2620,113 @@ export abstract class Expression implements ProtoValueSerializable, UserData { ); } + /** + * @beta + * Creates an expression that calculates the difference between this timestamp and another timestamp. + * + * @example + * ```typescript + * // Calculate the difference determined by fields 'startTime' and 'unit'. + * field("endTime").timestampDiff(field("startTime"), field("unit")); + * ``` + * + * @param start - The expression evaluating to the starting timestamp. + * @param unit - The expression evaluates to a unit of time, must be one of 'microsecond', 'millisecond', 'second', 'minute', 'hour', 'day'. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the difference as an integer. + */ + timestampDiff(start: Expression, unit: Expression): FunctionExpression; + + /** + * @beta + * Creates an expression that calculates the difference between this timestamp and another timestamp. + * + * @example + * ```typescript + * // Calculate the difference in days between 'endTime' and 'startTime' fields. + * field("endTime").timestampDiff("startTime", "day"); + * ``` + * + * @param start - The field name of the starting timestamp. + * @param unit - The unit of time for the difference (e.g., "day", "hour"). + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the difference as an integer. + */ + timestampDiff( + start: string | Expression, + unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' + ): FunctionExpression; + timestampDiff( + start: string | Expression, + unit: + | 'microsecond' + | 'millisecond' + | 'second' + | 'minute' + | 'hour' + | 'day' + | Expression + ): FunctionExpression { + return new FunctionExpression( + 'timestamp_diff', + [this, fieldOrExpression(start), valueToDefaultExpr(unit)], + 'timestampDiff' + ); + } + + /** + * @beta + * Creates an expression that extracts a specified part from this timestamp expression. + * + * @example + * ```typescript + * // Extract the year from the 'createdAt' field. + * field('createdAt').timestampExtract('year') + * ``` + * + * @param part - The part to extract from the timestamp (e.g., "year", "month", "day"). + * @param timezone - The timezone to use for extraction. Valid values are from + * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1." + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the extracted part as an integer. + */ + timestampExtract( + part: TimePart, + timezone?: string | Expression + ): FunctionExpression; + + /** + * @beta + * Creates an expression that extracts a specified part from this timestamp expression. + * + * @example + * ```typescript + * // Extract the part specified by the field 'extractionPart' from 'createdAt'. + * field('createdAt').timestampExtract(field('extractionPart')) + * ``` + * + * @param part - The expression evaluating to the part to extract. + * @param timezone - The timezone to use for extraction. Valid values are from + * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1." + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the extracted part as an integer. + */ + timestampExtract( + part: Expression, + timezone?: string | Expression + ): FunctionExpression; + timestampExtract( + part: TimePart | Expression, + timezone?: string | Expression + ): FunctionExpression { + const internalPart = isString(part) ? part.toLowerCase() : part; + const args = [this, valueToDefaultExpr(internalPart)]; + if (timezone) { + args.push(valueToDefaultExpr(timezone)); + } + return new FunctionExpression( + 'timestamp_extract', + args, + 'timestampExtract' + ); + } + /** * @beta * @@ -3385,6 +3492,12 @@ export type TimeGranularity = | 'year' | 'isoYear'; +/** + * @beta + * Specify time parts for `timestampExtract` expressions. + */ +export type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; + /** * @beta * @@ -10836,7 +10949,7 @@ export function split( * @example * ```typescript * // Truncate the 'createdAt' timestamp to the beginning of the day. - * field('createdAt').timestampTruncate('day') + * timestampTruncate('createdAt', 'day') * ``` * * @param fieldName - Truncate the timestamp value contained in this field. @@ -10858,7 +10971,7 @@ export function timestampTruncate( * @example * ```typescript * // Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. - * field('createdAt').timestampTruncate(field('granularity')) + * timestampTruncate('createdAt', field('granularity')) * ``` * * @param fieldName - Truncate the timestamp value contained in this field. @@ -10880,7 +10993,7 @@ export function timestampTruncate( * @example * ```typescript * // Truncate the 'createdAt' timestamp to the beginning of the day. - * field('createdAt').timestampTruncate('day') + * timestampTruncate(field('createdAt'), 'day') * ``` * * @param timestampExpression - Truncate the timestamp value that is returned by this expression. @@ -10902,7 +11015,7 @@ export function timestampTruncate( * @example * ```typescript * // Truncate the 'createdAt' timestamp to the granularity specified in the field 'granularity'. - * field('createdAt').timestampTruncate(field('granularity')) + * timestampTruncate(field('createdAt'), field('granularity')) * ``` * * @param timestampExpression - Truncate the timestamp value that is returned by this expression. @@ -10930,6 +11043,233 @@ export function timestampTruncate( ); } +/** + * @beta + * Creates an expression that calculates the difference between two timestamps. + * + * @example + * ```typescript + * // Calculate the difference in days between 'endTime' and 'startTime' fields. + * timestampDiff('endTime', 'startTime', 'day') + * ``` + * + * @param endFieldName - The name of the field representing the ending timestamp. + * @param startFieldName - The name of the field representing the starting timestamp. + * @param unit - The unit of time for the difference (e.g., "day", "hour"). + * @returns A new `Expression` representing the difference as an integer. + */ +export function timestampDiff( + endFieldName: string, + startFieldName: string, + unit: + | 'microsecond' + | 'millisecond' + | 'second' + | 'minute' + | 'hour' + | 'day' + | Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that calculates the difference between two timestamps. + * + * @example + * ```typescript + * // Calculate the difference in days between 'endTime' field and a starting timestamp expression. + * timestampDiff('endTime', field('startTime'), 'day') + * ``` + * + * @param endFieldName - The name of the field representing the ending timestamp. + * @param startExpression - The starting timestamp for the difference calculation. + * @param unit - The unit of time for the difference (e.g., "day", "hour"). + * @returns A new `Expression` representing the difference as an integer. + */ +export function timestampDiff( + endFieldName: string, + startExpression: Expression, + unit: + | 'microsecond' + | 'millisecond' + | 'second' + | 'minute' + | 'hour' + | 'day' + | Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that calculates the difference between two timestamps. + * + * @example + * ```typescript + * // Calculate the difference in days between an ending timestamp expression and 'startTime' field. + * timestampDiff(field('endTime'), 'startTime', 'day') + * ``` + * + * @param endExpression - The ending timestamp for the difference calculation. + * @param startFieldName - The name of the field representing the starting timestamp. + * @param unit - The unit of time for the difference (e.g., "day", "hour"). + * @returns A new `Expression` representing the difference as an integer. + */ +export function timestampDiff( + endExpression: Expression, + startFieldName: string, + unit: + | 'microsecond' + | 'millisecond' + | 'second' + | 'minute' + | 'hour' + | 'day' + | Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that calculates the difference between two timestamps. + * + * @example + * ```typescript + * // Calculate the difference in days between two timestamp expressions. + * timestampDiff(field('endTime'), field('startTime'), 'day') + * ``` + * + * @param endExpression - The ending timestamp for the difference calculation. + * @param startExpression - The starting timestamp for the difference calculation. + * @param unit - The unit of time for the difference (e.g., "day", "hour"). + * @returns A new `Expression` representing the difference as an integer. + */ +export function timestampDiff( + endExpression: Expression, + startExpression: Expression, + unit: + | 'microsecond' + | 'millisecond' + | 'second' + | 'minute' + | 'hour' + | 'day' + | Expression +): FunctionExpression; +export function timestampDiff( + endFieldNameOrExpression: string | Expression, + startFieldNameOrExpression: string | Expression, + unit: + | 'microsecond' + | 'millisecond' + | 'second' + | 'minute' + | 'hour' + | 'day' + | Expression +): FunctionExpression { + const normalizedEnd = fieldOrExpression(endFieldNameOrExpression); + const normalizedStart = fieldOrExpression(startFieldNameOrExpression); + const normalizedUnit = valueToDefaultExpr(unit); + return normalizedEnd.timestampDiff(normalizedStart, normalizedUnit); +} + +/** + * @beta + * Creates an expression that extracts a specified part from a timestamp. + * + * @example + * ```typescript + * // Extract the year from the 'createdAt' timestamp. + * timestampExtract('createdAt', 'year') + * ``` + * + * @param fieldName - The name of the field representing the timestamp. + * @param part - The part to extract from the timestamp (e.g., "year", "month", "day"). + * @param timezone - The timezone to use for extraction. Valid values are from + * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1." + * @returns A new `Expression` representing the extracted part as an integer. + */ +export function timestampExtract( + fieldName: string, + part: TimePart, + timezone?: string | Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that extracts a specified part from a timestamp. + * + * @example + * ```typescript + * // Extract the part specified by the field 'part' from 'createdAt'. + * timestampExtract('createdAt', field('part')) + * ``` + * + * @param fieldName - The name of the field representing the timestamp. + * @param part - The expression evaluating to the part to extract. + * @param timezone - The timezone to use for extraction. Valid values are from + * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1." + * @returns A new `Expression` representing the extracted part as an integer. + */ +export function timestampExtract( + fieldName: string, + part: Expression, + timezone?: string | Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that extracts a specified part from a timestamp. + * + * @example + * ```typescript + * // Extract the year from the timestamp returned by the expression. + * timestampExtract(field('createdAt'), 'year') + * ``` + * + * @param timestampExpression - The expression evaluating to the timestamp. + * @param part - The part to extract from the timestamp (e.g., "year", "month", "day"). + * @param timezone - The timezone to use for extraction. Valid values are from + * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1." + * @returns A new `Expression` representing the extracted part as an integer. + */ +export function timestampExtract( + timestampExpression: Expression, + part: TimePart, + timezone?: string | Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that extracts a specified part from a timestamp. + * + * @example + * ```typescript + * // Extract the part specified by the field 'part' from the timestamp. + * timestampExtract(field('createdAt'), field('part')) + * ``` + * + * @param timestampExpression - The expression evaluating to the timestamp. + * @param part - The expression evaluating to the part to extract. + * @param timezone - The timezone to use for extraction. Valid values are from + * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1." + * @returns A new `Expression` representing the extracted part as an integer. + */ +export function timestampExtract( + timestampExpression: Expression, + part: Expression, + timezone?: string | Expression +): FunctionExpression; +export function timestampExtract( + fieldNameOrExpression: string | Expression, + part: TimePart | Expression, + timezone?: string | Expression +): FunctionExpression { + return fieldOrExpression(fieldNameOrExpression).timestampExtract( + valueToDefaultExpr(isString(part) ? part.toLowerCase() : part), + timezone + ); +} + // TODO(new-expression): Add new top-level expression function definitions above this line /** diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index fe8c5e5051..e8c00885de 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -170,6 +170,8 @@ import { arraySum, PipelineSnapshot, timestampTruncate, + timestampDiff, + timestampExtract, split, type, isType @@ -5129,6 +5131,73 @@ apiDescribe.skipClassic('Pipelines', persistence => { }); }); + it('supports timestamp difference', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .select( + constant(new Timestamp(1741437296, 123456789)).as('end'), + constant(new Timestamp(1741428000, 0)).as('start') + ) + .select( + timestampDiff(field('end'), field('start'), 'hour').as('diffHour'), + field('end') + .timestampDiff(field('start'), 'minute') + .as('diffMinute'), + field('end') + .timestampDiff(field('start'), 'second') + .as('diffSecond'), + field('start').timestampDiff(field('end'), 'hour').as('diffHourNeg') + ) + ); + + expectResults(snapshot, { + diffHour: 2, + diffMinute: 154, + diffSecond: 9296, + diffHourNeg: -2 + }); + }).timeout(10000); + + it('supports timestamp extraction', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .select(constant(new Timestamp(1741437296, 123456789)).as('ts')) + .select( + timestampExtract(field('ts'), 'year').as('year'), + field('ts').timestampExtract('month').as('month'), + timestampExtract(field('ts'), 'day').as('day'), + field('ts').timestampExtract('hour').as('hour'), + timestampExtract(field('ts'), 'minute').as('minute'), + field('ts').timestampExtract('second').as('second'), + timestampExtract(field('ts'), 'millisecond').as('millis'), + field('ts').timestampExtract('microsecond').as('micros'), + timestampExtract(field('ts'), 'dayofyear').as('dayOfYear'), + field('ts') + .timestampExtract('hour', 'America/Los_Angeles') + .as('hourLa') + ) + ); + + expectResults(snapshot, { + year: 2025, + month: 3, + day: 8, + hour: 12, + minute: 34, + second: 56, + millis: 123, + micros: 123456, + dayOfYear: 67, + hourLa: 4 + }); + }).timeout(10000); + it('supports split', async () => { const results = await execute( firestore diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 9372ff04b2..4dea47cd1f 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -123,6 +123,9 @@ import { timestampToUnixSeconds, timestampAdd, timestampSubtract, + timestampTruncate, + timestampDiff, + timestampExtract, ascending, descending, FunctionExpression, @@ -3922,6 +3925,127 @@ describe.skipClassic('Firestore Pipelines', () => { }); }).timeout(10000); + it('supports timestamp truncation', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .select( + constant(new Timestamp(1741437296, 123456789)).as('timestamp') + ) + .select( + timestampTruncate(field('timestamp'), 'year').as('truncYear'), + timestampTruncate(field('timestamp'), 'month').as('truncMonth'), + timestampTruncate(field('timestamp'), 'day').as('truncDay'), + timestampTruncate(field('timestamp'), 'hour').as('truncHour'), + timestampTruncate(field('timestamp'), 'minute').as('truncMinute'), + timestampTruncate(field('timestamp'), 'second').as('truncSecond'), + timestampTruncate(field('timestamp'), 'isoWeek').as('truncIsoWeek') + ) + ); + + expectResults(snapshot, { + truncYear: new Timestamp(1735689600, 0), + truncMonth: new Timestamp(1740787200, 0), + truncDay: new Timestamp(1741392000, 0), + truncHour: new Timestamp(1741435200, 0), + truncMinute: new Timestamp(1741437240, 0), + truncSecond: new Timestamp(1741437296, 0), + truncIsoWeek: new Timestamp(1740960000, 0) + }); + }).timeout(10000); + + it('supports timestamp truncation with timezone', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .select( + constant(new Timestamp(1741437296, 123456789)).as('timestamp') + ) + .select( + timestampTruncate( + field('timestamp'), + 'day', + 'America/Los_Angeles' + ).as('truncDayLa') + ) + ); + + expectResults(snapshot, { + truncDayLa: new Timestamp(1741420800, 0) + }); + }).timeout(10000); + + it('supports timestamp difference', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .select( + constant(new Timestamp(1741437296, 123456789)).as('end'), + constant(new Timestamp(1741428000, 0)).as('start') + ) + .select( + timestampDiff(field('end'), field('start'), 'hour').as('diffHour'), + field('end') + .timestampDiff(field('start'), 'minute') + .as('diffMinute'), + field('end') + .timestampDiff(field('start'), 'second') + .as('diffSecond'), + field('start').timestampDiff(field('end'), 'hour').as('diffHourNeg') + ) + ); + + expectResults(snapshot, { + diffHour: 2, + diffMinute: 154, + diffSecond: 9296, + diffHourNeg: -2 + }); + }).timeout(10000); + + it('supports timestamp extraction', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol) + .limit(1) + .select(constant(new Timestamp(1741437296, 123456789)).as('ts')) + .select( + timestampExtract(field('ts'), 'year').as('year'), + field('ts').timestampExtract('month').as('month'), + timestampExtract(field('ts'), 'day').as('day'), + field('ts').timestampExtract('hour').as('hour'), + timestampExtract(field('ts'), 'minute').as('minute'), + field('ts').timestampExtract('second').as('second'), + timestampExtract(field('ts'), 'millisecond').as('millis'), + field('ts').timestampExtract('microsecond').as('micros'), + timestampExtract(field('ts'), 'dayofyear').as('dayOfYear'), + field('ts') + .timestampExtract('hour', 'America/Los_Angeles') + .as('hourLa') + ) + ); + + expectResults(snapshot, { + year: 2025, + month: 3, + day: 8, + hour: 12, + minute: 34, + second: 56, + millis: 123, + micros: 123456, + dayOfYear: 67, + hourLa: 4 + }); + }).timeout(10000); + it('supports byteLength', async () => { const snapshot = await execute( firestore From 5a5db88cca82cf5370d67a8e8cf0ae2013ce75dc Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 25 Mar 2026 10:46:53 -0700 Subject: [PATCH 110/174] remove dependabot.yml (#9743) --- .github/dependabot.yml | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index c98f8fb04d..0000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,20 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "npm" - directories: - - "/" - - "/packages/*" - - "/integration/*" - - "/e2e/*" - - "/repo-scripts/**/*" - exclude-paths: - - "packages/auth/demo" - - "packages/auth/cordova/demo" - - "packages/auth-compat/demo" - schedule: - interval: "daily" - - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "daily" From 4e99d4ba66a9a28558cd504826ae04fd07251c1b Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Wed, 25 Mar 2026 14:17:06 -0400 Subject: [PATCH 111/174] fix(firestore): read user data in internal pipeline proto serialization (#9752) --- .changeset/sour-peaches-attend.md | 5 +++++ .../firestore/src/remote/internal_serializer.ts | 13 +++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 .changeset/sour-peaches-attend.md diff --git a/.changeset/sour-peaches-attend.md b/.changeset/sour-peaches-attend.md new file mode 100644 index 0000000000..a0be554f67 --- /dev/null +++ b/.changeset/sour-peaches-attend.md @@ -0,0 +1,5 @@ +--- +'@firebase/firestore': patch +--- + +Read user data when using internal pipeline proto serialization. diff --git a/packages/firestore/src/remote/internal_serializer.ts b/packages/firestore/src/remote/internal_serializer.ts index 1e759dab81..d282bff1e5 100644 --- a/packages/firestore/src/remote/internal_serializer.ts +++ b/packages/firestore/src/remote/internal_serializer.ts @@ -26,6 +26,10 @@ import { AggregateSpec } from '../lite-api/aggregate_types'; import { getDatastore } from '../lite-api/components'; import { Pipeline } from '../lite-api/pipeline'; import { Query } from '../lite-api/reference'; +import { + newUserDataReader, + UserDataSource +} from '../lite-api/user_data_reader'; import { ExecutePipelineRequest as ProtoExecutePipelineRequest } from '../protos/firestore_proto_api'; import { cast } from '../util/input_validation'; import { mapToArray } from '../util/obj'; @@ -116,6 +120,15 @@ export function _internalPipelineToExecutePipelineRequestProto( // eslint-disable-next-line @typescript-eslint/no-explicit-any ): any { const firestore = cast(pipeline._db, Firestore); + + const userDataReader = newUserDataReader(firestore); + const context = userDataReader.createContext( + UserDataSource.Argument, + '_internalPipelineToExecutePipelineRequestProto' + ); + + pipeline._readUserData(context); + const datastore = getDatastore(firestore); const serializer = datastore.serializer; if (serializer === undefined) { From 334b266fec0fe63466dbb59bebe4d092bc3a924e Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Thu, 26 Mar 2026 13:03:52 -0400 Subject: [PATCH 112/174] fix(firestore): Read user data from pipeline in union stage (#9765) --- .changeset/stupid-turtles-grow.md | 5 ++++ packages/firestore/src/lite-api/stage.ts | 1 + .../test/integration/api/pipeline.test.ts | 29 +++++++++++++++++++ packages/firestore/test/lite/pipeline.test.ts | 29 +++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 .changeset/stupid-turtles-grow.md diff --git a/.changeset/stupid-turtles-grow.md b/.changeset/stupid-turtles-grow.md new file mode 100644 index 0000000000..5f4204fcda --- /dev/null +++ b/.changeset/stupid-turtles-grow.md @@ -0,0 +1,5 @@ +--- +'@firebase/firestore': patch +--- + +Read user data from pipeline in union stage. Fixes [GitHub Issue #9764](https://github.com/firebase/firebase-js-sdk/issues/9764) diff --git a/packages/firestore/src/lite-api/stage.ts b/packages/firestore/src/lite-api/stage.ts index 1cca37d4f6..0d6a17f08d 100644 --- a/packages/firestore/src/lite-api/stage.ts +++ b/packages/firestore/src/lite-api/stage.ts @@ -626,6 +626,7 @@ export class Union extends Stage { } _readUserData(context: ParseContext): void { + this.other._readUserData(context); super._readUserData(context); } } diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index e8c00885de..24e2405c4c 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -1910,6 +1910,35 @@ apiDescribe.skipClassic('Pipelines', persistence => { ); }); + it('run pipeline with user data with union', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .union( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + ) + .sort(field(documentIdFieldPath()).ascending()) + ); + expectResults( + snapshot, + 'book1', + 'book1', + 'book10', + 'book2', + 'book3', + 'book4', + 'book5', + 'book6', + 'book7', + 'book8', + 'book9' + ); + }); + it('supports options', async () => { const snapshot = await execute( firestore diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 4dea47cd1f..110009e9a7 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -1898,6 +1898,35 @@ describe.skipClassic('Firestore Pipelines', () => { ); }); + it('run pipeline with user data with union', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .union( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', "The Hitchhiker's Guide to the Galaxy")) + ) + .sort(field(documentIdFieldPath()).ascending()) + ); + expectResults( + snapshot, + 'book1', + 'book1', + 'book10', + 'book2', + 'book3', + 'book4', + 'book5', + 'book6', + 'book7', + 'book8', + 'book9' + ); + }); + it('supports options', async () => { const snapshot = await execute( firestore From dd10ed777b7bb4790c89225aa0a5be0a9d59e9a6 Mon Sep 17 00:00:00 2001 From: Yvonne Pan <103622026+yvonnep165@users.noreply.github.com> Date: Thu, 26 Mar 2026 13:34:18 -0400 Subject: [PATCH 113/174] fix(firestore): Refactor the parameters for timestamp expressions and fix bug for timeGranularity lowercase (#9750) * Add timestampTrunc, timestampDiff and timestampExtract expressions * Add changeset * Fix formatting * Fix variable names to follow camelCase * Generate documentation * Fix the int64 documentation error * Fix formatting * Add a test for isoWeek for timestampTruncate * Refactor the parameters for timestamp expressions and change all timegranularity value to lowercase * Remove duplicate timePart variables * Fix documentation error --- .changeset/orange-schools-bake.md | 6 + .../firestore-lite-pipelines.api.md | 27 ++-- common/api-review/firestore-pipelines.api.md | 27 ++-- .../firestore_lite_pipelines.expression.md | 16 +- docs-devsite/firestore_lite_pipelines.md | 80 ++++++---- .../firestore_pipelines.expression.md | 16 +- docs-devsite/firestore_pipelines.md | 80 ++++++---- .../firestore/lite/pipelines/pipelines.ts | 1 + packages/firestore/src/api_pipelines.ts | 1 + .../firestore/src/lite-api/expressions.ts | 147 +++++------------- packages/firestore/test/lite/pipeline.test.ts | 4 +- 11 files changed, 185 insertions(+), 220 deletions(-) create mode 100644 .changeset/orange-schools-bake.md diff --git a/.changeset/orange-schools-bake.md b/.changeset/orange-schools-bake.md new file mode 100644 index 0000000000..6976b8301e --- /dev/null +++ b/.changeset/orange-schools-bake.md @@ -0,0 +1,6 @@ +--- +'firebase': patch +'@firebase/firestore': patch +--- + +Refactor the parameters for timestamp expressions and change all timegranularity value to lowercase diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index dd54c9c827..8cf3be4d73 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -762,11 +762,11 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ timestampAdd(unit: Expression, amount: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ - timestampAdd(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + timestampAdd(unit: TimeUnit, amount: number): FunctionExpression; /* Excluded from this release type: _readUserData */ timestampDiff(start: Expression, unit: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ - timestampDiff(start: string | Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'): FunctionExpression; + timestampDiff(start: string | Expression, unit: TimeUnit): FunctionExpression; /* Excluded from this release type: _readUserData */ timestampExtract(part: TimePart, timezone?: string | Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ @@ -774,7 +774,7 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ - timestampSubtract(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + timestampSubtract(unit: TimeUnit, amount: number): FunctionExpression; /* Excluded from this release type: _readUserData */ timestampToUnixMicros(): FunctionExpression; /* Excluded from this release type: _readUserData */ @@ -1487,7 +1487,7 @@ export function sum(fieldName: string): AggregateFunction; export function switchOn(condition: BooleanExpression, result: Expression, ...others: Array): FunctionExpression; // @beta -export type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; +export type TimeGranularity = TimeUnit | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoweek' | 'month' | 'quarter' | 'year' | 'isoyear'; // @beta export type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; @@ -1496,22 +1496,22 @@ export type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; export function timestampAdd(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; // @beta -export function timestampAdd(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export function timestampAdd(timestamp: Expression, unit: TimeUnit, amount: number): FunctionExpression; // @beta -export function timestampAdd(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export function timestampAdd(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; // @beta -export function timestampDiff(endFieldName: string, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export function timestampDiff(endFieldName: string, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; // @beta -export function timestampDiff(endFieldName: string, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export function timestampDiff(endFieldName: string, startExpression: Expression, unit: TimeUnit | Expression): FunctionExpression; // @beta -export function timestampDiff(endExpression: Expression, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export function timestampDiff(endExpression: Expression, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; // @beta -export function timestampDiff(endExpression: Expression, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export function timestampDiff(endExpression: Expression, startExpression: Expression, unit: TimeUnit | Expression): FunctionExpression; // @beta export function timestampExtract(fieldName: string, part: TimePart, timezone?: string | Expression): FunctionExpression; @@ -1529,10 +1529,10 @@ export function timestampExtract(timestampExpression: Expression, part: Expressi export function timestampSubtract(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; // @beta -export function timestampSubtract(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export function timestampSubtract(timestamp: Expression, unit: TimeUnit, amount: number): FunctionExpression; // @beta -export function timestampSubtract(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export function timestampSubtract(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; // @beta export function timestampToUnixMicros(expr: Expression): FunctionExpression; @@ -1564,6 +1564,9 @@ export function timestampTruncate(timestampExpression: Expression, granularity: // @beta export function timestampTruncate(timestampExpression: Expression, granularity: Expression, timezone?: string | Expression): FunctionExpression; +// @beta +export type TimeUnit = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'; + // @beta export function toLower(fieldName: string): FunctionExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 3a2de9e77a..c49fddf2f7 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -765,11 +765,11 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ timestampAdd(unit: Expression, amount: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ - timestampAdd(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + timestampAdd(unit: TimeUnit, amount: number): FunctionExpression; /* Excluded from this release type: _readUserData */ timestampDiff(start: Expression, unit: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ - timestampDiff(start: string | Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'): FunctionExpression; + timestampDiff(start: string | Expression, unit: TimeUnit): FunctionExpression; /* Excluded from this release type: _readUserData */ timestampExtract(part: TimePart, timezone?: string | Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ @@ -777,7 +777,7 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ - timestampSubtract(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; + timestampSubtract(unit: TimeUnit, amount: number): FunctionExpression; /* Excluded from this release type: _readUserData */ timestampToUnixMicros(): FunctionExpression; /* Excluded from this release type: _readUserData */ @@ -1529,7 +1529,7 @@ export function sum(fieldName: string): AggregateFunction; export function switchOn(condition: BooleanExpression, result: Expression, ...others: Array): FunctionExpression; // @beta -export type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; +export type TimeGranularity = TimeUnit | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoweek' | 'month' | 'quarter' | 'year' | 'isoyear'; // @beta export type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; @@ -1538,22 +1538,22 @@ export type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; export function timestampAdd(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; // @beta -export function timestampAdd(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export function timestampAdd(timestamp: Expression, unit: TimeUnit, amount: number): FunctionExpression; // @beta -export function timestampAdd(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export function timestampAdd(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; // @beta -export function timestampDiff(endFieldName: string, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export function timestampDiff(endFieldName: string, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; // @beta -export function timestampDiff(endFieldName: string, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export function timestampDiff(endFieldName: string, startExpression: Expression, unit: TimeUnit | Expression): FunctionExpression; // @beta -export function timestampDiff(endExpression: Expression, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export function timestampDiff(endExpression: Expression, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; // @beta -export function timestampDiff(endExpression: Expression, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export function timestampDiff(endExpression: Expression, startExpression: Expression, unit: TimeUnit | Expression): FunctionExpression; // @beta export function timestampExtract(fieldName: string, part: TimePart, timezone?: string | Expression): FunctionExpression; @@ -1571,10 +1571,10 @@ export function timestampExtract(timestampExpression: Expression, part: Expressi export function timestampSubtract(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; // @beta -export function timestampSubtract(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export function timestampSubtract(timestamp: Expression, unit: TimeUnit, amount: number): FunctionExpression; // @beta -export function timestampSubtract(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export function timestampSubtract(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; // @beta export function timestampToUnixMicros(expr: Expression): FunctionExpression; @@ -1606,6 +1606,9 @@ export function timestampTruncate(timestampExpression: Expression, granularity: // @beta export function timestampTruncate(timestampExpression: Expression, granularity: Expression, timezone?: string | Expression): FunctionExpression; +// @beta +export type TimeUnit = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'; + // @beta export function toLower(fieldName: string): FunctionExpression; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index 3e4c060e9c..25c485e5ba 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -4797,14 +4797,14 @@ Creates an expression that adds a specified amount of time to this timestamp exp Signature: ```typescript -timestampAdd(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +timestampAdd(unit: TimeUnit, amount: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) | The unit of time to add (e.g., "day", "hour"). | | amount | number | The amount of time to add. | Returns: @@ -4867,7 +4867,7 @@ Creates an expression that calculates the difference between this timestamp and Signature: ```typescript -timestampDiff(start: string | Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'): FunctionExpression; +timestampDiff(start: string | Expression, unit: TimeUnit): FunctionExpression; ``` #### Parameters @@ -4875,7 +4875,7 @@ timestampDiff(start: string | Expression, unit: 'microsecond' | 'millisecond' | | Parameter | Type | Description | | --- | --- | --- | | start | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The field name of the starting timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time for the difference (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) | The unit of time for the difference (e.g., "day", "hour"). | Returns: @@ -5007,14 +5007,14 @@ Creates an expression that subtracts a specified amount of time from this timest Signature: ```typescript -timestampSubtract(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +timestampSubtract(unit: TimeUnit, amount: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) | The unit of time to subtract (e.g., "day", "hour"). | | amount | number | The amount of time to subtract. | Returns: @@ -5137,7 +5137,7 @@ timestampTruncate(granularity: TimeGranularity, timezone?: string | Expression): [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the truncated timestamp. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the truncated timestamp. ### Example @@ -5172,7 +5172,7 @@ timestampTruncate(granularity: Expression, timezone?: string | Expression): Func [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the truncated timestamp. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the truncated timestamp. ### Example diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 4cb6c81bd1..de497b10be 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -75,11 +75,11 @@ https://github.com/firebase/firebase-js-sdk | [array(elements)](./firestore_lite_pipelines.md#array_7d853aa) | (Public Preview) Creates an expression that creates a Firestore array value from an input array. | | [map(elements)](./firestore_lite_pipelines.md#map_ce5dee1) | (Public Preview) Creates an expression that creates a Firestore map value from an input object. | | function(endExpression, ...) | -| [timestampDiff(endExpression, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_8cb2a38) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | -| [timestampDiff(endExpression, startExpression, unit)](./firestore_lite_pipelines.md#timestampdiff_33aecb4) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endExpression, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_4370feb) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endExpression, startExpression, unit)](./firestore_lite_pipelines.md#timestampdiff_bc0830f) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | | function(endFieldName, ...) | -| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_c062afd) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | -| [timestampDiff(endFieldName, startExpression, unit)](./firestore_lite_pipelines.md#timestampdiff_8244545) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_f60102c) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endFieldName, startExpression, unit)](./firestore_lite_pipelines.md#timestampdiff_6e54d92) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | | function(expr, ...) | | [abs(expr)](./firestore_lite_pipelines.md#abs_005f3d4) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | | [ascending(expr)](./firestore_lite_pipelines.md#ascending_005f3d4) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. | @@ -255,10 +255,10 @@ https://github.com/firebase/firebase-js-sdk | [subtract(fieldName, expression)](./firestore_lite_pipelines.md#subtract_1e91657) | (Public Preview) Creates an expression that subtracts an expression from a field's value. | | [subtract(fieldName, value)](./firestore_lite_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. | | [sum(fieldName)](./firestore_lite_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. | -| [timestampAdd(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampadd_341fe7d) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. | +| [timestampAdd(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampadd_3b0a297) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. | | [timestampExtract(fieldName, part, timezone)](./firestore_lite_pipelines.md#timestampextract_a51c205) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | | [timestampExtract(fieldName, part, timezone)](./firestore_lite_pipelines.md#timestampextract_2d51eac) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | -| [timestampSubtract(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_341fe7d) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. | +| [timestampSubtract(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_3b0a297) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. | | [timestampToUnixMicros(fieldName)](./firestore_lite_pipelines.md#timestamptounixmicros_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | | [timestampToUnixMillis(fieldName)](./firestore_lite_pipelines.md#timestamptounixmillis_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | | [timestampToUnixSeconds(fieldName)](./firestore_lite_pipelines.md#timestamptounixseconds_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | @@ -359,9 +359,9 @@ https://github.com/firebase/firebase-js-sdk | [trim(stringExpression, valueToTrim)](./firestore_lite_pipelines.md#trim_dd54322) | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array expression. | | function(timestamp, ...) | | [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_98418f9) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | -| [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_ffe8e57) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | +| [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_06ef927) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | | [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_98418f9) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | -| [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_ffe8e57) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | +| [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_06ef927) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | | function(timestampExpression, ...) | | [timestampExtract(timestampExpression, part, timezone)](./firestore_lite_pipelines.md#timestampextract_b2f8f48) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | | [timestampExtract(timestampExpression, part, timezone)](./firestore_lite_pipelines.md#timestampextract_73e0311) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | @@ -458,6 +458,7 @@ https://github.com/firebase/firebase-js-sdk | [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | (Public Preview) Specify time granularity for expressions. | | [TimePart](./firestore_lite_pipelines.md#timepart) | (Public Preview) Specify time parts for timestampExtract expressions. | +| [TimeUnit](./firestore_lite_pipelines.md#timeunit) | (Public Preview) Specify time units for expressions. | | [Type](./firestore_lite_pipelines.md#type) | (Public Preview) An enumeration of the different types generated by the Firestore backend.
    • Numerics evaluate directly to backend representation (int64 or float64), not JS number.
    • JavaScript Date and firestore Timestamp objects strictly evaluate to 'timestamp'.
    • Advanced configurations parsing backend types (such as decimal128, max_key or min_key from BSON) are also incorporated in this union string type. Note that decimal128 is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    | | [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | | [UnnestStageOptions](./firestore_lite_pipelines.md#unneststageoptions) | (Public Preview) Represents the specific options available for configuring an UnnestStage within a pipeline. | @@ -2120,7 +2121,7 @@ map({foo: 'bar', baz: field('baz')}).as('data'); ## function(endExpression, ...) -### timestampDiff(endExpression, startFieldName, unit) {:#timestampdiff_8cb2a38} +### timestampDiff(endExpression, startFieldName, unit) {:#timestampdiff_4370feb} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -2130,7 +2131,7 @@ Creates an expression that calculates the difference between two timestamps. Signature: ```typescript -export declare function timestampDiff(endExpression: Expression, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export declare function timestampDiff(endExpression: Expression, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; ``` #### Parameters @@ -2139,7 +2140,7 @@ export declare function timestampDiff(endExpression: Expression, startFieldName: | --- | --- | --- | | endExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The ending timestamp for the difference calculation. | | startFieldName | string | The name of the field representing the starting timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | Returns: @@ -2156,7 +2157,7 @@ timestampDiff(field('endTime'), 'startTime', 'day') ``` -### timestampDiff(endExpression, startExpression, unit) {:#timestampdiff_33aecb4} +### timestampDiff(endExpression, startExpression, unit) {:#timestampdiff_bc0830f} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -2166,7 +2167,7 @@ Creates an expression that calculates the difference between two timestamps. Signature: ```typescript -export declare function timestampDiff(endExpression: Expression, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export declare function timestampDiff(endExpression: Expression, startExpression: Expression, unit: TimeUnit | Expression): FunctionExpression; ``` #### Parameters @@ -2175,7 +2176,7 @@ export declare function timestampDiff(endExpression: Expression, startExpression | --- | --- | --- | | endExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The ending timestamp for the difference calculation. | | startExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The starting timestamp for the difference calculation. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | Returns: @@ -2194,7 +2195,7 @@ timestampDiff(field('endTime'), field('startTime'), 'day') ## function(endFieldName, ...) -### timestampDiff(endFieldName, startFieldName, unit) {:#timestampdiff_c062afd} +### timestampDiff(endFieldName, startFieldName, unit) {:#timestampdiff_f60102c} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -2204,7 +2205,7 @@ Creates an expression that calculates the difference between two timestamps. Signature: ```typescript -export declare function timestampDiff(endFieldName: string, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export declare function timestampDiff(endFieldName: string, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; ``` #### Parameters @@ -2213,7 +2214,7 @@ export declare function timestampDiff(endFieldName: string, startFieldName: stri | --- | --- | --- | | endFieldName | string | The name of the field representing the ending timestamp. | | startFieldName | string | The name of the field representing the starting timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | Returns: @@ -2230,7 +2231,7 @@ timestampDiff('endTime', 'startTime', 'day') ``` -### timestampDiff(endFieldName, startExpression, unit) {:#timestampdiff_8244545} +### timestampDiff(endFieldName, startExpression, unit) {:#timestampdiff_6e54d92} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -2240,7 +2241,7 @@ Creates an expression that calculates the difference between two timestamps. Signature: ```typescript -export declare function timestampDiff(endFieldName: string, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export declare function timestampDiff(endFieldName: string, startExpression: Expression, unit: TimeUnit | Expression): FunctionExpression; ``` #### Parameters @@ -2249,7 +2250,7 @@ export declare function timestampDiff(endFieldName: string, startExpression: Exp | --- | --- | --- | | endFieldName | string | The name of the field representing the ending timestamp. | | startExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The starting timestamp for the difference calculation. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | Returns: @@ -8191,7 +8192,7 @@ sum("orderAmount").as("totalRevenue"); ``` -### timestampAdd(fieldName, unit, amount) {:#timestampadd_341fe7d} +### timestampAdd(fieldName, unit, amount) {:#timestampadd_3b0a297} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -8201,7 +8202,7 @@ Creates an expression that adds a specified amount of time to a timestamp repres Signature: ```typescript -export declare function timestampAdd(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export declare function timestampAdd(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; ``` #### Parameters @@ -8209,7 +8210,7 @@ export declare function timestampAdd(fieldName: string, unit: 'microsecond' | 'm | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field representing the timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) | The unit of time to add (e.g., "day", "hour"). | | amount | number | The amount of time to add. | Returns: @@ -8299,7 +8300,7 @@ timestampExtract('createdAt', field('part')) ``` -### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_341fe7d} +### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_3b0a297} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -8309,7 +8310,7 @@ Creates an expression that subtracts a specified amount of time from a timestamp Signature: ```typescript -export declare function timestampSubtract(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export declare function timestampSubtract(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; ``` #### Parameters @@ -8317,7 +8318,7 @@ export declare function timestampSubtract(fieldName: string, unit: 'microsecond' | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field representing the timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) | The unit of time to subtract (e.g., "day", "hour"). | | amount | number | The amount of time to subtract. | Returns: @@ -11292,7 +11293,7 @@ timestampAdd(field("timestamp"), field("unit"), field("amount")); ``` -### timestampAdd(timestamp, unit, amount) {:#timestampadd_ffe8e57} +### timestampAdd(timestamp, unit, amount) {:#timestampadd_06ef927} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -11302,7 +11303,7 @@ Creates an expression that adds a specified amount of time to a timestamp. Signature: ```typescript -export declare function timestampAdd(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export declare function timestampAdd(timestamp: Expression, unit: TimeUnit, amount: number): FunctionExpression; ``` #### Parameters @@ -11310,7 +11311,7 @@ export declare function timestampAdd(timestamp: Expression, unit: 'microsecond' | Parameter | Type | Description | | --- | --- | --- | | timestamp | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) | The unit of time to add (e.g., "day", "hour"). | | amount | number | The amount of time to add. | Returns: @@ -11364,7 +11365,7 @@ timestampSubtract(field("timestamp"), field("unit"), field("amount")); ``` -### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_ffe8e57} +### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_06ef927} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -11374,7 +11375,7 @@ Creates an expression that subtracts a specified amount of time from a timestamp Signature: ```typescript -export declare function timestampSubtract(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export declare function timestampSubtract(timestamp: Expression, unit: TimeUnit, amount: number): FunctionExpression; ``` #### Parameters @@ -11382,7 +11383,7 @@ export declare function timestampSubtract(timestamp: Expression, unit: 'microsec | Parameter | Type | Description | | --- | --- | --- | | timestamp | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) | The unit of time to subtract (e.g., "day", "hour"). | | amount | number | The amount of time to subtract. | Returns: @@ -12581,7 +12582,7 @@ Specify time granularity for expressions. Signature: ```typescript -export declare type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; +export declare type TimeGranularity = TimeUnit | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoweek' | 'month' | 'quarter' | 'year' | 'isoyear'; ``` ## TimePart @@ -12597,6 +12598,19 @@ Specify time parts for `timestampExtract` expressions. export declare type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; ``` +## TimeUnit + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Specify time units for expressions. + +Signature: + +```typescript +export declare type TimeUnit = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'; +``` + ## Type > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index c4cc20b192..2418427357 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -4797,14 +4797,14 @@ Creates an expression that adds a specified amount of time to this timestamp exp Signature: ```typescript -timestampAdd(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +timestampAdd(unit: TimeUnit, amount: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_pipelines.md#timeunit) | The unit of time to add (e.g., "day", "hour"). | | amount | number | The amount of time to add. | Returns: @@ -4867,7 +4867,7 @@ Creates an expression that calculates the difference between this timestamp and Signature: ```typescript -timestampDiff(start: string | Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'): FunctionExpression; +timestampDiff(start: string | Expression, unit: TimeUnit): FunctionExpression; ``` #### Parameters @@ -4875,7 +4875,7 @@ timestampDiff(start: string | Expression, unit: 'microsecond' | 'millisecond' | | Parameter | Type | Description | | --- | --- | --- | | start | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The field name of the starting timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time for the difference (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_pipelines.md#timeunit) | The unit of time for the difference (e.g., "day", "hour"). | Returns: @@ -5007,14 +5007,14 @@ Creates an expression that subtracts a specified amount of time from this timest Signature: ```typescript -timestampSubtract(unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +timestampSubtract(unit: TimeUnit, amount: number): FunctionExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_pipelines.md#timeunit) | The unit of time to subtract (e.g., "day", "hour"). | | amount | number | The amount of time to subtract. | Returns: @@ -5137,7 +5137,7 @@ timestampTruncate(granularity: TimeGranularity, timezone?: string | Expression): [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the truncated timestamp. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the truncated timestamp. ### Example @@ -5172,7 +5172,7 @@ timestampTruncate(granularity: Expression, timezone?: string | Expression): Func [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the truncated timestamp. +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the truncated timestamp. ### Example diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index f9e1c381e1..a271da069f 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -75,11 +75,11 @@ https://github.com/firebase/firebase-js-sdk | [array(elements)](./firestore_pipelines.md#array_7d853aa) | (Public Preview) Creates an expression that creates a Firestore array value from an input array. | | [map(elements)](./firestore_pipelines.md#map_ce5dee1) | (Public Preview) Creates an expression that creates a Firestore map value from an input object. | | function(endExpression, ...) | -| [timestampDiff(endExpression, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_8cb2a38) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | -| [timestampDiff(endExpression, startExpression, unit)](./firestore_pipelines.md#timestampdiff_33aecb4) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endExpression, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_4370feb) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endExpression, startExpression, unit)](./firestore_pipelines.md#timestampdiff_bc0830f) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | | function(endFieldName, ...) | -| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_c062afd) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | -| [timestampDiff(endFieldName, startExpression, unit)](./firestore_pipelines.md#timestampdiff_8244545) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_f60102c) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endFieldName, startExpression, unit)](./firestore_pipelines.md#timestampdiff_6e54d92) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | | function(expr, ...) | | [abs(expr)](./firestore_pipelines.md#abs_005f3d4) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | | [ascending(expr)](./firestore_pipelines.md#ascending_005f3d4) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. | @@ -255,10 +255,10 @@ https://github.com/firebase/firebase-js-sdk | [subtract(fieldName, expression)](./firestore_pipelines.md#subtract_1e91657) | (Public Preview) Creates an expression that subtracts an expression from a field's value. | | [subtract(fieldName, value)](./firestore_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. | | [sum(fieldName)](./firestore_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. | -| [timestampAdd(fieldName, unit, amount)](./firestore_pipelines.md#timestampadd_341fe7d) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. | +| [timestampAdd(fieldName, unit, amount)](./firestore_pipelines.md#timestampadd_3b0a297) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. | | [timestampExtract(fieldName, part, timezone)](./firestore_pipelines.md#timestampextract_a51c205) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | | [timestampExtract(fieldName, part, timezone)](./firestore_pipelines.md#timestampextract_2d51eac) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | -| [timestampSubtract(fieldName, unit, amount)](./firestore_pipelines.md#timestampsubtract_341fe7d) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. | +| [timestampSubtract(fieldName, unit, amount)](./firestore_pipelines.md#timestampsubtract_3b0a297) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. | | [timestampToUnixMicros(fieldName)](./firestore_pipelines.md#timestamptounixmicros_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | | [timestampToUnixMillis(fieldName)](./firestore_pipelines.md#timestamptounixmillis_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | | [timestampToUnixSeconds(fieldName)](./firestore_pipelines.md#timestamptounixseconds_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | @@ -362,9 +362,9 @@ https://github.com/firebase/firebase-js-sdk | [trim(stringExpression, valueToTrim)](./firestore_pipelines.md#trim_dd54322) | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array expression. | | function(timestamp, ...) | | [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_98418f9) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | -| [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_ffe8e57) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | +| [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_06ef927) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | | [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_98418f9) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | -| [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_ffe8e57) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | +| [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_06ef927) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | | function(timestampExpression, ...) | | [timestampExtract(timestampExpression, part, timezone)](./firestore_pipelines.md#timestampextract_b2f8f48) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | | [timestampExtract(timestampExpression, part, timezone)](./firestore_pipelines.md#timestampextract_73e0311) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | @@ -464,6 +464,7 @@ https://github.com/firebase/firebase-js-sdk | [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | | [TimeGranularity](./firestore_pipelines.md#timegranularity) | (Public Preview) Specify time granularity for expressions. | | [TimePart](./firestore_pipelines.md#timepart) | (Public Preview) Specify time parts for timestampExtract expressions. | +| [TimeUnit](./firestore_pipelines.md#timeunit) | (Public Preview) Specify time units for expressions. | | [Type](./firestore_pipelines.md#type) | (Public Preview) An enumeration of the different types generated by the Firestore backend.
    • Numerics evaluate directly to backend representation (int64 or float64), not JS number.
    • JavaScript Date and firestore Timestamp objects strictly evaluate to 'timestamp'.
    • Advanced configurations parsing backend types (such as decimal128, max_key or min_key from BSON) are also incorporated in this union string type. Note that decimal128 is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    | | [UnionStageOptions](./firestore_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | | [UnnestStageOptions](./firestore_pipelines.md#unneststageoptions) | (Public Preview) Represents the specific options available for configuring an UnnestStage within a pipeline. | @@ -2126,7 +2127,7 @@ map({foo: 'bar', baz: field('baz')}).as('data'); ## function(endExpression, ...) -### timestampDiff(endExpression, startFieldName, unit) {:#timestampdiff_8cb2a38} +### timestampDiff(endExpression, startFieldName, unit) {:#timestampdiff_4370feb} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -2136,7 +2137,7 @@ Creates an expression that calculates the difference between two timestamps. Signature: ```typescript -export declare function timestampDiff(endExpression: Expression, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export declare function timestampDiff(endExpression: Expression, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; ``` #### Parameters @@ -2145,7 +2146,7 @@ export declare function timestampDiff(endExpression: Expression, startFieldName: | --- | --- | --- | | endExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The ending timestamp for the difference calculation. | | startFieldName | string | The name of the field representing the starting timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_pipelines.md#timeunit) \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | Returns: @@ -2162,7 +2163,7 @@ timestampDiff(field('endTime'), 'startTime', 'day') ``` -### timestampDiff(endExpression, startExpression, unit) {:#timestampdiff_33aecb4} +### timestampDiff(endExpression, startExpression, unit) {:#timestampdiff_bc0830f} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -2172,7 +2173,7 @@ Creates an expression that calculates the difference between two timestamps. Signature: ```typescript -export declare function timestampDiff(endExpression: Expression, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export declare function timestampDiff(endExpression: Expression, startExpression: Expression, unit: TimeUnit | Expression): FunctionExpression; ``` #### Parameters @@ -2181,7 +2182,7 @@ export declare function timestampDiff(endExpression: Expression, startExpression | --- | --- | --- | | endExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The ending timestamp for the difference calculation. | | startExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The starting timestamp for the difference calculation. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_pipelines.md#timeunit) \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | Returns: @@ -2200,7 +2201,7 @@ timestampDiff(field('endTime'), field('startTime'), 'day') ## function(endFieldName, ...) -### timestampDiff(endFieldName, startFieldName, unit) {:#timestampdiff_c062afd} +### timestampDiff(endFieldName, startFieldName, unit) {:#timestampdiff_f60102c} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -2210,7 +2211,7 @@ Creates an expression that calculates the difference between two timestamps. Signature: ```typescript -export declare function timestampDiff(endFieldName: string, startFieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export declare function timestampDiff(endFieldName: string, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; ``` #### Parameters @@ -2219,7 +2220,7 @@ export declare function timestampDiff(endFieldName: string, startFieldName: stri | --- | --- | --- | | endFieldName | string | The name of the field representing the ending timestamp. | | startFieldName | string | The name of the field representing the starting timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_pipelines.md#timeunit) \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | Returns: @@ -2236,7 +2237,7 @@ timestampDiff('endTime', 'startTime', 'day') ``` -### timestampDiff(endFieldName, startExpression, unit) {:#timestampdiff_8244545} +### timestampDiff(endFieldName, startExpression, unit) {:#timestampdiff_6e54d92} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -2246,7 +2247,7 @@ Creates an expression that calculates the difference between two timestamps. Signature: ```typescript -export declare function timestampDiff(endFieldName: string, startExpression: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | Expression): FunctionExpression; +export declare function timestampDiff(endFieldName: string, startExpression: Expression, unit: TimeUnit | Expression): FunctionExpression; ``` #### Parameters @@ -2255,7 +2256,7 @@ export declare function timestampDiff(endFieldName: string, startExpression: Exp | --- | --- | --- | | endFieldName | string | The name of the field representing the ending timestamp. | | startExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The starting timestamp for the difference calculation. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_pipelines.md#timeunit) \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | Returns: @@ -8197,7 +8198,7 @@ sum("orderAmount").as("totalRevenue"); ``` -### timestampAdd(fieldName, unit, amount) {:#timestampadd_341fe7d} +### timestampAdd(fieldName, unit, amount) {:#timestampadd_3b0a297} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -8207,7 +8208,7 @@ Creates an expression that adds a specified amount of time to a timestamp repres Signature: ```typescript -export declare function timestampAdd(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export declare function timestampAdd(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; ``` #### Parameters @@ -8215,7 +8216,7 @@ export declare function timestampAdd(fieldName: string, unit: 'microsecond' | 'm | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field representing the timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_pipelines.md#timeunit) | The unit of time to add (e.g., "day", "hour"). | | amount | number | The amount of time to add. | Returns: @@ -8305,7 +8306,7 @@ timestampExtract('createdAt', field('part')) ``` -### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_341fe7d} +### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_3b0a297} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -8315,7 +8316,7 @@ Creates an expression that subtracts a specified amount of time from a timestamp Signature: ```typescript -export declare function timestampSubtract(fieldName: string, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export declare function timestampSubtract(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; ``` #### Parameters @@ -8323,7 +8324,7 @@ export declare function timestampSubtract(fieldName: string, unit: 'microsecond' | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field representing the timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_pipelines.md#timeunit) | The unit of time to subtract (e.g., "day", "hour"). | | amount | number | The amount of time to subtract. | Returns: @@ -11367,7 +11368,7 @@ timestampAdd(field("timestamp"), field("unit"), field("amount")); ``` -### timestampAdd(timestamp, unit, amount) {:#timestampadd_ffe8e57} +### timestampAdd(timestamp, unit, amount) {:#timestampadd_06ef927} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -11377,7 +11378,7 @@ Creates an expression that adds a specified amount of time to a timestamp. Signature: ```typescript -export declare function timestampAdd(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export declare function timestampAdd(timestamp: Expression, unit: TimeUnit, amount: number): FunctionExpression; ``` #### Parameters @@ -11385,7 +11386,7 @@ export declare function timestampAdd(timestamp: Expression, unit: 'microsecond' | Parameter | Type | Description | | --- | --- | --- | | timestamp | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to add (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_pipelines.md#timeunit) | The unit of time to add (e.g., "day", "hour"). | | amount | number | The amount of time to add. | Returns: @@ -11439,7 +11440,7 @@ timestampSubtract(field("timestamp"), field("unit"), field("amount")); ``` -### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_ffe8e57} +### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_06ef927} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -11449,7 +11450,7 @@ Creates an expression that subtracts a specified amount of time from a timestamp Signature: ```typescript -export declare function timestampSubtract(timestamp: Expression, unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', amount: number): FunctionExpression; +export declare function timestampSubtract(timestamp: Expression, unit: TimeUnit, amount: number): FunctionExpression; ``` #### Parameters @@ -11457,7 +11458,7 @@ export declare function timestampSubtract(timestamp: Expression, unit: 'microsec | Parameter | Type | Description | | --- | --- | --- | | timestamp | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the timestamp. | -| unit | 'microsecond' \| 'millisecond' \| 'second' \| 'minute' \| 'hour' \| 'day' | The unit of time to subtract (e.g., "day", "hour"). | +| unit | [TimeUnit](./firestore_pipelines.md#timeunit) | The unit of time to subtract (e.g., "day", "hour"). | | amount | number | The amount of time to subtract. | Returns: @@ -12656,7 +12657,7 @@ Specify time granularity for expressions. Signature: ```typescript -export declare type TimeGranularity = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoWeek' | 'month' | 'quarter' | 'year' | 'isoYear'; +export declare type TimeGranularity = TimeUnit | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoweek' | 'month' | 'quarter' | 'year' | 'isoyear'; ``` ## TimePart @@ -12672,6 +12673,19 @@ Specify time parts for `timestampExtract` expressions. export declare type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; ``` +## TimeUnit + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Specify time units for expressions. + +Signature: + +```typescript +export declare type TimeUnit = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'; +``` + ## Type > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index db02745c84..e8943abb1c 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -226,5 +226,6 @@ export { AggregateFunction, TimeGranularity, TimePart, + TimeUnit, Type } from '../../src/lite-api/expressions'; diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index 5c6dd9baf7..1d3da2565c 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -195,6 +195,7 @@ export { Selectable, TimeGranularity, TimePart, + TimeUnit, Type } from './lite-api/expressions'; diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index 459d8e2310..09090c8672 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -2546,19 +2546,9 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @param amount - The amount of time to add. * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the resulting timestamp. */ + timestampAdd(unit: TimeUnit, amount: number): FunctionExpression; timestampAdd( - unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', - amount: number - ): FunctionExpression; - timestampAdd( - unit: - | Expression - | 'microsecond' - | 'millisecond' - | 'second' - | 'minute' - | 'hour' - | 'day', + unit: Expression | TimeUnit, amount: Expression | number ): FunctionExpression { return new FunctionExpression( @@ -2598,19 +2588,9 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @param amount - The amount of time to subtract. * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the resulting timestamp. */ + timestampSubtract(unit: TimeUnit, amount: number): FunctionExpression; timestampSubtract( - unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', - amount: number - ): FunctionExpression; - timestampSubtract( - unit: - | Expression - | 'microsecond' - | 'millisecond' - | 'second' - | 'minute' - | 'hour' - | 'day', + unit: Expression | TimeUnit, amount: Expression | number ): FunctionExpression { return new FunctionExpression( @@ -2650,20 +2630,10 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @param unit - The unit of time for the difference (e.g., "day", "hour"). * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the difference as an integer. */ + timestampDiff(start: string | Expression, unit: TimeUnit): FunctionExpression; timestampDiff( start: string | Expression, - unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day' - ): FunctionExpression; - timestampDiff( - start: string | Expression, - unit: - | 'microsecond' - | 'millisecond' - | 'second' - | 'minute' - | 'hour' - | 'day' - | Expression + unit: TimeUnit | Expression ): FunctionExpression { return new FunctionExpression( 'timestamp_diff', @@ -2715,8 +2685,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { part: TimePart | Expression, timezone?: string | Expression ): FunctionExpression { - const internalPart = isString(part) ? part.toLowerCase() : part; - const args = [this, valueToDefaultExpr(internalPart)]; + const args = [this, valueToDefaultExpr(part)]; if (timezone) { args.push(valueToDefaultExpr(timezone)); } @@ -3368,7 +3337,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @param granularity - The granularity to truncate to. * @param timezone - The timezone to use for truncation. Valid values are from * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". - * @returns A new `Expression` representing the truncated timestamp. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the truncated timestamp. */ timestampTruncate( granularity: TimeGranularity, @@ -3387,7 +3356,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @param granularity - The granularity to truncate to. * @param timezone - The timezone to use for truncation. Valid values are from * the TZ database (e.g., "America/Los_Angeles") or in the format "Etc/GMT-1". - * @returns A new `Expression` representing the truncated timestamp. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the truncated timestamp. */ timestampTruncate( granularity: Expression, @@ -3397,11 +3366,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { granularity: TimeGranularity | Expression, timezone?: string | Expression ): FunctionExpression { - const internalGranularity = isString(granularity) - ? granularity.toLowerCase() - : granularity; - - const args = [this, valueToDefaultExpr(internalGranularity)]; + const args = [this, valueToDefaultExpr(granularity)]; if (timezone) { args.push(valueToDefaultExpr(timezone)); } @@ -3469,15 +3434,22 @@ export abstract class Expression implements ProtoValueSerializable, UserData { /** * @beta - * Specify time granularity for expressions. + * Specify time units for expressions. */ -export type TimeGranularity = +export type TimeUnit = | 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' - | 'day' + | 'day'; + +/** + * @beta + * Specify time granularity for expressions. + */ +export type TimeGranularity = + | TimeUnit | 'week' | 'week(monday)' | 'week(tuesday)' @@ -3486,11 +3458,11 @@ export type TimeGranularity = | 'week(friday)' | 'week(saturday)' | 'week(sunday)' - | 'isoWeek' + | 'isoweek' | 'month' | 'quarter' | 'year' - | 'isoYear'; + | 'isoyear'; /** * @beta @@ -9788,7 +9760,7 @@ export function timestampAdd( */ export function timestampAdd( timestamp: Expression, - unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', + unit: TimeUnit, amount: number ): FunctionExpression; @@ -9810,19 +9782,12 @@ export function timestampAdd( */ export function timestampAdd( fieldName: string, - unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', + unit: TimeUnit, amount: number ): FunctionExpression; export function timestampAdd( timestamp: Expression | string, - unit: - | Expression - | 'microsecond' - | 'millisecond' - | 'second' - | 'minute' - | 'hour' - | 'day', + unit: TimeUnit | Expression, amount: Expression | number ): FunctionExpression { const normalizedTimestamp = fieldOrExpression(timestamp); @@ -9871,7 +9836,7 @@ export function timestampSubtract( */ export function timestampSubtract( timestamp: Expression, - unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', + unit: TimeUnit, amount: number ): FunctionExpression; @@ -9893,19 +9858,12 @@ export function timestampSubtract( */ export function timestampSubtract( fieldName: string, - unit: 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day', + unit: TimeUnit, amount: number ): FunctionExpression; export function timestampSubtract( timestamp: Expression | string, - unit: - | Expression - | 'microsecond' - | 'millisecond' - | 'second' - | 'minute' - | 'hour' - | 'day', + unit: TimeUnit | Expression, amount: Expression | number ): FunctionExpression { const normalizedTimestamp = fieldOrExpression(timestamp); @@ -11035,7 +10993,7 @@ export function timestampTruncate( timezone?: string | Expression ): FunctionExpression { const internalGranularity = isString(granularity) - ? valueToDefaultExpr(granularity.toLowerCase()) + ? valueToDefaultExpr(granularity) : granularity; return fieldOrExpression(fieldNameOrExpression).timestampTruncate( internalGranularity, @@ -11061,14 +11019,7 @@ export function timestampTruncate( export function timestampDiff( endFieldName: string, startFieldName: string, - unit: - | 'microsecond' - | 'millisecond' - | 'second' - | 'minute' - | 'hour' - | 'day' - | Expression + unit: TimeUnit | Expression ): FunctionExpression; /** @@ -11089,14 +11040,7 @@ export function timestampDiff( export function timestampDiff( endFieldName: string, startExpression: Expression, - unit: - | 'microsecond' - | 'millisecond' - | 'second' - | 'minute' - | 'hour' - | 'day' - | Expression + unit: TimeUnit | Expression ): FunctionExpression; /** @@ -11117,14 +11061,7 @@ export function timestampDiff( export function timestampDiff( endExpression: Expression, startFieldName: string, - unit: - | 'microsecond' - | 'millisecond' - | 'second' - | 'minute' - | 'hour' - | 'day' - | Expression + unit: TimeUnit | Expression ): FunctionExpression; /** @@ -11145,26 +11082,12 @@ export function timestampDiff( export function timestampDiff( endExpression: Expression, startExpression: Expression, - unit: - | 'microsecond' - | 'millisecond' - | 'second' - | 'minute' - | 'hour' - | 'day' - | Expression + unit: TimeUnit | Expression ): FunctionExpression; export function timestampDiff( endFieldNameOrExpression: string | Expression, startFieldNameOrExpression: string | Expression, - unit: - | 'microsecond' - | 'millisecond' - | 'second' - | 'minute' - | 'hour' - | 'day' - | Expression + unit: TimeUnit | Expression ): FunctionExpression { const normalizedEnd = fieldOrExpression(endFieldNameOrExpression); const normalizedStart = fieldOrExpression(startFieldNameOrExpression); @@ -11265,7 +11188,7 @@ export function timestampExtract( timezone?: string | Expression ): FunctionExpression { return fieldOrExpression(fieldNameOrExpression).timestampExtract( - valueToDefaultExpr(isString(part) ? part.toLowerCase() : part), + valueToDefaultExpr(part), timezone ); } diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 110009e9a7..a16f59be26 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -3970,7 +3970,7 @@ describe.skipClassic('Firestore Pipelines', () => { timestampTruncate(field('timestamp'), 'hour').as('truncHour'), timestampTruncate(field('timestamp'), 'minute').as('truncMinute'), timestampTruncate(field('timestamp'), 'second').as('truncSecond'), - timestampTruncate(field('timestamp'), 'isoWeek').as('truncIsoWeek') + timestampTruncate(field('timestamp'), 'isoweek').as('truncIsoweek') ) ); @@ -3981,7 +3981,7 @@ describe.skipClassic('Firestore Pipelines', () => { truncHour: new Timestamp(1741435200, 0), truncMinute: new Timestamp(1741437240, 0), truncSecond: new Timestamp(1741437296, 0), - truncIsoWeek: new Timestamp(1740960000, 0) + truncIsoweek: new Timestamp(1740960000, 0) }); }).timeout(10000); From 3ddfe88696201a8d0aff115c6676a7c087fd2c43 Mon Sep 17 00:00:00 2001 From: Mark Duckworth <1124037+MarkDuckworth@users.noreply.github.com> Date: Fri, 27 Mar 2026 11:19:42 -0400 Subject: [PATCH 114/174] ci: Updated named db tests to run against enterprise db (#9770) --- packages/firestore/karma.conf.js | 7 +++ packages/firestore/package.json | 8 ++-- packages/firestore/scripts/run-tests.ts | 9 ++++ .../test/integration/api/pipeline.test.ts | 45 ++++++++++--------- .../integration/api/query_to_pipeline.test.ts | 20 ++++++--- .../integration/browser/indexeddb.test.ts | 4 +- .../test/integration/util/settings.ts | 10 +++++ packages/firestore/test/lite/pipeline.test.ts | 6 +-- .../firestore/test/util/mocha_extensions.ts | 9 ++-- 9 files changed, 79 insertions(+), 39 deletions(-) diff --git a/packages/firestore/karma.conf.js b/packages/firestore/karma.conf.js index 51a158b8c3..34950b7900 100644 --- a/packages/firestore/karma.conf.js +++ b/packages/firestore/karma.conf.js @@ -52,6 +52,13 @@ module.exports = function (config) { }; } + if (argv.firestoreEdition) { + karmaConfig.client = { + ...karmaConfig.client, + firestoreEdition: argv.firestoreEdition + }; + } + config.set(karmaConfig); }; diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 6812380ce1..39f638db04 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -24,9 +24,9 @@ "prettier": "prettier --write '*.js' '@(lite|src|test|scripts)/**/*.ts' 'test/unit/remote/bloom_filter_golden_test_data/*.json'", "test:lite": "ts-node ./scripts/run-tests.ts --emulator --platform node_lite --main=lite/index.ts 'test/lite/**/*.test.ts'", "test:lite:prod": "ts-node ./scripts/run-tests.ts --platform node_lite --main=lite/index.ts 'test/lite/**/*.test.ts'", - "test:lite:prod:nameddb": "ts-node ./scripts/run-tests.ts --platform node_lite --databaseId=test-db --main=lite/index.ts 'test/lite/**/*.test.ts'", + "test:lite:prod:nameddb": "ts-node ./scripts/run-tests.ts --platform node_lite --databaseId=enterprise --main=lite/index.ts --firestoreEdition=enterprise 'test/lite/**/*.test.ts'", "test:lite:browser": "karma start --lite", - "test:lite:browser:nameddb": "karma start --lite --databaseId=test-db", + "test:lite:browser:nameddb": "karma start --lite --databaseId=enterprise --firestoreEdition=enterprise", "test:lite:browser:debug": "karma start --browsers=Chrome --lite --auto-watch", "test": "run-s --npm-path npm lint assertion-id:check test:all", "test:ci": "node ../../scripts/run_tests_in_ci.js -s test:all:ci", @@ -39,12 +39,12 @@ "test:browser:prod": "karma start --targetBackend=prod", "test:webkit:prod": "BROWSERS=WebkitHeadless karma start --targetBackend=prod", "test:webkit:unit": "BROWSERS=WebkitHeadless karma start --unit --targetBackend=prod", - "test:browser:prod:nameddb": "karma start --targetBackend=prod --databaseId=test-db", + "test:browser:prod:nameddb": "karma start --targetBackend=prod --databaseId=enterprise --firestoreEdition=enterprise", "test:browser:unit": "karma start --unit", "test:browser:debug": "karma start --browsers=Chrome --auto-watch", "test:node": "ts-node ./scripts/run-tests.ts --main=test/register.ts --emulator 'test/{,!(browser|lite)/**/}*.test.ts'", "test:node:prod": "ts-node ./scripts/run-tests.ts --main=test/register.ts 'test/{,!(browser|lite)/**/}*.test.ts'", - "test:node:prod:nameddb": "ts-node ./scripts/run-tests.ts --main=test/register.ts --databaseId=test-db 'test/{,!(browser|lite)/**/}*.test.ts'", + "test:node:prod:nameddb": "ts-node ./scripts/run-tests.ts --main=test/register.ts --databaseId=enterprise --firestoreEdition=enterprise 'test/{,!(browser|lite)/**/}*.test.ts'", "test:node:persistence": "ts-node ./scripts/run-tests.ts --main=test/register.ts --persistence --emulator 'test/{,!(browser|lite)/**/}*.test.ts'", "test:node:persistence:prod": "ts-node ./scripts/run-tests.ts --main=test/register.ts --persistence 'test/{,!(browser|lite)/**/}*.test.ts'", "test:travis": "ts-node --compiler-options='{\"module\":\"commonjs\"}' ../../scripts/emulator-testing/firestore-test-runner.ts", diff --git a/packages/firestore/scripts/run-tests.ts b/packages/firestore/scripts/run-tests.ts index 74644bd93d..2ec66ce167 100644 --- a/packages/firestore/scripts/run-tests.ts +++ b/packages/firestore/scripts/run-tests.ts @@ -39,6 +39,9 @@ const argv = yargs databaseId: { type: 'string' }, + firestoreEdition: { + type: 'string' + }, grep: { type: 'string', description: 'Filter tests by name (regex)' @@ -79,6 +82,12 @@ if (argv.databaseId) { process.env.FIRESTORE_TARGET_DB_ID = argv.databaseId; } +if (argv.firestoreEdition) { + if (argv.firestoreEdition.toLowerCase() === 'enterprise') { + process.env.RUN_ENTERPRISE_TESTS = 'true'; + } +} + if (argv.grep) { args.push('--grep', argv.grep); } diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 24e2405c4c..fa6abdd626 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -179,7 +179,7 @@ import { use(chaiAsPromised); -const timestampDeltaMS = 1000; +const timestampDeltaMS = 10000; apiDescribe.skipClassic('Pipelines', persistence => { addEqualityMatcher(); @@ -712,16 +712,18 @@ apiDescribe.skipClassic('Pipelines', persistence => { it('throws on undefined in a map', async () => { expect(() => { - firestore - .pipeline() - .collection(randomCol.path) - .limit(1) - .select( - map({ - 'number': 1, - undefined - }).as('foo') - ); + void execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select( + map({ + 'number': 1, + undefined + }).as('foo') + ) + ); }).to.throw( 'Function map() called with invalid data. Unsupported field value: undefined' ); @@ -729,11 +731,13 @@ apiDescribe.skipClassic('Pipelines', persistence => { it('throws on undefined in an array', async () => { expect(() => { - firestore - .pipeline() - .collection(randomCol.path) - .limit(1) - .select(array([1, undefined]).as('foo')); + void execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select(array([1, undefined]).as('foo')) + ); }).to.throw( 'Function array() called with invalid data. Unsupported field value: undefined' ); @@ -2345,8 +2349,6 @@ apiDescribe.skipClassic('Pipelines', persistence => { const err = e as FirebaseError; expect(err['code']).to.equal('invalid-argument'); expect(typeof err['message']).to.equal('string'); - - expect(err['message']).to.match(/^3 INVALID_ARGUMENT: .*$/); } }); }); @@ -4140,9 +4142,10 @@ apiDescribe.skipClassic('Pipelines', persistence => { .limit(1) .select(field('rating').exp().as('expRating')) ); - expectResults(snapshot, { - expRating: 109.94717245212352 - }); + expect(snapshot.results[0].get('expRating')).to.be.approximately( + 109.94717245212352, + 0.00001 + ); }); it('can compute e to the power of a numeric value with the top-level function', async () => { diff --git a/packages/firestore/test/integration/api/query_to_pipeline.test.ts b/packages/firestore/test/integration/api/query_to_pipeline.test.ts index 42c1663161..61260abfcd 100644 --- a/packages/firestore/test/integration/api/query_to_pipeline.test.ts +++ b/packages/firestore/test/integration/api/query_to_pipeline.test.ts @@ -608,7 +608,9 @@ apiDescribe.skipClassic('Query to Pipeline', persistence => { ); }); - it('supports eq nan', () => { + // TODO(pipeline) fix test or SDK + // eslint-disable-next-line -- no-restricted-properties + it.skip('supports eq nan', () => { return withTestCollection( PERSISTENCE_MODE_UNSPECIFIED, { @@ -624,7 +626,9 @@ apiDescribe.skipClassic('Query to Pipeline', persistence => { ); }); - it('supports neq nan', () => { + // TODO(pipeline) fix test or SDK + // eslint-disable-next-line -- no-restricted-properties + it.skip('supports neq nan', () => { return withTestCollection( PERSISTENCE_MODE_UNSPECIFIED, { @@ -779,7 +783,9 @@ apiDescribe.skipClassic('Query to Pipeline', persistence => { ); }); - it('supports not in with 1', () => { + // TODO(pipeline) fix test or SDK + // eslint-disable-next-line -- no-restricted-properties + it.skip('supports not in with 1', () => { return withTestCollection( PERSISTENCE_MODE_UNSPECIFIED, { @@ -815,7 +821,9 @@ apiDescribe.skipClassic('Query to Pipeline', persistence => { ); }); - it('not-in removes existence filter', () => { + // TODO(pipeline) fix test or SDK + // eslint-disable-next-line -- no-restricted-properties + it.skip('not-in removes existence filter', () => { return withTestCollection( PERSISTENCE_MODE_UNSPECIFIED, { @@ -833,7 +841,9 @@ apiDescribe.skipClassic('Query to Pipeline', persistence => { ); }); - it('not-equal removes existence filter', () => { + // TODO(pipeline) fix test or SDK + // eslint-disable-next-line -- no-restricted-properties + it.skip('not-equal removes existence filter', () => { return withTestCollection( PERSISTENCE_MODE_UNSPECIFIED, { diff --git a/packages/firestore/test/integration/browser/indexeddb.test.ts b/packages/firestore/test/integration/browser/indexeddb.test.ts index 27e0e3a085..ff7c1c64ad 100644 --- a/packages/firestore/test/integration/browser/indexeddb.test.ts +++ b/packages/firestore/test/integration/browser/indexeddb.test.ts @@ -38,7 +38,9 @@ describe('where indexeddb is not available: ', () => { return; } - it('fails with code unimplemented', () => { + // TODO(pipeline) fix test or SDK + // eslint-disable-next-line -- no-restricted-properties + it.skip('fails with code unimplemented', () => { // withTestDb will fail the test if persistence is requested but it fails // so we'll enable persistence here instead. return withTestDb(PERSISTENCE_MODE_UNSPECIFIED, db => { diff --git a/packages/firestore/test/integration/util/settings.ts b/packages/firestore/test/integration/util/settings.ts index 6fcb513a9a..b47232730a 100644 --- a/packages/firestore/test/integration/util/settings.ts +++ b/packages/firestore/test/integration/util/settings.ts @@ -37,6 +37,8 @@ const PROJECT_CONFIG = require('../../../../../config/project.json'); export const TARGET_DB_ID: string | '(default)' = getTargetDbId(); +export const RUN_ENTERPRISE_TESTS: boolean = getRunEnterpriseTests(); + const TARGET_BACKEND: TargetBackend = getTargetBackend(); export const USE_EMULATOR: boolean = TARGET_BACKEND === TargetBackend.EMULATOR; @@ -62,6 +64,14 @@ function getTargetDbId(): string | '(default)' { return '(default)'; } +function getRunEnterpriseTests(): boolean { + const karma = typeof __karma__ !== 'undefined' ? __karma__ : undefined; + if (karma && karma.config.firestoreEdition === 'enterprise') { + return true; + } + return !!process.env.RUN_ENTERPRISE_TESTS; +} + function parseTargetBackend(targetBackend: string): TargetBackend { switch (targetBackend) { case 'emulator': diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index a16f59be26..4dfbcd491d 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -183,7 +183,7 @@ import { use(chaiAsPromised); -const timestampDeltaMS = 1000; +const timestampDeltaMS = 10000; describe.skipClassic('Firestore Pipelines', () => { addEqualityMatcher(); @@ -2334,10 +2334,6 @@ describe.skipClassic('Firestore Pipelines', () => { // Backend returns the code as `failed-precondition` when using the REST transport expect(err['code']).to.equal('failed-precondition'); expect(typeof err['message']).to.equal('string'); - - expect(err['message']).to.match( - /Request failed with error: Expected value type of MAP_VALUE when parsing 'fields' but received FIELD_REFERENCE_VALUE instead/ - ); } }); }); diff --git a/packages/firestore/test/util/mocha_extensions.ts b/packages/firestore/test/util/mocha_extensions.ts index df8598e5fe..30df4ddee2 100644 --- a/packages/firestore/test/util/mocha_extensions.ts +++ b/packages/firestore/test/util/mocha_extensions.ts @@ -17,7 +17,10 @@ /* eslint-disable no-restricted-properties */ -import { USE_EMULATOR } from '../integration/util/settings'; +import { + USE_EMULATOR, + RUN_ENTERPRISE_TESTS +} from '../integration/util/settings'; // Helper to make a type itselt (T) and optionally union that with (T['skip']) type tOrSkipT = T | (T extends { skip: unknown } ? T['skip'] : T); @@ -64,7 +67,7 @@ export function mixinSkipImplementations(obj: unknown): void { if (this === describe.skip) { return this; } - if (process.env.RUN_ENTERPRISE_TESTS) { + if (RUN_ENTERPRISE_TESTS) { return this.skip; } return this; @@ -79,7 +82,7 @@ export function mixinSkipImplementations(obj: unknown): void { if (this === describe.skip) { return this; } - if (!process.env.RUN_ENTERPRISE_TESTS) { + if (!RUN_ENTERPRISE_TESTS) { return this.skip; } return this; From 742e17a8e079edc6112f110663dd4b05fcb44240 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 31 Mar 2026 10:20:51 -0400 Subject: [PATCH 115/174] test(firestore): update nested fields test to reflect backend change (#9717) The backend now supports nested field modification in the addFields and select changes. All aliases with a `.` are now treated as a nested field path. This change updates the tests to reflect this new behaviour. --- .../test/integration/api/pipeline.test.ts | 91 ++++++++++--------- packages/firestore/test/lite/pipeline.test.ts | 90 ++++++++++-------- 2 files changed, 100 insertions(+), 81 deletions(-) diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index fa6abdd626..70596045e5 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -2349,10 +2349,13 @@ apiDescribe.skipClassic('Pipelines', persistence => { const err = e as FirebaseError; expect(err['code']).to.equal('invalid-argument'); expect(typeof err['message']).to.equal('string'); + + expect(err['message']).to.match( + /Expected fields to be MAP_VALUE, but was FIELD_REFERENCE_VALUE./ + ); } }); }); - describe('function expressions', () => { it('logical max works', async () => { const snapshot = await execute( @@ -2362,7 +2365,7 @@ apiDescribe.skipClassic('Pipelines', persistence => { .select( 'title', logicalMaximum(constant(1960), field('published'), 1961).as( - 'published-safe' + 'publishedSafe' ) ) .sort(field('title').ascending()) @@ -2370,9 +2373,9 @@ apiDescribe.skipClassic('Pipelines', persistence => { ); expectResults( snapshot, - { title: '1984', 'published-safe': 1961 }, - { title: 'Crime and Punishment', 'published-safe': 1961 }, - { title: 'Dune', 'published-safe': 1965 } + { title: '1984', 'publishedSafe': 1961 }, + { title: 'Crime and Punishment', 'publishedSafe': 1961 }, + { title: 'Dune', 'publishedSafe': 1965 } ); }); @@ -2384,7 +2387,7 @@ apiDescribe.skipClassic('Pipelines', persistence => { .select( 'title', logicalMinimum(constant(1960), field('published'), 1961).as( - 'published-safe' + 'publishedSafe' ) ) .sort(field('title').ascending()) @@ -2392,9 +2395,9 @@ apiDescribe.skipClassic('Pipelines', persistence => { ); expectResults( snapshot, - { title: '1984', 'published-safe': 1949 }, - { title: 'Crime and Punishment', 'published-safe': 1866 }, - { title: 'Dune', 'published-safe': 1960 } + { title: '1984', 'publishedSafe': 1949 }, + { title: 'Crime and Punishment', 'publishedSafe': 1866 }, + { title: 'Dune', 'publishedSafe': 1960 } ); }); @@ -2409,7 +2412,7 @@ apiDescribe.skipClassic('Pipelines', persistence => { lessThan(field('published'), 1960), constant(1960), field('published') - ).as('published-safe'), + ).as('publishedSafe'), field('rating') .greaterThanOrEqual(4.5) .conditional(constant('great'), constant('good')) @@ -2420,13 +2423,13 @@ apiDescribe.skipClassic('Pipelines', persistence => { ); expectResults( snapshot, - { title: '1984', 'published-safe': 1960, rating: 'good' }, + { title: '1984', 'publishedSafe': 1960, rating: 'good' }, { title: 'Crime and Punishment', - 'published-safe': 1960, + 'publishedSafe': 1960, rating: 'good' }, - { title: 'Dune', 'published-safe': 1965, rating: 'great' } + { title: 'Dune', 'publishedSafe': 1965, rating: 'great' } ); }); @@ -2935,9 +2938,11 @@ apiDescribe.skipClassic('Pipelines', persistence => { snapshot, { title: "The Hitchhiker's Guide to the Galaxy", - 'awards.hugo': true + awards: { + hugo: true + } }, - { title: 'Dune', 'awards.hugo': true } + { title: 'Dune', awards: { hugo: true } } ); }); @@ -2950,7 +2955,7 @@ apiDescribe.skipClassic('Pipelines', persistence => { .replaceWith( map({ title: 'foo', - nested: { + nestedField: { level: { '1': 'bar' }, @@ -2962,13 +2967,17 @@ apiDescribe.skipClassic('Pipelines', persistence => { ) .select( 'title', - field('nested.level.1'), - mapGet('nested', 'level.1').mapGet('level.2').as('nested') + field('nestedField.level.1'), + mapGet('nestedField', 'level.1').mapGet('level.2').as('nested') ) ); expectResults(snapshot, { title: 'foo', - 'nested.level.`1`': 'bar', + nestedField: { + level: { + '1': 'bar' + } + }, nested: 'baz' }); }); @@ -4278,17 +4287,17 @@ apiDescribe.skipClassic('Pipelines', persistence => { }) ) .select( - field('foo').round(0).as('0'), - round('foo', 1).as('1'), - round('foo', constant(2)).as('2'), - round(field('foo'), 4).as('4') + field('foo').round(0).as('roundedTo0'), + round('foo', 1).as('roundedTo1'), + round('foo', constant(2)).as('roundedTo2'), + round(field('foo'), 4).as('roundedTo4') ) ); expectResults(snapshot, { - '0': 4, - '1': 4.1, - '2': 4.12, - '4': 4.1235 + roundedTo0: 4, + roundedTo1: 4.1, + roundedTo2: 4.12, + roundedTo4: 4.1235 }); }); @@ -4332,17 +4341,17 @@ apiDescribe.skipClassic('Pipelines', persistence => { }) ) .select( - field('foo').trunc(0).as('0'), - trunc('foo', 1).as('1'), - trunc('foo', constant(2)).as('2'), - trunc(field('foo'), 4).as('4') + field('foo').trunc(0).as('truncatedTo0'), + trunc('foo', 1).as('truncatedTo1'), + trunc('foo', constant(2)).as('truncatedTo2'), + trunc(field('foo'), 4).as('truncatedTo4') ) ); expectResults(snapshot, { - '0': 4, - '1': 4.1, - '2': 4.12, - '4': 4.1234 + truncatedTo0: 4, + truncatedTo1: 4.1, + truncatedTo2: 4.12, + truncatedTo4: 4.1234 }); }); @@ -4966,15 +4975,15 @@ apiDescribe.skipClassic('Pipelines', persistence => { constant(1).as('pos1') ) .select( - abs('neg10').as('10'), - abs(field('neg22')).as('22'), - field('pos1').as('1') + abs('neg10').as('abs10'), + abs(field('neg22')).as('abs22'), + field('pos1').as('abs1') ) ); expectResults(snapshot, { - '10': 10, - '22': 22.22, - '1': 1 + 'abs10': 10, + 'abs22': 22.22, + 'abs1': 1 }); }); diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 4dfbcd491d..547f60efdd 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -2334,6 +2334,10 @@ describe.skipClassic('Firestore Pipelines', () => { // Backend returns the code as `failed-precondition` when using the REST transport expect(err['code']).to.equal('failed-precondition'); expect(typeof err['message']).to.equal('string'); + + expect(err['message']).to.match( + /Request failed with error: Expected fields to be MAP_VALUE, but was FIELD_REFERENCE_VALUE./ + ); } }); }); @@ -2347,7 +2351,7 @@ describe.skipClassic('Firestore Pipelines', () => { .select( 'title', logicalMaximum(constant(1960), field('published'), 1961).as( - 'published-safe' + 'publishedSafe' ) ) .sort(field('title').ascending()) @@ -2355,9 +2359,9 @@ describe.skipClassic('Firestore Pipelines', () => { ); expectResults( snapshot, - { title: '1984', 'published-safe': 1961 }, - { title: 'Crime and Punishment', 'published-safe': 1961 }, - { title: 'Dune', 'published-safe': 1965 } + { title: '1984', 'publishedSafe': 1961 }, + { title: 'Crime and Punishment', 'publishedSafe': 1961 }, + { title: 'Dune', 'publishedSafe': 1965 } ); }); @@ -2369,7 +2373,7 @@ describe.skipClassic('Firestore Pipelines', () => { .select( 'title', logicalMinimum(constant(1960), field('published'), 1961).as( - 'published-safe' + 'publishedSafe' ) ) .sort(field('title').ascending()) @@ -2377,9 +2381,9 @@ describe.skipClassic('Firestore Pipelines', () => { ); expectResults( snapshot, - { title: '1984', 'published-safe': 1949 }, - { title: 'Crime and Punishment', 'published-safe': 1866 }, - { title: 'Dune', 'published-safe': 1960 } + { title: '1984', 'publishedSafe': 1949 }, + { title: 'Crime and Punishment', 'publishedSafe': 1866 }, + { title: 'Dune', 'publishedSafe': 1960 } ); }); @@ -2394,7 +2398,7 @@ describe.skipClassic('Firestore Pipelines', () => { lessThan(field('published'), 1960), constant(1960), field('published') - ).as('published-safe'), + ).as('publishedSafe'), field('rating') .greaterThanOrEqual(4.5) .conditional(constant('great'), constant('good')) @@ -2405,13 +2409,13 @@ describe.skipClassic('Firestore Pipelines', () => { ); expectResults( snapshot, - { title: '1984', 'published-safe': 1960, rating: 'good' }, + { title: '1984', 'publishedSafe': 1960, rating: 'good' }, { title: 'Crime and Punishment', - 'published-safe': 1960, + 'publishedSafe': 1960, rating: 'good' }, - { title: 'Dune', 'published-safe': 1965, rating: 'great' } + { title: 'Dune', 'publishedSafe': 1965, rating: 'great' } ); }); @@ -2921,9 +2925,11 @@ describe.skipClassic('Firestore Pipelines', () => { snapshot, { title: "The Hitchhiker's Guide to the Galaxy", - 'awards.hugo': true + awards: { + hugo: true + } }, - { title: 'Dune', 'awards.hugo': true } + { title: 'Dune', awards: { hugo: true } } ); }); @@ -2936,7 +2942,7 @@ describe.skipClassic('Firestore Pipelines', () => { .replaceWith( map({ title: 'foo', - nested: { + nestedField: { level: { '1': 'bar' }, @@ -2948,13 +2954,17 @@ describe.skipClassic('Firestore Pipelines', () => { ) .select( 'title', - field('nested.level.1'), - mapGet('nested', 'level.1').mapGet('level.2').as('nested') + field('nestedField.level.1'), + mapGet('nestedField', 'level.1').mapGet('level.2').as('nested') ) ); expectResults(snapshot, { title: 'foo', - 'nested.level.`1`': 'bar', + nestedField: { + level: { + '1': 'bar' + } + }, nested: 'baz' }); }); @@ -4335,17 +4345,17 @@ describe.skipClassic('Firestore Pipelines', () => { }) ) .select( - field('foo').round(0).as('0'), - round('foo', 1).as('1'), - round('foo', constant(2)).as('2'), - round(field('foo'), 4).as('4') + field('foo').round(0).as('roundedTo0'), + round('foo', 1).as('roundedTo1'), + round('foo', constant(2)).as('roundedTo2'), + round(field('foo'), 4).as('roundedTo4') ) ); expectResults(snapshot, { - '0': 4, - '1': 4.1, - '2': 4.12, - '4': 4.1235 + roundedTo0: 4, + roundedTo1: 4.1, + roundedTo2: 4.12, + roundedTo4: 4.1235 }); }); @@ -4389,17 +4399,17 @@ describe.skipClassic('Firestore Pipelines', () => { }) ) .select( - field('foo').trunc(0).as('0'), - trunc('foo', 1).as('1'), - trunc('foo', constant(2)).as('2'), - trunc(field('foo'), 4).as('4') + field('foo').trunc(0).as('truncatedTo0'), + trunc('foo', 1).as('truncatedTo1'), + trunc('foo', constant(2)).as('truncatedTo2'), + trunc(field('foo'), 4).as('truncatedTo4') ) ); expectResults(snapshot, { - '0': 4, - '1': 4.1, - '2': 4.12, - '4': 4.1234 + truncatedTo0: 4, + truncatedTo1: 4.1, + truncatedTo2: 4.12, + truncatedTo4: 4.1234 }); }); @@ -5135,15 +5145,15 @@ describe.skipClassic('Firestore Pipelines', () => { constant(1).as('pos1') ) .select( - abs('neg10').as('10'), - abs(field('neg22')).as('22'), - field('pos1').as('1') + abs('neg10').as('abs10'), + abs(field('neg22')).as('abs22'), + field('pos1').as('abs1') ) ); expectResults(snapshot, { - '10': 10, - '22': 22.22, - '1': 1 + 'abs10': 10, + 'abs22': 22.22, + 'abs1': 1 }); }); From e8f14eb499f10246b96759f58479905ab8f02e4c Mon Sep 17 00:00:00 2001 From: Mila <107142260+milaGGL@users.noreply.github.com> Date: Tue, 31 Mar 2026 12:13:12 -0400 Subject: [PATCH 116/174] feat(firestore): Add `ifNull` and `coalesce` expressions (#9753) --- .changeset/rotten-tigers-bake.md | 6 + .../firestore-lite-pipelines.api.md | 24 ++ common/api-review/firestore-pipelines.api.md | 24 ++ .../firestore_lite_pipelines.expression.md | 111 ++++++++ docs-devsite/firestore_lite_pipelines.md | 228 +++++++++++++++++ .../firestore_pipelines.expression.md | 111 ++++++++ docs-devsite/firestore_pipelines.md | 228 +++++++++++++++++ .../firestore/lite/pipelines/pipelines.ts | 2 + packages/firestore/src/api_pipelines.ts | 2 + .../firestore/src/lite-api/expressions.ts | 236 ++++++++++++++++++ .../test/integration/api/pipeline.test.ts | 91 ++++++- packages/firestore/test/lite/pipeline.test.ts | 91 ++++++- 12 files changed, 1152 insertions(+), 2 deletions(-) create mode 100644 .changeset/rotten-tigers-bake.md diff --git a/.changeset/rotten-tigers-bake.md b/.changeset/rotten-tigers-bake.md new file mode 100644 index 0000000000..0f0c544146 --- /dev/null +++ b/.changeset/rotten-tigers-bake.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/firestore': minor +--- + +Add support for pipeline expressions `ifNull` and `coalesce`. diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index 8cf3be4d73..fd4165b5df 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -274,6 +274,12 @@ export function charLength(fieldName: string): FunctionExpression; // @beta export function charLength(stringExpression: Expression): FunctionExpression; +// @beta +export function coalesce(expression: Expression, replacement: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function coalesce(fieldName: string, replacement: Expression | unknown, ...others: Array): FunctionExpression; + // @beta export type CollectionGroupStageOptions = StageOptions & { collectionId: string; @@ -557,6 +563,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ charLength(): FunctionExpression; /* Excluded from this release type: _readUserData */ + coalesce(replacement: Expression | unknown, ...others: Array): FunctionExpression; + /* Excluded from this release type: _readUserData */ collectionId(): FunctionExpression; /* Excluded from this release type: _readUserData */ concat(second: Expression | unknown, ...others: Array): FunctionExpression; @@ -624,6 +632,10 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ ifError(catchValue: unknown): FunctionExpression; /* Excluded from this release type: _readUserData */ + ifNull(elseExpression: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + ifNull(elseValue: unknown): FunctionExpression; + /* Excluded from this release type: _readUserData */ isAbsent(): BooleanExpression; /* Excluded from this release type: _readUserData */ isError(): BooleanExpression; @@ -906,6 +918,18 @@ export function ifError(tryExpr: Expression, catchExpr: Expression): FunctionExp // @beta export function ifError(tryExpr: Expression, catchValue: unknown): FunctionExpression; +// @beta +export function ifNull(ifExpr: Expression, elseExpr: Expression): FunctionExpression; + +// @beta +export function ifNull(ifExpr: Expression, elseValue: unknown): FunctionExpression; + +// @beta +export function ifNull(ifFieldName: string, elseExpr: Expression): FunctionExpression; + +// @beta +export function ifNull(ifFieldName: string, elseValue: unknown): FunctionExpression; + // @beta export function isAbsent(value: Expression): BooleanExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index c49fddf2f7..29e929c080 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -274,6 +274,12 @@ export function charLength(fieldName: string): FunctionExpression; // @beta export function charLength(stringExpression: Expression): FunctionExpression; +// @beta +export function coalesce(expression: Expression, replacement: Expression | unknown, ...others: Array): FunctionExpression; + +// @beta +export function coalesce(fieldName: string, replacement: Expression | unknown, ...others: Array): FunctionExpression; + // @beta export type CollectionGroupStageOptions = StageOptions & { collectionId: string; @@ -560,6 +566,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ charLength(): FunctionExpression; /* Excluded from this release type: _readUserData */ + coalesce(replacement: Expression | unknown, ...others: Array): FunctionExpression; + /* Excluded from this release type: _readUserData */ collectionId(): FunctionExpression; /* Excluded from this release type: _readUserData */ concat(second: Expression | unknown, ...others: Array): FunctionExpression; @@ -627,6 +635,10 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ ifError(catchValue: unknown): FunctionExpression; /* Excluded from this release type: _readUserData */ + ifNull(elseExpression: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + ifNull(elseValue: unknown): FunctionExpression; + /* Excluded from this release type: _readUserData */ isAbsent(): BooleanExpression; /* Excluded from this release type: _readUserData */ isError(): BooleanExpression; @@ -909,6 +921,18 @@ export function ifError(tryExpr: Expression, catchExpr: Expression): FunctionExp // @beta export function ifError(tryExpr: Expression, catchValue: unknown): FunctionExpression; +// @beta +export function ifNull(ifExpr: Expression, elseExpr: Expression): FunctionExpression; + +// @beta +export function ifNull(ifExpr: Expression, elseValue: unknown): FunctionExpression; + +// @beta +export function ifNull(ifFieldName: string, elseExpr: Expression): FunctionExpression; + +// @beta +export function ifNull(ifFieldName: string, elseValue: unknown): FunctionExpression; + // @beta export function isAbsent(value: Expression): BooleanExpression; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index 25c485e5ba..25ce29755b 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -78,6 +78,7 @@ export declare abstract class Expression | [byteLength()](./firestore_lite_pipelines.expression.md#expressionbytelength) | | (Public Preview) Creates an expression that calculates the length of this string expression in bytes. | | [ceil()](./firestore_lite_pipelines.expression.md#expressionceil) | | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | | [charLength()](./firestore_lite_pipelines.expression.md#expressioncharlength) | | (Public Preview) Creates an expression that calculates the character length of a string in UTF-8. | +| [coalesce(replacement, others)](./firestore_lite_pipelines.expression.md#expressioncoalesce) | | (Public Preview) Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | | [collectionId()](./firestore_lite_pipelines.expression.md#expressioncollectionid) | | (Public Preview) Creates an expression that returns the collection ID from a path. | | [concat(second, others)](./firestore_lite_pipelines.expression.md#expressionconcat) | | (Public Preview) Creates an expression that concatenates expression results together. | | [cosineDistance(vectorExpression)](./firestore_lite_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the cosine distance between two vectors. | @@ -110,6 +111,8 @@ export declare abstract class Expression | [ifAbsent(elseExpression)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | | [ifError(catchExpr)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. | | [ifError(catchValue)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifNull(elseExpression)](./firestore_lite_pipelines.expression.md#expressionifnull) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression evaluates to null, else return the result of this expression evaluation. | +| [ifNull(elseValue)](./firestore_lite_pipelines.expression.md#expressionifnull) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression evaluates to null, else return the result of this expression evaluation. | | [isAbsent()](./firestore_lite_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. | | [isError()](./firestore_lite_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. | | [isType(type)](./firestore_lite_pipelines.expression.md#expressionistype) | | (Public Preview) Creates an expression that checks if the result of this expression is of the given type. | @@ -1506,6 +1509,42 @@ field("name").charLength(); ``` +## Expression.coalesce() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. + +Signature: + +```typescript +coalesce(replacement: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| replacement | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The value to use if this expression evaluates to null. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional values to check if previous values are null. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the coalesce operation. + +### Example + + +```typescript +// Returns the value of the first non-null, non-absent field among 'preferredName', 'fullName', +// or the last argument if all previous fields are null. +field("preferredName").coalesce(field("fullName"), "Anonymous"); + +``` + ## Expression.collectionId() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2537,6 +2576,78 @@ field("title").arrayGet(0).ifError("Default Title"); ``` +## Expression.ifNull() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if this expression evaluates to null, else return the result of this expression evaluation. + +This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. + +Signature: + +```typescript +ifNull(elseExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elseExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The Expression that will be evaluated if this Expression evaluates to null. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the ifNull operation. + +### Example + + +```typescript +// Returns the user's preferred name, or if that is null, returns their full name. +field("preferredName").ifNull(field("fullName")) + +``` + +## Expression.ifNull() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if this expression evaluates to null, else return the result of this expression evaluation. + +This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. + +Signature: + +```typescript +ifNull(elseValue: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elseValue | unknown | The value that will be returned if this Expression evaluates to null. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the ifNull operation. + +### Example + + +```typescript +// Returns the user's display name, or returns "Anonymous" if the field is null. +field("displayName").ifNull("Anonymous") + +``` + ## Expression.isAbsent() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index de497b10be..f9bad335e2 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -99,6 +99,7 @@ https://github.com/firebase/firebase-js-sdk | [arraySum(expression)](./firestore_lite_pipelines.md#arraysum_1138a27) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | | [average(expression)](./firestore_lite_pipelines.md#average_1138a27) | (Public Preview) Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. | | [ceil(expression)](./firestore_lite_pipelines.md#ceil_1138a27) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | +| [coalesce(expression, replacement, others)](./firestore_lite_pipelines.md#coalesce_00859cb) | (Public Preview) Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | | [collectionId(expression)](./firestore_lite_pipelines.md#collectionid_1138a27) | (Public Preview) Creates an expression that returns the collection ID from a path. | | [count(expression)](./firestore_lite_pipelines.md#count_1138a27) | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. | | [divide(expression, value)](./firestore_lite_pipelines.md#divide_01df3cf) | (Public Preview) Creates an expression that divides an expression by a constant value. | @@ -177,6 +178,7 @@ https://github.com/firebase/firebase-js-sdk | [byteLength(fieldName)](./firestore_lite_pipelines.md#bytelength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. | | [ceil(fieldName)](./firestore_lite_pipelines.md#ceil_e5b0480) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | | [charLength(fieldName)](./firestore_lite_pipelines.md#charlength_e5b0480) | (Public Preview) Creates an expression that calculates the character length of a string field in UTF8. | +| [coalesce(fieldName, replacement, others)](./firestore_lite_pipelines.md#coalesce_249958e) | (Public Preview) Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | | [collectionId(fieldName)](./firestore_lite_pipelines.md#collectionid_e5b0480) | (Public Preview) Creates an expression that returns the collection ID from a path. | | [concat(fieldName, second, others)](./firestore_lite_pipelines.md#concat_828272e) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | | [cosineDistance(fieldName, vector)](./firestore_lite_pipelines.md#cosinedistance_463a23e) | (Public Preview) Calculates the Cosine distance between a field's vector value and a literal vector value. | @@ -295,9 +297,13 @@ https://github.com/firebase/firebase-js-sdk | function(ifExpr, ...) | | [ifAbsent(ifExpr, elseExpr)](./firestore_lite_pipelines.md#ifabsent_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | | [ifAbsent(ifExpr, elseValue)](./firestore_lite_pipelines.md#ifabsent_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | +| [ifNull(ifExpr, elseExpr)](./firestore_lite_pipelines.md#ifnull_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is null, else return the result of the ifExpr argument evaluation. | +| [ifNull(ifExpr, elseValue)](./firestore_lite_pipelines.md#ifnull_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is null, else return the result of the ifExpr argument evaluation. | | function(ifFieldName, ...) | | [ifAbsent(ifFieldName, elseExpr)](./firestore_lite_pipelines.md#ifabsent_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName is absent, else return the value of the field. | | [ifAbsent(ifFieldName, elseValue)](./firestore_lite_pipelines.md#ifabsent_d8f2823) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName is absent, else return the value of the field. | +| [ifNull(ifFieldName, elseExpr)](./firestore_lite_pipelines.md#ifnull_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName field is null, else return the value of the field. | +| [ifNull(ifFieldName, elseValue)](./firestore_lite_pipelines.md#ifnull_587c2f0) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName field is null, else return the value of the field. | | function(input, ...) | | [substring(input, position, length)](./firestore_lite_pipelines.md#substring_e6e0aa3) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | | [substring(input, position, length)](./firestore_lite_pipelines.md#substring_ab56dc6) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | @@ -2828,6 +2834,43 @@ ceil(field("price")); ``` +### coalesce(expression, replacement, others) {:#coalesce_00859cb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. + +Signature: + +```typescript +export declare function coalesce(expression: Expression, replacement: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The first expression to check for null. | +| replacement | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The fallback expression or value if the first one is null. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions to check if previous ones are null. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the coalesce operation. + +### Example + + +```typescript +// Returns the value of the first non-null, non-absent field among 'preferredName', 'fullName', +// or the last argument if all previous fields are null. +coalesce(field("preferredName"), field("fullName"), constant("Anonymous")) + +``` + ### collectionId(expression) {:#collectionid_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -5459,6 +5502,43 @@ charLength("name"); ``` +### coalesce(fieldName, replacement, others) {:#coalesce_249958e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. + +Signature: + +```typescript +export declare function coalesce(fieldName: string, replacement: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the first field to check for null. | +| replacement | [Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown | The fallback expression or value if the first one is null. | +| others | Array<[Expression](./firestore_lite_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions to check if previous ones are null. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the coalesce operation. + +### Example + + +```typescript +// Returns the value of the first non-null, non-absent field among 'preferredName', 'fullName', +// or the last argument if all previous fields are null. +coalesce("preferredName", field("fullName"), constant("Anonymous")) + +``` + ### collectionId(fieldName) {:#collectionid_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9417,6 +9497,80 @@ ifAbsent(field("optional_field"), "default_value") ``` +### ifNull(ifExpr, elseExpr) {:#ifnull_0e6d161} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseExpr` argument if `ifExpr` is null, else return the result of the `ifExpr` argument evaluation. + +This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. + +Signature: + +```typescript +export declare function ifNull(ifExpr: Expression, elseExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check for null. | +| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if ifExpr is null. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ifNull operation. + +### Example + + +```typescript +// Returns the user's preferred name, or if that is null, returns their full name. +ifNull(field("preferredName"), field("fullName")) + +``` + +### ifNull(ifExpr, elseValue) {:#ifnull_c34e5ed} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if `ifExpr` is null, else return the result of the `ifExpr` argument evaluation. + +This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. + +Signature: + +```typescript +export declare function ifNull(ifExpr: Expression, elseValue: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check for null. | +| elseValue | unknown | The value that will be returned if ifExpr evaluates to null. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ifNull operation. + +### Example + + +```typescript +// Returns the user's display name, or returns "Anonymous" if the field is null. +ifNull(field("displayName"), "Anonymous") + +``` + ## function(ifFieldName, ...) ### ifAbsent(ifFieldName, elseExpr) {:#ifabsent_e6dabea} @@ -9491,6 +9645,80 @@ ifAbsent("optional_field", "default_value") ``` +### ifNull(ifFieldName, elseExpr) {:#ifnull_e6dabea} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseExpr` argument if `ifFieldName` field is null, else return the value of the field. + +This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. + +Signature: + +```typescript +export declare function ifNull(ifFieldName: string, elseExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifFieldName | string | The field to check for null. | +| elseExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if ifFieldName is null. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ifNull operation. + +### Example + + +```typescript +// Returns the user's preferred name, or if that is null, returns their full name. +ifNull("preferredName", field("fullName")) + +``` + +### ifNull(ifFieldName, elseValue) {:#ifnull_587c2f0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if `ifFieldName` field is null, else return the value of the field. + +This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. + +Signature: + +```typescript +export declare function ifNull(ifFieldName: string, elseValue: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifFieldName | string | The field to check for null. | +| elseValue | unknown | The value that will be returned if ifFieldName is null. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ifNull operation. + +### Example + + +```typescript +// Returns the user's display name, or returns "Anonymous" if the field is null. +ifNull("displayName", "Anonymous") + +``` + ## function(input, ...) ### substring(input, position, length) {:#substring_e6e0aa3} diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 2418427357..9d8d72df89 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -78,6 +78,7 @@ export declare abstract class Expression | [byteLength()](./firestore_pipelines.expression.md#expressionbytelength) | | (Public Preview) Creates an expression that calculates the length of this string expression in bytes. | | [ceil()](./firestore_pipelines.expression.md#expressionceil) | | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | | [charLength()](./firestore_pipelines.expression.md#expressioncharlength) | | (Public Preview) Creates an expression that calculates the character length of a string in UTF-8. | +| [coalesce(replacement, others)](./firestore_pipelines.expression.md#expressioncoalesce) | | (Public Preview) Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | | [collectionId()](./firestore_pipelines.expression.md#expressioncollectionid) | | (Public Preview) Creates an expression that returns the collection ID from a path. | | [concat(second, others)](./firestore_pipelines.expression.md#expressionconcat) | | (Public Preview) Creates an expression that concatenates expression results together. | | [cosineDistance(vectorExpression)](./firestore_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the cosine distance between two vectors. | @@ -110,6 +111,8 @@ export declare abstract class Expression | [ifAbsent(elseExpression)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | | [ifError(catchExpr)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. | | [ifError(catchValue)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifNull(elseExpression)](./firestore_pipelines.expression.md#expressionifnull) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression evaluates to null, else return the result of this expression evaluation. | +| [ifNull(elseValue)](./firestore_pipelines.expression.md#expressionifnull) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression evaluates to null, else return the result of this expression evaluation. | | [isAbsent()](./firestore_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. | | [isError()](./firestore_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. | | [isType(type)](./firestore_pipelines.expression.md#expressionistype) | | (Public Preview) Creates an expression that checks if the result of this expression is of the given type. | @@ -1506,6 +1509,42 @@ field("name").charLength(); ``` +## Expression.coalesce() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. + +Signature: + +```typescript +coalesce(replacement: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| replacement | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The value to use if this expression evaluates to null. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional values to check if previous values are null. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the coalesce operation. + +### Example + + +```typescript +// Returns the value of the first non-null, non-absent field among 'preferredName', 'fullName', +// or the last argument if all previous fields are null. +field("preferredName").coalesce(field("fullName"), "Anonymous"); + +``` + ## Expression.collectionId() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -2537,6 +2576,78 @@ field("title").arrayGet(0).ifError("Default Title"); ``` +## Expression.ifNull() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if this expression evaluates to null, else return the result of this expression evaluation. + +This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. + +Signature: + +```typescript +ifNull(elseExpression: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elseExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The Expression that will be evaluated if this Expression evaluates to null. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the ifNull operation. + +### Example + + +```typescript +// Returns the user's preferred name, or if that is null, returns their full name. +field("preferredName").ifNull(field("fullName")) + +``` + +## Expression.ifNull() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if this expression evaluates to null, else return the result of this expression evaluation. + +This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. + +Signature: + +```typescript +ifNull(elseValue: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elseValue | unknown | The value that will be returned if this Expression evaluates to null. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the ifNull operation. + +### Example + + +```typescript +// Returns the user's display name, or returns "Anonymous" if the field is null. +field("displayName").ifNull("Anonymous") + +``` + ## Expression.isAbsent() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index a271da069f..889f0fbc9f 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -99,6 +99,7 @@ https://github.com/firebase/firebase-js-sdk | [arraySum(expression)](./firestore_pipelines.md#arraysum_1138a27) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | | [average(expression)](./firestore_pipelines.md#average_1138a27) | (Public Preview) Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. | | [ceil(expression)](./firestore_pipelines.md#ceil_1138a27) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | +| [coalesce(expression, replacement, others)](./firestore_pipelines.md#coalesce_00859cb) | (Public Preview) Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | | [collectionId(expression)](./firestore_pipelines.md#collectionid_1138a27) | (Public Preview) Creates an expression that returns the collection ID from a path. | | [count(expression)](./firestore_pipelines.md#count_1138a27) | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. | | [divide(expression, value)](./firestore_pipelines.md#divide_01df3cf) | (Public Preview) Creates an expression that divides an expression by a constant value. | @@ -177,6 +178,7 @@ https://github.com/firebase/firebase-js-sdk | [byteLength(fieldName)](./firestore_pipelines.md#bytelength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. | | [ceil(fieldName)](./firestore_pipelines.md#ceil_e5b0480) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | | [charLength(fieldName)](./firestore_pipelines.md#charlength_e5b0480) | (Public Preview) Creates an expression that calculates the character length of a string field in UTF8. | +| [coalesce(fieldName, replacement, others)](./firestore_pipelines.md#coalesce_249958e) | (Public Preview) Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | | [collectionId(fieldName)](./firestore_pipelines.md#collectionid_e5b0480) | (Public Preview) Creates an expression that returns the collection ID from a path. | | [concat(fieldName, second, others)](./firestore_pipelines.md#concat_828272e) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | | [cosineDistance(fieldName, vector)](./firestore_pipelines.md#cosinedistance_463a23e) | (Public Preview) Calculates the Cosine distance between a field's vector value and a literal vector value. | @@ -295,9 +297,13 @@ https://github.com/firebase/firebase-js-sdk | function(ifExpr, ...) | | [ifAbsent(ifExpr, elseExpr)](./firestore_pipelines.md#ifabsent_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | | [ifAbsent(ifExpr, elseValue)](./firestore_pipelines.md#ifabsent_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | +| [ifNull(ifExpr, elseExpr)](./firestore_pipelines.md#ifnull_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is null, else return the result of the ifExpr argument evaluation. | +| [ifNull(ifExpr, elseValue)](./firestore_pipelines.md#ifnull_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is null, else return the result of the ifExpr argument evaluation. | | function(ifFieldName, ...) | | [ifAbsent(ifFieldName, elseExpr)](./firestore_pipelines.md#ifabsent_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName is absent, else return the value of the field. | | [ifAbsent(ifFieldName, elseValue)](./firestore_pipelines.md#ifabsent_d8f2823) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName is absent, else return the value of the field. | +| [ifNull(ifFieldName, elseExpr)](./firestore_pipelines.md#ifnull_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName field is null, else return the value of the field. | +| [ifNull(ifFieldName, elseValue)](./firestore_pipelines.md#ifnull_587c2f0) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName field is null, else return the value of the field. | | function(input, ...) | | [substring(input, position, length)](./firestore_pipelines.md#substring_e6e0aa3) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | | [substring(input, position, length)](./firestore_pipelines.md#substring_ab56dc6) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | @@ -2834,6 +2840,43 @@ ceil(field("price")); ``` +### coalesce(expression, replacement, others) {:#coalesce_00859cb} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. + +Signature: + +```typescript +export declare function coalesce(expression: Expression, replacement: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The first expression to check for null. | +| replacement | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The fallback expression or value if the first one is null. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions to check if previous ones are null. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the coalesce operation. + +### Example + + +```typescript +// Returns the value of the first non-null, non-absent field among 'preferredName', 'fullName', +// or the last argument if all previous fields are null. +coalesce(field("preferredName"), field("fullName"), constant("Anonymous")) + +``` + ### collectionId(expression) {:#collectionid_1138a27} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -5465,6 +5508,43 @@ charLength("name"); ``` +### coalesce(fieldName, replacement, others) {:#coalesce_249958e} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. + +Signature: + +```typescript +export declare function coalesce(fieldName: string, replacement: Expression | unknown, ...others: Array): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the first field to check for null. | +| replacement | [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown | The fallback expression or value if the first one is null. | +| others | Array<[Expression](./firestore_pipelines.expression.md#expression_class) \| unknown> | Optional additional expressions to check if previous ones are null. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the coalesce operation. + +### Example + + +```typescript +// Returns the value of the first non-null, non-absent field among 'preferredName', 'fullName', +// or the last argument if all previous fields are null. +coalesce("preferredName", field("fullName"), constant("Anonymous")) + +``` + ### collectionId(fieldName) {:#collectionid_e5b0480} > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -9423,6 +9503,80 @@ ifAbsent(field("optional_field"), "default_value") ``` +### ifNull(ifExpr, elseExpr) {:#ifnull_0e6d161} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseExpr` argument if `ifExpr` is null, else return the result of the `ifExpr` argument evaluation. + +This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. + +Signature: + +```typescript +export declare function ifNull(ifExpr: Expression, elseExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check for null. | +| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if ifExpr is null. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ifNull operation. + +### Example + + +```typescript +// Returns the user's preferred name, or if that is null, returns their full name. +ifNull(field("preferredName"), field("fullName")) + +``` + +### ifNull(ifExpr, elseValue) {:#ifnull_c34e5ed} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if `ifExpr` is null, else return the result of the `ifExpr` argument evaluation. + +This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. + +Signature: + +```typescript +export declare function ifNull(ifExpr: Expression, elseValue: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check for null. | +| elseValue | unknown | The value that will be returned if ifExpr evaluates to null. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ifNull operation. + +### Example + + +```typescript +// Returns the user's display name, or returns "Anonymous" if the field is null. +ifNull(field("displayName"), "Anonymous") + +``` + ## function(ifFieldName, ...) ### ifAbsent(ifFieldName, elseExpr) {:#ifabsent_e6dabea} @@ -9497,6 +9651,80 @@ ifAbsent("optional_field", "default_value") ``` +### ifNull(ifFieldName, elseExpr) {:#ifnull_e6dabea} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseExpr` argument if `ifFieldName` field is null, else return the value of the field. + +This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. + +Signature: + +```typescript +export declare function ifNull(ifFieldName: string, elseExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifFieldName | string | The field to check for null. | +| elseExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression that will be evaluated and returned if ifFieldName is null. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ifNull operation. + +### Example + + +```typescript +// Returns the user's preferred name, or if that is null, returns their full name. +ifNull("preferredName", field("fullName")) + +``` + +### ifNull(ifFieldName, elseValue) {:#ifnull_587c2f0} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Creates an expression that returns the `elseValue` argument if `ifFieldName` field is null, else return the value of the field. + +This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. + +Signature: + +```typescript +export declare function ifNull(ifFieldName: string, elseValue: unknown): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ifFieldName | string | The field to check for null. | +| elseValue | unknown | The value that will be returned if ifFieldName is null. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the ifNull operation. + +### Example + + +```typescript +// Returns the user's display name, or returns "Anonymous" if the field is null. +ifNull("displayName", "Anonymous") + +``` + ## function(input, ...) ### substring(input, position, length) {:#substring_e6e0aa3} diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index e8943abb1c..898e24add8 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -208,6 +208,8 @@ export { concat, currentTimestamp, ifAbsent, + ifNull, + coalesce, join, length, arraySum, diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index 1d3da2565c..deb9eb4408 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -177,6 +177,8 @@ export { concat, currentTimestamp, ifAbsent, + ifNull, + coalesce, join, log10, arraySum, diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index 09090c8672..38954a633c 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -3219,6 +3219,84 @@ export abstract class Expression implements ProtoValueSerializable, UserData { ); } + /** + * @beta + * Creates an expression that returns the `elseValue` argument if this expression evaluates to null, else + * return the result of this expression evaluation. + * + * @remarks + * This function provides a fallback for both absent and explicit null values. In contrast, + * `ifAbsent()` only triggers for missing fields. + * + * @example + * ```typescript + * // Returns the user's preferred name, or if that is null, returns their full name. + * field("preferredName").ifNull(field("fullName")) + * ``` + * + * @param elseExpression - The Expression that will be evaluated if this Expression evaluates to null. + * @returns A new `Expression` representing the ifNull operation. + */ + ifNull(elseExpression: Expression): FunctionExpression; + + /** + * @beta + * Creates an expression that returns the `elseValue` argument if this expression evaluates to null, else + * return the result of this expression evaluation. + * + * @remarks + * This function provides a fallback for both absent and explicit null values. In contrast, + * `ifAbsent()` only triggers for missing fields. + * + * @example + * ```typescript + * // Returns the user's display name, or returns "Anonymous" if the field is null. + * field("displayName").ifNull("Anonymous") + * ``` + * + * @param elseValue - The value that will be returned if this Expression evaluates to null. + * @returns A new `Expression` representing the ifNull operation. + */ + ifNull(elseValue: unknown): FunctionExpression; + ifNull(elseValueOrExpression: Expression | unknown): FunctionExpression { + return new FunctionExpression( + 'if_null', + [this, valueToDefaultExpr(elseValueOrExpression)], + 'ifNull' + ); + } + + /** + * @beta + * Creates an expression that returns the first non-null, non-absent argument, without evaluating + * the rest of the arguments. When all arguments are null or absent, returns the last argument. + * + * @example + * ```typescript + * // Returns the value of the first non-null, non-absent field among 'preferredName', 'fullName', + * // or the last argument if all previous fields are null. + * field("preferredName").coalesce(field("fullName"), "Anonymous"); + * ``` + * + * @param replacement - The value to use if this expression evaluates to null. + * @param others - Optional additional values to check if previous values are null. + * @returns A new `Expression` representing the coalesce operation. + */ + coalesce( + replacement: Expression | unknown, + ...others: Array + ): FunctionExpression { + return new FunctionExpression( + 'coalesce', + [ + this, + valueToDefaultExpr(replacement), + ...others.map(valueToDefaultExpr) + ], + 'coalesce' + ); + } + /** * @beta * Creates an expression that joins the elements of an array into a string. @@ -10626,6 +10704,164 @@ export function ifAbsent( ); } +/** + * @beta + * Creates an expression that returns the `elseExpr` argument if `ifExpr` is null, else + * return the result of the `ifExpr` argument evaluation. + * + * @remarks + * This function provides a fallback for both absent and explicit null values. In contrast, + * `ifAbsent()` only triggers for missing fields. + * + * @example + * ```typescript + * // Returns the user's preferred name, or if that is null, returns their full name. + * ifNull(field("preferredName"), field("fullName")) + * ``` + * + * @param ifExpr - The expression to check for null. + * @param elseExpr - The expression that will be evaluated and returned if `ifExpr` is null. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the ifNull operation. + */ +export function ifNull( + ifExpr: Expression, + elseExpr: Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that returns the `elseValue` argument if `ifExpr` is null, else + * return the result of the `ifExpr` argument evaluation. + * + * @remarks + * This function provides a fallback for both absent and explicit null values. In contrast, + * `ifAbsent()` only triggers for missing fields. + * + * @example + * ```typescript + * // Returns the user's display name, or returns "Anonymous" if the field is null. + * ifNull(field("displayName"), "Anonymous") + * ``` + * + * @param ifExpr - The expression to check for null. + * @param elseValue - The value that will be returned if `ifExpr` evaluates to null. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the ifNull operation. + */ +export function ifNull( + ifExpr: Expression, + elseValue: unknown +): FunctionExpression; + +/** + * @beta + * Creates an expression that returns the `elseExpr` argument if `ifFieldName` field is null, else + * return the value of the field. + * + * @remarks + * This function provides a fallback for both absent and explicit null values. In contrast, + * `ifAbsent()` only triggers for missing fields. + * + * @example + * ```typescript + * // Returns the user's preferred name, or if that is null, returns their full name. + * ifNull("preferredName", field("fullName")) + * ``` + * + * @param ifFieldName - The field to check for null. + * @param elseExpr - The expression that will be evaluated and returned if `ifFieldName` is null. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the ifNull operation. + */ +export function ifNull( + ifFieldName: string, + elseExpr: Expression +): FunctionExpression; + +/** + * @beta + * Creates an expression that returns the `elseValue` argument if `ifFieldName` field is null, else + * return the value of the field. + * + * @remarks + * This function provides a fallback for both absent and explicit null values. In contrast, + * `ifAbsent()` only triggers for missing fields. + * + * @example + * ```typescript + * // Returns the user's display name, or returns "Anonymous" if the field is null. + * ifNull("displayName", "Anonymous") + * ``` + * + * @param ifFieldName - The field to check for null. + * @param elseValue - The value that will be returned if `ifFieldName` is null. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the ifNull operation. + */ +export function ifNull( + ifFieldName: string, + elseValue: unknown +): FunctionExpression; +export function ifNull( + fieldNameOrExpression: string | Expression, + elseValue: Expression | unknown +): FunctionExpression { + return fieldOrExpression(fieldNameOrExpression).ifNull(elseValue); +} + +/** + * @beta + * Creates an expression that returns the first non-null, non-absent argument, without evaluating + * the rest of the arguments. When all arguments are null or absent, returns the last argument. + * + * @example + * ```typescript + * // Returns the value of the first non-null, non-absent field among 'preferredName', 'fullName', + * // or the last argument if all previous fields are null. + * coalesce(field("preferredName"), field("fullName"), constant("Anonymous")) + * ``` + * + * @param expression - The first expression to check for null. + * @param replacement - The fallback expression or value if the first one is null. + * @param others - Optional additional expressions to check if previous ones are null. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the coalesce operation. + */ +export function coalesce( + expression: Expression, + replacement: Expression | unknown, + ...others: Array +): FunctionExpression; + +/** + * @beta + * Creates an expression that returns the first non-null, non-absent argument, without evaluating + * the rest of the arguments. When all arguments are null or absent, returns the last argument. + * + * @example + * ```typescript + * // Returns the value of the first non-null, non-absent field among 'preferredName', 'fullName', + * // or the last argument if all previous fields are null. + * coalesce("preferredName", field("fullName"), constant("Anonymous")) + * ``` + * + * @param fieldName - The name of the first field to check for null. + * @param replacement - The fallback expression or value if the first one is null. + * @param others - Optional additional expressions to check if previous ones are null. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the coalesce operation. + */ +export function coalesce( + fieldName: string, + replacement: Expression | unknown, + ...others: Array +): FunctionExpression; +export function coalesce( + fieldNameOrExpression: Expression | string, + replacement: Expression | unknown, + ...others: Array +): FunctionExpression { + return fieldOrExpression(fieldNameOrExpression).coalesce( + replacement, + ...others + ); +} + /** * @beta * Creates an expression that evaluates to the result corresponding to the first true condition. diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 70596045e5..03195a3401 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -174,7 +174,9 @@ import { timestampExtract, split, type, - isType + isType, + coalesce, + ifNull } from '../util/pipeline_export'; use(chaiAsPromised); @@ -5076,6 +5078,93 @@ apiDescribe.skipClassic('Pipelines', persistence => { }); }); + it('supports ifNull', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + title: 'foo', + name: null + }) + ) + .select( + ifNull('title', 'default title').as('staticMethod'), + field('title').ifNull('default title').as('instanceMethod'), + field('name').ifNull(field('title')).as('nameOrTitle'), + field('name').ifNull('default name').as('fieldIsNull'), + field('absent').ifNull('default name').as('fieldIsAbsent') + ) + ); + + expectResults(snapshot, { + staticMethod: 'foo', + instanceMethod: 'foo', + nameOrTitle: 'foo', + fieldIsNull: 'default name', + fieldIsAbsent: 'default name' + }); + }); + + it('supports coalesce', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + numberValue: 1, + stringValue: 'hello', + booleanValue: false, + nullValue: null, + nullValue2: null + }) + ) + .select( + coalesce(field('numberValue'), field('stringValue')).as( + 'staticMethod' + ), + field('numberValue') + .coalesce(field('stringValue')) + .as('instanceMethod'), + coalesce(field('nullValue'), field('stringValue')).as( + 'firstIsNull' + ), + coalesce( + field('nullValue'), + field('nullValue2'), + field('booleanValue') + ).as('lastIsNotNull'), + coalesce(field('nullValue'), field('nullValue2')).as( + 'allFieldsNull' + ), + coalesce( + field('nullValue'), + field('nullValue2'), + constant('default') + ).as('allFieldsNullWithDefault'), + coalesce( + field('absentField'), + field('numberValue'), + constant('default') + ).as('withAbsentField') + ) + ); + + expectResults(snapshot, { + staticMethod: 1, + instanceMethod: 1, + firstIsNull: 'hello', + lastIsNotNull: false, + allFieldsNull: null, + allFieldsNullWithDefault: 'default', + withAbsentField: 1 + }); + }); + it('supports join', async () => { const snapshot = await execute( firestore diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 547f60efdd..f5e2047607 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -166,6 +166,7 @@ import { concat, currentTimestamp, ifAbsent, + coalesce, join, arraySum, arrayFirst, @@ -178,7 +179,8 @@ import { arrayMinimumN, arrayIndexOf, arrayIndexOfAll, - arrayLastIndexOf + arrayLastIndexOf, + ifNull } from './pipeline_export'; use(chaiAsPromised); @@ -5246,6 +5248,93 @@ describe.skipClassic('Firestore Pipelines', () => { }); }); + it('supports ifNull', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + title: 'foo', + name: null + }) + ) + .select( + ifNull('title', 'default title').as('staticMethod'), + field('title').ifNull('default title').as('instanceMethod'), + field('name').ifNull(field('title')).as('nameOrTitle'), + field('name').ifNull('default name').as('fieldIsNull'), + field('absent').ifNull('default name').as('fieldIsAbsent') + ) + ); + + expectResults(snapshot, { + staticMethod: 'foo', + instanceMethod: 'foo', + nameOrTitle: 'foo', + fieldIsNull: 'default name', + fieldIsAbsent: 'default name' + }); + }); + + it('supports coalesce', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + numberValue: 1, + stringValue: 'hello', + booleanValue: false, + nullValue: null, + nullValue2: null + }) + ) + .select( + coalesce(field('numberValue'), field('stringValue')).as( + 'staticMethod' + ), + field('numberValue') + .coalesce(field('stringValue')) + .as('instanceMethod'), + coalesce(field('nullValue'), field('stringValue')).as( + 'firstIsNull' + ), + coalesce( + field('nullValue'), + field('nullValue2'), + field('booleanValue') + ).as('lastIsNotNull'), + coalesce(field('nullValue'), field('nullValue2')).as( + 'allFieldsNull' + ), + coalesce( + field('nullValue'), + field('nullValue2'), + constant('default') + ).as('allFieldsNullWithDefault'), + coalesce( + field('absentField'), + field('numberValue'), + constant('default') + ).as('withAbsentField') + ) + ); + + expectResults(snapshot, { + staticMethod: 1, + instanceMethod: 1, + firstIsNull: 'hello', + lastIsNotNull: false, + allFieldsNull: null, + allFieldsNullWithDefault: 'default', + withAbsentField: 1 + }); + }); + it('supports join', async () => { const snapshot = await execute( firestore From f87c15e97af9913182ebaa1afb94a3fe802e04f4 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 31 Mar 2026 10:33:43 -0700 Subject: [PATCH 117/174] fix(ai): Fix responseSchema bug (#9791) --- .changeset/shiny-papayas-begin.md | 5 ++ .../ai/src/models/generative-model.test.ts | 72 ++++++++++++++++++- packages/ai/src/models/generative-model.ts | 9 ++- 3 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 .changeset/shiny-papayas-begin.md diff --git a/.changeset/shiny-papayas-begin.md b/.changeset/shiny-papayas-begin.md new file mode 100644 index 0000000000..27fd6a9a9a --- /dev/null +++ b/.changeset/shiny-papayas-begin.md @@ -0,0 +1,5 @@ +--- +'@firebase/ai': patch +--- + +Fixed a bug that causes the model to error if the user specifies `responseSchema` or `responseJsonSchema`. diff --git a/packages/ai/src/models/generative-model.test.ts b/packages/ai/src/models/generative-model.test.ts index fb90e1fbf0..f11a24b66f 100644 --- a/packages/ai/src/models/generative-model.test.ts +++ b/packages/ai/src/models/generative-model.test.ts @@ -15,7 +15,7 @@ * limitations under the License. */ import { use, expect } from 'chai'; -import { GenerativeModel } from './generative-model'; +import { GenerativeModel, validateGenerationConfig } from './generative-model'; import { FunctionCallingMode, AI, @@ -956,3 +956,73 @@ describe('GenerativeModel dispatch logic', () => { }); }); }); + +describe('validateGenerationConfig', () => { + it('does not allow setting both thinkingBudget and thinkingLevel', () => { + expect(() => { + validateGenerationConfig({ + thinkingConfig: { + thinkingBudget: 200 + } + }); + }).to.not.throw(); + expect(() => { + validateGenerationConfig({ + thinkingConfig: { + thinkingLevel: ThinkingLevel.LOW + } + }); + }).to.not.throw(); + expect(() => { + validateGenerationConfig({ + thinkingConfig: { + thinkingBudget: 200, + thinkingLevel: ThinkingLevel.LOW + } + }); + }).to.throw(); + }); + it('does not allow setting both responseSchema and responseJsonSchema', () => { + expect(() => { + validateGenerationConfig({ + responseSchema: {}, + responseMimeType: 'application/json' + }); + }).to.not.throw(); + expect(() => { + validateGenerationConfig({ + responseJsonSchema: {}, + responseMimeType: 'application/json' + }); + }).to.not.throw(); + expect(() => { + validateGenerationConfig({ + responseSchema: {}, + responseJsonSchema: {}, + responseMimeType: 'application/json' + }); + }).to.throw(); + }); + it( + 'throws if responseSchema or responseJsonSchema are set' + + ' and responseMimeType is not "application/json"', + () => { + expect(() => { + validateGenerationConfig({ + responseSchema: {} + }); + }).to.throw(); + expect(() => { + validateGenerationConfig({ + responseJsonSchema: {} + }); + }).to.throw(); + expect(() => { + validateGenerationConfig({ + responseJsonSchema: {}, + responseMimeType: 'text/plain' + }); + }).to.throw(); + } + ); +}); diff --git a/packages/ai/src/models/generative-model.ts b/packages/ai/src/models/generative-model.ts index 5a76b62918..25727e65d0 100644 --- a/packages/ai/src/models/generative-model.ts +++ b/packages/ai/src/models/generative-model.ts @@ -190,7 +190,9 @@ export class GenerativeModel extends AIModel { * Client-side validation of some common `GenerationConfig` pitfalls, in order * to save the developer a wasted request. */ -function validateGenerationConfig(generationConfig: GenerationConfig): void { +export function validateGenerationConfig( + generationConfig: GenerationConfig +): void { if ( // != allows for null and undefined. 0 is considered "set" by the model generationConfig.thinkingConfig?.thinkingBudget != null && @@ -214,11 +216,12 @@ function validateGenerationConfig(generationConfig: GenerationConfig): void { if ( (generationConfig.responseSchema != null || generationConfig.responseJsonSchema != null) && - generationConfig.responseMimeType + generationConfig.responseMimeType !== 'application/json' ) { throw new AIError( AIErrorCode.UNSUPPORTED, - `responseMimeType must be set if responseSchema or responseJsonSchema are set.` + `responseMimeType must be set to "application/json" if` + + ` responseSchema or responseJsonSchema are set.` ); } } From cccb6d058cc2dac5495b797740697902ddfd4a93 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 31 Mar 2026 13:09:00 -0700 Subject: [PATCH 118/174] docs(ai): Imagen deprecation comments (#9771) --- .changeset/angry-ears-grow.md | 6 +++ common/api-review/ai.api.md | 35 ++++++++------- docs-devsite/ai.imagengcsimage.md | 5 +++ docs-devsite/ai.imagengenerationconfig.md | 5 +++ docs-devsite/ai.imagengenerationresponse.md | 5 +++ docs-devsite/ai.imagenimageformat.md | 5 +++ docs-devsite/ai.imageninlineimage.md | 5 +++ docs-devsite/ai.imagenmodel.md | 5 +++ docs-devsite/ai.imagenmodelparams.md | 5 +++ docs-devsite/ai.imagensafetysettings.md | 5 +++ docs-devsite/ai.md | 43 ++++++++++++++++-- docs-devsite/ai.templateimagenmodel.md | 14 +++--- packages/ai/src/api.ts | 12 ++++- packages/ai/src/models/imagen-model.ts | 5 +++ .../ai/src/models/template-imagen-model.ts | 5 ++- .../ai/src/requests/imagen-image-format.ts | 5 +++ packages/ai/src/types/imagen/requests.ts | 45 +++++++++++++++++++ packages/ai/src/types/imagen/responses.ts | 16 +++++++ 18 files changed, 194 insertions(+), 32 deletions(-) create mode 100644 .changeset/angry-ears-grow.md diff --git a/.changeset/angry-ears-grow.md b/.changeset/angry-ears-grow.md new file mode 100644 index 0000000000..0aba2d0288 --- /dev/null +++ b/.changeset/angry-ears-grow.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +[deprecated] All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 59fdd75113..0a4dcfe1ce 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -575,7 +575,7 @@ export function getAI(app?: FirebaseApp, options?: AIOptions): AI; // @public export function getGenerativeModel(ai: AI, modelParams: ModelParams | HybridParams, requestOptions?: RequestOptions): GenerativeModel; -// @public +// @public @deprecated export function getImagenModel(ai: AI, modelParams: ImagenModelParams, requestOptions?: RequestOptions): ImagenModel; // @beta @@ -584,7 +584,7 @@ export function getLiveGenerativeModel(ai: AI, modelParams: LiveModelParams): Li // @beta export function getTemplateGenerativeModel(ai: AI, requestOptions?: RequestOptions): TemplateGenerativeModel; -// @beta +// @public @deprecated export function getTemplateImagenModel(ai: AI, requestOptions?: RequestOptions): TemplateImagenModel; // @public @@ -744,7 +744,7 @@ export interface HybridParams { onDeviceParams?: OnDeviceParams; } -// @public +// @public @deprecated export const ImagenAspectRatio: { readonly SQUARE: "1:1"; readonly LANDSCAPE_3x4: "3:4"; @@ -753,16 +753,16 @@ export const ImagenAspectRatio: { readonly PORTRAIT_9x16: "9:16"; }; -// @public +// @public @deprecated export type ImagenAspectRatio = (typeof ImagenAspectRatio)[keyof typeof ImagenAspectRatio]; -// @public +// @public @deprecated export interface ImagenGCSImage { gcsURI: string; mimeType: string; } -// @public +// @public @deprecated export interface ImagenGenerationConfig { addWatermark?: boolean; aspectRatio?: ImagenAspectRatio; @@ -771,13 +771,13 @@ export interface ImagenGenerationConfig { numberOfImages?: number; } -// @public +// @public @deprecated export interface ImagenGenerationResponse { filteredReason?: string; images: T[]; } -// @public +// @public @deprecated export class ImagenImageFormat { compressionQuality?: number; static jpeg(compressionQuality?: number): ImagenImageFormat; @@ -785,13 +785,13 @@ export class ImagenImageFormat { static png(): ImagenImageFormat; } -// @public +// @public @deprecated export interface ImagenInlineImage { bytesBase64Encoded: string; mimeType: string; } -// @public +// @public @deprecated export class ImagenModel extends AIModel { constructor(ai: AI, modelParams: ImagenModelParams, requestOptions?: RequestOptions | undefined); generateImages(prompt: string, singleRequestOptions?: SingleRequestOptions): Promise>; @@ -803,24 +803,24 @@ export class ImagenModel extends AIModel { safetySettings?: ImagenSafetySettings; } -// @public +// @public @deprecated export interface ImagenModelParams { generationConfig?: ImagenGenerationConfig; model: string; safetySettings?: ImagenSafetySettings; } -// @public +// @public @deprecated export const ImagenPersonFilterLevel: { readonly BLOCK_ALL: "dont_allow"; readonly ALLOW_ADULT: "allow_adult"; readonly ALLOW_ALL: "allow_all"; }; -// @public +// @public @deprecated export type ImagenPersonFilterLevel = (typeof ImagenPersonFilterLevel)[keyof typeof ImagenPersonFilterLevel]; -// @public +// @public @deprecated export const ImagenSafetyFilterLevel: { readonly BLOCK_LOW_AND_ABOVE: "block_low_and_above"; readonly BLOCK_MEDIUM_AND_ABOVE: "block_medium_and_above"; @@ -828,10 +828,10 @@ export const ImagenSafetyFilterLevel: { readonly BLOCK_NONE: "block_none"; }; -// @public +// @public @deprecated export type ImagenSafetyFilterLevel = (typeof ImagenSafetyFilterLevel)[keyof typeof ImagenSafetyFilterLevel]; -// @public +// @public @deprecated export interface ImagenSafetySettings { personFilterLevel?: ImagenPersonFilterLevel; safetyFilterLevel?: ImagenSafetyFilterLevel; @@ -1359,11 +1359,12 @@ export class TemplateGenerativeModel { requestOptions?: RequestOptions; } -// @beta +// @public @deprecated export class TemplateImagenModel { constructor(ai: AI, requestOptions?: RequestOptions); // @internal (undocumented) _apiSettings: ApiSettings; + // @beta generateImages(templateId: string, templateVariables: object, singleRequestOptions?: SingleRequestOptions): Promise>; requestOptions?: RequestOptions; } diff --git a/docs-devsite/ai.imagengcsimage.md b/docs-devsite/ai.imagengcsimage.md index cd11d8ee35..53ae030c1a 100644 --- a/docs-devsite/ai.imagengcsimage.md +++ b/docs-devsite/ai.imagengcsimage.md @@ -10,6 +10,11 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # ImagenGCSImage interface +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + An image generated by Imagen, stored in a Cloud Storage for Firebase bucket. This feature is not available yet. diff --git a/docs-devsite/ai.imagengenerationconfig.md b/docs-devsite/ai.imagengenerationconfig.md index 5557904577..11387bb928 100644 --- a/docs-devsite/ai.imagengenerationconfig.md +++ b/docs-devsite/ai.imagengenerationconfig.md @@ -10,6 +10,11 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # ImagenGenerationConfig interface +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + Configuration options for generating images with Imagen. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images-imagen) for more details. diff --git a/docs-devsite/ai.imagengenerationresponse.md b/docs-devsite/ai.imagengenerationresponse.md index 033c966f09..eb159b75a4 100644 --- a/docs-devsite/ai.imagengenerationresponse.md +++ b/docs-devsite/ai.imagengenerationresponse.md @@ -10,6 +10,11 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # ImagenGenerationResponse interface +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + The response from a request to generate images with Imagen. Signature: diff --git a/docs-devsite/ai.imagenimageformat.md b/docs-devsite/ai.imagenimageformat.md index df22d8266f..792124fb84 100644 --- a/docs-devsite/ai.imagenimageformat.md +++ b/docs-devsite/ai.imagenimageformat.md @@ -10,6 +10,11 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # ImagenImageFormat class +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + Defines the image format for images generated by Imagen. Use this class to specify the desired format (JPEG or PNG) and compression quality for images generated by Imagen. This is typically included as part of [ImagenModelParams](./ai.imagenmodelparams.md#imagenmodelparams_interface). diff --git a/docs-devsite/ai.imageninlineimage.md b/docs-devsite/ai.imageninlineimage.md index b2b541e301..a1894f7a9f 100644 --- a/docs-devsite/ai.imageninlineimage.md +++ b/docs-devsite/ai.imageninlineimage.md @@ -10,6 +10,11 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # ImagenInlineImage interface +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + An image generated by Imagen, represented as inline data. Signature: diff --git a/docs-devsite/ai.imagenmodel.md b/docs-devsite/ai.imagenmodel.md index 6559723878..b8380ddbc9 100644 --- a/docs-devsite/ai.imagenmodel.md +++ b/docs-devsite/ai.imagenmodel.md @@ -10,6 +10,11 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # ImagenModel class +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + Class for Imagen model APIs. This class provides methods for generating images using the Imagen model. diff --git a/docs-devsite/ai.imagenmodelparams.md b/docs-devsite/ai.imagenmodelparams.md index 6d7566bc4d..db4661f13b 100644 --- a/docs-devsite/ai.imagenmodelparams.md +++ b/docs-devsite/ai.imagenmodelparams.md @@ -10,6 +10,11 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # ImagenModelParams interface +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + Parameters for configuring an [ImagenModel](./ai.imagenmodel.md#imagenmodel_class). Signature: diff --git a/docs-devsite/ai.imagensafetysettings.md b/docs-devsite/ai.imagensafetysettings.md index bc71f116d4..784a068656 100644 --- a/docs-devsite/ai.imagensafetysettings.md +++ b/docs-devsite/ai.imagensafetysettings.md @@ -10,6 +10,11 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # ImagenSafetySettings interface +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + Settings for controlling the aggressiveness of filtering out sensitive content. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) for more details. diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index ea796aab13..1ed2527a81 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -23,7 +23,7 @@ The Firebase AI Web SDK. | [getImagenModel(ai, modelParams, requestOptions)](./ai.md#getimagenmodel_e1f6645) | Returns an [ImagenModel](./ai.imagenmodel.md#imagenmodel_class) class with methods for using Imagen.Only Imagen 3 models (named imagen-3.0-*) are supported. | | [getLiveGenerativeModel(ai, modelParams)](./ai.md#getlivegenerativemodel_f2099ac) | (Public Preview) Returns a [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) class for real-time, bidirectional communication.The Live API is only supported in modern browser windows and Node >= 22. | | [getTemplateGenerativeModel(ai, requestOptions)](./ai.md#gettemplategenerativemodel_9476bbc) | (Public Preview) Returns a [TemplateGenerativeModel](./ai.templategenerativemodel.md#templategenerativemodel_class) class for executing server-side templates. | -| [getTemplateImagenModel(ai, requestOptions)](./ai.md#gettemplateimagenmodel_9476bbc) | (Public Preview) Returns a [TemplateImagenModel](./ai.templateimagenmodel.md#templateimagenmodel_class) class for executing server-side Imagen templates. | +| [getTemplateImagenModel(ai, requestOptions)](./ai.md#gettemplateimagenmodel_9476bbc) | Returns a [TemplateImagenModel](./ai.templateimagenmodel.md#templateimagenmodel_class) class for executing server-side Imagen templates. | | function(liveSession, ...) | | [startAudioConversation(liveSession, options)](./ai.md#startaudioconversation_01c8e7f) | (Public Preview) Starts a real-time, bidirectional audio conversation with the model. This helper function manages the complexities of microphone access, audio recording, playback, and interruptions. | @@ -50,7 +50,7 @@ The Firebase AI Web SDK. | [Schema](./ai.schema.md#schema_class) | Parent class encompassing all Schema types, with static methods that allow building specific Schema types. This class can be converted with JSON.stringify() into a JSON string accepted by Vertex AI REST endpoints. (This string conversion is automatically done when calling SDK methods.) | | [StringSchema](./ai.stringschema.md#stringschema_class) | Schema class for "string" types. Can be used with or without enum values. | | [TemplateGenerativeModel](./ai.templategenerativemodel.md#templategenerativemodel_class) | (Public Preview) [GenerativeModel](./ai.generativemodel.md#generativemodel_class) APIs that execute on a server-side template.This class should only be instantiated with [getTemplateGenerativeModel()](./ai.md#gettemplategenerativemodel_9476bbc). | -| [TemplateImagenModel](./ai.templateimagenmodel.md#templateimagenmodel_class) | (Public Preview) Class for Imagen model APIs that execute on a server-side template.This class should only be instantiated with [getTemplateImagenModel()](./ai.md#gettemplateimagenmodel_9476bbc). | +| [TemplateImagenModel](./ai.templateimagenmodel.md#templateimagenmodel_class) | Class for Imagen model APIs that execute on a server-side template.This class should only be instantiated with [getTemplateImagenModel()](./ai.md#gettemplateimagenmodel_9476bbc). | | [VertexAIBackend](./ai.vertexaibackend.md#vertexaibackend_class) | Configuration class for the Vertex AI Gemini API.Use this with [AIOptions](./ai.aioptions.md#aioptions_interface) when initializing the AI service via [getAI()](./ai.md#getai_a94a413) to specify the Vertex AI Gemini API as the backend. | ## Interfaces @@ -293,6 +293,11 @@ export declare function getGenerativeModel(ai: AI, modelParams: ModelParams | Hy ### getImagenModel(ai, modelParams, requestOptions) {:#getimagenmodel_e1f6645} +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + Returns an [ImagenModel](./ai.imagenmodel.md#imagenmodel_class) class with methods for using Imagen. Only Imagen 3 models (named `imagen-3.0-*`) are supported. @@ -375,7 +380,9 @@ export declare function getTemplateGenerativeModel(ai: AI, requestOptions?: Requ ### getTemplateImagenModel(ai, requestOptions) {:#gettemplateimagenmodel_9476bbc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). > Returns a [TemplateImagenModel](./ai.templateimagenmodel.md#templateimagenmodel_class) class for executing server-side Imagen templates. @@ -632,6 +639,11 @@ HarmSeverity: { ## ImagenAspectRatio +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + Aspect ratios for Imagen images. To specify an aspect ratio for generated images, set the `aspectRatio` property in your [ImagenGenerationConfig](./ai.imagengenerationconfig.md#imagengenerationconfig_interface). @@ -652,6 +664,11 @@ ImagenAspectRatio: { ## ImagenPersonFilterLevel +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + A filter level controlling whether generation of images containing people or faces is allowed. See the personGeneration documentation for more details. @@ -668,6 +685,11 @@ ImagenPersonFilterLevel: { ## ImagenSafetyFilterLevel +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + A filter level controlling how aggressively to filter sensitive content. Text prompts provided as inputs and images (generated or uploaded) through Imagen on Vertex AI are assessed against a list of safety filters, which include 'harmful categories' (for example, `violence`, `sexual`, `derogatory`, and `toxic`). This filter level controls how aggressively to filter out potentially harmful content from responses. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) and the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters) for more details. @@ -960,6 +982,11 @@ export type HarmSeverity = (typeof HarmSeverity)[keyof typeof HarmSeverity]; ## ImagenAspectRatio +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + Aspect ratios for Imagen images. To specify an aspect ratio for generated images, set the `aspectRatio` property in your [ImagenGenerationConfig](./ai.imagengenerationconfig.md#imagengenerationconfig_interface). @@ -974,6 +1001,11 @@ export type ImagenAspectRatio = (typeof ImagenAspectRatio)[keyof typeof ImagenAs ## ImagenPersonFilterLevel +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + A filter level controlling whether generation of images containing people or faces is allowed. See the personGeneration documentation for more details. @@ -986,6 +1018,11 @@ export type ImagenPersonFilterLevel = (typeof ImagenPersonFilterLevel)[keyof typ ## ImagenSafetyFilterLevel +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). +> + A filter level controlling how aggressively to filter sensitive content. Text prompts provided as inputs and images (generated or uploaded) through Imagen on Vertex AI are assessed against a list of safety filters, which include 'harmful categories' (for example, `violence`, `sexual`, `derogatory`, and `toxic`). This filter level controls how aggressively to filter out potentially harmful content from responses. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) and the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters) for more details. diff --git a/docs-devsite/ai.templateimagenmodel.md b/docs-devsite/ai.templateimagenmodel.md index 3b33d94f71..c85f7e7a65 100644 --- a/docs-devsite/ai.templateimagenmodel.md +++ b/docs-devsite/ai.templateimagenmodel.md @@ -10,7 +10,9 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # TemplateImagenModel class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> Warning: This API is now obsolete. +> +> All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). > Class for Imagen model APIs that execute on a server-side template. @@ -27,13 +29,13 @@ export declare class TemplateImagenModel | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(ai, requestOptions)](./ai.templateimagenmodel.md#templateimagenmodelconstructor) | | (Public Preview) Constructs a new instance of the TemplateImagenModel class | +| [(constructor)(ai, requestOptions)](./ai.templateimagenmodel.md#templateimagenmodelconstructor) | | Constructs a new instance of the TemplateImagenModel class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [requestOptions](./ai.templateimagenmodel.md#templateimagenmodelrequestoptions) | | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) | (Public Preview) Additional options to use when making requests. | +| [requestOptions](./ai.templateimagenmodel.md#templateimagenmodelrequestoptions) | | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) | Additional options to use when making requests. | ## Methods @@ -43,9 +45,6 @@ export declare class TemplateImagenModel ## TemplateImagenModel.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `TemplateImagenModel` class Signature: @@ -63,9 +62,6 @@ constructor(ai: AI, requestOptions?: RequestOptions); ## TemplateImagenModel.requestOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Additional options to use when making requests. Signature: diff --git a/packages/ai/src/api.ts b/packages/ai/src/api.ts index aaf7fe4219..e1e23eac87 100644 --- a/packages/ai/src/api.ts +++ b/packages/ai/src/api.ts @@ -191,6 +191,11 @@ export function getGenerativeModel( * * Only Imagen 3 models (named `imagen-3.0-*`) are supported. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @param ai - An {@link AI} instance. * @param modelParams - Parameters to use when making Imagen requests. * @param requestOptions - Additional options to use when making requests. @@ -260,10 +265,13 @@ export function getTemplateGenerativeModel( * Returns a {@link TemplateImagenModel} class for executing server-side * Imagen templates. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @param ai - An {@link AI} instance. * @param requestOptions - Additional options to use when making requests. - * - * @beta */ export function getTemplateImagenModel( ai: AI, diff --git a/packages/ai/src/models/imagen-model.ts b/packages/ai/src/models/imagen-model.ts index beeb01ac12..56eca08135 100644 --- a/packages/ai/src/models/imagen-model.ts +++ b/packages/ai/src/models/imagen-model.ts @@ -51,6 +51,11 @@ import { AIModel } from './ai-model'; * } * ``` * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export class ImagenModel extends AIModel { diff --git a/packages/ai/src/models/template-imagen-model.ts b/packages/ai/src/models/template-imagen-model.ts index be4d10f72d..aae5f78d1c 100644 --- a/packages/ai/src/models/template-imagen-model.ts +++ b/packages/ai/src/models/template-imagen-model.ts @@ -32,7 +32,10 @@ import { initApiSettings } from './utils'; * * This class should only be instantiated with {@link getTemplateImagenModel}. * - * @beta + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. */ export class TemplateImagenModel { /** diff --git a/packages/ai/src/requests/imagen-image-format.ts b/packages/ai/src/requests/imagen-image-format.ts index e07d4cec81..a6fd6dba8f 100644 --- a/packages/ai/src/requests/imagen-image-format.ts +++ b/packages/ai/src/requests/imagen-image-format.ts @@ -32,6 +32,11 @@ import { logger } from '../logger'; * } * ``` * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export class ImagenImageFormat { diff --git a/packages/ai/src/types/imagen/requests.ts b/packages/ai/src/types/imagen/requests.ts index 4cd5934294..03b41a75ed 100644 --- a/packages/ai/src/types/imagen/requests.ts +++ b/packages/ai/src/types/imagen/requests.ts @@ -20,6 +20,11 @@ import { ImagenImageFormat } from '../../requests/imagen-image-format'; /** * Parameters for configuring an {@link ImagenModel}. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export interface ImagenModelParams { @@ -49,6 +54,11 @@ export interface ImagenModelParams { * See the {@link http://firebase.google.com/docs/vertex-ai/generate-images-imagen | documentation} for * more details. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export interface ImagenGenerationConfig { @@ -108,6 +118,11 @@ export interface ImagenGenerationConfig { * and the {@link https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters | Responsible AI and usage guidelines} * for more details. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export const ImagenSafetyFilterLevel = { @@ -142,6 +157,11 @@ export const ImagenSafetyFilterLevel = { * and the {@link https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters | Responsible AI and usage guidelines} * for more details. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export type ImagenSafetyFilterLevel = @@ -153,6 +173,11 @@ export type ImagenSafetyFilterLevel = * See the personGeneration * documentation for more details. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export const ImagenPersonFilterLevel = { @@ -184,6 +209,11 @@ export const ImagenPersonFilterLevel = { * See the personGeneration * documentation for more details. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export type ImagenPersonFilterLevel = @@ -195,6 +225,11 @@ export type ImagenPersonFilterLevel = * See the {@link http://firebase.google.com/docs/vertex-ai/generate-images | documentation } * for more details. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export interface ImagenSafetySettings { @@ -218,6 +253,11 @@ export interface ImagenSafetySettings { * See the {@link http://firebase.google.com/docs/vertex-ai/generate-images | documentation } * for more details and examples of the supported aspect ratios. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export const ImagenAspectRatio = { @@ -252,6 +292,11 @@ export const ImagenAspectRatio = { * See the {@link http://firebase.google.com/docs/vertex-ai/generate-images | documentation } * for more details and examples of the supported aspect ratios. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export type ImagenAspectRatio = diff --git a/packages/ai/src/types/imagen/responses.ts b/packages/ai/src/types/imagen/responses.ts index b0985ea604..af98c4636a 100644 --- a/packages/ai/src/types/imagen/responses.ts +++ b/packages/ai/src/types/imagen/responses.ts @@ -18,6 +18,11 @@ /** * An image generated by Imagen, represented as inline data. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export interface ImagenInlineImage { @@ -37,6 +42,12 @@ export interface ImagenInlineImage { * An image generated by Imagen, stored in a Cloud Storage for Firebase bucket. * * This feature is not available yet. + * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export interface ImagenGCSImage { @@ -57,6 +68,11 @@ export interface ImagenGCSImage { /** * The response from a request to generate images with Imagen. * + * @deprecated All Imagen models are deprecated and will shut down as + * early as June 2026. As a replacement, you can + * {@link https://firebase.google.com/docs/ai-logic/imagen-models-migration | + * migrate your apps to use Gemini Image models (the "Nano Banana" models)}. + * * @public */ export interface ImagenGenerationResponse< From bfb9accdc35d09039b4929fd0775985e01b81953 Mon Sep 17 00:00:00 2001 From: wu-hui <53845758+wu-hui@users.noreply.github.com> Date: Tue, 31 Mar 2026 19:05:43 -0400 Subject: [PATCH 119/174] feat(firestore): remove beta tags for pipelines. (#9772) --- .../firestore-lite-pipelines.api.md | 766 +++---- common/api-review/firestore-pipelines.api.md | 792 ++++--- ...estore_lite_pipelines.aggregatefunction.md | 18 +- ...restore_lite_pipelines.aliasedaggregate.md | 18 +- ...estore_lite_pipelines.aliasedexpression.md | 29 +- ...estore_lite_pipelines.booleanexpression.md | 38 +- .../firestore_lite_pipelines.expression.md | 848 ++------ .../firestore_lite_pipelines.field.md | 28 +- ...store_lite_pipelines.functionexpression.md | 18 +- docs-devsite/firestore_lite_pipelines.md | 1873 ++++------------ .../firestore_lite_pipelines.ordering.md | 18 +- .../firestore_lite_pipelines.pipeline.md | 148 +- ...firestore_lite_pipelines.pipelineresult.md | 33 +- ...restore_lite_pipelines.pipelinesnapshot.md | 18 +- ...firestore_lite_pipelines.pipelinesource.md | 48 +- .../firestore_lite_pipelines.selectable.md | 8 +- .../firestore_lite_pipelines.stageoptions.md | 8 +- .../firestore_pipelines.aggregatefunction.md | 18 +- .../firestore_pipelines.aliasedaggregate.md | 18 +- .../firestore_pipelines.aliasedexpression.md | 29 +- .../firestore_pipelines.booleanexpression.md | 38 +- .../firestore_pipelines.expression.md | 848 ++------ docs-devsite/firestore_pipelines.field.md | 28 +- .../firestore_pipelines.functionexpression.md | 18 +- docs-devsite/firestore_pipelines.md | 1885 ++++------------- docs-devsite/firestore_pipelines.ordering.md | 18 +- docs-devsite/firestore_pipelines.pipeline.md | 643 ++++-- ...estore_pipelines.pipelineexecuteoptions.md | 18 +- .../firestore_pipelines.pipelineresult.md | 33 +- .../firestore_pipelines.pipelinesnapshot.md | 18 +- .../firestore_pipelines.pipelinesource.md | 48 +- .../firestore_pipelines.selectable.md | 8 +- .../firestore_pipelines.stageoptions.md | 8 +- packages/firestore/src/api/pipeline.ts | 3 - packages/firestore/src/api/pipeline_impl.ts | 4 - .../firestore/src/lite-api/expressions.ts | 535 ----- .../firestore/src/lite-api/pipeline-result.ts | 12 +- .../firestore/src/lite-api/pipeline-source.ts | 10 - packages/firestore/src/lite-api/pipeline.ts | 30 - .../firestore/src/lite-api/pipeline_impl.ts | 3 - .../src/lite-api/pipeline_options.ts | 5 - packages/firestore/src/lite-api/stage.ts | 60 - .../firestore/src/lite-api/stage_options.ts | 48 - packages/firestore/src/util/types.ts | 1 - 44 files changed, 2521 insertions(+), 6575 deletions(-) diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index fd4165b5df..c69b50d3d3 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -6,24 +6,24 @@ import { FirebaseApp } from '@firebase/app'; -// @beta +// @public export function abs(expr: Expression): FunctionExpression; -// @beta +// @public export function abs(fieldName: string): FunctionExpression; -// @beta +// @public export function add(first: Expression, second: Expression | unknown): FunctionExpression; -// @beta +// @public export function add(fieldName: string, second: Expression | unknown): FunctionExpression; -// @beta +// @public export type AddFieldsStageOptions = StageOptions & { fields: Selectable[]; }; -// @beta +// @public export class AggregateFunction { constructor(name: string, params: Expression[]); as(name: string): AliasedAggregate; @@ -31,13 +31,13 @@ export class AggregateFunction { exprType: ExpressionType; } -// @beta +// @public export type AggregateStageOptions = StageOptions & { accumulators: AliasedAggregate[]; groups?: Array; }; -// @beta +// @public export class AliasedAggregate { constructor(aggregate: AggregateFunction, alias: string, _methodName: string | undefined); // (undocumented) @@ -46,7 +46,7 @@ export class AliasedAggregate { readonly alias: string; } -// @beta (undocumented) +// @public (undocumented) export class AliasedExpression implements Selectable { constructor(expr: Expression, alias: string, _methodName: string | undefined); // (undocumented) @@ -59,193 +59,193 @@ export class AliasedExpression implements Selectable { selectable: true; } -// @beta +// @public export function and(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; -// @beta +// @public export function array(elements: unknown[]): FunctionExpression; -// @beta +// @public export function arrayAgg(expression: Expression): AggregateFunction; -// @beta +// @public export function arrayAgg(fieldName: string): AggregateFunction; -// @beta +// @public export function arrayAggDistinct(expression: Expression): AggregateFunction; -// @beta +// @public export function arrayAggDistinct(fieldName: string): AggregateFunction; -// @beta +// @public export function arrayConcat(firstArray: Expression, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; -// @beta +// @public export function arrayConcat(firstArrayField: string, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; -// @beta +// @public export function arrayContains(array: Expression, element: Expression): BooleanExpression; -// @beta +// @public export function arrayContains(array: Expression, element: unknown): BooleanExpression; -// @beta +// @public export function arrayContains(fieldName: string, element: Expression): BooleanExpression; -// @beta +// @public export function arrayContains(fieldName: string, element: unknown): BooleanExpression; -// @beta +// @public export function arrayContainsAll(array: Expression, values: Array): BooleanExpression; -// @beta +// @public export function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; -// @beta +// @public export function arrayContainsAll(array: Expression, arrayExpression: Expression): BooleanExpression; -// @beta +// @public export function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; -// @beta +// @public export function arrayContainsAny(array: Expression, values: Array): BooleanExpression; -// @beta +// @public export function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; -// @beta +// @public export function arrayContainsAny(array: Expression, values: Expression): BooleanExpression; -// @beta +// @public export function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; -// @beta +// @public export function arrayFirst(fieldName: string): FunctionExpression; -// @beta +// @public export function arrayFirst(arrayExpression: Expression): FunctionExpression; -// @beta +// @public export function arrayFirstN(fieldName: string, n: number): FunctionExpression; -// @beta +// @public export function arrayFirstN(fieldName: string, n: Expression): FunctionExpression; -// @beta +// @public export function arrayFirstN(arrayExpression: Expression, n: number): FunctionExpression; -// @beta +// @public export function arrayFirstN(arrayExpression: Expression, n: Expression): FunctionExpression; -// @beta +// @public export function arrayGet(arrayField: string, offset: number): FunctionExpression; -// @beta +// @public export function arrayGet(arrayField: string, offsetExpr: Expression): FunctionExpression; -// @beta +// @public export function arrayGet(arrayExpression: Expression, offset: number): FunctionExpression; -// @beta +// @public export function arrayGet(arrayExpression: Expression, offsetExpr: Expression): FunctionExpression; -// @beta +// @public export function arrayIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; -// @beta +// @public export function arrayIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; -// @beta +// @public export function arrayIndexOfAll(fieldName: string, search: unknown | Expression): FunctionExpression; -// @beta +// @public export function arrayIndexOfAll(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; -// @beta +// @public export function arrayLast(fieldName: string): FunctionExpression; -// @beta +// @public export function arrayLast(arrayExpression: Expression): FunctionExpression; -// @beta +// @public export function arrayLastIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; -// @beta +// @public export function arrayLastIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; -// @beta +// @public export function arrayLastN(fieldName: string, n: number): FunctionExpression; -// @beta +// @public export function arrayLastN(fieldName: string, n: Expression): FunctionExpression; -// @beta +// @public export function arrayLastN(arrayExpression: Expression, n: number): FunctionExpression; -// @beta +// @public export function arrayLastN(arrayExpression: Expression, n: Expression): FunctionExpression; -// @beta +// @public export function arrayLength(fieldName: string): FunctionExpression; -// @beta +// @public export function arrayLength(array: Expression): FunctionExpression; -// @beta +// @public export function arrayMaximum(fieldName: string): FunctionExpression; -// @beta +// @public export function arrayMaximum(arrayExpression: Expression): FunctionExpression; -// @beta +// @public export function arrayMaximumN(fieldName: string, n: number): FunctionExpression; -// @beta +// @public export function arrayMaximumN(fieldName: string, n: Expression): FunctionExpression; -// @beta +// @public export function arrayMaximumN(arrayExpression: Expression, n: number): FunctionExpression; -// @beta +// @public export function arrayMaximumN(arrayExpression: Expression, n: Expression): FunctionExpression; -// @beta +// @public export function arrayMinimum(fieldName: string): FunctionExpression; -// @beta +// @public export function arrayMinimum(arrayExpression: Expression): FunctionExpression; -// @beta +// @public export function arrayMinimumN(fieldName: string, n: number): FunctionExpression; -// @beta +// @public export function arrayMinimumN(fieldName: string, n: Expression): FunctionExpression; -// @beta +// @public export function arrayMinimumN(arrayExpression: Expression, n: number): FunctionExpression; -// @beta +// @public export function arrayMinimumN(arrayExpression: Expression, n: Expression): FunctionExpression; -// @beta +// @public export function arraySum(fieldName: string): FunctionExpression; -// @beta +// @public export function arraySum(expression: Expression): FunctionExpression; -// @beta +// @public export function ascending(expr: Expression): Ordering; -// @beta +// @public export function ascending(fieldName: string): Ordering; -// @beta +// @public export function average(expression: Expression): AggregateFunction; -// @beta +// @public export function average(fieldName: string): AggregateFunction; -// @beta +// @public export abstract class BooleanExpression extends Expression { conditional(thenExpr: Expression, elseExpr: Expression): FunctionExpression; countIf(): AggregateFunction; @@ -256,230 +256,230 @@ export abstract class BooleanExpression extends Expression { not(): BooleanExpression; } -// @beta +// @public export function byteLength(expr: Expression): FunctionExpression; -// @beta +// @public export function byteLength(fieldName: string): FunctionExpression; -// @beta +// @public export function ceil(fieldName: string): FunctionExpression; -// @beta +// @public export function ceil(expression: Expression): FunctionExpression; -// @beta +// @public export function charLength(fieldName: string): FunctionExpression; -// @beta +// @public export function charLength(stringExpression: Expression): FunctionExpression; -// @beta +// @public export function coalesce(expression: Expression, replacement: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function coalesce(fieldName: string, replacement: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export type CollectionGroupStageOptions = StageOptions & { collectionId: string; forceIndex?: string; }; -// @beta +// @public export function collectionId(fieldName: string): FunctionExpression; -// @beta +// @public export function collectionId(expression: Expression): FunctionExpression; -// @beta +// @public export type CollectionStageOptions = StageOptions & { collection: string | Query; forceIndex?: string; }; -// @beta +// @public export function concat(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function concat(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function conditional(condition: BooleanExpression, thenExpr: Expression, elseExpr: Expression): FunctionExpression; -// @beta +// @public export function constant(value: number): Expression; -// @beta +// @public export function constant(value: string): Expression; -// @beta +// @public export function constant(value: boolean): BooleanExpression; -// @beta +// @public export function constant(value: null): Expression; -// @beta +// @public export function constant(value: GeoPoint): Expression; -// @beta +// @public export function constant(value: Timestamp): Expression; -// @beta +// @public export function constant(value: Date): Expression; -// @beta +// @public export function constant(value: Bytes): Expression; -// @beta +// @public export function constant(value: DocumentReference): Expression; -// @beta +// @public export function constant(value: VectorValue): Expression; -// @beta +// @public export function cosineDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; -// @beta +// @public export function cosineDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; -// @beta +// @public export function cosineDistance(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; -// @beta +// @public export function cosineDistance(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; -// @beta +// @public export function count(expression: Expression): AggregateFunction; -// @beta +// @public export function count(fieldName: string): AggregateFunction; -// @beta +// @public export function countAll(): AggregateFunction; -// @beta +// @public export function countDistinct(expr: Expression | string): AggregateFunction; -// @beta +// @public export function countIf(booleanExpr: BooleanExpression): AggregateFunction; -// @beta +// @public export function currentTimestamp(): FunctionExpression; -// @beta +// @public export type DatabaseStageOptions = StageOptions & {}; -// @beta +// @public export function descending(expr: Expression): Ordering; -// @beta +// @public export function descending(fieldName: string): Ordering; -// @beta +// @public export type DistinctStageOptions = StageOptions & { groups: Array; }; -// @beta +// @public export function divide(left: Expression, right: Expression): FunctionExpression; -// @beta +// @public export function divide(expression: Expression, value: unknown): FunctionExpression; -// @beta +// @public export function divide(fieldName: string, expressions: Expression): FunctionExpression; -// @beta +// @public export function divide(fieldName: string, value: unknown): FunctionExpression; -// @beta +// @public export function documentId(documentPath: string | DocumentReference): FunctionExpression; -// @beta +// @public export function documentId(documentPathExpr: Expression): FunctionExpression; -// @beta +// @public export type DocumentsStageOptions = StageOptions & { docs: Array; }; -// @beta +// @public export function dotProduct(fieldName: string, vector: number[] | VectorValue): FunctionExpression; -// @beta +// @public export function dotProduct(fieldName: string, vectorExpression: Expression): FunctionExpression; -// @beta +// @public export function dotProduct(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; -// @beta +// @public export function dotProduct(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; -// @beta +// @public export function endsWith(fieldName: string, suffix: string): BooleanExpression; -// @beta +// @public export function endsWith(fieldName: string, suffix: Expression): BooleanExpression; -// @beta +// @public export function endsWith(stringExpression: Expression, suffix: string): BooleanExpression; -// @beta +// @public export function endsWith(stringExpression: Expression, suffix: Expression): BooleanExpression; -// @beta +// @public export function equal(left: Expression, right: Expression): BooleanExpression; -// @beta +// @public export function equal(expression: Expression, value: unknown): BooleanExpression; -// @beta +// @public export function equal(fieldName: string, expression: Expression): BooleanExpression; -// @beta +// @public export function equal(fieldName: string, value: unknown): BooleanExpression; -// @beta +// @public export function equalAny(expression: Expression, values: Array): BooleanExpression; -// @beta +// @public export function equalAny(expression: Expression, arrayExpression: Expression): BooleanExpression; -// @beta +// @public export function equalAny(fieldName: string, values: Array): BooleanExpression; -// @beta +// @public export function equalAny(fieldName: string, arrayExpression: Expression): BooleanExpression; -// @beta +// @public export function euclideanDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; -// @beta +// @public export function euclideanDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; -// @beta +// @public export function euclideanDistance(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; -// @beta +// @public export function euclideanDistance(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; -// @beta +// @public export function execute(pipeline: Pipeline): Promise; -// @beta +// @public export function exists(value: Expression): BooleanExpression; -// @beta +// @public export function exists(fieldName: string): BooleanExpression; -// @beta +// @public export function exp(expression: Expression): FunctionExpression; -// @beta +// @public export function exp(fieldName: string): FunctionExpression; -// @beta +// @public export abstract class Expression { abs(): FunctionExpression; /* Excluded from this release type: _readUserData */ @@ -821,10 +821,10 @@ export abstract class Expression { vectorLength(): FunctionExpression; } -// @beta +// @public export type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression'; -// @beta +// @public export class Field extends Expression implements Selectable { // (undocumented) get alias(): string; @@ -838,13 +838,13 @@ export class Field extends Expression implements Selectable { selectable: true; } -// @beta +// @public export function field(name: string): Field; -// @beta +// @public export function field(path: FieldPath): Field; -// @beta +// @public export type FindNearestStageOptions = StageOptions & { field: Field | string; vectorValue: VectorValue | number[]; @@ -853,19 +853,19 @@ export type FindNearestStageOptions = StageOptions & { distanceField?: string; }; -// @beta +// @public export function first(expression: Expression): AggregateFunction; -// @beta +// @public export function first(fieldName: string): AggregateFunction; -// @beta +// @public export function floor(expr: Expression): FunctionExpression; -// @beta +// @public export function floor(fieldName: string): FunctionExpression; -// @beta +// @public export class FunctionExpression extends Expression { constructor(name: string, params: Expression[]); constructor(name: string, params: Expression[], _methodName: string | undefined); @@ -873,314 +873,314 @@ export class FunctionExpression extends Expression { readonly expressionType: ExpressionType; } -// @beta +// @public export function greaterThan(left: Expression, right: Expression): BooleanExpression; -// @beta +// @public export function greaterThan(expression: Expression, value: unknown): BooleanExpression; -// @beta +// @public export function greaterThan(fieldName: string, expression: Expression): BooleanExpression; -// @beta +// @public export function greaterThan(fieldName: string, value: unknown): BooleanExpression; -// @beta +// @public export function greaterThanOrEqual(left: Expression, right: Expression): BooleanExpression; -// @beta +// @public export function greaterThanOrEqual(expression: Expression, value: unknown): BooleanExpression; -// @beta +// @public export function greaterThanOrEqual(fieldName: string, value: Expression): BooleanExpression; -// @beta +// @public export function greaterThanOrEqual(fieldName: string, value: unknown): BooleanExpression; -// @beta +// @public export function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expression; -// @beta +// @public export function ifAbsent(ifExpr: Expression, elseValue: unknown): Expression; -// @beta +// @public export function ifAbsent(ifFieldName: string, elseExpr: Expression): Expression; -// @beta +// @public export function ifAbsent(ifFieldName: string | Expression, elseValue: Expression | unknown): Expression; -// @beta +// @public export function ifError(tryExpr: BooleanExpression, catchExpr: BooleanExpression): BooleanExpression; -// @beta +// @public export function ifError(tryExpr: Expression, catchExpr: Expression): FunctionExpression; -// @beta +// @public export function ifError(tryExpr: Expression, catchValue: unknown): FunctionExpression; -// @beta +// @public export function ifNull(ifExpr: Expression, elseExpr: Expression): FunctionExpression; -// @beta +// @public export function ifNull(ifExpr: Expression, elseValue: unknown): FunctionExpression; -// @beta +// @public export function ifNull(ifFieldName: string, elseExpr: Expression): FunctionExpression; -// @beta +// @public export function ifNull(ifFieldName: string, elseValue: unknown): FunctionExpression; -// @beta +// @public export function isAbsent(value: Expression): BooleanExpression; -// @beta +// @public export function isAbsent(field: string): BooleanExpression; -// @beta +// @public export function isError(value: Expression): BooleanExpression; -// @beta +// @public export function isType(fieldName: string, type: Type): BooleanExpression; -// @beta +// @public export function isType(expression: Expression, type: Type): BooleanExpression; -// @beta +// @public export function join(arrayFieldName: string, delimiter: string): Expression; -// @beta +// @public export function join(arrayExpression: Expression, delimiterExpression: Expression): Expression; -// @beta +// @public export function join(arrayExpression: Expression, delimiter: string): Expression; -// @beta +// @public export function join(arrayFieldName: string, delimiterExpression: Expression): Expression; -// @beta +// @public export function last(expression: Expression): AggregateFunction; -// @beta +// @public export function last(fieldName: string): AggregateFunction; -// @beta +// @public function length_2(fieldName: string): FunctionExpression; -// @beta +// @public function length_2(expression: Expression): FunctionExpression; export { length_2 as length } -// @beta +// @public export function lessThan(left: Expression, right: Expression): BooleanExpression; -// @beta +// @public export function lessThan(expression: Expression, value: unknown): BooleanExpression; -// @beta +// @public export function lessThan(fieldName: string, expression: Expression): BooleanExpression; -// @beta +// @public export function lessThan(fieldName: string, value: unknown): BooleanExpression; -// @beta +// @public export function lessThanOrEqual(left: Expression, right: Expression): BooleanExpression; -// @beta +// @public export function lessThanOrEqual(expression: Expression, value: unknown): BooleanExpression; -// @beta +// @public export function lessThanOrEqual(fieldName: string, expression: Expression): BooleanExpression; -// @beta +// @public export function lessThanOrEqual(fieldName: string, value: unknown): BooleanExpression; -// @beta +// @public export function like(fieldName: string, pattern: string): BooleanExpression; -// @beta +// @public export function like(fieldName: string, pattern: Expression): BooleanExpression; -// @beta +// @public export function like(stringExpression: Expression, pattern: string): BooleanExpression; -// @beta +// @public export function like(stringExpression: Expression, pattern: Expression): BooleanExpression; -// @beta +// @public export type LimitStageOptions = StageOptions & { limit: number; }; -// @beta +// @public export function ln(fieldName: string): FunctionExpression; -// @beta +// @public export function ln(expression: Expression): FunctionExpression; -// @beta +// @public export function log(expression: Expression, base: number): FunctionExpression; -// @beta +// @public export function log(expression: Expression, base: Expression): FunctionExpression; -// @beta +// @public export function log(fieldName: string, base: number): FunctionExpression; -// @beta +// @public export function log(fieldName: string, base: Expression): FunctionExpression; -// @beta +// @public export function log10(fieldName: string): FunctionExpression; -// @beta +// @public export function log10(expression: Expression): FunctionExpression; -// @beta +// @public export function logicalMaximum(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function logicalMaximum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function logicalMinimum(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function logicalMinimum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function ltrim(fieldName: string, valueToTrim?: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function ltrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function map(elements: Record): FunctionExpression; -// @beta +// @public export function mapEntries(mapField: string): FunctionExpression; -// @beta +// @public export function mapEntries(mapExpression: Expression): FunctionExpression; -// @beta +// @public export function mapGet(fieldName: string, subField: string): FunctionExpression; -// @beta +// @public export function mapGet(mapExpression: Expression, subField: string): FunctionExpression; -// @beta +// @public export function mapKeys(mapField: string): FunctionExpression; -// @beta +// @public export function mapKeys(mapExpression: Expression): FunctionExpression; -// @beta +// @public export function mapMerge(mapField: string, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; -// @beta +// @public export function mapMerge(firstMap: Record | Expression, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; -// @beta +// @public export function mapRemove(mapField: string, key: string): FunctionExpression; -// @beta +// @public export function mapRemove(mapExpr: Expression, key: string): FunctionExpression; -// @beta +// @public export function mapRemove(mapField: string, keyExpr: Expression): FunctionExpression; -// @beta +// @public export function mapRemove(mapExpr: Expression, keyExpr: Expression): FunctionExpression; -// @beta +// @public export function mapSet(mapField: string, key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; -// @beta +// @public export function mapSet(mapExpression: Expression, key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; -// @beta +// @public export function mapValues(mapField: string): FunctionExpression; -// @beta +// @public export function mapValues(mapExpression: Expression): FunctionExpression; -// @beta +// @public export function maximum(expression: Expression): AggregateFunction; -// @beta +// @public export function maximum(fieldName: string): AggregateFunction; -// @beta +// @public export function minimum(expression: Expression): AggregateFunction; -// @beta +// @public export function minimum(fieldName: string): AggregateFunction; -// @beta +// @public export function mod(left: Expression, right: Expression): FunctionExpression; -// @beta +// @public export function mod(expression: Expression, value: unknown): FunctionExpression; -// @beta +// @public export function mod(fieldName: string, expression: Expression): FunctionExpression; -// @beta +// @public export function mod(fieldName: string, value: unknown): FunctionExpression; -// @beta +// @public export function multiply(first: Expression, second: Expression | unknown): FunctionExpression; -// @beta +// @public export function multiply(fieldName: string, second: Expression | unknown): FunctionExpression; -// @beta +// @public export function nor(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; -// @beta +// @public export function not(booleanExpr: BooleanExpression): BooleanExpression; -// @beta +// @public export function notEqual(left: Expression, right: Expression): BooleanExpression; -// @beta +// @public export function notEqual(expression: Expression, value: unknown): BooleanExpression; -// @beta +// @public export function notEqual(fieldName: string, expression: Expression): BooleanExpression; -// @beta +// @public export function notEqual(fieldName: string, value: unknown): BooleanExpression; -// @beta +// @public export function notEqualAny(element: Expression, values: Array): BooleanExpression; -// @beta +// @public export function notEqualAny(fieldName: string, values: Array): BooleanExpression; -// @beta +// @public export function notEqualAny(element: Expression, arrayExpression: Expression): BooleanExpression; -// @beta +// @public export function notEqualAny(fieldName: string, arrayExpression: Expression): BooleanExpression; -// @beta +// @public export type OffsetStageOptions = StageOptions & { offset: number; }; -// @beta +// @public export type OneOf = { [K in keyof T]: Pick & { [P in Exclude]?: undefined; }; }[keyof T]; -// @beta +// @public export function or(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; -// @beta +// @public export class Ordering { constructor(expr: Expression, direction: 'ascending' | 'descending', _methodName: string | undefined); // (undocumented) @@ -1189,7 +1189,7 @@ export class Ordering { readonly expr: Expression; } -// @beta +// @public export class Pipeline { addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; addFields(options: AddFieldsStageOptions): Pipeline; @@ -1224,7 +1224,7 @@ export class Pipeline { where(options: WhereStageOptions): Pipeline; } -// @beta +// @public export class PipelineResult { /* Excluded from this release type: _ref */ /* Excluded from this release type: _fields */ @@ -1237,14 +1237,14 @@ export class PipelineResult { get updateTime(): Timestamp | undefined; } -// @beta +// @public export class PipelineSnapshot { constructor(pipeline: Pipeline, results: PipelineResult[], executionTime?: Timestamp); get executionTime(): Timestamp; get results(): PipelineResult[]; } -// @beta +// @public export class PipelineSource { collection(collection: string | Query): PipelineType; /* Excluded from this release type: _createPipeline */ @@ -1273,404 +1273,404 @@ export class PipelineSource { documents(options: DocumentsStageOptions): PipelineType; } -// @beta +// @public export function pow(base: Expression, exponent: Expression): FunctionExpression; -// @beta +// @public export function pow(base: Expression, exponent: number): FunctionExpression; -// @beta +// @public export function pow(base: string, exponent: Expression): FunctionExpression; -// @beta +// @public export function pow(base: string, exponent: number): FunctionExpression; -// @beta +// @public export function rand(): FunctionExpression; -// @beta +// @public export function regexContains(fieldName: string, pattern: string): BooleanExpression; -// @beta +// @public export function regexContains(fieldName: string, pattern: Expression): BooleanExpression; -// @beta +// @public export function regexContains(stringExpression: Expression, pattern: string): BooleanExpression; -// @beta +// @public export function regexContains(stringExpression: Expression, pattern: Expression): BooleanExpression; -// @beta +// @public export function regexFind(fieldName: string, pattern: string): FunctionExpression; -// @beta +// @public export function regexFind(fieldName: string, pattern: Expression): FunctionExpression; -// @beta +// @public export function regexFind(stringExpression: Expression, pattern: string): FunctionExpression; -// @beta +// @public export function regexFind(stringExpression: Expression, pattern: Expression): FunctionExpression; -// @beta +// @public export function regexFindAll(fieldName: string, pattern: string): FunctionExpression; -// @beta +// @public export function regexFindAll(fieldName: string, pattern: Expression): FunctionExpression; -// @beta +// @public export function regexFindAll(stringExpression: Expression, pattern: string): FunctionExpression; -// @beta +// @public export function regexFindAll(stringExpression: Expression, pattern: Expression): FunctionExpression; -// @beta +// @public export function regexMatch(fieldName: string, pattern: string): BooleanExpression; -// @beta +// @public export function regexMatch(fieldName: string, pattern: Expression): BooleanExpression; -// @beta +// @public export function regexMatch(stringExpression: Expression, pattern: string): BooleanExpression; -// @beta +// @public export function regexMatch(stringExpression: Expression, pattern: Expression): BooleanExpression; -// @beta +// @public export type RemoveFieldsStageOptions = StageOptions & { fields: Array; }; -// @beta +// @public export type ReplaceWithStageOptions = StageOptions & { map: Expression | string; }; -// @beta +// @public export function reverse(stringExpression: Expression): FunctionExpression; -// @beta +// @public export function reverse(field: string): FunctionExpression; -// @beta +// @public export function round(fieldName: string): FunctionExpression; -// @beta +// @public export function round(expression: Expression): FunctionExpression; -// @beta +// @public export function round(fieldName: string, decimalPlaces: number | Expression): FunctionExpression; -// @beta +// @public export function round(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; -// @beta +// @public export function rtrim(fieldName: string, valueToTrim?: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function rtrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export type SampleStageOptions = StageOptions & OneOf<{ percentage: number; documents: number; }>; -// @beta +// @public export interface Selectable { // (undocumented) selectable: true; } -// @beta +// @public export type SelectStageOptions = StageOptions & { selections: Array; }; -// @beta +// @public export type SortStageOptions = StageOptions & { orderings: Ordering[]; }; -// @beta +// @public export function split(fieldName: string, delimiter: string): FunctionExpression; -// @beta +// @public export function split(fieldName: string, delimiter: Expression): FunctionExpression; -// @beta +// @public export function split(expression: Expression, delimiter: string): FunctionExpression; -// @beta +// @public export function split(expression: Expression, delimiter: Expression): FunctionExpression; -// @beta +// @public export function sqrt(expression: Expression): FunctionExpression; -// @beta +// @public export function sqrt(fieldName: string): FunctionExpression; -// @beta +// @public export interface StageOptions { rawOptions?: { [name: string]: unknown; }; } -// @beta +// @public export function startsWith(fieldName: string, prefix: string): BooleanExpression; -// @beta +// @public export function startsWith(fieldName: string, prefix: Expression): BooleanExpression; -// @beta +// @public export function startsWith(stringExpression: Expression, prefix: string): BooleanExpression; -// @beta +// @public export function startsWith(stringExpression: Expression, prefix: Expression): BooleanExpression; -// @beta +// @public export function stringConcat(fieldName: string, secondString: Expression | string, ...otherStrings: Array): FunctionExpression; -// @beta +// @public export function stringConcat(firstString: Expression, secondString: Expression | string, ...otherStrings: Array): FunctionExpression; -// @beta +// @public export function stringContains(fieldName: string, substring: string): BooleanExpression; -// @beta +// @public export function stringContains(fieldName: string, substring: Expression): BooleanExpression; -// @beta +// @public export function stringContains(stringExpression: Expression, substring: string): BooleanExpression; -// @beta +// @public export function stringContains(stringExpression: Expression, substring: Expression): BooleanExpression; -// @beta +// @public export function stringIndexOf(fieldName: string, search: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function stringIndexOf(expression: Expression, search: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function stringRepeat(fieldName: string, repetitions: number | Expression): FunctionExpression; -// @beta +// @public export function stringRepeat(expression: Expression, repetitions: number | Expression): FunctionExpression; -// @beta +// @public export function stringReplaceAll(fieldName: string, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function stringReplaceAll(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function stringReplaceOne(fieldName: string, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function stringReplaceOne(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function stringReverse(stringExpression: Expression): FunctionExpression; -// @beta +// @public export function stringReverse(field: string): FunctionExpression; -// @beta +// @public export function substring(field: string, position: number, length?: number): FunctionExpression; -// @beta +// @public export function substring(input: Expression, position: number, length?: number): FunctionExpression; -// @beta +// @public export function substring(field: string, position: Expression, length?: Expression): FunctionExpression; -// @beta +// @public export function substring(input: Expression, position: Expression, length?: Expression): FunctionExpression; -// @beta +// @public export function subtract(left: Expression, right: Expression): FunctionExpression; -// @beta +// @public export function subtract(expression: Expression, value: unknown): FunctionExpression; -// @beta +// @public export function subtract(fieldName: string, expression: Expression): FunctionExpression; -// @beta +// @public export function subtract(fieldName: string, value: unknown): FunctionExpression; -// @beta +// @public export function sum(expression: Expression): AggregateFunction; -// @beta +// @public export function sum(fieldName: string): AggregateFunction; -// @beta +// @public export function switchOn(condition: BooleanExpression, result: Expression, ...others: Array): FunctionExpression; -// @beta +// @public export type TimeGranularity = TimeUnit | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoweek' | 'month' | 'quarter' | 'year' | 'isoyear'; -// @beta +// @public export type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; -// @beta +// @public export function timestampAdd(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; -// @beta +// @public export function timestampAdd(timestamp: Expression, unit: TimeUnit, amount: number): FunctionExpression; -// @beta +// @public export function timestampAdd(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; -// @beta +// @public export function timestampDiff(endFieldName: string, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; -// @beta +// @public export function timestampDiff(endFieldName: string, startExpression: Expression, unit: TimeUnit | Expression): FunctionExpression; -// @beta +// @public export function timestampDiff(endExpression: Expression, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; -// @beta +// @public export function timestampDiff(endExpression: Expression, startExpression: Expression, unit: TimeUnit | Expression): FunctionExpression; -// @beta +// @public export function timestampExtract(fieldName: string, part: TimePart, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampExtract(fieldName: string, part: Expression, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampExtract(timestampExpression: Expression, part: TimePart, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampExtract(timestampExpression: Expression, part: Expression, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampSubtract(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; -// @beta +// @public export function timestampSubtract(timestamp: Expression, unit: TimeUnit, amount: number): FunctionExpression; -// @beta +// @public export function timestampSubtract(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; -// @beta +// @public export function timestampToUnixMicros(expr: Expression): FunctionExpression; -// @beta +// @public export function timestampToUnixMicros(fieldName: string): FunctionExpression; -// @beta +// @public export function timestampToUnixMillis(expr: Expression): FunctionExpression; -// @beta +// @public export function timestampToUnixMillis(fieldName: string): FunctionExpression; -// @beta +// @public export function timestampToUnixSeconds(expr: Expression): FunctionExpression; -// @beta +// @public export function timestampToUnixSeconds(fieldName: string): FunctionExpression; -// @beta +// @public export function timestampTruncate(fieldName: string, granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampTruncate(fieldName: string, granularity: Expression, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampTruncate(timestampExpression: Expression, granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampTruncate(timestampExpression: Expression, granularity: Expression, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export type TimeUnit = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'; -// @beta +// @public export function toLower(fieldName: string): FunctionExpression; -// @beta +// @public export function toLower(stringExpression: Expression): FunctionExpression; -// @beta +// @public export function toUpper(fieldName: string): FunctionExpression; -// @beta +// @public export function toUpper(stringExpression: Expression): FunctionExpression; -// @beta +// @public export function trim(fieldName: string, valueToTrim?: string | Expression): FunctionExpression; -// @beta +// @public export function trim(stringExpression: Expression, valueToTrim?: string | Expression): FunctionExpression; -// @beta +// @public export function trunc(fieldName: string): FunctionExpression; -// @beta +// @public export function trunc(expression: Expression): FunctionExpression; -// @beta +// @public export function trunc(fieldName: string, decimalPlaces: number | Expression): FunctionExpression; -// @beta +// @public export function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; -// @beta +// @public export type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp'; -// @beta +// @public export function type(fieldName: string): FunctionExpression; -// @beta +// @public export function type(expression: Expression): FunctionExpression; -// @beta +// @public export type UnionStageOptions = StageOptions & { other: Pipeline; }; -// @beta +// @public export function unixMicrosToTimestamp(expr: Expression): FunctionExpression; -// @beta +// @public export function unixMicrosToTimestamp(fieldName: string): FunctionExpression; -// @beta +// @public export function unixMillisToTimestamp(expr: Expression): FunctionExpression; -// @beta +// @public export function unixMillisToTimestamp(fieldName: string): FunctionExpression; -// @beta +// @public export function unixSecondsToTimestamp(expr: Expression): FunctionExpression; -// @beta +// @public export function unixSecondsToTimestamp(fieldName: string): FunctionExpression; -// @beta +// @public export type UnnestStageOptions = StageOptions & { selectable: Selectable; indexField?: string; }; -// @beta +// @public export function vectorLength(vectorExpression: Expression): FunctionExpression; -// @beta +// @public export function vectorLength(fieldName: string): FunctionExpression; -// @beta +// @public export type WhereStageOptions = StageOptions & { condition: BooleanExpression; }; -// @beta +// @public export function xor(first: BooleanExpression, second: BooleanExpression, ...additionalConditions: BooleanExpression[]): BooleanExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 29e929c080..7b9cf6a147 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -6,24 +6,24 @@ import { FirebaseApp } from '@firebase/app'; -// @beta +// @public export function abs(expr: Expression): FunctionExpression; -// @beta +// @public export function abs(fieldName: string): FunctionExpression; -// @beta +// @public export function add(first: Expression, second: Expression | unknown): FunctionExpression; -// @beta +// @public export function add(fieldName: string, second: Expression | unknown): FunctionExpression; -// @beta +// @public export type AddFieldsStageOptions = StageOptions & { fields: Selectable[]; }; -// @beta +// @public export class AggregateFunction { constructor(name: string, params: Expression[]); as(name: string): AliasedAggregate; @@ -31,13 +31,13 @@ export class AggregateFunction { exprType: ExpressionType; } -// @beta +// @public export type AggregateStageOptions = StageOptions & { accumulators: AliasedAggregate[]; groups?: Array; }; -// @beta +// @public export class AliasedAggregate { constructor(aggregate: AggregateFunction, alias: string, _methodName: string | undefined); // (undocumented) @@ -46,7 +46,7 @@ export class AliasedAggregate { readonly alias: string; } -// @beta (undocumented) +// @public (undocumented) export class AliasedExpression implements Selectable { constructor(expr: Expression, alias: string, _methodName: string | undefined); // (undocumented) @@ -59,193 +59,193 @@ export class AliasedExpression implements Selectable { selectable: true; } -// @beta +// @public export function and(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; -// @beta +// @public export function array(elements: unknown[]): FunctionExpression; -// @beta +// @public export function arrayAgg(expression: Expression): AggregateFunction; -// @beta +// @public export function arrayAgg(fieldName: string): AggregateFunction; -// @beta +// @public export function arrayAggDistinct(expression: Expression): AggregateFunction; -// @beta +// @public export function arrayAggDistinct(fieldName: string): AggregateFunction; -// @beta +// @public export function arrayConcat(firstArray: Expression, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; -// @beta +// @public export function arrayConcat(firstArrayField: string, secondArray: Expression | unknown[], ...otherArrays: Array): FunctionExpression; -// @beta +// @public export function arrayContains(array: Expression, element: Expression): BooleanExpression; -// @beta +// @public export function arrayContains(array: Expression, element: unknown): BooleanExpression; -// @beta +// @public export function arrayContains(fieldName: string, element: Expression): BooleanExpression; -// @beta +// @public export function arrayContains(fieldName: string, element: unknown): BooleanExpression; -// @beta +// @public export function arrayContainsAll(array: Expression, values: Array): BooleanExpression; -// @beta +// @public export function arrayContainsAll(fieldName: string, values: Array): BooleanExpression; -// @beta +// @public export function arrayContainsAll(array: Expression, arrayExpression: Expression): BooleanExpression; -// @beta +// @public export function arrayContainsAll(fieldName: string, arrayExpression: Expression): BooleanExpression; -// @beta +// @public export function arrayContainsAny(array: Expression, values: Array): BooleanExpression; -// @beta +// @public export function arrayContainsAny(fieldName: string, values: Array): BooleanExpression; -// @beta +// @public export function arrayContainsAny(array: Expression, values: Expression): BooleanExpression; -// @beta +// @public export function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; -// @beta +// @public export function arrayFirst(fieldName: string): FunctionExpression; -// @beta +// @public export function arrayFirst(arrayExpression: Expression): FunctionExpression; -// @beta +// @public export function arrayFirstN(fieldName: string, n: number): FunctionExpression; -// @beta +// @public export function arrayFirstN(fieldName: string, n: Expression): FunctionExpression; -// @beta +// @public export function arrayFirstN(arrayExpression: Expression, n: number): FunctionExpression; -// @beta +// @public export function arrayFirstN(arrayExpression: Expression, n: Expression): FunctionExpression; -// @beta +// @public export function arrayGet(arrayField: string, offset: number): FunctionExpression; -// @beta +// @public export function arrayGet(arrayField: string, offsetExpr: Expression): FunctionExpression; -// @beta +// @public export function arrayGet(arrayExpression: Expression, offset: number): FunctionExpression; -// @beta +// @public export function arrayGet(arrayExpression: Expression, offsetExpr: Expression): FunctionExpression; -// @beta +// @public export function arrayIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; -// @beta +// @public export function arrayIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; -// @beta +// @public export function arrayIndexOfAll(fieldName: string, search: unknown | Expression): FunctionExpression; -// @beta +// @public export function arrayIndexOfAll(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; -// @beta +// @public export function arrayLast(fieldName: string): FunctionExpression; -// @beta +// @public export function arrayLast(arrayExpression: Expression): FunctionExpression; -// @beta +// @public export function arrayLastIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; -// @beta +// @public export function arrayLastIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; -// @beta +// @public export function arrayLastN(fieldName: string, n: number): FunctionExpression; -// @beta +// @public export function arrayLastN(fieldName: string, n: Expression): FunctionExpression; -// @beta +// @public export function arrayLastN(arrayExpression: Expression, n: number): FunctionExpression; -// @beta +// @public export function arrayLastN(arrayExpression: Expression, n: Expression): FunctionExpression; -// @beta +// @public export function arrayLength(fieldName: string): FunctionExpression; -// @beta +// @public export function arrayLength(array: Expression): FunctionExpression; -// @beta +// @public export function arrayMaximum(fieldName: string): FunctionExpression; -// @beta +// @public export function arrayMaximum(arrayExpression: Expression): FunctionExpression; -// @beta +// @public export function arrayMaximumN(fieldName: string, n: number): FunctionExpression; -// @beta +// @public export function arrayMaximumN(fieldName: string, n: Expression): FunctionExpression; -// @beta +// @public export function arrayMaximumN(arrayExpression: Expression, n: number): FunctionExpression; -// @beta +// @public export function arrayMaximumN(arrayExpression: Expression, n: Expression): FunctionExpression; -// @beta +// @public export function arrayMinimum(fieldName: string): FunctionExpression; -// @beta +// @public export function arrayMinimum(arrayExpression: Expression): FunctionExpression; -// @beta +// @public export function arrayMinimumN(fieldName: string, n: number): FunctionExpression; -// @beta +// @public export function arrayMinimumN(fieldName: string, n: Expression): FunctionExpression; -// @beta +// @public export function arrayMinimumN(arrayExpression: Expression, n: number): FunctionExpression; -// @beta +// @public export function arrayMinimumN(arrayExpression: Expression, n: Expression): FunctionExpression; -// @beta +// @public export function arraySum(fieldName: string): FunctionExpression; -// @beta +// @public export function arraySum(expression: Expression): FunctionExpression; -// @beta +// @public export function ascending(expr: Expression): Ordering; -// @beta +// @public export function ascending(fieldName: string): Ordering; -// @beta +// @public export function average(expression: Expression): AggregateFunction; -// @beta +// @public export function average(fieldName: string): AggregateFunction; -// @beta +// @public export abstract class BooleanExpression extends Expression { conditional(thenExpr: Expression, elseExpr: Expression): FunctionExpression; countIf(): AggregateFunction; @@ -256,233 +256,233 @@ export abstract class BooleanExpression extends Expression { not(): BooleanExpression; } -// @beta +// @public export function byteLength(expr: Expression): FunctionExpression; -// @beta +// @public export function byteLength(fieldName: string): FunctionExpression; -// @beta +// @public export function ceil(fieldName: string): FunctionExpression; -// @beta +// @public export function ceil(expression: Expression): FunctionExpression; -// @beta +// @public export function charLength(fieldName: string): FunctionExpression; -// @beta +// @public export function charLength(stringExpression: Expression): FunctionExpression; -// @beta +// @public export function coalesce(expression: Expression, replacement: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function coalesce(fieldName: string, replacement: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export type CollectionGroupStageOptions = StageOptions & { collectionId: string; forceIndex?: string; }; -// @beta +// @public export function collectionId(fieldName: string): FunctionExpression; -// @beta +// @public export function collectionId(expression: Expression): FunctionExpression; -// @beta +// @public export type CollectionStageOptions = StageOptions & { collection: string | Query; forceIndex?: string; }; -// @beta +// @public export function concat(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function concat(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function conditional(condition: BooleanExpression, thenExpr: Expression, elseExpr: Expression): FunctionExpression; -// @beta +// @public export function constant(value: number): Expression; -// @beta +// @public export function constant(value: string): Expression; -// @beta +// @public export function constant(value: boolean): BooleanExpression; -// @beta +// @public export function constant(value: null): Expression; -// @beta +// @public export function constant(value: GeoPoint): Expression; -// @beta +// @public export function constant(value: Timestamp): Expression; -// @beta +// @public export function constant(value: Date): Expression; -// @beta +// @public export function constant(value: Bytes): Expression; -// @beta +// @public export function constant(value: DocumentReference): Expression; -// @beta +// @public export function constant(value: VectorValue): Expression; -// @beta +// @public export function cosineDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; -// @beta +// @public export function cosineDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; -// @beta +// @public export function cosineDistance(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; -// @beta +// @public export function cosineDistance(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; -// @beta +// @public export function count(expression: Expression): AggregateFunction; -// @beta +// @public export function count(fieldName: string): AggregateFunction; -// @beta +// @public export function countAll(): AggregateFunction; -// @beta +// @public export function countDistinct(expr: Expression | string): AggregateFunction; -// @beta +// @public export function countIf(booleanExpr: BooleanExpression): AggregateFunction; -// @beta +// @public export function currentTimestamp(): FunctionExpression; -// @beta +// @public export type DatabaseStageOptions = StageOptions & {}; -// @beta +// @public export function descending(expr: Expression): Ordering; -// @beta +// @public export function descending(fieldName: string): Ordering; -// @beta +// @public export type DistinctStageOptions = StageOptions & { groups: Array; }; -// @beta +// @public export function divide(left: Expression, right: Expression): FunctionExpression; -// @beta +// @public export function divide(expression: Expression, value: unknown): FunctionExpression; -// @beta +// @public export function divide(fieldName: string, expressions: Expression): FunctionExpression; -// @beta +// @public export function divide(fieldName: string, value: unknown): FunctionExpression; -// @beta +// @public export function documentId(documentPath: string | DocumentReference): FunctionExpression; -// @beta +// @public export function documentId(documentPathExpr: Expression): FunctionExpression; -// @beta +// @public export type DocumentsStageOptions = StageOptions & { docs: Array; }; -// @beta +// @public export function dotProduct(fieldName: string, vector: number[] | VectorValue): FunctionExpression; -// @beta +// @public export function dotProduct(fieldName: string, vectorExpression: Expression): FunctionExpression; -// @beta +// @public export function dotProduct(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; -// @beta +// @public export function dotProduct(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; -// @beta +// @public export function endsWith(fieldName: string, suffix: string): BooleanExpression; -// @beta +// @public export function endsWith(fieldName: string, suffix: Expression): BooleanExpression; -// @beta +// @public export function endsWith(stringExpression: Expression, suffix: string): BooleanExpression; -// @beta +// @public export function endsWith(stringExpression: Expression, suffix: Expression): BooleanExpression; -// @beta +// @public export function equal(left: Expression, right: Expression): BooleanExpression; -// @beta +// @public export function equal(expression: Expression, value: unknown): BooleanExpression; -// @beta +// @public export function equal(fieldName: string, expression: Expression): BooleanExpression; -// @beta +// @public export function equal(fieldName: string, value: unknown): BooleanExpression; -// @beta +// @public export function equalAny(expression: Expression, values: Array): BooleanExpression; -// @beta +// @public export function equalAny(expression: Expression, arrayExpression: Expression): BooleanExpression; -// @beta +// @public export function equalAny(fieldName: string, values: Array): BooleanExpression; -// @beta +// @public export function equalAny(fieldName: string, arrayExpression: Expression): BooleanExpression; -// @beta +// @public export function euclideanDistance(fieldName: string, vector: number[] | VectorValue): FunctionExpression; -// @beta +// @public export function euclideanDistance(fieldName: string, vectorExpression: Expression): FunctionExpression; -// @beta +// @public export function euclideanDistance(vectorExpression: Expression, vector: number[] | VectorValue): FunctionExpression; -// @beta +// @public export function euclideanDistance(vectorExpression: Expression, otherVectorExpression: Expression): FunctionExpression; -// @beta +// @public export function execute(pipeline: Pipeline): Promise; -// @beta +// @public export function execute(options: PipelineExecuteOptions): Promise; -// @beta +// @public export function exists(value: Expression): BooleanExpression; -// @beta +// @public export function exists(fieldName: string): BooleanExpression; -// @beta +// @public export function exp(expression: Expression): FunctionExpression; -// @beta +// @public export function exp(fieldName: string): FunctionExpression; -// @beta +// @public export abstract class Expression { abs(): FunctionExpression; /* Excluded from this release type: _readUserData */ @@ -824,10 +824,10 @@ export abstract class Expression { vectorLength(): FunctionExpression; } -// @beta +// @public export type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression'; -// @beta +// @public export class Field extends Expression implements Selectable { // (undocumented) get alias(): string; @@ -841,13 +841,13 @@ export class Field extends Expression implements Selectable { selectable: true; } -// @beta +// @public export function field(name: string): Field; -// @beta +// @public export function field(path: FieldPath): Field; -// @beta +// @public export type FindNearestStageOptions = StageOptions & { field: Field | string; vectorValue: VectorValue | number[]; @@ -856,19 +856,19 @@ export type FindNearestStageOptions = StageOptions & { distanceField?: string; }; -// @beta +// @public export function first(expression: Expression): AggregateFunction; -// @beta +// @public export function first(fieldName: string): AggregateFunction; -// @beta +// @public export function floor(expr: Expression): FunctionExpression; -// @beta +// @public export function floor(fieldName: string): FunctionExpression; -// @beta +// @public export class FunctionExpression extends Expression { constructor(name: string, params: Expression[]); constructor(name: string, params: Expression[], _methodName: string | undefined); @@ -876,314 +876,314 @@ export class FunctionExpression extends Expression { readonly expressionType: ExpressionType; } -// @beta +// @public export function greaterThan(left: Expression, right: Expression): BooleanExpression; -// @beta +// @public export function greaterThan(expression: Expression, value: unknown): BooleanExpression; -// @beta +// @public export function greaterThan(fieldName: string, expression: Expression): BooleanExpression; -// @beta +// @public export function greaterThan(fieldName: string, value: unknown): BooleanExpression; -// @beta +// @public export function greaterThanOrEqual(left: Expression, right: Expression): BooleanExpression; -// @beta +// @public export function greaterThanOrEqual(expression: Expression, value: unknown): BooleanExpression; -// @beta +// @public export function greaterThanOrEqual(fieldName: string, value: Expression): BooleanExpression; -// @beta +// @public export function greaterThanOrEqual(fieldName: string, value: unknown): BooleanExpression; -// @beta +// @public export function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expression; -// @beta +// @public export function ifAbsent(ifExpr: Expression, elseValue: unknown): Expression; -// @beta +// @public export function ifAbsent(ifFieldName: string, elseExpr: Expression): Expression; -// @beta +// @public export function ifAbsent(ifFieldName: string | Expression, elseValue: Expression | unknown): Expression; -// @beta +// @public export function ifError(tryExpr: BooleanExpression, catchExpr: BooleanExpression): BooleanExpression; -// @beta +// @public export function ifError(tryExpr: Expression, catchExpr: Expression): FunctionExpression; -// @beta +// @public export function ifError(tryExpr: Expression, catchValue: unknown): FunctionExpression; -// @beta +// @public export function ifNull(ifExpr: Expression, elseExpr: Expression): FunctionExpression; -// @beta +// @public export function ifNull(ifExpr: Expression, elseValue: unknown): FunctionExpression; -// @beta +// @public export function ifNull(ifFieldName: string, elseExpr: Expression): FunctionExpression; -// @beta +// @public export function ifNull(ifFieldName: string, elseValue: unknown): FunctionExpression; -// @beta +// @public export function isAbsent(value: Expression): BooleanExpression; -// @beta +// @public export function isAbsent(field: string): BooleanExpression; -// @beta +// @public export function isError(value: Expression): BooleanExpression; -// @beta +// @public export function isType(fieldName: string, type: Type): BooleanExpression; -// @beta +// @public export function isType(expression: Expression, type: Type): BooleanExpression; -// @beta +// @public export function join(arrayFieldName: string, delimiter: string): Expression; -// @beta +// @public export function join(arrayExpression: Expression, delimiterExpression: Expression): Expression; -// @beta +// @public export function join(arrayExpression: Expression, delimiter: string): Expression; -// @beta +// @public export function join(arrayFieldName: string, delimiterExpression: Expression): Expression; -// @beta +// @public export function last(expression: Expression): AggregateFunction; -// @beta +// @public export function last(fieldName: string): AggregateFunction; -// @beta +// @public function length_2(fieldName: string): FunctionExpression; -// @beta +// @public function length_2(expression: Expression): FunctionExpression; export { length_2 as length } -// @beta +// @public export function lessThan(left: Expression, right: Expression): BooleanExpression; -// @beta +// @public export function lessThan(expression: Expression, value: unknown): BooleanExpression; -// @beta +// @public export function lessThan(fieldName: string, expression: Expression): BooleanExpression; -// @beta +// @public export function lessThan(fieldName: string, value: unknown): BooleanExpression; -// @beta +// @public export function lessThanOrEqual(left: Expression, right: Expression): BooleanExpression; -// @beta +// @public export function lessThanOrEqual(expression: Expression, value: unknown): BooleanExpression; -// @beta +// @public export function lessThanOrEqual(fieldName: string, expression: Expression): BooleanExpression; -// @beta +// @public export function lessThanOrEqual(fieldName: string, value: unknown): BooleanExpression; -// @beta +// @public export function like(fieldName: string, pattern: string): BooleanExpression; -// @beta +// @public export function like(fieldName: string, pattern: Expression): BooleanExpression; -// @beta +// @public export function like(stringExpression: Expression, pattern: string): BooleanExpression; -// @beta +// @public export function like(stringExpression: Expression, pattern: Expression): BooleanExpression; -// @beta +// @public export type LimitStageOptions = StageOptions & { limit: number; }; -// @beta +// @public export function ln(fieldName: string): FunctionExpression; -// @beta +// @public export function ln(expression: Expression): FunctionExpression; -// @beta +// @public export function log(expression: Expression, base: number): FunctionExpression; -// @beta +// @public export function log(expression: Expression, base: Expression): FunctionExpression; -// @beta +// @public export function log(fieldName: string, base: number): FunctionExpression; -// @beta +// @public export function log(fieldName: string, base: Expression): FunctionExpression; -// @beta +// @public export function log10(fieldName: string): FunctionExpression; -// @beta +// @public export function log10(expression: Expression): FunctionExpression; -// @beta +// @public export function logicalMaximum(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function logicalMaximum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function logicalMinimum(first: Expression, second: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function logicalMinimum(fieldName: string, second: Expression | unknown, ...others: Array): FunctionExpression; -// @beta +// @public export function ltrim(fieldName: string, valueToTrim?: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function ltrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function map(elements: Record): FunctionExpression; -// @beta +// @public export function mapEntries(mapField: string): FunctionExpression; -// @beta +// @public export function mapEntries(mapExpression: Expression): FunctionExpression; -// @beta +// @public export function mapGet(fieldName: string, subField: string): FunctionExpression; -// @beta +// @public export function mapGet(mapExpression: Expression, subField: string): FunctionExpression; -// @beta +// @public export function mapKeys(mapField: string): FunctionExpression; -// @beta +// @public export function mapKeys(mapExpression: Expression): FunctionExpression; -// @beta +// @public export function mapMerge(mapField: string, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; -// @beta +// @public export function mapMerge(firstMap: Record | Expression, secondMap: Record | Expression, ...otherMaps: Array | Expression>): FunctionExpression; -// @beta +// @public export function mapRemove(mapField: string, key: string): FunctionExpression; -// @beta +// @public export function mapRemove(mapExpr: Expression, key: string): FunctionExpression; -// @beta +// @public export function mapRemove(mapField: string, keyExpr: Expression): FunctionExpression; -// @beta +// @public export function mapRemove(mapExpr: Expression, keyExpr: Expression): FunctionExpression; -// @beta +// @public export function mapSet(mapField: string, key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; -// @beta +// @public export function mapSet(mapExpression: Expression, key: string | Expression, value: unknown, ...moreKeyValues: unknown[]): FunctionExpression; -// @beta +// @public export function mapValues(mapField: string): FunctionExpression; -// @beta +// @public export function mapValues(mapExpression: Expression): FunctionExpression; -// @beta +// @public export function maximum(expression: Expression): AggregateFunction; -// @beta +// @public export function maximum(fieldName: string): AggregateFunction; -// @beta +// @public export function minimum(expression: Expression): AggregateFunction; -// @beta +// @public export function minimum(fieldName: string): AggregateFunction; -// @beta +// @public export function mod(left: Expression, right: Expression): FunctionExpression; -// @beta +// @public export function mod(expression: Expression, value: unknown): FunctionExpression; -// @beta +// @public export function mod(fieldName: string, expression: Expression): FunctionExpression; -// @beta +// @public export function mod(fieldName: string, value: unknown): FunctionExpression; -// @beta +// @public export function multiply(first: Expression, second: Expression | unknown): FunctionExpression; -// @beta +// @public export function multiply(fieldName: string, second: Expression | unknown): FunctionExpression; -// @beta +// @public export function nor(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; -// @beta +// @public export function not(booleanExpr: BooleanExpression): BooleanExpression; -// @beta +// @public export function notEqual(left: Expression, right: Expression): BooleanExpression; -// @beta +// @public export function notEqual(expression: Expression, value: unknown): BooleanExpression; -// @beta +// @public export function notEqual(fieldName: string, expression: Expression): BooleanExpression; -// @beta +// @public export function notEqual(fieldName: string, value: unknown): BooleanExpression; -// @beta +// @public export function notEqualAny(element: Expression, values: Array): BooleanExpression; -// @beta +// @public export function notEqualAny(fieldName: string, values: Array): BooleanExpression; -// @beta +// @public export function notEqualAny(element: Expression, arrayExpression: Expression): BooleanExpression; -// @beta +// @public export function notEqualAny(fieldName: string, arrayExpression: Expression): BooleanExpression; -// @beta +// @public export type OffsetStageOptions = StageOptions & { offset: number; }; -// @beta +// @public export type OneOf = { [K in keyof T]: Pick & { [P in Exclude]?: undefined; }; }[keyof T]; -// @beta +// @public export function or(first: BooleanExpression, second: BooleanExpression, ...more: BooleanExpression[]): BooleanExpression; -// @beta +// @public export class Ordering { constructor(expr: Expression, direction: 'ascending' | 'descending', _methodName: string | undefined); // (undocumented) @@ -1192,69 +1192,49 @@ export class Ordering { readonly expr: Expression; } -// @beta (undocumented) +// @public (undocumented) export class Pipeline { - // (undocumented) addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; // (undocumented) addFields(options: AddFieldsStageOptions): Pipeline; - // (undocumented) aggregate(accumulator: AliasedAggregate, ...additionalAccumulators: AliasedAggregate[]): Pipeline; - // (undocumented) aggregate(options: AggregateStageOptions): Pipeline; - // (undocumented) distinct(group: string | Selectable, ...additionalGroups: Array): Pipeline; // (undocumented) distinct(options: DistinctStageOptions): Pipeline; - // (undocumented) findNearest(options: FindNearestStageOptions): Pipeline; - // (undocumented) limit(limit: number): Pipeline; // (undocumented) limit(options: LimitStageOptions): Pipeline; - // (undocumented) offset(offset: number): Pipeline; // (undocumented) offset(options: OffsetStageOptions): Pipeline; - // (undocumented) rawStage(name: string, params: unknown[], options?: { [key: string]: Expression | unknown; }): Pipeline; - // (undocumented) removeFields(fieldValue: Field | string, ...additionalFields: Array): Pipeline; // (undocumented) removeFields(options: RemoveFieldsStageOptions): Pipeline; - // (undocumented) replaceWith(fieldName: string): Pipeline; - // (undocumented) replaceWith(expr: Expression): Pipeline; // (undocumented) replaceWith(options: ReplaceWithStageOptions): Pipeline; - // (undocumented) sample(documents: number): Pipeline; - // (undocumented) sample(options: SampleStageOptions): Pipeline; - // (undocumented) select(selection: Selectable | string, ...additionalSelections: Array): Pipeline; - // (undocumented) select(options: SelectStageOptions): Pipeline; - // (undocumented) sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; // (undocumented) sort(options: SortStageOptions): Pipeline; - // (undocumented) union(other: Pipeline): Pipeline; // (undocumented) union(options: UnionStageOptions): Pipeline; - // (undocumented) unnest(selectable: Selectable, indexField?: string): Pipeline; // (undocumented) unnest(options: UnnestStageOptions): Pipeline; - // (undocumented) where(condition: BooleanExpression): Pipeline; - // (undocumented) where(options: WhereStageOptions): Pipeline; } -// @beta +// @public export interface PipelineExecuteOptions { indexMode?: 'recommended'; pipeline: Pipeline; @@ -1263,7 +1243,7 @@ export interface PipelineExecuteOptions { }; } -// @beta +// @public export class PipelineResult { /* Excluded from this release type: _ref */ /* Excluded from this release type: _fields */ @@ -1276,17 +1256,17 @@ export class PipelineResult { get updateTime(): Timestamp | undefined; } -// @beta +// @public export function pipelineResultEqual(left: PipelineResult, right: PipelineResult): boolean; -// @beta +// @public export class PipelineSnapshot { constructor(pipeline: Pipeline, results: PipelineResult[], executionTime?: Timestamp); get executionTime(): Timestamp; get results(): PipelineResult[]; } -// @beta +// @public export class PipelineSource { collection(collection: string | Query): PipelineType; /* Excluded from this release type: _createPipeline */ @@ -1315,404 +1295,404 @@ export class PipelineSource { documents(options: DocumentsStageOptions): PipelineType; } -// @beta +// @public export function pow(base: Expression, exponent: Expression): FunctionExpression; -// @beta +// @public export function pow(base: Expression, exponent: number): FunctionExpression; -// @beta +// @public export function pow(base: string, exponent: Expression): FunctionExpression; -// @beta +// @public export function pow(base: string, exponent: number): FunctionExpression; -// @beta +// @public export function rand(): FunctionExpression; -// @beta +// @public export function regexContains(fieldName: string, pattern: string): BooleanExpression; -// @beta +// @public export function regexContains(fieldName: string, pattern: Expression): BooleanExpression; -// @beta +// @public export function regexContains(stringExpression: Expression, pattern: string): BooleanExpression; -// @beta +// @public export function regexContains(stringExpression: Expression, pattern: Expression): BooleanExpression; -// @beta +// @public export function regexFind(fieldName: string, pattern: string): FunctionExpression; -// @beta +// @public export function regexFind(fieldName: string, pattern: Expression): FunctionExpression; -// @beta +// @public export function regexFind(stringExpression: Expression, pattern: string): FunctionExpression; -// @beta +// @public export function regexFind(stringExpression: Expression, pattern: Expression): FunctionExpression; -// @beta +// @public export function regexFindAll(fieldName: string, pattern: string): FunctionExpression; -// @beta +// @public export function regexFindAll(fieldName: string, pattern: Expression): FunctionExpression; -// @beta +// @public export function regexFindAll(stringExpression: Expression, pattern: string): FunctionExpression; -// @beta +// @public export function regexFindAll(stringExpression: Expression, pattern: Expression): FunctionExpression; -// @beta +// @public export function regexMatch(fieldName: string, pattern: string): BooleanExpression; -// @beta +// @public export function regexMatch(fieldName: string, pattern: Expression): BooleanExpression; -// @beta +// @public export function regexMatch(stringExpression: Expression, pattern: string): BooleanExpression; -// @beta +// @public export function regexMatch(stringExpression: Expression, pattern: Expression): BooleanExpression; -// @beta +// @public export type RemoveFieldsStageOptions = StageOptions & { fields: Array; }; -// @beta +// @public export type ReplaceWithStageOptions = StageOptions & { map: Expression | string; }; -// @beta +// @public export function reverse(stringExpression: Expression): FunctionExpression; -// @beta +// @public export function reverse(field: string): FunctionExpression; -// @beta +// @public export function round(fieldName: string): FunctionExpression; -// @beta +// @public export function round(expression: Expression): FunctionExpression; -// @beta +// @public export function round(fieldName: string, decimalPlaces: number | Expression): FunctionExpression; -// @beta +// @public export function round(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; -// @beta +// @public export function rtrim(fieldName: string, valueToTrim?: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function rtrim(expression: Expression, valueToTrim?: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export type SampleStageOptions = StageOptions & OneOf<{ percentage: number; documents: number; }>; -// @beta +// @public export interface Selectable { // (undocumented) selectable: true; } -// @beta +// @public export type SelectStageOptions = StageOptions & { selections: Array; }; -// @beta +// @public export type SortStageOptions = StageOptions & { orderings: Ordering[]; }; -// @beta +// @public export function split(fieldName: string, delimiter: string): FunctionExpression; -// @beta +// @public export function split(fieldName: string, delimiter: Expression): FunctionExpression; -// @beta +// @public export function split(expression: Expression, delimiter: string): FunctionExpression; -// @beta +// @public export function split(expression: Expression, delimiter: Expression): FunctionExpression; -// @beta +// @public export function sqrt(expression: Expression): FunctionExpression; -// @beta +// @public export function sqrt(fieldName: string): FunctionExpression; -// @beta +// @public export interface StageOptions { rawOptions?: { [name: string]: unknown; }; } -// @beta +// @public export function startsWith(fieldName: string, prefix: string): BooleanExpression; -// @beta +// @public export function startsWith(fieldName: string, prefix: Expression): BooleanExpression; -// @beta +// @public export function startsWith(stringExpression: Expression, prefix: string): BooleanExpression; -// @beta +// @public export function startsWith(stringExpression: Expression, prefix: Expression): BooleanExpression; -// @beta +// @public export function stringConcat(fieldName: string, secondString: Expression | string, ...otherStrings: Array): FunctionExpression; -// @beta +// @public export function stringConcat(firstString: Expression, secondString: Expression | string, ...otherStrings: Array): FunctionExpression; -// @beta +// @public export function stringContains(fieldName: string, substring: string): BooleanExpression; -// @beta +// @public export function stringContains(fieldName: string, substring: Expression): BooleanExpression; -// @beta +// @public export function stringContains(stringExpression: Expression, substring: string): BooleanExpression; -// @beta +// @public export function stringContains(stringExpression: Expression, substring: Expression): BooleanExpression; -// @beta +// @public export function stringIndexOf(fieldName: string, search: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function stringIndexOf(expression: Expression, search: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function stringRepeat(fieldName: string, repetitions: number | Expression): FunctionExpression; -// @beta +// @public export function stringRepeat(expression: Expression, repetitions: number | Expression): FunctionExpression; -// @beta +// @public export function stringReplaceAll(fieldName: string, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function stringReplaceAll(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function stringReplaceOne(fieldName: string, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function stringReplaceOne(expression: Expression, find: string | Expression | Bytes, replacement: string | Expression | Bytes): FunctionExpression; -// @beta +// @public export function stringReverse(stringExpression: Expression): FunctionExpression; -// @beta +// @public export function stringReverse(field: string): FunctionExpression; -// @beta +// @public export function substring(field: string, position: number, length?: number): FunctionExpression; -// @beta +// @public export function substring(input: Expression, position: number, length?: number): FunctionExpression; -// @beta +// @public export function substring(field: string, position: Expression, length?: Expression): FunctionExpression; -// @beta +// @public export function substring(input: Expression, position: Expression, length?: Expression): FunctionExpression; -// @beta +// @public export function subtract(left: Expression, right: Expression): FunctionExpression; -// @beta +// @public export function subtract(expression: Expression, value: unknown): FunctionExpression; -// @beta +// @public export function subtract(fieldName: string, expression: Expression): FunctionExpression; -// @beta +// @public export function subtract(fieldName: string, value: unknown): FunctionExpression; -// @beta +// @public export function sum(expression: Expression): AggregateFunction; -// @beta +// @public export function sum(fieldName: string): AggregateFunction; -// @beta +// @public export function switchOn(condition: BooleanExpression, result: Expression, ...others: Array): FunctionExpression; -// @beta +// @public export type TimeGranularity = TimeUnit | 'week' | 'week(monday)' | 'week(tuesday)' | 'week(wednesday)' | 'week(thursday)' | 'week(friday)' | 'week(saturday)' | 'week(sunday)' | 'isoweek' | 'month' | 'quarter' | 'year' | 'isoyear'; -// @beta +// @public export type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; -// @beta +// @public export function timestampAdd(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; -// @beta +// @public export function timestampAdd(timestamp: Expression, unit: TimeUnit, amount: number): FunctionExpression; -// @beta +// @public export function timestampAdd(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; -// @beta +// @public export function timestampDiff(endFieldName: string, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; -// @beta +// @public export function timestampDiff(endFieldName: string, startExpression: Expression, unit: TimeUnit | Expression): FunctionExpression; -// @beta +// @public export function timestampDiff(endExpression: Expression, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; -// @beta +// @public export function timestampDiff(endExpression: Expression, startExpression: Expression, unit: TimeUnit | Expression): FunctionExpression; -// @beta +// @public export function timestampExtract(fieldName: string, part: TimePart, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampExtract(fieldName: string, part: Expression, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampExtract(timestampExpression: Expression, part: TimePart, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampExtract(timestampExpression: Expression, part: Expression, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampSubtract(timestamp: Expression, unit: Expression, amount: Expression): FunctionExpression; -// @beta +// @public export function timestampSubtract(timestamp: Expression, unit: TimeUnit, amount: number): FunctionExpression; -// @beta +// @public export function timestampSubtract(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; -// @beta +// @public export function timestampToUnixMicros(expr: Expression): FunctionExpression; -// @beta +// @public export function timestampToUnixMicros(fieldName: string): FunctionExpression; -// @beta +// @public export function timestampToUnixMillis(expr: Expression): FunctionExpression; -// @beta +// @public export function timestampToUnixMillis(fieldName: string): FunctionExpression; -// @beta +// @public export function timestampToUnixSeconds(expr: Expression): FunctionExpression; -// @beta +// @public export function timestampToUnixSeconds(fieldName: string): FunctionExpression; -// @beta +// @public export function timestampTruncate(fieldName: string, granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampTruncate(fieldName: string, granularity: Expression, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampTruncate(timestampExpression: Expression, granularity: TimeGranularity, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export function timestampTruncate(timestampExpression: Expression, granularity: Expression, timezone?: string | Expression): FunctionExpression; -// @beta +// @public export type TimeUnit = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'; -// @beta +// @public export function toLower(fieldName: string): FunctionExpression; -// @beta +// @public export function toLower(stringExpression: Expression): FunctionExpression; -// @beta +// @public export function toUpper(fieldName: string): FunctionExpression; -// @beta +// @public export function toUpper(stringExpression: Expression): FunctionExpression; -// @beta +// @public export function trim(fieldName: string, valueToTrim?: string | Expression): FunctionExpression; -// @beta +// @public export function trim(stringExpression: Expression, valueToTrim?: string | Expression): FunctionExpression; -// @beta +// @public export function trunc(fieldName: string): FunctionExpression; -// @beta +// @public export function trunc(expression: Expression): FunctionExpression; -// @beta +// @public export function trunc(fieldName: string, decimalPlaces: number | Expression): FunctionExpression; -// @beta +// @public export function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; -// @beta +// @public export type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp'; -// @beta +// @public export function type(fieldName: string): FunctionExpression; -// @beta +// @public export function type(expression: Expression): FunctionExpression; -// @beta +// @public export type UnionStageOptions = StageOptions & { other: Pipeline; }; -// @beta +// @public export function unixMicrosToTimestamp(expr: Expression): FunctionExpression; -// @beta +// @public export function unixMicrosToTimestamp(fieldName: string): FunctionExpression; -// @beta +// @public export function unixMillisToTimestamp(expr: Expression): FunctionExpression; -// @beta +// @public export function unixMillisToTimestamp(fieldName: string): FunctionExpression; -// @beta +// @public export function unixSecondsToTimestamp(expr: Expression): FunctionExpression; -// @beta +// @public export function unixSecondsToTimestamp(fieldName: string): FunctionExpression; -// @beta +// @public export type UnnestStageOptions = StageOptions & { selectable: Selectable; indexField?: string; }; -// @beta +// @public export function vectorLength(vectorExpression: Expression): FunctionExpression; -// @beta +// @public export function vectorLength(fieldName: string): FunctionExpression; -// @beta +// @public export type WhereStageOptions = StageOptions & { condition: BooleanExpression; }; -// @beta +// @public export function xor(first: BooleanExpression, second: BooleanExpression, ...additionalConditions: BooleanExpression[]): BooleanExpression; diff --git a/docs-devsite/firestore_lite_pipelines.aggregatefunction.md b/docs-devsite/firestore_lite_pipelines.aggregatefunction.md index fe3dfc3b93..d79b5a4804 100644 --- a/docs-devsite/firestore_lite_pipelines.aggregatefunction.md +++ b/docs-devsite/firestore_lite_pipelines.aggregatefunction.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # AggregateFunction class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - A class that represents an aggregate function. Signature: @@ -25,25 +22,22 @@ export declare class AggregateFunction | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(name, params)](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunctionconstructor) | | (Public Preview) Constructs a new instance of the AggregateFunction class | +| [(constructor)(name, params)](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunctionconstructor) | | Constructs a new instance of the AggregateFunction class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [exprType](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunctionexprtype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) | +| [exprType](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunctionexprtype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | | ## Methods | Method | Modifiers | Description | | --- | --- | --- | -| [as(name)](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunctionas) | | (Public Preview) Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. | +| [as(name)](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunctionas) | | Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. | ## AggregateFunction.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `AggregateFunction` class Signature: @@ -61,9 +55,6 @@ constructor(name: string, params: Expression[]); ## AggregateFunction.exprType -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -72,9 +63,6 @@ exprType: ExpressionType; ## AggregateFunction.as() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. Signature: diff --git a/docs-devsite/firestore_lite_pipelines.aliasedaggregate.md b/docs-devsite/firestore_lite_pipelines.aliasedaggregate.md index 47f02ca732..6a449e52fe 100644 --- a/docs-devsite/firestore_lite_pipelines.aliasedaggregate.md +++ b/docs-devsite/firestore_lite_pipelines.aliasedaggregate.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # AliasedAggregate class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An AggregateFunction with alias. Signature: @@ -25,20 +22,17 @@ export declare class AliasedAggregate | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(aggregate, alias, \_methodName)](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregateconstructor) | | (Public Preview) Constructs a new instance of the AliasedAggregate class | +| [(constructor)(aggregate, alias, \_methodName)](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregateconstructor) | | Constructs a new instance of the AliasedAggregate class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [aggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregateaggregate) | | [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) | (Public Preview) | -| [alias](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregatealias) | | string | (Public Preview) | +| [aggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregateaggregate) | | [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) | | +| [alias](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregatealias) | | string | | ## AliasedAggregate.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `AliasedAggregate` class Signature: @@ -57,9 +51,6 @@ constructor(aggregate: AggregateFunction, alias: string, _methodName: string | u ## AliasedAggregate.aggregate -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -68,9 +59,6 @@ readonly aggregate: AggregateFunction; ## AliasedAggregate.alias -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/firestore_lite_pipelines.aliasedexpression.md b/docs-devsite/firestore_lite_pipelines.aliasedexpression.md index 9e65be574c..c95a7dc139 100644 --- a/docs-devsite/firestore_lite_pipelines.aliasedexpression.md +++ b/docs-devsite/firestore_lite_pipelines.aliasedexpression.md @@ -10,10 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # AliasedExpression class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - - Signature: ```typescript @@ -25,22 +21,19 @@ export declare class AliasedExpression implements Selectable | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(expr, alias, \_methodName)](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionconstructor) | | (Public Preview) Constructs a new instance of the AliasedExpression class | +| [(constructor)(expr, alias, \_methodName)](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionconstructor) | | Constructs a new instance of the AliasedExpression class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [alias](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionalias) | | string | (Public Preview) | -| [expr](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionexpr) | | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | (Public Preview) | -| [exprType](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionexprtype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) | -| [selectable](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionselectable) | | true | (Public Preview) | +| [alias](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionalias) | | string | | +| [expr](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionexpr) | | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | +| [exprType](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionexprtype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | | +| [selectable](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpressionselectable) | | true | | ## AliasedExpression.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `AliasedExpression` class Signature: @@ -59,9 +52,6 @@ constructor(expr: Expression, alias: string, _methodName: string | undefined); ## AliasedExpression.alias -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -70,9 +60,6 @@ readonly alias: string; ## AliasedExpression.expr -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -81,9 +68,6 @@ readonly expr: Expression; ## AliasedExpression.exprType -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -92,9 +76,6 @@ exprType: ExpressionType; ## AliasedExpression.selectable -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/firestore_lite_pipelines.booleanexpression.md b/docs-devsite/firestore_lite_pipelines.booleanexpression.md index 1b4b918bed..0612ff42f5 100644 --- a/docs-devsite/firestore_lite_pipelines.booleanexpression.md +++ b/docs-devsite/firestore_lite_pipelines.booleanexpression.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # BooleanExpression class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An interface that represents a filter condition. Signature: @@ -26,19 +23,16 @@ export declare abstract class BooleanExpression extends Expression | Method | Modifiers | Description | | --- | --- | --- | -| [conditional(thenExpr, elseExpr)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressionconditional) | | (Public Preview) Creates a conditional expression that evaluates to the 'then' expression if this expression evaluates to true, or evaluates to the 'else' expression if this expressions evaluates false. | -| [countIf()](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioncountif) | | (Public Preview) Creates an aggregation that finds the count of input documents satisfying this boolean expression. | -| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | -| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | -| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | -| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | -| [not()](./firestore_lite_pipelines.booleanexpression.md#booleanexpressionnot) | | (Public Preview) Creates an expression that negates this boolean expression. | +| [conditional(thenExpr, elseExpr)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressionconditional) | | Creates a conditional expression that evaluates to the 'then' expression if this expression evaluates to true, or evaluates to the 'else' expression if this expressions evaluates false. | +| [countIf()](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioncountif) | | Creates an aggregation that finds the count of input documents satisfying this boolean expression. | +| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_lite_pipelines.booleanexpression.md#booleanexpressioniferror) | | Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [not()](./firestore_lite_pipelines.booleanexpression.md#booleanexpressionnot) | | Creates an expression that negates this boolean expression. | ## BooleanExpression.conditional() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a conditional expression that evaluates to the 'then' expression if `this` expression evaluates to `true`, or evaluates to the 'else' expression if `this` expressions evaluates `false`. Signature: @@ -71,9 +65,6 @@ field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Min ## BooleanExpression.countIf() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the count of input documents satisfying this boolean expression. Signature: @@ -98,9 +89,6 @@ field("score").greaterThan(90).countIf().as("highestScore"); ## BooleanExpression.ifError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. Signature: @@ -133,9 +121,6 @@ constant(50).divide(field('length')).greaterThan(1).ifError(constant(false)); ## BooleanExpression.ifError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. Signature: @@ -168,9 +153,6 @@ constant(50).divide(field('length')).greaterThan(1).ifError(false); ## BooleanExpression.ifError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. Signature: @@ -202,9 +184,6 @@ constant(50).divide(field('length')).greaterThan(1).ifError(constant(0)); ## BooleanExpression.ifError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. Signature: @@ -236,9 +215,6 @@ constant(50).divide(field('length')).greaterThan(1).ifError(0); ## BooleanExpression.not() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that negates this boolean expression. Signature: diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index 25ce29755b..98f04f933e 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # Expression class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents an expression that can be evaluated to a value within the execution of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class). Expressions are the building blocks for creating complex queries and transformations in Firestore pipelines. They can represent: @@ -31,186 +28,183 @@ export declare abstract class Expression | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [expressionType](./firestore_lite_pipelines.expression.md#expressionexpressiontype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) | +| [expressionType](./firestore_lite_pipelines.expression.md#expressionexpressiontype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | | ## Methods | Method | Modifiers | Description | | --- | --- | --- | -| [abs()](./firestore_lite_pipelines.expression.md#expressionabs) | | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | -| [add(second)](./firestore_lite_pipelines.expression.md#expressionadd) | | (Public Preview) Creates an expression that adds this expression to another expression. | -| [arrayAgg()](./firestore_lite_pipelines.expression.md#expressionarrayagg) | | (Public Preview) Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. | -| [arrayAggDistinct()](./firestore_lite_pipelines.expression.md#expressionarrayaggdistinct) | | (Public Preview) Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. | -| [arrayConcat(secondArray, otherArrays)](./firestore_lite_pipelines.expression.md#expressionarrayconcat) | | (Public Preview) Creates an expression that concatenates an array expression with one or more other arrays. | -| [arrayContains(expression)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific element. | -| [arrayContains(value)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific value. | -| [arrayContainsAll(values)](./firestore_lite_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. | -| [arrayContainsAll(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. | -| [arrayContainsAny(values)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. | -| [arrayContainsAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. | -| [arrayFirst()](./firestore_lite_pipelines.expression.md#expressionarrayfirst) | | (Public Preview) Returns the first element of the array. | -| [arrayFirstN(n)](./firestore_lite_pipelines.expression.md#expressionarrayfirstn) | | (Public Preview) Returns the first n elements of the array. | -| [arrayFirstN(n)](./firestore_lite_pipelines.expression.md#expressionarrayfirstn) | | (Public Preview) Returns the first n elements of the array. | -| [arrayGet(offset)](./firestore_lite_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | -| [arrayGet(offsetExpr)](./firestore_lite_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | -| [arrayIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionarrayindexof) | | (Public Preview) Returns the first index of the search value in the array, or -1 if not found. | -| [arrayIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionarrayindexof) | | (Public Preview) Returns the first index of the search value in the array, or -1 if not found. | -| [arrayIndexOfAll(search)](./firestore_lite_pipelines.expression.md#expressionarrayindexofall) | | (Public Preview) Returns all indices of the search value in the array. | -| [arrayIndexOfAll(search)](./firestore_lite_pipelines.expression.md#expressionarrayindexofall) | | (Public Preview) Returns all indices of the search value in the array. | -| [arrayLast()](./firestore_lite_pipelines.expression.md#expressionarraylast) | | (Public Preview) Returns the last element of the array. | -| [arrayLastIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionarraylastindexof) | | (Public Preview) Returns the last index of the search value in the array, or -1 if not found. | -| [arrayLastIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionarraylastindexof) | | (Public Preview) Returns the last index of the search value in the array, or -1 if not found. | -| [arrayLastN(n)](./firestore_lite_pipelines.expression.md#expressionarraylastn) | | (Public Preview) Returns the last n elements of the array. | -| [arrayLastN(n)](./firestore_lite_pipelines.expression.md#expressionarraylastn) | | (Public Preview) Returns the last n elements of the array. | -| [arrayLength()](./firestore_lite_pipelines.expression.md#expressionarraylength) | | (Public Preview) Creates an expression that calculates the length of an array. | -| [arrayMaximum()](./firestore_lite_pipelines.expression.md#expressionarraymaximum) | | (Public Preview) Returns the maximum value in the array. | -| [arrayMaximumN(n)](./firestore_lite_pipelines.expression.md#expressionarraymaximumn) | | (Public Preview) Returns the largest n elements of the array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMaximumN(n)](./firestore_lite_pipelines.expression.md#expressionarraymaximumn) | | (Public Preview) Returns the largest n elements of the array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMinimum()](./firestore_lite_pipelines.expression.md#expressionarrayminimum) | | (Public Preview) Returns the minimum value in the array. | -| [arrayMinimumN(n)](./firestore_lite_pipelines.expression.md#expressionarrayminimumn) | | (Public Preview) Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMinimumN(n)](./firestore_lite_pipelines.expression.md#expressionarrayminimumn) | | (Public Preview) Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayReverse()](./firestore_lite_pipelines.expression.md#expressionarrayreverse) | | (Public Preview) Creates an expression that reverses an array. | -| [arraySum()](./firestore_lite_pipelines.expression.md#expressionarraysum) | | (Public Preview) Creates an expression that computes the sum of the elements in an array. | -| [as(name)](./firestore_lite_pipelines.expression.md#expressionas) | | (Public Preview) 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. | -| [asBoolean()](./firestore_lite_pipelines.expression.md#expressionasboolean) | | (Public Preview) Wraps the expression in a \[BooleanExpression\]. | -| [ascending()](./firestore_lite_pipelines.expression.md#expressionascending) | | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on this expression. | -| [average()](./firestore_lite_pipelines.expression.md#expressionaverage) | | (Public Preview) Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. | -| [byteLength()](./firestore_lite_pipelines.expression.md#expressionbytelength) | | (Public Preview) Creates an expression that calculates the length of this string expression in bytes. | -| [ceil()](./firestore_lite_pipelines.expression.md#expressionceil) | | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | -| [charLength()](./firestore_lite_pipelines.expression.md#expressioncharlength) | | (Public Preview) Creates an expression that calculates the character length of a string in UTF-8. | -| [coalesce(replacement, others)](./firestore_lite_pipelines.expression.md#expressioncoalesce) | | (Public Preview) Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | -| [collectionId()](./firestore_lite_pipelines.expression.md#expressioncollectionid) | | (Public Preview) Creates an expression that returns the collection ID from a path. | -| [concat(second, others)](./firestore_lite_pipelines.expression.md#expressionconcat) | | (Public Preview) Creates an expression that concatenates expression results together. | -| [cosineDistance(vectorExpression)](./firestore_lite_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the cosine distance between two vectors. | -| [cosineDistance(vector)](./firestore_lite_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the Cosine distance between two vectors. | -| [count()](./firestore_lite_pipelines.expression.md#expressioncount) | | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. | -| [countDistinct()](./firestore_lite_pipelines.expression.md#expressioncountdistinct) | | (Public Preview) Creates an aggregation that counts the number of distinct values of the expression or field. | -| [descending()](./firestore_lite_pipelines.expression.md#expressiondescending) | | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on this expression. | -| [divide(divisor)](./firestore_lite_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by another expression. | -| [divide(divisor)](./firestore_lite_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by a constant value. | -| [documentId()](./firestore_lite_pipelines.expression.md#expressiondocumentid) | | (Public Preview) Creates an expression that returns the document ID from a path. | -| [dotProduct(vectorExpression)](./firestore_lite_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. | -| [dotProduct(vector)](./firestore_lite_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. | -| [endsWith(suffix)](./firestore_lite_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix. | -| [endsWith(suffix)](./firestore_lite_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix (represented as an expression). | -| [equal(expression)](./firestore_lite_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to another expression. | -| [equal(value)](./firestore_lite_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to a constant value. | -| [equalAny(values)](./firestore_lite_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. | -| [equalAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. | -| [euclideanDistance(vectorExpression)](./firestore_lite_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. | -| [euclideanDistance(vector)](./firestore_lite_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. | -| [exists()](./firestore_lite_pipelines.expression.md#expressionexists) | | (Public Preview) Creates an expression that checks if a field exists in the document. | -| [exp()](./firestore_lite_pipelines.expression.md#expressionexp) | | (Public Preview) Creates an expression that computes e to the power of this expression. | -| [first()](./firestore_lite_pipelines.expression.md#expressionfirst) | | (Public Preview) Creates an aggregation that finds the first value of an expression across multiple stage inputs. | -| [floor()](./firestore_lite_pipelines.expression.md#expressionfloor) | | (Public Preview) Creates an expression that computes the floor of a numeric value. | -| [greaterThan(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than another expression. | -| [greaterThan(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than a constant value. | -| [greaterThanOrEqual(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to another expression. | -| [greaterThanOrEqual(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to a constant value. | -| [ifAbsent(elseValue)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | -| [ifAbsent(elseExpression)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | -| [ifError(catchExpr)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. | -| [ifError(catchValue)](./firestore_lite_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | -| [ifNull(elseExpression)](./firestore_lite_pipelines.expression.md#expressionifnull) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression evaluates to null, else return the result of this expression evaluation. | -| [ifNull(elseValue)](./firestore_lite_pipelines.expression.md#expressionifnull) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression evaluates to null, else return the result of this expression evaluation. | -| [isAbsent()](./firestore_lite_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. | -| [isError()](./firestore_lite_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. | -| [isType(type)](./firestore_lite_pipelines.expression.md#expressionistype) | | (Public Preview) Creates an expression that checks if the result of this expression is of the given type. | -| [join(delimiterExpression)](./firestore_lite_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array into a string. | -| [join(delimiter)](./firestore_lite_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array field into a string. | -| [last()](./firestore_lite_pipelines.expression.md#expressionlast) | | (Public Preview) Creates an aggregation that finds the last value of an expression across multiple stage inputs. | -| [length()](./firestore_lite_pipelines.expression.md#expressionlength) | | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | -| [lessThan(experession)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than another expression. | -| [lessThan(value)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than a constant value. | -| [lessThanOrEqual(expression)](./firestore_lite_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to another expression. | -| [lessThanOrEqual(value)](./firestore_lite_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to a constant value. | -| [like(pattern)](./firestore_lite_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. | -| [like(pattern)](./firestore_lite_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. | -| [ln()](./firestore_lite_pipelines.expression.md#expressionln) | | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. | -| [log10()](./firestore_lite_pipelines.expression.md#expressionlog10) | | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | -| [logicalMaximum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalmaximum) | | (Public Preview) Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. | -| [logicalMinimum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalminimum) | | (Public Preview) Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. | -| [ltrim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressionltrim) | | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | -| [mapEntries()](./firestore_lite_pipelines.expression.md#expressionmapentries) | | (Public Preview) 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" }, ...]. | -| [mapGet(subfield)](./firestore_lite_pipelines.expression.md#expressionmapget) | | (Public Preview) Accesses a value from a map (object) field using the provided key. | -| [mapKeys()](./firestore_lite_pipelines.expression.md#expressionmapkeys) | | (Public Preview) Creates an expression that returns the keys of a map. | -| [mapMerge(secondMap, otherMaps)](./firestore_lite_pipelines.expression.md#expressionmapmerge) | | (Public Preview) Creates an expression that merges multiple map values. | -| [mapRemove(key)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | -| [mapRemove(keyExpr)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | -| [mapSet(key, value, moreKeyValues)](./firestore_lite_pipelines.expression.md#expressionmapset) | | (Public Preview) Creates an expression that returns a new map with the specified entries added or updated. | -| [mapValues()](./firestore_lite_pipelines.expression.md#expressionmapvalues) | | (Public Preview) Creates an expression that returns the values of a map. | -| [maximum()](./firestore_lite_pipelines.expression.md#expressionmaximum) | | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | -| [minimum()](./firestore_lite_pipelines.expression.md#expressionminimum) | | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | -| [mod(expression)](./firestore_lite_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. | -| [mod(value)](./firestore_lite_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. | -| [multiply(second)](./firestore_lite_pipelines.expression.md#expressionmultiply) | | (Public Preview) Creates an expression that multiplies this expression by another expression. | -| [notEqual(expression)](./firestore_lite_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to another expression. | -| [notEqual(value)](./firestore_lite_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to a constant value. | -| [notEqualAny(values)](./firestore_lite_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the provided values or expressions. | -| [notEqualAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. | -| [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of another expression. | -| [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of a constant value. | -| [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. | -| [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. | -| [regexFind(pattern)](./firestore_lite_pipelines.expression.md#expressionregexfind) | | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFind(pattern)](./firestore_lite_pipelines.expression.md#expressionregexfind) | | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFindAll(pattern)](./firestore_lite_pipelines.expression.md#expressionregexfindall) | | (Public Preview) Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFindAll(pattern)](./firestore_lite_pipelines.expression.md#expressionregexfindall) | | (Public Preview) Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexMatch(pattern)](./firestore_lite_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. | -| [regexMatch(pattern)](./firestore_lite_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. | -| [reverse()](./firestore_lite_pipelines.expression.md#expressionreverse) | | (Public Preview) Creates an expression that reverses this string expression. | -| [round()](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | -| [round(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | -| [round(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | -| [rtrim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressionrtrim) | | (Public Preview) Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | -| [split(delimiter)](./firestore_lite_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | -| [split(delimiter)](./firestore_lite_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | -| [sqrt()](./firestore_lite_pipelines.expression.md#expressionsqrt) | | (Public Preview) Creates an expression that computes the square root of a numeric value. | -| [startsWith(prefix)](./firestore_lite_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix. | -| [startsWith(prefix)](./firestore_lite_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix (represented as an expression). | -| [stringConcat(secondString, otherStrings)](./firestore_lite_pipelines.expression.md#expressionstringconcat) | | (Public Preview) Creates an expression that concatenates string expressions together. | -| [stringContains(substring)](./firestore_lite_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified substring. | -| [stringContains(expr)](./firestore_lite_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains the string represented by another expression. | -| [stringIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionstringindexof) | | (Public Preview) Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | -| [stringRepeat(repetitions)](./firestore_lite_pipelines.expression.md#expressionstringrepeat) | | (Public Preview) Creates an expression that repeats a string or byte array a specified number of times. | -| [stringReplaceAll(find, replacement)](./firestore_lite_pipelines.expression.md#expressionstringreplaceall) | | (Public Preview) Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | -| [stringReplaceOne(find, replacement)](./firestore_lite_pipelines.expression.md#expressionstringreplaceone) | | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | -| [stringReverse()](./firestore_lite_pipelines.expression.md#expressionstringreverse) | | (Public Preview) Creates an expression that reverses a string. | -| [substring(position, length)](./firestore_lite_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | -| [substring(position, length)](./firestore_lite_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | -| [subtract(subtrahend)](./firestore_lite_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts another expression from this expression. | -| [subtract(subtrahend)](./firestore_lite_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts a constant value from this expression. | -| [sum()](./firestore_lite_pipelines.expression.md#expressionsum) | | (Public Preview) Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. | -| [timestampAdd(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. | -| [timestampAdd(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. | -| [timestampDiff(start, unit)](./firestore_lite_pipelines.expression.md#expressiontimestampdiff) | | (Public Preview) Creates an expression that calculates the difference between this timestamp and another timestamp. | -| [timestampDiff(start, unit)](./firestore_lite_pipelines.expression.md#expressiontimestampdiff) | | (Public Preview) Creates an expression that calculates the difference between this timestamp and another timestamp. | -| [timestampExtract(part, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestampextract) | | (Public Preview) Creates an expression that extracts a specified part from this timestamp expression. | -| [timestampExtract(part, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestampextract) | | (Public Preview) Creates an expression that extracts a specified part from this timestamp expression. | -| [timestampSubtract(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. | -| [timestampSubtract(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. | -| [timestampToUnixMicros()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixmicros) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampToUnixMillis()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixmillis) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampToUnixSeconds()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixseconds) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampTruncate(granularity, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestamptruncate) | | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [timestampTruncate(granularity, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestamptruncate) | | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [toLower()](./firestore_lite_pipelines.expression.md#expressiontolower) | | (Public Preview) Creates an expression that converts a string to lowercase. | -| [toUpper()](./firestore_lite_pipelines.expression.md#expressiontoupper) | | (Public Preview) Creates an expression that converts a string to uppercase. | -| [trim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressiontrim) | | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array. | -| [trunc()](./firestore_lite_pipelines.expression.md#expressiontrunc) | | (Public Preview) Creates an expression that truncates the numeric value to an integer. | -| [trunc(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressiontrunc) | | (Public Preview) Creates an expression that truncates a numeric value to the specified number of decimal places. | -| [trunc(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressiontrunc) | | (Public Preview) Creates an expression that truncates a numeric value to the specified number of decimal places. | -| [type()](./firestore_lite_pipelines.expression.md#expressiontype) | | (Public Preview) Creates an expression that returns the data type of this expression's result, as a string. | -| [unixMicrosToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixmicrostotimestamp) | | (Public Preview) 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. | -| [unixMillisToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixmillistotimestamp) | | (Public Preview) 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. | -| [unixSecondsToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixsecondstotimestamp) | | (Public Preview) 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. | -| [vectorLength()](./firestore_lite_pipelines.expression.md#expressionvectorlength) | | (Public Preview) Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. | +| [abs()](./firestore_lite_pipelines.expression.md#expressionabs) | | Creates an expression that computes the absolute value of a numeric value. | +| [add(second)](./firestore_lite_pipelines.expression.md#expressionadd) | | Creates an expression that adds this expression to another expression. | +| [arrayAgg()](./firestore_lite_pipelines.expression.md#expressionarrayagg) | | Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. | +| [arrayAggDistinct()](./firestore_lite_pipelines.expression.md#expressionarrayaggdistinct) | | Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. | +| [arrayConcat(secondArray, otherArrays)](./firestore_lite_pipelines.expression.md#expressionarrayconcat) | | Creates an expression that concatenates an array expression with one or more other arrays. | +| [arrayContains(expression)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | Creates an expression that checks if an array contains a specific element. | +| [arrayContains(value)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | Creates an expression that checks if an array contains a specific value. | +| [arrayContainsAll(values)](./firestore_lite_pipelines.expression.md#expressionarraycontainsall) | | Creates an expression that checks if an array contains all the specified elements. | +| [arrayContainsAll(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsall) | | Creates an expression that checks if an array contains all the specified elements. | +| [arrayContainsAny(values)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | Creates an expression that checks if an array contains any of the specified elements. | +| [arrayContainsAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | Creates an expression that checks if an array contains any of the specified elements. | +| [arrayFirst()](./firestore_lite_pipelines.expression.md#expressionarrayfirst) | | Returns the first element of the array. | +| [arrayFirstN(n)](./firestore_lite_pipelines.expression.md#expressionarrayfirstn) | | Returns the first n elements of the array. | +| [arrayFirstN(n)](./firestore_lite_pipelines.expression.md#expressionarrayfirstn) | | Returns the first n elements of the array. | +| [arrayGet(offset)](./firestore_lite_pipelines.expression.md#expressionarrayget) | | Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(offsetExpr)](./firestore_lite_pipelines.expression.md#expressionarrayget) | | Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionarrayindexof) | | Returns the first index of the search value in the array, or -1 if not found. | +| [arrayIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionarrayindexof) | | Returns the first index of the search value in the array, or -1 if not found. | +| [arrayIndexOfAll(search)](./firestore_lite_pipelines.expression.md#expressionarrayindexofall) | | Returns all indices of the search value in the array. | +| [arrayIndexOfAll(search)](./firestore_lite_pipelines.expression.md#expressionarrayindexofall) | | Returns all indices of the search value in the array. | +| [arrayLast()](./firestore_lite_pipelines.expression.md#expressionarraylast) | | Returns the last element of the array. | +| [arrayLastIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionarraylastindexof) | | Returns the last index of the search value in the array, or -1 if not found. | +| [arrayLastIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionarraylastindexof) | | Returns the last index of the search value in the array, or -1 if not found. | +| [arrayLastN(n)](./firestore_lite_pipelines.expression.md#expressionarraylastn) | | Returns the last n elements of the array. | +| [arrayLastN(n)](./firestore_lite_pipelines.expression.md#expressionarraylastn) | | Returns the last n elements of the array. | +| [arrayLength()](./firestore_lite_pipelines.expression.md#expressionarraylength) | | Creates an expression that calculates the length of an array. | +| [arrayMaximum()](./firestore_lite_pipelines.expression.md#expressionarraymaximum) | | Returns the maximum value in the array. | +| [arrayMaximumN(n)](./firestore_lite_pipelines.expression.md#expressionarraymaximumn) | | Returns the largest n elements of the array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMaximumN(n)](./firestore_lite_pipelines.expression.md#expressionarraymaximumn) | | Returns the largest n elements of the array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimum()](./firestore_lite_pipelines.expression.md#expressionarrayminimum) | | Returns the minimum value in the array. | +| [arrayMinimumN(n)](./firestore_lite_pipelines.expression.md#expressionarrayminimumn) | | Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimumN(n)](./firestore_lite_pipelines.expression.md#expressionarrayminimumn) | | Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayReverse()](./firestore_lite_pipelines.expression.md#expressionarrayreverse) | | Creates an expression that reverses an array. | +| [arraySum()](./firestore_lite_pipelines.expression.md#expressionarraysum) | | Creates an expression that computes the sum of the elements in an array. | +| [as(name)](./firestore_lite_pipelines.expression.md#expressionas) | | 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. | +| [asBoolean()](./firestore_lite_pipelines.expression.md#expressionasboolean) | | Wraps the expression in a \[BooleanExpression\]. | +| [ascending()](./firestore_lite_pipelines.expression.md#expressionascending) | | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on this expression. | +| [average()](./firestore_lite_pipelines.expression.md#expressionaverage) | | Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. | +| [byteLength()](./firestore_lite_pipelines.expression.md#expressionbytelength) | | Creates an expression that calculates the length of this string expression in bytes. | +| [ceil()](./firestore_lite_pipelines.expression.md#expressionceil) | | Creates an expression that computes the ceiling of a numeric value. | +| [charLength()](./firestore_lite_pipelines.expression.md#expressioncharlength) | | Creates an expression that calculates the character length of a string in UTF-8. | +| [coalesce(replacement, others)](./firestore_lite_pipelines.expression.md#expressioncoalesce) | | Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | +| [collectionId()](./firestore_lite_pipelines.expression.md#expressioncollectionid) | | Creates an expression that returns the collection ID from a path. | +| [concat(second, others)](./firestore_lite_pipelines.expression.md#expressionconcat) | | Creates an expression that concatenates expression results together. | +| [cosineDistance(vectorExpression)](./firestore_lite_pipelines.expression.md#expressioncosinedistance) | | Calculates the cosine distance between two vectors. | +| [cosineDistance(vector)](./firestore_lite_pipelines.expression.md#expressioncosinedistance) | | Calculates the Cosine distance between two vectors. | +| [count()](./firestore_lite_pipelines.expression.md#expressioncount) | | Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. | +| [countDistinct()](./firestore_lite_pipelines.expression.md#expressioncountdistinct) | | Creates an aggregation that counts the number of distinct values of the expression or field. | +| [descending()](./firestore_lite_pipelines.expression.md#expressiondescending) | | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on this expression. | +| [divide(divisor)](./firestore_lite_pipelines.expression.md#expressiondivide) | | Creates an expression that divides this expression by another expression. | +| [divide(divisor)](./firestore_lite_pipelines.expression.md#expressiondivide) | | Creates an expression that divides this expression by a constant value. | +| [documentId()](./firestore_lite_pipelines.expression.md#expressiondocumentid) | | Creates an expression that returns the document ID from a path. | +| [dotProduct(vectorExpression)](./firestore_lite_pipelines.expression.md#expressiondotproduct) | | Calculates the dot product between two vectors. | +| [dotProduct(vector)](./firestore_lite_pipelines.expression.md#expressiondotproduct) | | Calculates the dot product between two vectors. | +| [endsWith(suffix)](./firestore_lite_pipelines.expression.md#expressionendswith) | | Creates an expression that checks if a string ends with a given postfix. | +| [endsWith(suffix)](./firestore_lite_pipelines.expression.md#expressionendswith) | | Creates an expression that checks if a string ends with a given postfix (represented as an expression). | +| [equal(expression)](./firestore_lite_pipelines.expression.md#expressionequal) | | Creates an expression that checks if this expression is equal to another expression. | +| [equal(value)](./firestore_lite_pipelines.expression.md#expressionequal) | | Creates an expression that checks if this expression is equal to a constant value. | +| [equalAny(values)](./firestore_lite_pipelines.expression.md#expressionequalany) | | Creates an expression that checks if this expression is equal to any of the provided values or expressions. | +| [equalAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionequalany) | | Creates an expression that checks if this expression is equal to any of the provided values or expressions. | +| [euclideanDistance(vectorExpression)](./firestore_lite_pipelines.expression.md#expressioneuclideandistance) | | Calculates the Euclidean distance between two vectors. | +| [euclideanDistance(vector)](./firestore_lite_pipelines.expression.md#expressioneuclideandistance) | | Calculates the Euclidean distance between two vectors. | +| [exists()](./firestore_lite_pipelines.expression.md#expressionexists) | | Creates an expression that checks if a field exists in the document. | +| [exp()](./firestore_lite_pipelines.expression.md#expressionexp) | | Creates an expression that computes e to the power of this expression. | +| [first()](./firestore_lite_pipelines.expression.md#expressionfirst) | | Creates an aggregation that finds the first value of an expression across multiple stage inputs. | +| [floor()](./firestore_lite_pipelines.expression.md#expressionfloor) | | Creates an expression that computes the floor of a numeric value. | +| [greaterThan(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | Creates an expression that checks if this expression is greater than another expression. | +| [greaterThan(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | Creates an expression that checks if this expression is greater than a constant value. | +| [greaterThanOrEqual(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | Creates an expression that checks if this expression is greater than or equal to another expression. | +| [greaterThanOrEqual(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | Creates an expression that checks if this expression is greater than or equal to a constant value. | +| [ifAbsent(elseValue)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | +| [ifAbsent(elseExpression)](./firestore_lite_pipelines.expression.md#expressionifabsent) | | Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | +| [ifError(catchExpr)](./firestore_lite_pipelines.expression.md#expressioniferror) | | Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_lite_pipelines.expression.md#expressioniferror) | | Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifNull(elseExpression)](./firestore_lite_pipelines.expression.md#expressionifnull) | | Creates an expression that returns the elseValue argument if this expression evaluates to null, else return the result of this expression evaluation. | +| [ifNull(elseValue)](./firestore_lite_pipelines.expression.md#expressionifnull) | | Creates an expression that returns the elseValue argument if this expression evaluates to null, else return the result of this expression evaluation. | +| [isAbsent()](./firestore_lite_pipelines.expression.md#expressionisabsent) | | Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. | +| [isError()](./firestore_lite_pipelines.expression.md#expressioniserror) | | Creates an expression that checks if a given expression produces an error. | +| [isType(type)](./firestore_lite_pipelines.expression.md#expressionistype) | | Creates an expression that checks if the result of this expression is of the given type. | +| [join(delimiterExpression)](./firestore_lite_pipelines.expression.md#expressionjoin) | | Creates an expression that joins the elements of an array into a string. | +| [join(delimiter)](./firestore_lite_pipelines.expression.md#expressionjoin) | | Creates an expression that joins the elements of an array field into a string. | +| [last()](./firestore_lite_pipelines.expression.md#expressionlast) | | Creates an aggregation that finds the last value of an expression across multiple stage inputs. | +| [length()](./firestore_lite_pipelines.expression.md#expressionlength) | | Creates an expression that calculates the length of a string, array, map, vector, or bytes. | +| [lessThan(experession)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | Creates an expression that checks if this expression is less than another expression. | +| [lessThan(value)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | Creates an expression that checks if this expression is less than a constant value. | +| [lessThanOrEqual(expression)](./firestore_lite_pipelines.expression.md#expressionlessthanorequal) | | Creates an expression that checks if this expression is less than or equal to another expression. | +| [lessThanOrEqual(value)](./firestore_lite_pipelines.expression.md#expressionlessthanorequal) | | Creates an expression that checks if this expression is less than or equal to a constant value. | +| [like(pattern)](./firestore_lite_pipelines.expression.md#expressionlike) | | Creates an expression that performs a case-sensitive string comparison. | +| [like(pattern)](./firestore_lite_pipelines.expression.md#expressionlike) | | Creates an expression that performs a case-sensitive string comparison. | +| [ln()](./firestore_lite_pipelines.expression.md#expressionln) | | Creates an expression that computes the natural logarithm of a numeric value. | +| [log10()](./firestore_lite_pipelines.expression.md#expressionlog10) | | Creates an expression that computes the base-10 logarithm of a numeric value. | +| [logicalMaximum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalmaximum) | | Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. | +| [logicalMinimum(second, others)](./firestore_lite_pipelines.expression.md#expressionlogicalminimum) | | Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. | +| [ltrim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressionltrim) | | Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | +| [mapEntries()](./firestore_lite_pipelines.expression.md#expressionmapentries) | | 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" }, ...]. | +| [mapGet(subfield)](./firestore_lite_pipelines.expression.md#expressionmapget) | | Accesses a value from a map (object) field using the provided key. | +| [mapKeys()](./firestore_lite_pipelines.expression.md#expressionmapkeys) | | Creates an expression that returns the keys of a map. | +| [mapMerge(secondMap, otherMaps)](./firestore_lite_pipelines.expression.md#expressionmapmerge) | | Creates an expression that merges multiple map values. | +| [mapRemove(key)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | Creates an expression that removes a key from the map produced by evaluating this expression. | +| [mapRemove(keyExpr)](./firestore_lite_pipelines.expression.md#expressionmapremove) | | Creates an expression that removes a key from the map produced by evaluating this expression. | +| [mapSet(key, value, moreKeyValues)](./firestore_lite_pipelines.expression.md#expressionmapset) | | Creates an expression that returns a new map with the specified entries added or updated. | +| [mapValues()](./firestore_lite_pipelines.expression.md#expressionmapvalues) | | Creates an expression that returns the values of a map. | +| [maximum()](./firestore_lite_pipelines.expression.md#expressionmaximum) | | Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | +| [minimum()](./firestore_lite_pipelines.expression.md#expressionminimum) | | Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | +| [mod(expression)](./firestore_lite_pipelines.expression.md#expressionmod) | | Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. | +| [mod(value)](./firestore_lite_pipelines.expression.md#expressionmod) | | Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. | +| [multiply(second)](./firestore_lite_pipelines.expression.md#expressionmultiply) | | Creates an expression that multiplies this expression by another expression. | +| [notEqual(expression)](./firestore_lite_pipelines.expression.md#expressionnotequal) | | Creates an expression that checks if this expression is not equal to another expression. | +| [notEqual(value)](./firestore_lite_pipelines.expression.md#expressionnotequal) | | Creates an expression that checks if this expression is not equal to a constant value. | +| [notEqualAny(values)](./firestore_lite_pipelines.expression.md#expressionnotequalany) | | Creates an expression that checks if this expression is not equal to any of the provided values or expressions. | +| [notEqualAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionnotequalany) | | Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. | +| [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | Creates an expression that returns the value of this expression raised to the power of another expression. | +| [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | Creates an expression that returns the value of this expression raised to the power of a constant value. | +| [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | Creates an expression that checks if a string contains a specified regular expression as a substring. | +| [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | Creates an expression that checks if a string contains a specified regular expression as a substring. | +| [regexFind(pattern)](./firestore_lite_pipelines.expression.md#expressionregexfind) | | Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFind(pattern)](./firestore_lite_pipelines.expression.md#expressionregexfind) | | Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(pattern)](./firestore_lite_pipelines.expression.md#expressionregexfindall) | | Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(pattern)](./firestore_lite_pipelines.expression.md#expressionregexfindall) | | Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexMatch(pattern)](./firestore_lite_pipelines.expression.md#expressionregexmatch) | | Creates an expression that checks if a string matches a specified regular expression. | +| [regexMatch(pattern)](./firestore_lite_pipelines.expression.md#expressionregexmatch) | | Creates an expression that checks if a string matches a specified regular expression. | +| [reverse()](./firestore_lite_pipelines.expression.md#expressionreverse) | | Creates an expression that reverses this string expression. | +| [round()](./firestore_lite_pipelines.expression.md#expressionround) | | Creates an expression that rounds a numeric value to the nearest whole number. | +| [round(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressionround) | | Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [round(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressionround) | | Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [rtrim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressionrtrim) | | Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | +| [split(delimiter)](./firestore_lite_pipelines.expression.md#expressionsplit) | | Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | +| [split(delimiter)](./firestore_lite_pipelines.expression.md#expressionsplit) | | Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | +| [sqrt()](./firestore_lite_pipelines.expression.md#expressionsqrt) | | Creates an expression that computes the square root of a numeric value. | +| [startsWith(prefix)](./firestore_lite_pipelines.expression.md#expressionstartswith) | | Creates an expression that checks if a string starts with a given prefix. | +| [startsWith(prefix)](./firestore_lite_pipelines.expression.md#expressionstartswith) | | Creates an expression that checks if a string starts with a given prefix (represented as an expression). | +| [stringConcat(secondString, otherStrings)](./firestore_lite_pipelines.expression.md#expressionstringconcat) | | Creates an expression that concatenates string expressions together. | +| [stringContains(substring)](./firestore_lite_pipelines.expression.md#expressionstringcontains) | | Creates an expression that checks if a string contains a specified substring. | +| [stringContains(expr)](./firestore_lite_pipelines.expression.md#expressionstringcontains) | | Creates an expression that checks if a string contains the string represented by another expression. | +| [stringIndexOf(search)](./firestore_lite_pipelines.expression.md#expressionstringindexof) | | Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | +| [stringRepeat(repetitions)](./firestore_lite_pipelines.expression.md#expressionstringrepeat) | | Creates an expression that repeats a string or byte array a specified number of times. | +| [stringReplaceAll(find, replacement)](./firestore_lite_pipelines.expression.md#expressionstringreplaceall) | | Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | +| [stringReplaceOne(find, replacement)](./firestore_lite_pipelines.expression.md#expressionstringreplaceone) | | Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | +| [stringReverse()](./firestore_lite_pipelines.expression.md#expressionstringreverse) | | Creates an expression that reverses a string. | +| [substring(position, length)](./firestore_lite_pipelines.expression.md#expressionsubstring) | | Creates an expression that returns a substring of the results of this expression. | +| [substring(position, length)](./firestore_lite_pipelines.expression.md#expressionsubstring) | | Creates an expression that returns a substring of the results of this expression. | +| [subtract(subtrahend)](./firestore_lite_pipelines.expression.md#expressionsubtract) | | Creates an expression that subtracts another expression from this expression. | +| [subtract(subtrahend)](./firestore_lite_pipelines.expression.md#expressionsubtract) | | Creates an expression that subtracts a constant value from this expression. | +| [sum()](./firestore_lite_pipelines.expression.md#expressionsum) | | Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. | +| [timestampAdd(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampadd) | | Creates an expression that adds a specified amount of time to this timestamp expression. | +| [timestampAdd(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampadd) | | Creates an expression that adds a specified amount of time to this timestamp expression. | +| [timestampDiff(start, unit)](./firestore_lite_pipelines.expression.md#expressiontimestampdiff) | | Creates an expression that calculates the difference between this timestamp and another timestamp. | +| [timestampDiff(start, unit)](./firestore_lite_pipelines.expression.md#expressiontimestampdiff) | | Creates an expression that calculates the difference between this timestamp and another timestamp. | +| [timestampExtract(part, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestampextract) | | Creates an expression that extracts a specified part from this timestamp expression. | +| [timestampExtract(part, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestampextract) | | Creates an expression that extracts a specified part from this timestamp expression. | +| [timestampSubtract(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampsubtract) | | Creates an expression that subtracts a specified amount of time from this timestamp expression. | +| [timestampSubtract(unit, amount)](./firestore_lite_pipelines.expression.md#expressiontimestampsubtract) | | Creates an expression that subtracts a specified amount of time from this timestamp expression. | +| [timestampToUnixMicros()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixmicros) | | Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixMillis()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixmillis) | | Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixSeconds()](./firestore_lite_pipelines.expression.md#expressiontimestamptounixseconds) | | Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampTruncate(granularity, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestamptruncate) | | Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(granularity, timezone)](./firestore_lite_pipelines.expression.md#expressiontimestamptruncate) | | Creates an expression that truncates a timestamp to a specified granularity. | +| [toLower()](./firestore_lite_pipelines.expression.md#expressiontolower) | | Creates an expression that converts a string to lowercase. | +| [toUpper()](./firestore_lite_pipelines.expression.md#expressiontoupper) | | Creates an expression that converts a string to uppercase. | +| [trim(valueToTrim)](./firestore_lite_pipelines.expression.md#expressiontrim) | | Creates an expression that removes leading and trailing characters from a string or byte array. | +| [trunc()](./firestore_lite_pipelines.expression.md#expressiontrunc) | | Creates an expression that truncates the numeric value to an integer. | +| [trunc(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressiontrunc) | | Creates an expression that truncates a numeric value to the specified number of decimal places. | +| [trunc(decimalPlaces)](./firestore_lite_pipelines.expression.md#expressiontrunc) | | Creates an expression that truncates a numeric value to the specified number of decimal places. | +| [type()](./firestore_lite_pipelines.expression.md#expressiontype) | | Creates an expression that returns the data type of this expression's result, as a string. | +| [unixMicrosToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixmicrostotimestamp) | | 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. | +| [unixMillisToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixmillistotimestamp) | | 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. | +| [unixSecondsToTimestamp()](./firestore_lite_pipelines.expression.md#expressionunixsecondstotimestamp) | | 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. | +| [vectorLength()](./firestore_lite_pipelines.expression.md#expressionvectorlength) | | Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. | ## Expression.expressionType -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -219,9 +213,6 @@ abstract readonly expressionType: ExpressionType; ## Expression.abs() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the absolute value of a numeric value. Signature: @@ -246,9 +237,6 @@ field("price").abs(); ## Expression.add() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds this expression to another expression. Signature: @@ -280,9 +268,6 @@ field("quantity").add(field("reserve")); ## Expression.arrayAgg() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. 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. @@ -309,9 +294,6 @@ field("tags").arrayAgg().as("allTags"); ## Expression.arrayAggDistinct() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. 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. @@ -338,9 +320,6 @@ field("tags").arrayAggDistinct().as("allDistinctTags"); ## Expression.arrayConcat() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates an array expression with one or more other arrays. Signature: @@ -373,9 +352,6 @@ field("items").arrayConcat(field("otherItems")); ## Expression.arrayContains() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array contains a specific element. Signature: @@ -407,9 +383,6 @@ field("sizes").arrayContains(field("selectedSize")); ## Expression.arrayContains() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array contains a specific value. Signature: @@ -441,9 +414,6 @@ field("colors").arrayContains("red"); ## Expression.arrayContainsAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array contains all the specified elements. Signature: @@ -475,9 +445,6 @@ field("tags").arrayContainsAll([field("tag1"), "tag2"]); ## Expression.arrayContainsAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array contains all the specified elements. Signature: @@ -509,9 +476,6 @@ field("tags").arrayContainsAll(array([field("tag1"), "tag2"])); ## Expression.arrayContainsAny() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array contains any of the specified elements. Signature: @@ -543,9 +507,6 @@ field("categories").arrayContainsAny([field("cate1"), field("cate2")]); ## Expression.arrayContainsAny() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array contains any of the specified elements. Signature: @@ -578,9 +539,6 @@ field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); ## Expression.arrayFirst() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the first element of the array. Signature: @@ -605,9 +563,6 @@ field("myArray").arrayFirst(); ## Expression.arrayFirstN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the first `n` elements of the array. Signature: @@ -639,9 +594,6 @@ field("myArray").arrayFirstN(3); ## Expression.arrayFirstN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the first `n` elements of the array. Signature: @@ -673,9 +625,6 @@ field("myArray").arrayFirstN(field("count")); ## Expression.arrayGet() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: @@ -707,9 +656,6 @@ field('tags').arrayGet(1); ## Expression.arrayGet() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: @@ -742,9 +688,6 @@ field('tags').arrayGet(field('favoriteTag')); ## Expression.arrayIndexOf() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the first index of the search value in the array, or -1 if not found. Signature: @@ -776,9 +719,6 @@ field("myArray").arrayIndexOf(3); ## Expression.arrayIndexOf() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the first index of the search value in the array, or -1 if not found. Signature: @@ -810,9 +750,6 @@ field("myArray").arrayIndexOf(field("searchVal")); ## Expression.arrayIndexOfAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all indices of the search value in the array. Signature: @@ -844,9 +781,6 @@ field("myArray").arrayIndexOfAll(3); ## Expression.arrayIndexOfAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all indices of the search value in the array. Signature: @@ -878,9 +812,6 @@ field("myArray").arrayIndexOfAll(field("searchVal")); ## Expression.arrayLast() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the last element of the array. Signature: @@ -905,9 +836,6 @@ field("myArray").arrayLast(); ## Expression.arrayLastIndexOf() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the last index of the search value in the array, or -1 if not found. Signature: @@ -939,9 +867,6 @@ field("myArray").arrayLastIndexOf(3); ## Expression.arrayLastIndexOf() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the last index of the search value in the array, or -1 if not found. Signature: @@ -973,9 +898,6 @@ field("myArray").arrayLastIndexOf(field("searchVal")); ## Expression.arrayLastN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the last `n` elements of the array. Signature: @@ -1007,9 +929,6 @@ field("myArray").arrayLastN(3); ## Expression.arrayLastN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the last `n` elements of the array. Signature: @@ -1041,9 +960,6 @@ field("myArray").arrayLastN(field("count")); ## Expression.arrayLength() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of an array. Signature: @@ -1068,9 +984,6 @@ field("cart").arrayLength(); ## Expression.arrayMaximum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the maximum value in the array. Signature: @@ -1095,9 +1008,6 @@ field("myArray").arrayMaximum(); ## Expression.arrayMaximumN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the largest `n` elements of the array. Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1131,9 +1041,6 @@ field("myArray").arrayMaximumN(3); ## Expression.arrayMaximumN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the largest `n` elements of the array. Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1167,9 +1074,6 @@ field("myArray").arrayMaximumN(field("count")); ## Expression.arrayMinimum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the minimum value in the array. Signature: @@ -1194,9 +1098,6 @@ field("myArray").arrayMinimum(); ## Expression.arrayMinimumN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the smallest `n` elements of the array. Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1230,9 +1131,6 @@ field("myArray").arrayMinimumN(3); ## Expression.arrayMinimumN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the smallest `n` elements of the array. Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1266,9 +1164,6 @@ field("myArray").arrayMinimumN(field("count")); ## Expression.arrayReverse() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses an array. Signature: @@ -1293,9 +1188,6 @@ field("myArray").arrayReverse(); ## Expression.arraySum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the sum of the elements in an array. Signature: @@ -1320,9 +1212,6 @@ field("scores").arraySum(); ## Expression.as() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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. @@ -1357,9 +1246,6 @@ firestore.pipeline().collection("items") ## Expression.asBoolean() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Wraps the expression in a \[BooleanExpression\]. Signature: @@ -1375,9 +1261,6 @@ A \[BooleanExpression\] representing the same expression. ## Expression.ascending() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on this expression. Signature: @@ -1403,9 +1286,6 @@ firestore.pipeline().collection("users") ## Expression.average() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. Signature: @@ -1430,9 +1310,6 @@ field("age").average().as("averageAge"); ## Expression.byteLength() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of this string expression in bytes. Signature: @@ -1457,9 +1334,6 @@ field("myString").byteLength(); ## Expression.ceil() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the ceiling of a numeric value. Signature: @@ -1484,9 +1358,6 @@ field("price").ceil(); ## Expression.charLength() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the character length of a string in UTF-8. Signature: @@ -1511,9 +1382,6 @@ field("name").charLength(); ## Expression.coalesce() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. Signature: @@ -1547,9 +1415,6 @@ field("preferredName").coalesce(field("fullName"), "Anonymous"); ## Expression.collectionId() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the collection ID from a path. Signature: @@ -1574,9 +1439,6 @@ field("__path__").collectionId(); ## Expression.concat() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates expression results together. Signature: @@ -1609,9 +1471,6 @@ field("firstName").concat(constant(" "), field("lastName")); ## Expression.cosineDistance() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the cosine distance between two vectors. Signature: @@ -1643,9 +1502,6 @@ field("userVector").cosineDistance(field("itemVector")); ## Expression.cosineDistance() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Cosine distance between two vectors. Signature: @@ -1677,9 +1533,6 @@ field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); ## Expression.count() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. Signature: @@ -1704,9 +1557,6 @@ field("productId").count().as("totalProducts"); ## Expression.countDistinct() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the number of distinct values of the expression or field. Signature: @@ -1731,9 +1581,6 @@ field("productId").countDistinct().as("distinctProducts"); ## Expression.descending() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on this expression. Signature: @@ -1759,9 +1606,6 @@ firestore.pipeline().collection("users") ## Expression.divide() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that divides this expression by another expression. Signature: @@ -1793,9 +1637,6 @@ field("total").divide(field("count")); ## Expression.divide() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that divides this expression by a constant value. Signature: @@ -1827,9 +1668,6 @@ field("value").divide(10); ## Expression.documentId() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the document ID from a path. Signature: @@ -1854,9 +1692,6 @@ field("__path__").documentId(); ## Expression.dotProduct() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the dot product between two vectors. Signature: @@ -1888,9 +1723,6 @@ field("features").dotProduct([0.5, 0.8, 0.2]); ## Expression.dotProduct() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the dot product between two vectors. Signature: @@ -1922,9 +1754,6 @@ field("features").dotProduct(new VectorValue([0.5, 0.8, 0.2])); ## Expression.endsWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string ends with a given postfix. Signature: @@ -1956,9 +1785,6 @@ field("filename").endsWith(".txt"); ## Expression.endsWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string ends with a given postfix (represented as an expression). Signature: @@ -1990,9 +1816,6 @@ field("url").endsWith(field("extension")); ## Expression.equal() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is equal to another expression. Signature: @@ -2024,9 +1847,6 @@ field("age").equal(21); ## Expression.equal() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is equal to a constant value. Signature: @@ -2058,9 +1878,6 @@ field("city").equal("London"); ## Expression.equalAny() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is equal to any of the provided values or expressions. Signature: @@ -2092,9 +1909,6 @@ field("category").equalAny(["Electronics", field("primaryType")]); ## Expression.equalAny() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is equal to any of the provided values or expressions. Signature: @@ -2126,9 +1940,6 @@ field("category").equalAny(array(["Electronics", field("primaryType")])); ## Expression.euclideanDistance() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Euclidean distance between two vectors. Signature: @@ -2160,9 +1971,6 @@ field("location").euclideanDistance([37.7749, -122.4194]); ## Expression.euclideanDistance() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Euclidean distance between two vectors. Signature: @@ -2194,9 +2002,6 @@ field("location").euclideanDistance(new VectorValue([37.7749, -122.4194])); ## Expression.exists() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field exists in the document. Signature: @@ -2221,9 +2026,6 @@ field("phoneNumber").exists(); ## Expression.exp() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes e to the power of this expression. Signature: @@ -2248,9 +2050,6 @@ field("value").exp(); ## Expression.first() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the first value of an expression across multiple stage inputs. Signature: @@ -2275,9 +2074,6 @@ field("rating").first().as("firstRating"); ## Expression.floor() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the floor of a numeric value. Signature: @@ -2302,9 +2098,6 @@ field("price").floor(); ## Expression.greaterThan() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is greater than another expression. Signature: @@ -2336,9 +2129,6 @@ field("age").greaterThan(field("limit")); ## Expression.greaterThan() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is greater than a constant value. Signature: @@ -2370,9 +2160,6 @@ field("price").greaterThan(100); ## Expression.greaterThanOrEqual() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is greater than or equal to another expression. Signature: @@ -2404,9 +2191,6 @@ field("quantity").greaterThanOrEqual(field('requirement').add(1)); ## Expression.greaterThanOrEqual() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is greater than or equal to a constant value. Signature: @@ -2438,9 +2222,6 @@ field("score").greaterThanOrEqual(80); ## Expression.ifAbsent() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of this expression evaluation. Signature: @@ -2473,9 +2254,6 @@ field("optional_field").ifAbsent("default_value") ## Expression.ifAbsent() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of this expression evaluation. Signature: @@ -2508,9 +2286,6 @@ field("optional_field").ifAbsent(field('default_field')) ## Expression.ifError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the result of the `catchExpr` argument if there is an error, else return the result of this expression. Signature: @@ -2543,9 +2318,6 @@ field("title").arrayGet(0).ifError(field("title")); ## Expression.ifError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. Signature: @@ -2578,9 +2350,6 @@ field("title").arrayGet(0).ifError("Default Title"); ## Expression.ifNull() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if this expression evaluates to null, else return the result of this expression evaluation. This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. @@ -2614,9 +2383,6 @@ field("preferredName").ifNull(field("fullName")) ## Expression.ifNull() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if this expression evaluates to null, else return the result of this expression evaluation. This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. @@ -2650,9 +2416,6 @@ field("displayName").ifNull("Anonymous") ## Expression.isAbsent() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns `true` if the result of this expression is absent. Otherwise, returns `false` even if the value is `null`. Signature: @@ -2677,9 +2440,6 @@ field("value").isAbsent(); ## Expression.isError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a given expression produces an error. Signature: @@ -2704,9 +2464,6 @@ field("title").arrayContains(1).isError(); ## Expression.isType() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the result of this expression is of the given type. Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. @@ -2740,9 +2497,6 @@ field('price').isType('int64'); ## Expression.join() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that joins the elements of an array into a string. Signature: @@ -2774,9 +2528,6 @@ field("tags").join(field("separator")) ## Expression.join() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that joins the elements of an array field into a string. Signature: @@ -2808,9 +2559,6 @@ field("tags").join(", ") ## Expression.last() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the last value of an expression across multiple stage inputs. Signature: @@ -2835,9 +2583,6 @@ field("rating").last().as("lastRating"); ## Expression.length() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of a string, array, map, vector, or bytes. Signature: @@ -2865,9 +2610,6 @@ field("cart").length(); ## Expression.lessThan() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is less than another expression. Signature: @@ -2899,9 +2641,6 @@ field("age").lessThan(field('limit')); ## Expression.lessThan() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is less than a constant value. Signature: @@ -2933,9 +2672,6 @@ field("price").lessThan(50); ## Expression.lessThanOrEqual() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is less than or equal to another expression. Signature: @@ -2967,9 +2703,6 @@ field("quantity").lessThan(constant(20)); ## Expression.lessThanOrEqual() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is less than or equal to a constant value. Signature: @@ -3001,9 +2734,6 @@ field("score").lessThan(70); ## Expression.like() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a case-sensitive string comparison. Signature: @@ -3035,9 +2765,6 @@ field("title").like("%guide%"); ## Expression.like() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a case-sensitive string comparison. Signature: @@ -3069,9 +2796,6 @@ field("title").like("%guide%"); ## Expression.ln() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the natural logarithm of a numeric value. Signature: @@ -3096,9 +2820,6 @@ field("value").ln(); ## Expression.log10() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the base-10 logarithm of a numeric value. Signature: @@ -3123,9 +2844,6 @@ field("value").log10(); ## Expression.logicalMaximum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. Signature: @@ -3158,9 +2876,6 @@ field("timestamp").logicalMaximum(currentTimestamp()); ## Expression.logicalMinimum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. Signature: @@ -3193,9 +2908,6 @@ field("timestamp").logicalMinimum(currentTimestamp()); ## Expression.ltrim() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. Signature: @@ -3230,9 +2942,6 @@ field("userInput").ltrim('"'); ## Expression.mapEntries() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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" }, ...]`. Signature: @@ -3257,9 +2966,6 @@ field("address").mapEntries(); ## Expression.mapGet() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Accesses a value from a map (object) field using the provided key. Signature: @@ -3291,9 +2997,6 @@ field("address").mapGet("city"); ## Expression.mapKeys() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the keys of a map. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -3320,9 +3023,6 @@ field("address").mapKeys(); ## Expression.mapMerge() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that merges multiple map values. Signature: @@ -3356,9 +3056,6 @@ field('settings').mapMerge({ enabled: true }, conditional(field('isAdmin'), { ad ## Expression.mapRemove() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes a key from the map produced by evaluating this expression. Signature: @@ -3390,9 +3087,6 @@ map({foo: 'bar', baz: true}).mapRemove('baz'); ## Expression.mapRemove() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes a key from the map produced by evaluating this expression. Signature: @@ -3425,9 +3119,6 @@ map({foo: 'bar', baz: true}).mapRemove(constant('baz')); ## Expression.mapSet() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a new map with the specified entries added or updated. 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`. @@ -3463,9 +3154,6 @@ field("address").mapSet("city", "San Francisco"); ## Expression.mapValues() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the values of a map. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -3492,9 +3180,6 @@ field("address").mapValues(); ## Expression.maximum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the maximum value of a field across multiple stage inputs. Signature: @@ -3519,9 +3204,6 @@ field("score").maximum().as("highestScore"); ## Expression.minimum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the minimum value of a field across multiple stage inputs. Signature: @@ -3546,9 +3228,6 @@ field("price").minimum().as("lowestPrice"); ## Expression.mod() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. Signature: @@ -3580,9 +3259,6 @@ field("value").mod(field("divisor")); ## Expression.mod() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. Signature: @@ -3614,9 +3290,6 @@ field("value").mod(10); ## Expression.multiply() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that multiplies this expression by another expression. Signature: @@ -3648,9 +3321,6 @@ field("quantity").multiply(field("price")); ## Expression.notEqual() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is not equal to another expression. Signature: @@ -3682,9 +3352,6 @@ field("status").notEqual("completed"); ## Expression.notEqual() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is not equal to a constant value. Signature: @@ -3716,9 +3383,6 @@ field("country").notEqual("USA"); ## Expression.notEqualAny() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is not equal to any of the provided values or expressions. Signature: @@ -3750,9 +3414,6 @@ field("status").notEqualAny(["pending", field("rejectedStatus")]); ## Expression.notEqualAny() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. Signature: @@ -3784,9 +3445,6 @@ field("status").notEqualAny(field('rejectedStatuses')); ## Expression.pow() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the value of this expression raised to the power of another expression. Signature: @@ -3818,9 +3476,6 @@ field("base").pow(field("exponent")); ## Expression.pow() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the value of this expression raised to the power of a constant value. Signature: @@ -3852,9 +3507,6 @@ field("base").pow(2); ## Expression.regexContains() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string contains a specified regular expression as a substring. Signature: @@ -3886,9 +3538,6 @@ field("description").regexContains("(?i)example"); ## Expression.regexContains() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string contains a specified regular expression as a substring. Signature: @@ -3920,9 +3569,6 @@ field("description").regexContains(field("regex")); ## Expression.regexFind() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first substring of a string expression that matches a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -3956,9 +3602,6 @@ field("email").regexFind("@.+") ## Expression.regexFind() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first substring of a string expression that matches a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -3992,9 +3635,6 @@ field("email").regexFind(field("domain")) ## Expression.regexFindAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -4028,9 +3668,6 @@ field("content").regexFindAll("#[A-Za-z0-9_]+") ## Expression.regexFindAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -4064,9 +3701,6 @@ field("content").regexFindAll(field("names")) ## Expression.regexMatch() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string matches a specified regular expression. Signature: @@ -4098,9 +3732,6 @@ field("email").regexMatch("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); ## Expression.regexMatch() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string matches a specified regular expression. Signature: @@ -4132,9 +3763,6 @@ field("email").regexMatch(field("regex")); ## Expression.reverse() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses this string expression. Signature: @@ -4159,9 +3787,6 @@ field("myString").reverse(); ## Expression.round() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the nearest whole number. Signature: @@ -4186,9 +3811,6 @@ field("price").round(); ## Expression.round() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the specified number of decimal places. Signature: @@ -4220,9 +3842,6 @@ field("price").round(2); ## Expression.round() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the specified number of decimal places. Signature: @@ -4254,9 +3873,6 @@ field("price").round(constant(2)); ## Expression.rtrim() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. Signature: @@ -4291,9 +3907,6 @@ field("userInput").rtrim('"'); ## Expression.split() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. Signature: @@ -4325,9 +3938,6 @@ field('scoresCsv').split(',') ## Expression.split() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. Signature: @@ -4359,9 +3969,6 @@ field('scores').split(conditional(field('format').equal('csv'), constant(','), c ## Expression.sqrt() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the square root of a numeric value. Signature: @@ -4386,9 +3993,6 @@ field("value").sqrt(); ## Expression.startsWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string starts with a given prefix. Signature: @@ -4420,9 +4024,6 @@ field("name").startsWith("Mr."); ## Expression.startsWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string starts with a given prefix (represented as an expression). Signature: @@ -4454,9 +4055,6 @@ field("fullName").startsWith(field("firstName")); ## Expression.stringConcat() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates string expressions together. Signature: @@ -4489,9 +4087,6 @@ field("firstName").stringConcat(constant(" "), field("lastName")); ## Expression.stringContains() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string contains a specified substring. Signature: @@ -4523,9 +4118,6 @@ field("description").stringContains("example"); ## Expression.stringContains() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string contains the string represented by another expression. Signature: @@ -4557,9 +4149,6 @@ field("description").stringContains(field("keyword")); ## Expression.stringIndexOf() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that finds the index of the first occurrence of a substring or byte sequence. Signature: @@ -4591,9 +4180,6 @@ field("text").stringIndexOf("foo"); ## Expression.stringRepeat() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that repeats a string or byte array a specified number of times. Signature: @@ -4625,9 +4211,6 @@ field("label").stringRepeat(3); ## Expression.stringReplaceAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. Signature: @@ -4660,9 +4243,6 @@ field("text").stringReplaceAll("foo", "bar"); ## Expression.stringReplaceOne() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. Signature: @@ -4695,9 +4275,6 @@ field("text").stringReplaceOne("foo", "bar"); ## Expression.stringReverse() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses a string. Signature: @@ -4722,9 +4299,6 @@ field("myString").stringReverse(); ## Expression.substring() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a substring of the results of this expression. Signature: @@ -4746,9 +4320,6 @@ substring(position: number, length?: number): FunctionExpression; ## Expression.substring() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a substring of the results of this expression. Signature: @@ -4770,9 +4341,6 @@ substring(position: Expression, length?: Expression): FunctionExpression; ## Expression.subtract() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts another expression from this expression. Signature: @@ -4804,9 +4372,6 @@ field("price").subtract(field("discount")); ## Expression.subtract() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a constant value from this expression. Signature: @@ -4838,9 +4403,6 @@ field("total").subtract(20); ## Expression.sum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. Signature: @@ -4865,9 +4427,6 @@ field("orderAmount").sum().as("totalRevenue"); ## Expression.timestampAdd() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds a specified amount of time to this timestamp expression. Signature: @@ -4900,9 +4459,6 @@ field("timestamp").timestampAdd(field("unit"), field("amount")); ## Expression.timestampAdd() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds a specified amount of time to this timestamp expression. Signature: @@ -4935,9 +4491,6 @@ field("timestamp").timestampAdd("day", 1); ## Expression.timestampDiff() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the difference between this timestamp and another timestamp. Signature: @@ -4970,9 +4523,6 @@ field("endTime").timestampDiff(field("startTime"), field("unit")); ## Expression.timestampDiff() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the difference between this timestamp and another timestamp. Signature: @@ -5005,9 +4555,6 @@ field("endTime").timestampDiff("startTime", "day"); ## Expression.timestampExtract() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that extracts a specified part from this timestamp expression. Signature: @@ -5040,9 +4587,6 @@ field('createdAt').timestampExtract('year') ## Expression.timestampExtract() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that extracts a specified part from this timestamp expression. Signature: @@ -5075,9 +4619,6 @@ field('createdAt').timestampExtract(field('extractionPart')) ## Expression.timestampSubtract() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a specified amount of time from this timestamp expression. Signature: @@ -5110,9 +4651,6 @@ field("timestamp").timestampSubtract(field("unit"), field("amount")); ## Expression.timestampSubtract() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a specified amount of time from this timestamp expression. Signature: @@ -5145,9 +4683,6 @@ field("timestamp").timestampSubtract("day", 1); ## Expression.timestampToUnixMicros() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -5172,9 +4707,6 @@ field("timestamp").timestampToUnixMicros(); ## Expression.timestampToUnixMillis() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -5199,9 +4731,6 @@ field("timestamp").timestampToUnixMillis(); ## Expression.timestampToUnixSeconds() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -5226,9 +4755,6 @@ field("timestamp").timestampToUnixSeconds(); ## Expression.timestampTruncate() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a timestamp to a specified granularity. Signature: @@ -5261,9 +4787,6 @@ field('createdAt').timestampTruncate('day') ## Expression.timestampTruncate() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a timestamp to a specified granularity. Signature: @@ -5296,9 +4819,6 @@ field('createdAt').timestampTruncate(field('granularity')) ## Expression.toLower() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a string to lowercase. Signature: @@ -5323,9 +4843,6 @@ field("name").toLower(); ## Expression.toUpper() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a string to uppercase. Signature: @@ -5350,9 +4867,6 @@ field("title").toUpper(); ## Expression.trim() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes leading and trailing characters from a string or byte array. Signature: @@ -5387,9 +4901,6 @@ field("userInput").trim('"'); ## Expression.trunc() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates the numeric value to an integer. Signature: @@ -5414,9 +4925,6 @@ field("rating").trunc(); ## Expression.trunc() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a numeric value to the specified number of decimal places. Signature: @@ -5448,9 +4956,6 @@ field("rating").trunc(2); ## Expression.trunc() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a numeric value to the specified number of decimal places. Signature: @@ -5482,9 +4987,6 @@ field("rating").trunc(constant(2)); ## Expression.type() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the data type of this expression's result, as a string. This is evaluated on the backend. This means: 1. Generic typed elements (like `array`) 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"`. @@ -5511,9 +5013,6 @@ field('title').type() ## Expression.unixMicrosToTimestamp() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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. Signature: @@ -5538,9 +5037,6 @@ field("microseconds").unixMicrosToTimestamp(); ## Expression.unixMillisToTimestamp() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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. Signature: @@ -5565,9 +5061,6 @@ field("milliseconds").unixMillisToTimestamp(); ## Expression.unixSecondsToTimestamp() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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. Signature: @@ -5592,9 +5085,6 @@ field("seconds").unixSecondsToTimestamp(); ## Expression.vectorLength() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. Signature: diff --git a/docs-devsite/firestore_lite_pipelines.field.md b/docs-devsite/firestore_lite_pipelines.field.md index f3b7ad7288..22e83878f1 100644 --- a/docs-devsite/firestore_lite_pipelines.field.md +++ b/docs-devsite/firestore_lite_pipelines.field.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # Field class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents a reference to a field in a Firestore document, or outputs of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) stage.

    Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines. @@ -32,17 +29,14 @@ export declare class Field extends Expression implements Selectable | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [alias](./firestore_lite_pipelines.field.md#fieldalias) | | string | (Public Preview) | -| [expr](./firestore_lite_pipelines.field.md#fieldexpr) | | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | (Public Preview) | -| [expressionType](./firestore_lite_pipelines.field.md#fieldexpressiontype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) | -| [fieldName](./firestore_lite_pipelines.field.md#fieldfieldname) | | string | (Public Preview) | -| [selectable](./firestore_lite_pipelines.field.md#fieldselectable) | | true | (Public Preview) | +| [alias](./firestore_lite_pipelines.field.md#fieldalias) | | string | | +| [expr](./firestore_lite_pipelines.field.md#fieldexpr) | | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | +| [expressionType](./firestore_lite_pipelines.field.md#fieldexpressiontype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | | +| [fieldName](./firestore_lite_pipelines.field.md#fieldfieldname) | | string | | +| [selectable](./firestore_lite_pipelines.field.md#fieldselectable) | | true | | ## Field.alias -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -51,9 +45,6 @@ get alias(): string; ## Field.expr -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -62,9 +53,6 @@ get expr(): Expression; ## Field.expressionType -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -73,9 +61,6 @@ readonly expressionType: ExpressionType; ## Field.fieldName -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -84,9 +69,6 @@ get fieldName(): string; ## Field.selectable -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/firestore_lite_pipelines.functionexpression.md b/docs-devsite/firestore_lite_pipelines.functionexpression.md index 22f7670d2e..a7897b6d4e 100644 --- a/docs-devsite/firestore_lite_pipelines.functionexpression.md +++ b/docs-devsite/firestore_lite_pipelines.functionexpression.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # FunctionExpression class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - This class defines the base class for Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) functions, which can be evaluated within pipeline execution. Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_pipelines.md#and_e0c48bd), [equal()](./firestore_pipelines.md#equal_b3c3382), or the methods on [Expression](./firestore_pipelines.expression.md#expression_class) ([Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), etc.) to construct new Function instances. @@ -28,20 +25,17 @@ export declare class FunctionExpression extends Expression | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(name, params)](./firestore_lite_pipelines.functionexpression.md#functionexpressionconstructor) | | (Public Preview) Constructs a new instance of the FunctionExpression class | -| [(constructor)(name, params, \_methodName)](./firestore_lite_pipelines.functionexpression.md#functionexpressionconstructor) | | (Public Preview) Constructs a new instance of the FunctionExpression class | +| [(constructor)(name, params)](./firestore_lite_pipelines.functionexpression.md#functionexpressionconstructor) | | Constructs a new instance of the FunctionExpression class | +| [(constructor)(name, params, \_methodName)](./firestore_lite_pipelines.functionexpression.md#functionexpressionconstructor) | | Constructs a new instance of the FunctionExpression class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [expressionType](./firestore_lite_pipelines.functionexpression.md#functionexpressionexpressiontype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) | +| [expressionType](./firestore_lite_pipelines.functionexpression.md#functionexpressionexpressiontype) | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | | ## FunctionExpression.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `FunctionExpression` class Signature: @@ -59,9 +53,6 @@ constructor(name: string, params: Expression[]); ## FunctionExpression.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `FunctionExpression` class Signature: @@ -80,9 +71,6 @@ constructor(name: string, params: Expression[], _methodName: string | undefined) ## FunctionExpression.expressionType -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index f9bad335e2..2df2241972 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -16,414 +16,414 @@ https://github.com/firebase/firebase-js-sdk | Function | Description | | --- | --- | | function() | -| [countAll()](./firestore_lite_pipelines.md#countall) | (Public Preview) Creates an aggregation that counts the total number of stage inputs. | -| [currentTimestamp()](./firestore_lite_pipelines.md#currenttimestamp) | (Public Preview) Creates an expression that evaluates to the current server timestamp. | -| [rand()](./firestore_lite_pipelines.md#rand) | (Public Preview) Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. | +| [countAll()](./firestore_lite_pipelines.md#countall) | Creates an aggregation that counts the total number of stage inputs. | +| [currentTimestamp()](./firestore_lite_pipelines.md#currenttimestamp) | Creates an expression that evaluates to the current server timestamp. | +| [rand()](./firestore_lite_pipelines.md#rand) | Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. | | function(array, ...) | -| [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_a00ea48) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. | -| [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_7328608) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. | -| [arrayContainsAll(array, values)](./firestore_lite_pipelines.md#arraycontainsall_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. | -| [arrayContainsAll(array, arrayExpression)](./firestore_lite_pipelines.md#arraycontainsall_7b535db) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. | -| [arrayContainsAny(array, values)](./firestore_lite_pipelines.md#arraycontainsany_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. | -| [arrayContainsAny(array, values)](./firestore_lite_pipelines.md#arraycontainsany_c381a96) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. | -| [arrayLength(array)](./firestore_lite_pipelines.md#arraylength_195e339) | (Public Preview) Creates an expression that calculates the length of an array expression. | +| [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_a00ea48) | Creates an expression that checks if an array expression contains a specific element. | +| [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_7328608) | Creates an expression that checks if an array expression contains a specific element. | +| [arrayContainsAll(array, values)](./firestore_lite_pipelines.md#arraycontainsall_c658ad5) | Creates an expression that checks if an array expression contains all the specified elements. | +| [arrayContainsAll(array, arrayExpression)](./firestore_lite_pipelines.md#arraycontainsall_7b535db) | Creates an expression that checks if an array expression contains all the specified elements. | +| [arrayContainsAny(array, values)](./firestore_lite_pipelines.md#arraycontainsany_c658ad5) | Creates an expression that checks if an array expression contains any of the specified elements. | +| [arrayContainsAny(array, values)](./firestore_lite_pipelines.md#arraycontainsany_c381a96) | Creates an expression that checks if an array expression contains any of the specified elements. | +| [arrayLength(array)](./firestore_lite_pipelines.md#arraylength_195e339) | Creates an expression that calculates the length of an array expression. | | function(arrayExpression, ...) | -| [arrayFirst(arrayExpression)](./firestore_lite_pipelines.md#arrayfirst_f574e12) | (Public Preview) Creates an expression that returns the first element of an array. | -| [arrayFirstN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayfirstn_bff7f91) | (Public Preview) Creates an expression that returns the first n elements of an array. | -| [arrayFirstN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayfirstn_19b4ef8) | (Public Preview) Creates an expression that returns the first n elements of an array. | -| [arrayGet(arrayExpression, offset)](./firestore_lite_pipelines.md#arrayget_f2e27cc) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | -| [arrayGet(arrayExpression, offsetExpr)](./firestore_lite_pipelines.md#arrayget_484550d) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | -| [arrayIndexOf(arrayExpression, search)](./firestore_lite_pipelines.md#arrayindexof_694a0b4) | (Public Preview) Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. | -| [arrayIndexOfAll(arrayExpression, search)](./firestore_lite_pipelines.md#arrayindexofall_694a0b4) | (Public Preview) Creates an expression that returns all indices of the search value in an array. | -| [arrayLast(arrayExpression)](./firestore_lite_pipelines.md#arraylast_f574e12) | (Public Preview) Creates an expression that returns the last element of an array. | -| [arrayLastIndexOf(arrayExpression, search)](./firestore_lite_pipelines.md#arraylastindexof_694a0b4) | (Public Preview) Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. | -| [arrayLastN(arrayExpression, n)](./firestore_lite_pipelines.md#arraylastn_bff7f91) | (Public Preview) Creates an expression that returns the last n elements of an array. | -| [arrayLastN(arrayExpression, n)](./firestore_lite_pipelines.md#arraylastn_19b4ef8) | (Public Preview) Creates an expression that returns the last n elements of an array. | -| [arrayMaximum(arrayExpression)](./firestore_lite_pipelines.md#arraymaximum_f574e12) | (Public Preview) Creates an expression that returns the maximum value in an array. | -| [arrayMaximumN(arrayExpression, n)](./firestore_lite_pipelines.md#arraymaximumn_bff7f91) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMaximumN(arrayExpression, n)](./firestore_lite_pipelines.md#arraymaximumn_19b4ef8) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMinimum(arrayExpression)](./firestore_lite_pipelines.md#arrayminimum_f574e12) | (Public Preview) Creates an expression that returns the minimum value in an array. | -| [arrayMinimumN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayminimumn_bff7f91) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMinimumN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayminimumn_19b4ef8) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [join(arrayExpression, delimiterExpression)](./firestore_lite_pipelines.md#join_313e6aa) | (Public Preview) Creates an expression that joins the elements of an array into a string. | -| [join(arrayExpression, delimiter)](./firestore_lite_pipelines.md#join_d088d29) | (Public Preview) Creates an expression that joins the elements of an array into a string. | +| [arrayFirst(arrayExpression)](./firestore_lite_pipelines.md#arrayfirst_f574e12) | Creates an expression that returns the first element of an array. | +| [arrayFirstN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayfirstn_bff7f91) | Creates an expression that returns the first n elements of an array. | +| [arrayFirstN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayfirstn_19b4ef8) | Creates an expression that returns the first n elements of an array. | +| [arrayGet(arrayExpression, offset)](./firestore_lite_pipelines.md#arrayget_f2e27cc) | Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(arrayExpression, offsetExpr)](./firestore_lite_pipelines.md#arrayget_484550d) | Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayIndexOf(arrayExpression, search)](./firestore_lite_pipelines.md#arrayindexof_694a0b4) | Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. | +| [arrayIndexOfAll(arrayExpression, search)](./firestore_lite_pipelines.md#arrayindexofall_694a0b4) | Creates an expression that returns all indices of the search value in an array. | +| [arrayLast(arrayExpression)](./firestore_lite_pipelines.md#arraylast_f574e12) | Creates an expression that returns the last element of an array. | +| [arrayLastIndexOf(arrayExpression, search)](./firestore_lite_pipelines.md#arraylastindexof_694a0b4) | Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. | +| [arrayLastN(arrayExpression, n)](./firestore_lite_pipelines.md#arraylastn_bff7f91) | Creates an expression that returns the last n elements of an array. | +| [arrayLastN(arrayExpression, n)](./firestore_lite_pipelines.md#arraylastn_19b4ef8) | Creates an expression that returns the last n elements of an array. | +| [arrayMaximum(arrayExpression)](./firestore_lite_pipelines.md#arraymaximum_f574e12) | Creates an expression that returns the maximum value in an array. | +| [arrayMaximumN(arrayExpression, n)](./firestore_lite_pipelines.md#arraymaximumn_bff7f91) | Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMaximumN(arrayExpression, n)](./firestore_lite_pipelines.md#arraymaximumn_19b4ef8) | Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimum(arrayExpression)](./firestore_lite_pipelines.md#arrayminimum_f574e12) | Creates an expression that returns the minimum value in an array. | +| [arrayMinimumN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayminimumn_bff7f91) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimumN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayminimumn_19b4ef8) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [join(arrayExpression, delimiterExpression)](./firestore_lite_pipelines.md#join_313e6aa) | Creates an expression that joins the elements of an array into a string. | +| [join(arrayExpression, delimiter)](./firestore_lite_pipelines.md#join_d088d29) | Creates an expression that joins the elements of an array into a string. | | function(arrayField, ...) | -| [arrayGet(arrayField, offset)](./firestore_lite_pipelines.md#arrayget_3f58471) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | -| [arrayGet(arrayField, offsetExpr)](./firestore_lite_pipelines.md#arrayget_1904c9a) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(arrayField, offset)](./firestore_lite_pipelines.md#arrayget_3f58471) | Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(arrayField, offsetExpr)](./firestore_lite_pipelines.md#arrayget_1904c9a) | Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | | function(arrayFieldName, ...) | -| [join(arrayFieldName, delimiter)](./firestore_lite_pipelines.md#join_478ef36) | (Public Preview) Creates an expression that joins the elements of an array into a string. | -| [join(arrayFieldName, delimiterExpression)](./firestore_lite_pipelines.md#join_829294c) | (Public Preview) Creates an expression that joins the elements of an array into a string. | +| [join(arrayFieldName, delimiter)](./firestore_lite_pipelines.md#join_478ef36) | Creates an expression that joins the elements of an array into a string. | +| [join(arrayFieldName, delimiterExpression)](./firestore_lite_pipelines.md#join_829294c) | Creates an expression that joins the elements of an array into a string. | | function(base, ...) | -| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_e4a9e64) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent expression. | -| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_93eae7f) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent. | -| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_a237721) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent expression. | -| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_f4d7908) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent. | +| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_e4a9e64) | Creates an expression that returns the value of the base expression raised to the power of the exponent expression. | +| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_93eae7f) | Creates an expression that returns the value of the base expression raised to the power of the exponent. | +| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_a237721) | Creates an expression that returns the value of the base field raised to the power of the exponent expression. | +| [pow(base, exponent)](./firestore_lite_pipelines.md#pow_f4d7908) | Creates an expression that returns the value of the base field raised to the power of the exponent. | | function(booleanExpr, ...) | -| [countIf(booleanExpr)](./firestore_lite_pipelines.md#countif_c5b8fb1) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. | -| [not(booleanExpr)](./firestore_lite_pipelines.md#not_c5b8fb1) | (Public Preview) Creates an expression that negates a filter condition. | +| [countIf(booleanExpr)](./firestore_lite_pipelines.md#countif_c5b8fb1) | Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. | +| [not(booleanExpr)](./firestore_lite_pipelines.md#not_c5b8fb1) | Creates an expression that negates a filter condition. | | function(condition, ...) | -| [conditional(condition, thenExpr, elseExpr)](./firestore_lite_pipelines.md#conditional_07a206d) | (Public Preview) Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. | -| [switchOn(condition, result, others)](./firestore_lite_pipelines.md#switchon_02b8caf) | (Public Preview) Creates an expression that evaluates to the result corresponding to the first true condition. | +| [conditional(condition, thenExpr, elseExpr)](./firestore_lite_pipelines.md#conditional_07a206d) | Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. | +| [switchOn(condition, result, others)](./firestore_lite_pipelines.md#switchon_02b8caf) | Creates an expression that evaluates to the result corresponding to the first true condition. | | function(documentPath, ...) | -| [documentId(documentPath)](./firestore_lite_pipelines.md#documentid_cef293c) | (Public Preview) Creates an expression that returns the document ID from a path. | +| [documentId(documentPath)](./firestore_lite_pipelines.md#documentid_cef293c) | Creates an expression that returns the document ID from a path. | | function(documentPathExpr, ...) | -| [documentId(documentPathExpr)](./firestore_lite_pipelines.md#documentid_9a69021) | (Public Preview) Creates an expression that returns the document ID from a path. | +| [documentId(documentPathExpr)](./firestore_lite_pipelines.md#documentid_9a69021) | Creates an expression that returns the document ID from a path. | | function(element, ...) | -| [notEqualAny(element, values)](./firestore_lite_pipelines.md#notequalany_c2c5bcb) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | -| [notEqualAny(element, arrayExpression)](./firestore_lite_pipelines.md#notequalany_16b2851) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | +| [notEqualAny(element, values)](./firestore_lite_pipelines.md#notequalany_c2c5bcb) | Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | +| [notEqualAny(element, arrayExpression)](./firestore_lite_pipelines.md#notequalany_16b2851) | Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | | function(elements, ...) | -| [array(elements)](./firestore_lite_pipelines.md#array_7d853aa) | (Public Preview) Creates an expression that creates a Firestore array value from an input array. | -| [map(elements)](./firestore_lite_pipelines.md#map_ce5dee1) | (Public Preview) Creates an expression that creates a Firestore map value from an input object. | +| [array(elements)](./firestore_lite_pipelines.md#array_7d853aa) | Creates an expression that creates a Firestore array value from an input array. | +| [map(elements)](./firestore_lite_pipelines.md#map_ce5dee1) | Creates an expression that creates a Firestore map value from an input object. | | function(endExpression, ...) | -| [timestampDiff(endExpression, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_4370feb) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | -| [timestampDiff(endExpression, startExpression, unit)](./firestore_lite_pipelines.md#timestampdiff_bc0830f) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endExpression, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_4370feb) | Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endExpression, startExpression, unit)](./firestore_lite_pipelines.md#timestampdiff_bc0830f) | Creates an expression that calculates the difference between two timestamps. | | function(endFieldName, ...) | -| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_f60102c) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | -| [timestampDiff(endFieldName, startExpression, unit)](./firestore_lite_pipelines.md#timestampdiff_6e54d92) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_f60102c) | Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endFieldName, startExpression, unit)](./firestore_lite_pipelines.md#timestampdiff_6e54d92) | Creates an expression that calculates the difference between two timestamps. | | function(expr, ...) | -| [abs(expr)](./firestore_lite_pipelines.md#abs_005f3d4) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | -| [ascending(expr)](./firestore_lite_pipelines.md#ascending_005f3d4) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. | -| [byteLength(expr)](./firestore_lite_pipelines.md#bytelength_005f3d4) | (Public Preview) Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. | -| [countDistinct(expr)](./firestore_lite_pipelines.md#countdistinct_3c28b08) | (Public Preview) Creates an aggregation that counts the number of distinct values of a field. | -| [descending(expr)](./firestore_lite_pipelines.md#descending_005f3d4) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. | -| [floor(expr)](./firestore_lite_pipelines.md#floor_005f3d4) | (Public Preview) Creates an expression that computes the floor of a numeric value. | -| [timestampToUnixMicros(expr)](./firestore_lite_pipelines.md#timestamptounixmicros_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampToUnixMillis(expr)](./firestore_lite_pipelines.md#timestamptounixmillis_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampToUnixSeconds(expr)](./firestore_lite_pipelines.md#timestamptounixseconds_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [unixMicrosToTimestamp(expr)](./firestore_lite_pipelines.md#unixmicrostotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | -| [unixMillisToTimestamp(expr)](./firestore_lite_pipelines.md#unixmillistotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | -| [unixSecondsToTimestamp(expr)](./firestore_lite_pipelines.md#unixsecondstotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [abs(expr)](./firestore_lite_pipelines.md#abs_005f3d4) | Creates an expression that computes the absolute value of a numeric value. | +| [ascending(expr)](./firestore_lite_pipelines.md#ascending_005f3d4) | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. | +| [byteLength(expr)](./firestore_lite_pipelines.md#bytelength_005f3d4) | Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. | +| [countDistinct(expr)](./firestore_lite_pipelines.md#countdistinct_3c28b08) | Creates an aggregation that counts the number of distinct values of a field. | +| [descending(expr)](./firestore_lite_pipelines.md#descending_005f3d4) | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. | +| [floor(expr)](./firestore_lite_pipelines.md#floor_005f3d4) | Creates an expression that computes the floor of a numeric value. | +| [timestampToUnixMicros(expr)](./firestore_lite_pipelines.md#timestamptounixmicros_005f3d4) | Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixMillis(expr)](./firestore_lite_pipelines.md#timestamptounixmillis_005f3d4) | Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixSeconds(expr)](./firestore_lite_pipelines.md#timestamptounixseconds_005f3d4) | Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [unixMicrosToTimestamp(expr)](./firestore_lite_pipelines.md#unixmicrostotimestamp_005f3d4) | Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixMillisToTimestamp(expr)](./firestore_lite_pipelines.md#unixmillistotimestamp_005f3d4) | Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixSecondsToTimestamp(expr)](./firestore_lite_pipelines.md#unixsecondstotimestamp_005f3d4) | Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | | function(expression, ...) | -| [arrayAgg(expression)](./firestore_lite_pipelines.md#arrayagg_1138a27) | (Public Preview) Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. | -| [arrayAggDistinct(expression)](./firestore_lite_pipelines.md#arrayaggdistinct_1138a27) | (Public Preview) Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. | -| [arraySum(expression)](./firestore_lite_pipelines.md#arraysum_1138a27) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | -| [average(expression)](./firestore_lite_pipelines.md#average_1138a27) | (Public Preview) Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. | -| [ceil(expression)](./firestore_lite_pipelines.md#ceil_1138a27) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | -| [coalesce(expression, replacement, others)](./firestore_lite_pipelines.md#coalesce_00859cb) | (Public Preview) Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | -| [collectionId(expression)](./firestore_lite_pipelines.md#collectionid_1138a27) | (Public Preview) Creates an expression that returns the collection ID from a path. | -| [count(expression)](./firestore_lite_pipelines.md#count_1138a27) | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. | -| [divide(expression, value)](./firestore_lite_pipelines.md#divide_01df3cf) | (Public Preview) Creates an expression that divides an expression by a constant value. | -| [equal(expression, value)](./firestore_lite_pipelines.md#equal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is equal to a constant value. | -| [equalAny(expression, values)](./firestore_lite_pipelines.md#equalany_7e759b5) | (Public Preview) Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. | -| [equalAny(expression, arrayExpression)](./firestore_lite_pipelines.md#equalany_214ce68) | (Public Preview) Creates an expression that checks if an expression is equal to any of the provided values. | -| [exp(expression)](./firestore_lite_pipelines.md#exp_1138a27) | (Public Preview) Creates an expression that computes e to the power of the expression's result. | -| [first(expression)](./firestore_lite_pipelines.md#first_1138a27) | (Public Preview) Creates an aggregation that finds the first value of an expression across multiple stage inputs. | -| [greaterThan(expression, value)](./firestore_lite_pipelines.md#greaterthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than a constant value. | -| [greaterThanOrEqual(expression, value)](./firestore_lite_pipelines.md#greaterthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than or equal to a constant value. | -| [isType(expression, type)](./firestore_lite_pipelines.md#istype_27398ce) | (Public Preview) Creates an expression that checks if the result of an expression is of the given type. | -| [last(expression)](./firestore_lite_pipelines.md#last_1138a27) | (Public Preview) Creates an aggregation that finds the last value of an expression across multiple stage inputs. | -| [length\_2(expression)](./firestore_lite_pipelines.md#length_2_1138a27) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | -| [lessThan(expression, value)](./firestore_lite_pipelines.md#lessthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than a constant value. | -| [lessThanOrEqual(expression, value)](./firestore_lite_pipelines.md#lessthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than or equal to a constant value. | -| [ln(expression)](./firestore_lite_pipelines.md#ln_1138a27) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. | -| [log(expression, base)](./firestore_lite_pipelines.md#log_ac183e2) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. | -| [log(expression, base)](./firestore_lite_pipelines.md#log_1894737) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. | -| [log10(expression)](./firestore_lite_pipelines.md#log10_1138a27) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | -| [ltrim(expression, valueToTrim)](./firestore_lite_pipelines.md#ltrim_775e2f2) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | -| [maximum(expression)](./firestore_lite_pipelines.md#maximum_1138a27) | (Public Preview) Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. | -| [minimum(expression)](./firestore_lite_pipelines.md#minimum_1138a27) | (Public Preview) Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. | -| [mod(expression, value)](./firestore_lite_pipelines.md#mod_01df3cf) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. | -| [notEqual(expression, value)](./firestore_lite_pipelines.md#notequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is not equal to a constant value. | -| [round(expression)](./firestore_lite_pipelines.md#round_1138a27) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | -| [round(expression, decimalPlaces)](./firestore_lite_pipelines.md#round_a3a92d0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | -| [rtrim(expression, valueToTrim)](./firestore_lite_pipelines.md#rtrim_775e2f2) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | -| [split(expression, delimiter)](./firestore_lite_pipelines.md#split_5b5612b) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | -| [split(expression, delimiter)](./firestore_lite_pipelines.md#split_5a171ed) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | -| [sqrt(expression)](./firestore_lite_pipelines.md#sqrt_1138a27) | (Public Preview) Creates an expression that computes the square root of a numeric value. | -| [stringIndexOf(expression, search)](./firestore_lite_pipelines.md#stringindexof_6dfca5f) | (Public Preview) Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | -| [stringRepeat(expression, repetitions)](./firestore_lite_pipelines.md#stringrepeat_a55ba16) | (Public Preview) Creates an expression that repeats a string or byte array a specified number of times. | -| [stringReplaceAll(expression, find, replacement)](./firestore_lite_pipelines.md#stringreplaceall_197ecbe) | (Public Preview) Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | -| [stringReplaceOne(expression, find, replacement)](./firestore_lite_pipelines.md#stringreplaceone_197ecbe) | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | -| [subtract(expression, value)](./firestore_lite_pipelines.md#subtract_01df3cf) | (Public Preview) Creates an expression that subtracts a constant value from an expression. | -| [sum(expression)](./firestore_lite_pipelines.md#sum_1138a27) | (Public Preview) Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. | -| [trunc(expression)](./firestore_lite_pipelines.md#trunc_1138a27) | (Public Preview) Creates an expression that truncates the numeric value of an expression to an integer. | -| [trunc(expression, decimalPlaces)](./firestore_lite_pipelines.md#trunc_a3a92d0) | (Public Preview) Creates an expression that truncates a numeric value to the specified number of decimal places. | -| [type(expression)](./firestore_lite_pipelines.md#type_1138a27) | (Public Preview) Creates an expression that returns the data type of an expression's result. | +| [arrayAgg(expression)](./firestore_lite_pipelines.md#arrayagg_1138a27) | Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. | +| [arrayAggDistinct(expression)](./firestore_lite_pipelines.md#arrayaggdistinct_1138a27) | Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. | +| [arraySum(expression)](./firestore_lite_pipelines.md#arraysum_1138a27) | Creates an expression that computes the sum of the elements in an array. | +| [average(expression)](./firestore_lite_pipelines.md#average_1138a27) | Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. | +| [ceil(expression)](./firestore_lite_pipelines.md#ceil_1138a27) | Creates an expression that computes the ceiling of a numeric value. | +| [coalesce(expression, replacement, others)](./firestore_lite_pipelines.md#coalesce_00859cb) | Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | +| [collectionId(expression)](./firestore_lite_pipelines.md#collectionid_1138a27) | Creates an expression that returns the collection ID from a path. | +| [count(expression)](./firestore_lite_pipelines.md#count_1138a27) | Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. | +| [divide(expression, value)](./firestore_lite_pipelines.md#divide_01df3cf) | Creates an expression that divides an expression by a constant value. | +| [equal(expression, value)](./firestore_lite_pipelines.md#equal_01df3cf) | Creates an expression that checks if an expression is equal to a constant value. | +| [equalAny(expression, values)](./firestore_lite_pipelines.md#equalany_7e759b5) | Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. | +| [equalAny(expression, arrayExpression)](./firestore_lite_pipelines.md#equalany_214ce68) | Creates an expression that checks if an expression is equal to any of the provided values. | +| [exp(expression)](./firestore_lite_pipelines.md#exp_1138a27) | Creates an expression that computes e to the power of the expression's result. | +| [first(expression)](./firestore_lite_pipelines.md#first_1138a27) | Creates an aggregation that finds the first value of an expression across multiple stage inputs. | +| [greaterThan(expression, value)](./firestore_lite_pipelines.md#greaterthan_01df3cf) | Creates an expression that checks if an expression is greater than a constant value. | +| [greaterThanOrEqual(expression, value)](./firestore_lite_pipelines.md#greaterthanorequal_01df3cf) | Creates an expression that checks if an expression is greater than or equal to a constant value. | +| [isType(expression, type)](./firestore_lite_pipelines.md#istype_27398ce) | Creates an expression that checks if the result of an expression is of the given type. | +| [last(expression)](./firestore_lite_pipelines.md#last_1138a27) | Creates an aggregation that finds the last value of an expression across multiple stage inputs. | +| [length\_2(expression)](./firestore_lite_pipelines.md#length_2_1138a27) | Creates an expression that calculates the length of a string, array, map, vector, or bytes. | +| [lessThan(expression, value)](./firestore_lite_pipelines.md#lessthan_01df3cf) | Creates an expression that checks if an expression is less than a constant value. | +| [lessThanOrEqual(expression, value)](./firestore_lite_pipelines.md#lessthanorequal_01df3cf) | Creates an expression that checks if an expression is less than or equal to a constant value. | +| [ln(expression)](./firestore_lite_pipelines.md#ln_1138a27) | Creates an expression that computes the natural logarithm of a numeric value. | +| [log(expression, base)](./firestore_lite_pipelines.md#log_ac183e2) | Creates an expression that computes the logarithm of an expression to a given base. | +| [log(expression, base)](./firestore_lite_pipelines.md#log_1894737) | Creates an expression that computes the logarithm of an expression to a given base. | +| [log10(expression)](./firestore_lite_pipelines.md#log10_1138a27) | Creates an expression that computes the base-10 logarithm of a numeric value. | +| [ltrim(expression, valueToTrim)](./firestore_lite_pipelines.md#ltrim_775e2f2) | Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | +| [maximum(expression)](./firestore_lite_pipelines.md#maximum_1138a27) | Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. | +| [minimum(expression)](./firestore_lite_pipelines.md#minimum_1138a27) | Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. | +| [mod(expression, value)](./firestore_lite_pipelines.md#mod_01df3cf) | Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. | +| [notEqual(expression, value)](./firestore_lite_pipelines.md#notequal_01df3cf) | Creates an expression that checks if an expression is not equal to a constant value. | +| [round(expression)](./firestore_lite_pipelines.md#round_1138a27) | Creates an expression that rounds a numeric value to the nearest whole number. | +| [round(expression, decimalPlaces)](./firestore_lite_pipelines.md#round_a3a92d0) | Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [rtrim(expression, valueToTrim)](./firestore_lite_pipelines.md#rtrim_775e2f2) | Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | +| [split(expression, delimiter)](./firestore_lite_pipelines.md#split_5b5612b) | Creates an expression that splits a string into an array of substrings based on the provided delimiter. | +| [split(expression, delimiter)](./firestore_lite_pipelines.md#split_5a171ed) | Creates an expression that splits a string into an array of substrings based on the provided delimiter. | +| [sqrt(expression)](./firestore_lite_pipelines.md#sqrt_1138a27) | Creates an expression that computes the square root of a numeric value. | +| [stringIndexOf(expression, search)](./firestore_lite_pipelines.md#stringindexof_6dfca5f) | Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | +| [stringRepeat(expression, repetitions)](./firestore_lite_pipelines.md#stringrepeat_a55ba16) | Creates an expression that repeats a string or byte array a specified number of times. | +| [stringReplaceAll(expression, find, replacement)](./firestore_lite_pipelines.md#stringreplaceall_197ecbe) | Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | +| [stringReplaceOne(expression, find, replacement)](./firestore_lite_pipelines.md#stringreplaceone_197ecbe) | Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | +| [subtract(expression, value)](./firestore_lite_pipelines.md#subtract_01df3cf) | Creates an expression that subtracts a constant value from an expression. | +| [sum(expression)](./firestore_lite_pipelines.md#sum_1138a27) | Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. | +| [trunc(expression)](./firestore_lite_pipelines.md#trunc_1138a27) | Creates an expression that truncates the numeric value of an expression to an integer. | +| [trunc(expression, decimalPlaces)](./firestore_lite_pipelines.md#trunc_a3a92d0) | Creates an expression that truncates a numeric value to the specified number of decimal places. | +| [type(expression)](./firestore_lite_pipelines.md#type_1138a27) | Creates an expression that returns the data type of an expression's result. | | function(field, ...) | -| [isAbsent(field)](./firestore_lite_pipelines.md#isabsent_0fb8cd4) | (Public Preview) Creates an expression that returns true if a field is absent. Otherwise, returns false even if the field value is null. | -| [reverse(field)](./firestore_lite_pipelines.md#reverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. | -| [stringReverse(field)](./firestore_lite_pipelines.md#stringreverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. | -| [substring(field, position, length)](./firestore_lite_pipelines.md#substring_0d9573a) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | -| [substring(field, position, length)](./firestore_lite_pipelines.md#substring_05cb14e) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| [isAbsent(field)](./firestore_lite_pipelines.md#isabsent_0fb8cd4) | Creates an expression that returns true if a field is absent. Otherwise, returns false even if the field value is null. | +| [reverse(field)](./firestore_lite_pipelines.md#reverse_0fb8cd4) | Creates an expression that reverses a string value in the specified field. | +| [stringReverse(field)](./firestore_lite_pipelines.md#stringreverse_0fb8cd4) | Creates an expression that reverses a string value in the specified field. | +| [substring(field, position, length)](./firestore_lite_pipelines.md#substring_0d9573a) | Creates an expression that returns a substring of a string or byte array. | +| [substring(field, position, length)](./firestore_lite_pipelines.md#substring_05cb14e) | Creates an expression that returns a substring of a string or byte array. | | function(fieldName, ...) | -| [abs(fieldName)](./firestore_lite_pipelines.md#abs_e5b0480) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | -| [add(fieldName, second)](./firestore_lite_pipelines.md#add_b75bb8b) | (Public Preview) Creates an expression that adds a field's value to an expression. | -| [arrayAgg(fieldName)](./firestore_lite_pipelines.md#arrayagg_e5b0480) | (Public Preview) Creates an aggregation that collects all values of a field across multiple stage inputs into an array. | -| [arrayAggDistinct(fieldName)](./firestore_lite_pipelines.md#arrayaggdistinct_e5b0480) | (Public Preview) Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. | -| [arrayContains(fieldName, element)](./firestore_lite_pipelines.md#arraycontains_aaace4a) | (Public Preview) Creates an expression that checks if a field's array value contains a specific element. | -| [arrayContains(fieldName, element)](./firestore_lite_pipelines.md#arraycontains_999590f) | (Public Preview) Creates an expression that checks if a field's array value contains a specific value. | -| [arrayContainsAll(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsall_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. | -| [arrayContainsAll(fieldName, arrayExpression)](./firestore_lite_pipelines.md#arraycontainsall_48da8d9) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. | -| [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. | -| [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_1b4f7cd) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. | -| [arrayFirst(fieldName)](./firestore_lite_pipelines.md#arrayfirst_e5b0480) | (Public Preview) Creates an expression that returns the first element of an array. | -| [arrayFirstN(fieldName, n)](./firestore_lite_pipelines.md#arrayfirstn_597a4d9) | (Public Preview) Creates an expression that returns the first n elements of an array. | -| [arrayFirstN(fieldName, n)](./firestore_lite_pipelines.md#arrayfirstn_1a86a2c) | (Public Preview) Creates an expression that returns the first n elements of an array. | -| [arrayIndexOf(fieldName, search)](./firestore_lite_pipelines.md#arrayindexof_5e4c2c3) | (Public Preview) Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. | -| [arrayIndexOfAll(fieldName, search)](./firestore_lite_pipelines.md#arrayindexofall_5e4c2c3) | (Public Preview) Creates an expression that returns all indices of the search value in an array. | -| [arrayLast(fieldName)](./firestore_lite_pipelines.md#arraylast_e5b0480) | (Public Preview) Creates an expression that returns the last element of an array. | -| [arrayLastIndexOf(fieldName, search)](./firestore_lite_pipelines.md#arraylastindexof_5e4c2c3) | (Public Preview) Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. | -| [arrayLastN(fieldName, n)](./firestore_lite_pipelines.md#arraylastn_597a4d9) | (Public Preview) Creates an expression that returns the last n elements of an array. | -| [arrayLastN(fieldName, n)](./firestore_lite_pipelines.md#arraylastn_1a86a2c) | (Public Preview) Creates an expression that returns the last n elements of an array. | -| [arrayLength(fieldName)](./firestore_lite_pipelines.md#arraylength_e5b0480) | (Public Preview) Creates an expression that calculates the length of an array in a specified field. | -| [arrayMaximum(fieldName)](./firestore_lite_pipelines.md#arraymaximum_e5b0480) | (Public Preview) Creates an expression that returns the maximum value in an array. | -| [arrayMaximumN(fieldName, n)](./firestore_lite_pipelines.md#arraymaximumn_597a4d9) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMaximumN(fieldName, n)](./firestore_lite_pipelines.md#arraymaximumn_1a86a2c) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMinimum(fieldName)](./firestore_lite_pipelines.md#arrayminimum_e5b0480) | (Public Preview) Creates an expression that returns the minimum value in an array. | -| [arrayMinimumN(fieldName, n)](./firestore_lite_pipelines.md#arrayminimumn_597a4d9) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMinimumN(fieldName, n)](./firestore_lite_pipelines.md#arrayminimumn_1a86a2c) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arraySum(fieldName)](./firestore_lite_pipelines.md#arraysum_e5b0480) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | -| [ascending(fieldName)](./firestore_lite_pipelines.md#ascending_e5b0480) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. | -| [average(fieldName)](./firestore_lite_pipelines.md#average_e5b0480) | (Public Preview) Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. | -| [byteLength(fieldName)](./firestore_lite_pipelines.md#bytelength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. | -| [ceil(fieldName)](./firestore_lite_pipelines.md#ceil_e5b0480) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | -| [charLength(fieldName)](./firestore_lite_pipelines.md#charlength_e5b0480) | (Public Preview) Creates an expression that calculates the character length of a string field in UTF8. | -| [coalesce(fieldName, replacement, others)](./firestore_lite_pipelines.md#coalesce_249958e) | (Public Preview) Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | -| [collectionId(fieldName)](./firestore_lite_pipelines.md#collectionid_e5b0480) | (Public Preview) Creates an expression that returns the collection ID from a path. | -| [concat(fieldName, second, others)](./firestore_lite_pipelines.md#concat_828272e) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | -| [cosineDistance(fieldName, vector)](./firestore_lite_pipelines.md#cosinedistance_463a23e) | (Public Preview) Calculates the Cosine distance between a field's vector value and a literal vector value. | -| [cosineDistance(fieldName, vectorExpression)](./firestore_lite_pipelines.md#cosinedistance_ed766a1) | (Public Preview) Calculates the Cosine distance between a field's vector value and a vector expression. | -| [count(fieldName)](./firestore_lite_pipelines.md#count_e5b0480) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the input field exists. | -| [descending(fieldName)](./firestore_lite_pipelines.md#descending_e5b0480) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on a field. | -| [divide(fieldName, expressions)](./firestore_lite_pipelines.md#divide_cf36e43) | (Public Preview) Creates an expression that divides a field's value by an expression. | -| [divide(fieldName, value)](./firestore_lite_pipelines.md#divide_65e2f32) | (Public Preview) Creates an expression that divides a field's value by a constant value. | -| [dotProduct(fieldName, vector)](./firestore_lite_pipelines.md#dotproduct_463a23e) | (Public Preview) Calculates the dot product between a field's vector value and a double array. | -| [dotProduct(fieldName, vectorExpression)](./firestore_lite_pipelines.md#dotproduct_ed766a1) | (Public Preview) Calculates the dot product between a field's vector value and a vector expression. | -| [endsWith(fieldName, suffix)](./firestore_lite_pipelines.md#endswith_05ca3b0) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. | -| [endsWith(fieldName, suffix)](./firestore_lite_pipelines.md#endswith_8fc0ebc) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. | -| [equal(fieldName, expression)](./firestore_lite_pipelines.md#equal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is equal to an expression. | -| [equal(fieldName, value)](./firestore_lite_pipelines.md#equal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is equal to a constant value. | -| [equalAny(fieldName, values)](./firestore_lite_pipelines.md#equalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. | -| [equalAny(fieldName, arrayExpression)](./firestore_lite_pipelines.md#equalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. | -| [euclideanDistance(fieldName, vector)](./firestore_lite_pipelines.md#euclideandistance_463a23e) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a double array. | -| [euclideanDistance(fieldName, vectorExpression)](./firestore_lite_pipelines.md#euclideandistance_ed766a1) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a vector expression. | -| [exists(fieldName)](./firestore_lite_pipelines.md#exists_e5b0480) | (Public Preview) Creates an expression that checks if a field exists. | -| [exp(fieldName)](./firestore_lite_pipelines.md#exp_e5b0480) | (Public Preview) Creates an expression that computes e to the power of the expression's result. | -| [first(fieldName)](./firestore_lite_pipelines.md#first_e5b0480) | (Public Preview) Creates an aggregation that finds the first value of a field across multiple stage inputs. | -| [floor(fieldName)](./firestore_lite_pipelines.md#floor_e5b0480) | (Public Preview) Creates an expression that computes the floor of a numeric value. | -| [greaterThan(fieldName, expression)](./firestore_lite_pipelines.md#greaterthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is greater than an expression. | -| [greaterThan(fieldName, value)](./firestore_lite_pipelines.md#greaterthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than a constant value. | -| [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_2e16acb) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to an expression. | -| [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to a constant value. | -| [isType(fieldName, type)](./firestore_lite_pipelines.md#istype_5da287e) | (Public Preview) Creates an expression that checks if the value in the specified field is of the given type. | -| [last(fieldName)](./firestore_lite_pipelines.md#last_e5b0480) | (Public Preview) Creates an aggregation that finds the last value of a field across multiple stage inputs. | -| [length\_2(fieldName)](./firestore_lite_pipelines.md#length_2_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | -| [lessThan(fieldName, expression)](./firestore_lite_pipelines.md#lessthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than an expression. | -| [lessThan(fieldName, value)](./firestore_lite_pipelines.md#lessthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than a constant value. | -| [lessThanOrEqual(fieldName, expression)](./firestore_lite_pipelines.md#lessthanorequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to an expression. | -| [lessThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#lessthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to a constant value. | -| [like(fieldName, pattern)](./firestore_lite_pipelines.md#like_67f7432) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. | -| [like(fieldName, pattern)](./firestore_lite_pipelines.md#like_cb1318d) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. | -| [ln(fieldName)](./firestore_lite_pipelines.md#ln_e5b0480) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. | -| [log(fieldName, base)](./firestore_lite_pipelines.md#log_a89e21b) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. | -| [log(fieldName, base)](./firestore_lite_pipelines.md#log_805b11f) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. | -| [log10(fieldName)](./firestore_lite_pipelines.md#log10_e5b0480) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | -| [logicalMaximum(fieldName, second, others)](./firestore_lite_pipelines.md#logicalmaximum_828272e) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | -| [logicalMinimum(fieldName, second, others)](./firestore_lite_pipelines.md#logicalminimum_828272e) | (Public Preview) Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. | -| [ltrim(fieldName, valueToTrim)](./firestore_lite_pipelines.md#ltrim_c0e3211) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | -| [mapGet(fieldName, subField)](./firestore_lite_pipelines.md#mapget_06663cf) | (Public Preview) Accesses a value from a map (object) field using the provided key. | -| [maximum(fieldName)](./firestore_lite_pipelines.md#maximum_e5b0480) | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | -| [minimum(fieldName)](./firestore_lite_pipelines.md#minimum_e5b0480) | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | -| [mod(fieldName, expression)](./firestore_lite_pipelines.md#mod_1e91657) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. | -| [mod(fieldName, value)](./firestore_lite_pipelines.md#mod_65e2f32) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. | -| [multiply(fieldName, second)](./firestore_lite_pipelines.md#multiply_b75bb8b) | (Public Preview) Creates an expression that multiplies a field's value by an expression. | -| [notEqual(fieldName, expression)](./firestore_lite_pipelines.md#notequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is not equal to an expression. | -| [notEqual(fieldName, value)](./firestore_lite_pipelines.md#notequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is not equal to a constant value. | -| [notEqualAny(fieldName, values)](./firestore_lite_pipelines.md#notequalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. | -| [notEqualAny(fieldName, arrayExpression)](./firestore_lite_pipelines.md#notequalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. | -| [regexContains(fieldName, pattern)](./firestore_lite_pipelines.md#regexcontains_67f7432) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. | -| [regexContains(fieldName, pattern)](./firestore_lite_pipelines.md#regexcontains_cb1318d) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. | -| [regexFind(fieldName, pattern)](./firestore_lite_pipelines.md#regexfind_67f7432) | (Public Preview) Creates an expression that returns the first substring of a string field that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFind(fieldName, pattern)](./firestore_lite_pipelines.md#regexfind_cb1318d) | (Public Preview) Creates an expression that returns the first substring of a string field that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFindAll(fieldName, pattern)](./firestore_lite_pipelines.md#regexfindall_67f7432) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFindAll(fieldName, pattern)](./firestore_lite_pipelines.md#regexfindall_cb1318d) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_67f7432) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | -| [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_cb1318d) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | -| [round(fieldName)](./firestore_lite_pipelines.md#round_e5b0480) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | -| [round(fieldName, decimalPlaces)](./firestore_lite_pipelines.md#round_07d0cf0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | -| [rtrim(fieldName, valueToTrim)](./firestore_lite_pipelines.md#rtrim_c0e3211) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | -| [split(fieldName, delimiter)](./firestore_lite_pipelines.md#split_2cfdd37) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | -| [split(fieldName, delimiter)](./firestore_lite_pipelines.md#split_f4fe06a) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | -| [sqrt(fieldName)](./firestore_lite_pipelines.md#sqrt_e5b0480) | (Public Preview) Creates an expression that computes the square root of a numeric value. | -| [startsWith(fieldName, prefix)](./firestore_lite_pipelines.md#startswith_89325cc) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. | -| [startsWith(fieldName, prefix)](./firestore_lite_pipelines.md#startswith_266c338) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. | -| [stringConcat(fieldName, secondString, otherStrings)](./firestore_lite_pipelines.md#stringconcat_d80077e) | (Public Preview) Creates an expression that concatenates string functions, fields or constants together. | -| [stringContains(fieldName, substring)](./firestore_lite_pipelines.md#stringcontains_5b94cfe) | (Public Preview) Creates an expression that checks if a string field contains a specified substring. | -| [stringContains(fieldName, substring)](./firestore_lite_pipelines.md#stringcontains_ac3ba47) | (Public Preview) Creates an expression that checks if a string field contains a substring specified by an expression. | -| [stringIndexOf(fieldName, search)](./firestore_lite_pipelines.md#stringindexof_6c4650e) | (Public Preview) Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | -| [stringRepeat(fieldName, repetitions)](./firestore_lite_pipelines.md#stringrepeat_e144a59) | (Public Preview) Creates an expression that repeats a string or byte array a specified number of times. | -| [stringReplaceAll(fieldName, find, replacement)](./firestore_lite_pipelines.md#stringreplaceall_b0db15f) | (Public Preview) Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | -| [stringReplaceOne(fieldName, find, replacement)](./firestore_lite_pipelines.md#stringreplaceone_b0db15f) | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | -| [subtract(fieldName, expression)](./firestore_lite_pipelines.md#subtract_1e91657) | (Public Preview) Creates an expression that subtracts an expression from a field's value. | -| [subtract(fieldName, value)](./firestore_lite_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. | -| [sum(fieldName)](./firestore_lite_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. | -| [timestampAdd(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampadd_3b0a297) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. | -| [timestampExtract(fieldName, part, timezone)](./firestore_lite_pipelines.md#timestampextract_a51c205) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | -| [timestampExtract(fieldName, part, timezone)](./firestore_lite_pipelines.md#timestampextract_2d51eac) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | -| [timestampSubtract(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_3b0a297) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. | -| [timestampToUnixMicros(fieldName)](./firestore_lite_pipelines.md#timestamptounixmicros_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampToUnixMillis(fieldName)](./firestore_lite_pipelines.md#timestamptounixmillis_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampToUnixSeconds(fieldName)](./firestore_lite_pipelines.md#timestamptounixseconds_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampTruncate(fieldName, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_b6c7512) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [timestampTruncate(fieldName, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_ed83d46) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [toLower(fieldName)](./firestore_lite_pipelines.md#tolower_e5b0480) | (Public Preview) Creates an expression that converts a string field to lowercase. | -| [toUpper(fieldName)](./firestore_lite_pipelines.md#toupper_e5b0480) | (Public Preview) Creates an expression that converts a string field to uppercase. | -| [trim(fieldName, valueToTrim)](./firestore_lite_pipelines.md#trim_c9f90ee) | (Public Preview) Creates an expression that removes leading and trailing whitespace from a string or byte array. | -| [trunc(fieldName)](./firestore_lite_pipelines.md#trunc_e5b0480) | (Public Preview) Creates an expression that truncates the numeric value of a field to an integer. | -| [trunc(fieldName, decimalPlaces)](./firestore_lite_pipelines.md#trunc_07d0cf0) | (Public Preview) Creates an expression that truncates a numeric expression to the specified number of decimal places. | -| [type(fieldName)](./firestore_lite_pipelines.md#type_e5b0480) | (Public Preview) Creates an expression that returns the data type of the data in the specified field. | -| [unixMicrosToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixmicrostotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | -| [unixMillisToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixmillistotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | -| [unixSecondsToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixsecondstotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | -| [vectorLength(fieldName)](./firestore_lite_pipelines.md#vectorlength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector represented by a field. | +| [abs(fieldName)](./firestore_lite_pipelines.md#abs_e5b0480) | Creates an expression that computes the absolute value of a numeric value. | +| [add(fieldName, second)](./firestore_lite_pipelines.md#add_b75bb8b) | Creates an expression that adds a field's value to an expression. | +| [arrayAgg(fieldName)](./firestore_lite_pipelines.md#arrayagg_e5b0480) | Creates an aggregation that collects all values of a field across multiple stage inputs into an array. | +| [arrayAggDistinct(fieldName)](./firestore_lite_pipelines.md#arrayaggdistinct_e5b0480) | Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. | +| [arrayContains(fieldName, element)](./firestore_lite_pipelines.md#arraycontains_aaace4a) | Creates an expression that checks if a field's array value contains a specific element. | +| [arrayContains(fieldName, element)](./firestore_lite_pipelines.md#arraycontains_999590f) | Creates an expression that checks if a field's array value contains a specific value. | +| [arrayContainsAll(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsall_8060b23) | Creates an expression that checks if a field's array value contains all the specified values or expressions. | +| [arrayContainsAll(fieldName, arrayExpression)](./firestore_lite_pipelines.md#arraycontainsall_48da8d9) | Creates an expression that checks if a field's array value contains all the specified values or expressions. | +| [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_8060b23) | Creates an expression that checks if a field's array value contains any of the specified elements. | +| [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_1b4f7cd) | Creates an expression that checks if a field's array value contains any of the specified elements. | +| [arrayFirst(fieldName)](./firestore_lite_pipelines.md#arrayfirst_e5b0480) | Creates an expression that returns the first element of an array. | +| [arrayFirstN(fieldName, n)](./firestore_lite_pipelines.md#arrayfirstn_597a4d9) | Creates an expression that returns the first n elements of an array. | +| [arrayFirstN(fieldName, n)](./firestore_lite_pipelines.md#arrayfirstn_1a86a2c) | Creates an expression that returns the first n elements of an array. | +| [arrayIndexOf(fieldName, search)](./firestore_lite_pipelines.md#arrayindexof_5e4c2c3) | Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. | +| [arrayIndexOfAll(fieldName, search)](./firestore_lite_pipelines.md#arrayindexofall_5e4c2c3) | Creates an expression that returns all indices of the search value in an array. | +| [arrayLast(fieldName)](./firestore_lite_pipelines.md#arraylast_e5b0480) | Creates an expression that returns the last element of an array. | +| [arrayLastIndexOf(fieldName, search)](./firestore_lite_pipelines.md#arraylastindexof_5e4c2c3) | Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. | +| [arrayLastN(fieldName, n)](./firestore_lite_pipelines.md#arraylastn_597a4d9) | Creates an expression that returns the last n elements of an array. | +| [arrayLastN(fieldName, n)](./firestore_lite_pipelines.md#arraylastn_1a86a2c) | Creates an expression that returns the last n elements of an array. | +| [arrayLength(fieldName)](./firestore_lite_pipelines.md#arraylength_e5b0480) | Creates an expression that calculates the length of an array in a specified field. | +| [arrayMaximum(fieldName)](./firestore_lite_pipelines.md#arraymaximum_e5b0480) | Creates an expression that returns the maximum value in an array. | +| [arrayMaximumN(fieldName, n)](./firestore_lite_pipelines.md#arraymaximumn_597a4d9) | Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMaximumN(fieldName, n)](./firestore_lite_pipelines.md#arraymaximumn_1a86a2c) | Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimum(fieldName)](./firestore_lite_pipelines.md#arrayminimum_e5b0480) | Creates an expression that returns the minimum value in an array. | +| [arrayMinimumN(fieldName, n)](./firestore_lite_pipelines.md#arrayminimumn_597a4d9) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimumN(fieldName, n)](./firestore_lite_pipelines.md#arrayminimumn_1a86a2c) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arraySum(fieldName)](./firestore_lite_pipelines.md#arraysum_e5b0480) | Creates an expression that computes the sum of the elements in an array. | +| [ascending(fieldName)](./firestore_lite_pipelines.md#ascending_e5b0480) | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. | +| [average(fieldName)](./firestore_lite_pipelines.md#average_e5b0480) | Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. | +| [byteLength(fieldName)](./firestore_lite_pipelines.md#bytelength_e5b0480) | Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. | +| [ceil(fieldName)](./firestore_lite_pipelines.md#ceil_e5b0480) | Creates an expression that computes the ceiling of a numeric value. | +| [charLength(fieldName)](./firestore_lite_pipelines.md#charlength_e5b0480) | Creates an expression that calculates the character length of a string field in UTF8. | +| [coalesce(fieldName, replacement, others)](./firestore_lite_pipelines.md#coalesce_249958e) | Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | +| [collectionId(fieldName)](./firestore_lite_pipelines.md#collectionid_e5b0480) | Creates an expression that returns the collection ID from a path. | +| [concat(fieldName, second, others)](./firestore_lite_pipelines.md#concat_828272e) | Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | +| [cosineDistance(fieldName, vector)](./firestore_lite_pipelines.md#cosinedistance_463a23e) | Calculates the Cosine distance between a field's vector value and a literal vector value. | +| [cosineDistance(fieldName, vectorExpression)](./firestore_lite_pipelines.md#cosinedistance_ed766a1) | Calculates the Cosine distance between a field's vector value and a vector expression. | +| [count(fieldName)](./firestore_lite_pipelines.md#count_e5b0480) | Creates an aggregation that counts the number of stage inputs where the input field exists. | +| [descending(fieldName)](./firestore_lite_pipelines.md#descending_e5b0480) | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on a field. | +| [divide(fieldName, expressions)](./firestore_lite_pipelines.md#divide_cf36e43) | Creates an expression that divides a field's value by an expression. | +| [divide(fieldName, value)](./firestore_lite_pipelines.md#divide_65e2f32) | Creates an expression that divides a field's value by a constant value. | +| [dotProduct(fieldName, vector)](./firestore_lite_pipelines.md#dotproduct_463a23e) | Calculates the dot product between a field's vector value and a double array. | +| [dotProduct(fieldName, vectorExpression)](./firestore_lite_pipelines.md#dotproduct_ed766a1) | Calculates the dot product between a field's vector value and a vector expression. | +| [endsWith(fieldName, suffix)](./firestore_lite_pipelines.md#endswith_05ca3b0) | Creates an expression that checks if a field's value ends with a given postfix. | +| [endsWith(fieldName, suffix)](./firestore_lite_pipelines.md#endswith_8fc0ebc) | Creates an expression that checks if a field's value ends with a given postfix. | +| [equal(fieldName, expression)](./firestore_lite_pipelines.md#equal_1e91657) | Creates an expression that checks if a field's value is equal to an expression. | +| [equal(fieldName, value)](./firestore_lite_pipelines.md#equal_65e2f32) | Creates an expression that checks if a field's value is equal to a constant value. | +| [equalAny(fieldName, values)](./firestore_lite_pipelines.md#equalany_8060b23) | Creates an expression that checks if a field's value is equal to any of the provided values or expressions. | +| [equalAny(fieldName, arrayExpression)](./firestore_lite_pipelines.md#equalany_48da8d9) | Creates an expression that checks if a field's value is equal to any of the provided values or expressions. | +| [euclideanDistance(fieldName, vector)](./firestore_lite_pipelines.md#euclideandistance_463a23e) | Calculates the Euclidean distance between a field's vector value and a double array. | +| [euclideanDistance(fieldName, vectorExpression)](./firestore_lite_pipelines.md#euclideandistance_ed766a1) | Calculates the Euclidean distance between a field's vector value and a vector expression. | +| [exists(fieldName)](./firestore_lite_pipelines.md#exists_e5b0480) | Creates an expression that checks if a field exists. | +| [exp(fieldName)](./firestore_lite_pipelines.md#exp_e5b0480) | Creates an expression that computes e to the power of the expression's result. | +| [first(fieldName)](./firestore_lite_pipelines.md#first_e5b0480) | Creates an aggregation that finds the first value of a field across multiple stage inputs. | +| [floor(fieldName)](./firestore_lite_pipelines.md#floor_e5b0480) | Creates an expression that computes the floor of a numeric value. | +| [greaterThan(fieldName, expression)](./firestore_lite_pipelines.md#greaterthan_1e91657) | Creates an expression that checks if a field's value is greater than an expression. | +| [greaterThan(fieldName, value)](./firestore_lite_pipelines.md#greaterthan_65e2f32) | Creates an expression that checks if a field's value is greater than a constant value. | +| [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_2e16acb) | Creates an expression that checks if a field's value is greater than or equal to an expression. | +| [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_65e2f32) | Creates an expression that checks if a field's value is greater than or equal to a constant value. | +| [isType(fieldName, type)](./firestore_lite_pipelines.md#istype_5da287e) | Creates an expression that checks if the value in the specified field is of the given type. | +| [last(fieldName)](./firestore_lite_pipelines.md#last_e5b0480) | Creates an aggregation that finds the last value of a field across multiple stage inputs. | +| [length\_2(fieldName)](./firestore_lite_pipelines.md#length_2_e5b0480) | Creates an expression that calculates the length of a string, array, map, vector, or bytes. | +| [lessThan(fieldName, expression)](./firestore_lite_pipelines.md#lessthan_1e91657) | Creates an expression that checks if a field's value is less than an expression. | +| [lessThan(fieldName, value)](./firestore_lite_pipelines.md#lessthan_65e2f32) | Creates an expression that checks if a field's value is less than a constant value. | +| [lessThanOrEqual(fieldName, expression)](./firestore_lite_pipelines.md#lessthanorequal_1e91657) | Creates an expression that checks if a field's value is less than or equal to an expression. | +| [lessThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#lessthanorequal_65e2f32) | Creates an expression that checks if a field's value is less than or equal to a constant value. | +| [like(fieldName, pattern)](./firestore_lite_pipelines.md#like_67f7432) | Creates an expression that performs a case-sensitive wildcard string comparison against a field. | +| [like(fieldName, pattern)](./firestore_lite_pipelines.md#like_cb1318d) | Creates an expression that performs a case-sensitive wildcard string comparison against a field. | +| [ln(fieldName)](./firestore_lite_pipelines.md#ln_e5b0480) | Creates an expression that computes the natural logarithm of a numeric value. | +| [log(fieldName, base)](./firestore_lite_pipelines.md#log_a89e21b) | Creates an expression that computes the logarithm of a field to a given base. | +| [log(fieldName, base)](./firestore_lite_pipelines.md#log_805b11f) | Creates an expression that computes the logarithm of a field to a given base. | +| [log10(fieldName)](./firestore_lite_pipelines.md#log10_e5b0480) | Creates an expression that computes the base-10 logarithm of a numeric value. | +| [logicalMaximum(fieldName, second, others)](./firestore_lite_pipelines.md#logicalmaximum_828272e) | Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | +| [logicalMinimum(fieldName, second, others)](./firestore_lite_pipelines.md#logicalminimum_828272e) | Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. | +| [ltrim(fieldName, valueToTrim)](./firestore_lite_pipelines.md#ltrim_c0e3211) | Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | +| [mapGet(fieldName, subField)](./firestore_lite_pipelines.md#mapget_06663cf) | Accesses a value from a map (object) field using the provided key. | +| [maximum(fieldName)](./firestore_lite_pipelines.md#maximum_e5b0480) | Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | +| [minimum(fieldName)](./firestore_lite_pipelines.md#minimum_e5b0480) | Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | +| [mod(fieldName, expression)](./firestore_lite_pipelines.md#mod_1e91657) | Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. | +| [mod(fieldName, value)](./firestore_lite_pipelines.md#mod_65e2f32) | Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. | +| [multiply(fieldName, second)](./firestore_lite_pipelines.md#multiply_b75bb8b) | Creates an expression that multiplies a field's value by an expression. | +| [notEqual(fieldName, expression)](./firestore_lite_pipelines.md#notequal_1e91657) | Creates an expression that checks if a field's value is not equal to an expression. | +| [notEqual(fieldName, value)](./firestore_lite_pipelines.md#notequal_65e2f32) | Creates an expression that checks if a field's value is not equal to a constant value. | +| [notEqualAny(fieldName, values)](./firestore_lite_pipelines.md#notequalany_8060b23) | Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. | +| [notEqualAny(fieldName, arrayExpression)](./firestore_lite_pipelines.md#notequalany_48da8d9) | Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. | +| [regexContains(fieldName, pattern)](./firestore_lite_pipelines.md#regexcontains_67f7432) | Creates an expression that checks if a string field contains a specified regular expression as a substring. | +| [regexContains(fieldName, pattern)](./firestore_lite_pipelines.md#regexcontains_cb1318d) | Creates an expression that checks if a string field contains a specified regular expression as a substring. | +| [regexFind(fieldName, pattern)](./firestore_lite_pipelines.md#regexfind_67f7432) | Creates an expression that returns the first substring of a string field that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFind(fieldName, pattern)](./firestore_lite_pipelines.md#regexfind_cb1318d) | Creates an expression that returns the first substring of a string field that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(fieldName, pattern)](./firestore_lite_pipelines.md#regexfindall_67f7432) | Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(fieldName, pattern)](./firestore_lite_pipelines.md#regexfindall_cb1318d) | Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_67f7432) | Creates an expression that checks if a string field matches a specified regular expression. | +| [regexMatch(fieldName, pattern)](./firestore_lite_pipelines.md#regexmatch_cb1318d) | Creates an expression that checks if a string field matches a specified regular expression. | +| [round(fieldName)](./firestore_lite_pipelines.md#round_e5b0480) | Creates an expression that rounds a numeric value to the nearest whole number. | +| [round(fieldName, decimalPlaces)](./firestore_lite_pipelines.md#round_07d0cf0) | Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [rtrim(fieldName, valueToTrim)](./firestore_lite_pipelines.md#rtrim_c0e3211) | Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | +| [split(fieldName, delimiter)](./firestore_lite_pipelines.md#split_2cfdd37) | Creates an expression that splits the value of a field on the provided delimiter. | +| [split(fieldName, delimiter)](./firestore_lite_pipelines.md#split_f4fe06a) | Creates an expression that splits the value of a field on the provided delimiter. | +| [sqrt(fieldName)](./firestore_lite_pipelines.md#sqrt_e5b0480) | Creates an expression that computes the square root of a numeric value. | +| [startsWith(fieldName, prefix)](./firestore_lite_pipelines.md#startswith_89325cc) | Creates an expression that checks if a field's value starts with a given prefix. | +| [startsWith(fieldName, prefix)](./firestore_lite_pipelines.md#startswith_266c338) | Creates an expression that checks if a field's value starts with a given prefix. | +| [stringConcat(fieldName, secondString, otherStrings)](./firestore_lite_pipelines.md#stringconcat_d80077e) | Creates an expression that concatenates string functions, fields or constants together. | +| [stringContains(fieldName, substring)](./firestore_lite_pipelines.md#stringcontains_5b94cfe) | Creates an expression that checks if a string field contains a specified substring. | +| [stringContains(fieldName, substring)](./firestore_lite_pipelines.md#stringcontains_ac3ba47) | Creates an expression that checks if a string field contains a substring specified by an expression. | +| [stringIndexOf(fieldName, search)](./firestore_lite_pipelines.md#stringindexof_6c4650e) | Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | +| [stringRepeat(fieldName, repetitions)](./firestore_lite_pipelines.md#stringrepeat_e144a59) | Creates an expression that repeats a string or byte array a specified number of times. | +| [stringReplaceAll(fieldName, find, replacement)](./firestore_lite_pipelines.md#stringreplaceall_b0db15f) | Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | +| [stringReplaceOne(fieldName, find, replacement)](./firestore_lite_pipelines.md#stringreplaceone_b0db15f) | Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | +| [subtract(fieldName, expression)](./firestore_lite_pipelines.md#subtract_1e91657) | Creates an expression that subtracts an expression from a field's value. | +| [subtract(fieldName, value)](./firestore_lite_pipelines.md#subtract_65e2f32) | Creates an expression that subtracts a constant value from a field's value. | +| [sum(fieldName)](./firestore_lite_pipelines.md#sum_e5b0480) | Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. | +| [timestampAdd(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampadd_3b0a297) | Creates an expression that adds a specified amount of time to a timestamp represented by a field. | +| [timestampExtract(fieldName, part, timezone)](./firestore_lite_pipelines.md#timestampextract_a51c205) | Creates an expression that extracts a specified part from a timestamp. | +| [timestampExtract(fieldName, part, timezone)](./firestore_lite_pipelines.md#timestampextract_2d51eac) | Creates an expression that extracts a specified part from a timestamp. | +| [timestampSubtract(fieldName, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_3b0a297) | Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. | +| [timestampToUnixMicros(fieldName)](./firestore_lite_pipelines.md#timestamptounixmicros_e5b0480) | Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixMillis(fieldName)](./firestore_lite_pipelines.md#timestamptounixmillis_e5b0480) | Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixSeconds(fieldName)](./firestore_lite_pipelines.md#timestamptounixseconds_e5b0480) | Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampTruncate(fieldName, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_b6c7512) | Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(fieldName, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_ed83d46) | Creates an expression that truncates a timestamp to a specified granularity. | +| [toLower(fieldName)](./firestore_lite_pipelines.md#tolower_e5b0480) | Creates an expression that converts a string field to lowercase. | +| [toUpper(fieldName)](./firestore_lite_pipelines.md#toupper_e5b0480) | Creates an expression that converts a string field to uppercase. | +| [trim(fieldName, valueToTrim)](./firestore_lite_pipelines.md#trim_c9f90ee) | Creates an expression that removes leading and trailing whitespace from a string or byte array. | +| [trunc(fieldName)](./firestore_lite_pipelines.md#trunc_e5b0480) | Creates an expression that truncates the numeric value of a field to an integer. | +| [trunc(fieldName, decimalPlaces)](./firestore_lite_pipelines.md#trunc_07d0cf0) | Creates an expression that truncates a numeric expression to the specified number of decimal places. | +| [type(fieldName)](./firestore_lite_pipelines.md#type_e5b0480) | Creates an expression that returns the data type of the data in the specified field. | +| [unixMicrosToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixmicrostotimestamp_e5b0480) | Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixMillisToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixmillistotimestamp_e5b0480) | Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixSecondsToTimestamp(fieldName)](./firestore_lite_pipelines.md#unixsecondstotimestamp_e5b0480) | Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [vectorLength(fieldName)](./firestore_lite_pipelines.md#vectorlength_e5b0480) | Creates an expression that calculates the length of a Firestore Vector represented by a field. | | function(first, ...) | -| [add(first, second)](./firestore_lite_pipelines.md#add_846ca1b) | (Public Preview) Creates an expression that adds two expressions together. | -| [and(first, second, more)](./firestore_lite_pipelines.md#and_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'AND' operation on multiple filter conditions. | -| [concat(first, second, others)](./firestore_lite_pipelines.md#concat_83be015) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | -| [logicalMaximum(first, second, others)](./firestore_lite_pipelines.md#logicalmaximum_83be015) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | -| [logicalMinimum(first, second, others)](./firestore_lite_pipelines.md#logicalminimum_83be015) | (Public Preview) Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. | -| [multiply(first, second)](./firestore_lite_pipelines.md#multiply_846ca1b) | (Public Preview) Creates an expression that multiplies two expressions together. | -| [nor(first, second, more)](./firestore_lite_pipelines.md#nor_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'NOR' operation on multiple filter conditions. | -| [or(first, second, more)](./firestore_lite_pipelines.md#or_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'OR' operation on multiple filter conditions. | -| [xor(first, second, additionalConditions)](./firestore_lite_pipelines.md#xor_8197113) | (Public Preview) Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. | +| [add(first, second)](./firestore_lite_pipelines.md#add_846ca1b) | Creates an expression that adds two expressions together. | +| [and(first, second, more)](./firestore_lite_pipelines.md#and_e0c48bd) | Creates an expression that performs a logical 'AND' operation on multiple filter conditions. | +| [concat(first, second, others)](./firestore_lite_pipelines.md#concat_83be015) | Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | +| [logicalMaximum(first, second, others)](./firestore_lite_pipelines.md#logicalmaximum_83be015) | Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | +| [logicalMinimum(first, second, others)](./firestore_lite_pipelines.md#logicalminimum_83be015) | Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. | +| [multiply(first, second)](./firestore_lite_pipelines.md#multiply_846ca1b) | Creates an expression that multiplies two expressions together. | +| [nor(first, second, more)](./firestore_lite_pipelines.md#nor_e0c48bd) | Creates an expression that performs a logical 'NOR' operation on multiple filter conditions. | +| [or(first, second, more)](./firestore_lite_pipelines.md#or_e0c48bd) | Creates an expression that performs a logical 'OR' operation on multiple filter conditions. | +| [xor(first, second, additionalConditions)](./firestore_lite_pipelines.md#xor_8197113) | Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. | | function(firstArray, ...) | -| [arrayConcat(firstArray, secondArray, otherArrays)](./firestore_lite_pipelines.md#arrayconcat_c00d5d7) | (Public Preview) Creates an expression that concatenates an array expression with other arrays. | +| [arrayConcat(firstArray, secondArray, otherArrays)](./firestore_lite_pipelines.md#arrayconcat_c00d5d7) | Creates an expression that concatenates an array expression with other arrays. | | function(firstArrayField, ...) | -| [arrayConcat(firstArrayField, secondArray, otherArrays)](./firestore_lite_pipelines.md#arrayconcat_f92063d) | (Public Preview) Creates an expression that concatenates a field's array value with other arrays. | +| [arrayConcat(firstArrayField, secondArray, otherArrays)](./firestore_lite_pipelines.md#arrayconcat_f92063d) | Creates an expression that concatenates a field's array value with other arrays. | | function(firstMap, ...) | -| [mapMerge(firstMap, secondMap, otherMaps)](./firestore_lite_pipelines.md#mapmerge_cfe77ce) | (Public Preview) Creates an expression that merges multiple map values. | +| [mapMerge(firstMap, secondMap, otherMaps)](./firestore_lite_pipelines.md#mapmerge_cfe77ce) | Creates an expression that merges multiple map values. | | function(firstString, ...) | -| [stringConcat(firstString, secondString, otherStrings)](./firestore_lite_pipelines.md#stringconcat_8a8d1b6) | (Public Preview) Creates an expression that concatenates string expressions together. | +| [stringConcat(firstString, secondString, otherStrings)](./firestore_lite_pipelines.md#stringconcat_8a8d1b6) | Creates an expression that concatenates string expressions together. | | function(ifExpr, ...) | -| [ifAbsent(ifExpr, elseExpr)](./firestore_lite_pipelines.md#ifabsent_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | -| [ifAbsent(ifExpr, elseValue)](./firestore_lite_pipelines.md#ifabsent_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | -| [ifNull(ifExpr, elseExpr)](./firestore_lite_pipelines.md#ifnull_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is null, else return the result of the ifExpr argument evaluation. | -| [ifNull(ifExpr, elseValue)](./firestore_lite_pipelines.md#ifnull_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is null, else return the result of the ifExpr argument evaluation. | +| [ifAbsent(ifExpr, elseExpr)](./firestore_lite_pipelines.md#ifabsent_0e6d161) | Creates an expression that returns the elseExpr argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | +| [ifAbsent(ifExpr, elseValue)](./firestore_lite_pipelines.md#ifabsent_c34e5ed) | Creates an expression that returns the elseValue argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | +| [ifNull(ifExpr, elseExpr)](./firestore_lite_pipelines.md#ifnull_0e6d161) | Creates an expression that returns the elseExpr argument if ifExpr is null, else return the result of the ifExpr argument evaluation. | +| [ifNull(ifExpr, elseValue)](./firestore_lite_pipelines.md#ifnull_c34e5ed) | Creates an expression that returns the elseValue argument if ifExpr is null, else return the result of the ifExpr argument evaluation. | | function(ifFieldName, ...) | -| [ifAbsent(ifFieldName, elseExpr)](./firestore_lite_pipelines.md#ifabsent_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName is absent, else return the value of the field. | -| [ifAbsent(ifFieldName, elseValue)](./firestore_lite_pipelines.md#ifabsent_d8f2823) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName is absent, else return the value of the field. | -| [ifNull(ifFieldName, elseExpr)](./firestore_lite_pipelines.md#ifnull_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName field is null, else return the value of the field. | -| [ifNull(ifFieldName, elseValue)](./firestore_lite_pipelines.md#ifnull_587c2f0) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName field is null, else return the value of the field. | +| [ifAbsent(ifFieldName, elseExpr)](./firestore_lite_pipelines.md#ifabsent_e6dabea) | Creates an expression that returns the elseExpr argument if ifFieldName is absent, else return the value of the field. | +| [ifAbsent(ifFieldName, elseValue)](./firestore_lite_pipelines.md#ifabsent_d8f2823) | Creates an expression that returns the elseValue argument if ifFieldName is absent, else return the value of the field. | +| [ifNull(ifFieldName, elseExpr)](./firestore_lite_pipelines.md#ifnull_e6dabea) | Creates an expression that returns the elseExpr argument if ifFieldName field is null, else return the value of the field. | +| [ifNull(ifFieldName, elseValue)](./firestore_lite_pipelines.md#ifnull_587c2f0) | Creates an expression that returns the elseValue argument if ifFieldName field is null, else return the value of the field. | | function(input, ...) | -| [substring(input, position, length)](./firestore_lite_pipelines.md#substring_e6e0aa3) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | -| [substring(input, position, length)](./firestore_lite_pipelines.md#substring_ab56dc6) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| [substring(input, position, length)](./firestore_lite_pipelines.md#substring_e6e0aa3) | Creates an expression that returns a substring of a string or byte array. | +| [substring(input, position, length)](./firestore_lite_pipelines.md#substring_ab56dc6) | Creates an expression that returns a substring of a string or byte array. | | function(left, ...) | -| [divide(left, right)](./firestore_lite_pipelines.md#divide_b3c3382) | (Public Preview) Creates an expression that divides two expressions. | -| [equal(left, right)](./firestore_lite_pipelines.md#equal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are equal. | -| [greaterThan(left, right)](./firestore_lite_pipelines.md#greaterthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than the second expression. | -| [greaterThanOrEqual(left, right)](./firestore_lite_pipelines.md#greaterthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than or equal to the second expression. | -| [lessThan(left, right)](./firestore_lite_pipelines.md#lessthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than the second expression. | -| [lessThanOrEqual(left, right)](./firestore_lite_pipelines.md#lessthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than or equal to the second expression. | -| [mod(left, right)](./firestore_lite_pipelines.md#mod_b3c3382) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing two expressions. | -| [notEqual(left, right)](./firestore_lite_pipelines.md#notequal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are not equal. | -| [subtract(left, right)](./firestore_lite_pipelines.md#subtract_b3c3382) | (Public Preview) Creates an expression that subtracts two expressions. | +| [divide(left, right)](./firestore_lite_pipelines.md#divide_b3c3382) | Creates an expression that divides two expressions. | +| [equal(left, right)](./firestore_lite_pipelines.md#equal_b3c3382) | Creates an expression that checks if two expressions are equal. | +| [greaterThan(left, right)](./firestore_lite_pipelines.md#greaterthan_b3c3382) | Creates an expression that checks if the first expression is greater than the second expression. | +| [greaterThanOrEqual(left, right)](./firestore_lite_pipelines.md#greaterthanorequal_b3c3382) | Creates an expression that checks if the first expression is greater than or equal to the second expression. | +| [lessThan(left, right)](./firestore_lite_pipelines.md#lessthan_b3c3382) | Creates an expression that checks if the first expression is less than the second expression. | +| [lessThanOrEqual(left, right)](./firestore_lite_pipelines.md#lessthanorequal_b3c3382) | Creates an expression that checks if the first expression is less than or equal to the second expression. | +| [mod(left, right)](./firestore_lite_pipelines.md#mod_b3c3382) | Creates an expression that calculates the modulo (remainder) of dividing two expressions. | +| [notEqual(left, right)](./firestore_lite_pipelines.md#notequal_b3c3382) | Creates an expression that checks if two expressions are not equal. | +| [subtract(left, right)](./firestore_lite_pipelines.md#subtract_b3c3382) | Creates an expression that subtracts two expressions. | | function(mapExpr, ...) | -| [mapRemove(mapExpr, key)](./firestore_lite_pipelines.md#mapremove_23c7d51) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. | -| [mapRemove(mapExpr, keyExpr)](./firestore_lite_pipelines.md#mapremove_9fbcaa3) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. | +| [mapRemove(mapExpr, key)](./firestore_lite_pipelines.md#mapremove_23c7d51) | Creates an expression that removes a key from the map produced by evaluating an expression. | +| [mapRemove(mapExpr, keyExpr)](./firestore_lite_pipelines.md#mapremove_9fbcaa3) | Creates an expression that removes a key from the map produced by evaluating an expression. | | function(mapExpression, ...) | -| [mapEntries(mapExpression)](./firestore_lite_pipelines.md#mapentries_9cf124c) | (Public Preview) 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" }, ...]. | -| [mapGet(mapExpression, subField)](./firestore_lite_pipelines.md#mapget_688c050) | (Public Preview) Accesses a value from a map (object) expression using the provided key. | -| [mapKeys(mapExpression)](./firestore_lite_pipelines.md#mapkeys_9cf124c) | (Public Preview) Creates an expression that returns the keys of a map. | -| [mapSet(mapExpression, key, value, moreKeyValues)](./firestore_lite_pipelines.md#mapset_45b48ff) | (Public Preview) Creates an expression that returns a new map with the specified entries added or updated. | -| [mapValues(mapExpression)](./firestore_lite_pipelines.md#mapvalues_9cf124c) | (Public Preview) Creates an expression that returns the values of a map. | +| [mapEntries(mapExpression)](./firestore_lite_pipelines.md#mapentries_9cf124c) | 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" }, ...]. | +| [mapGet(mapExpression, subField)](./firestore_lite_pipelines.md#mapget_688c050) | Accesses a value from a map (object) expression using the provided key. | +| [mapKeys(mapExpression)](./firestore_lite_pipelines.md#mapkeys_9cf124c) | Creates an expression that returns the keys of a map. | +| [mapSet(mapExpression, key, value, moreKeyValues)](./firestore_lite_pipelines.md#mapset_45b48ff) | Creates an expression that returns a new map with the specified entries added or updated. | +| [mapValues(mapExpression)](./firestore_lite_pipelines.md#mapvalues_9cf124c) | Creates an expression that returns the values of a map. | | function(mapField, ...) | -| [mapEntries(mapField)](./firestore_lite_pipelines.md#mapentries_83ad836) | (Public Preview) 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" }, ...]. | -| [mapKeys(mapField)](./firestore_lite_pipelines.md#mapkeys_83ad836) | (Public Preview) Creates an expression that returns the keys of a map. | -| [mapMerge(mapField, secondMap, otherMaps)](./firestore_lite_pipelines.md#mapmerge_70a564b) | (Public Preview) Creates an expression that merges multiple map values. | -| [mapRemove(mapField, key)](./firestore_lite_pipelines.md#mapremove_bd5726e) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. | -| [mapRemove(mapField, keyExpr)](./firestore_lite_pipelines.md#mapremove_8406d13) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. | -| [mapSet(mapField, key, value, moreKeyValues)](./firestore_lite_pipelines.md#mapset_baadc2a) | (Public Preview) Creates an expression that returns a new map with the specified entries added or updated. | -| [mapValues(mapField)](./firestore_lite_pipelines.md#mapvalues_83ad836) | (Public Preview) Creates an expression that returns the values of a map. | +| [mapEntries(mapField)](./firestore_lite_pipelines.md#mapentries_83ad836) | 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" }, ...]. | +| [mapKeys(mapField)](./firestore_lite_pipelines.md#mapkeys_83ad836) | Creates an expression that returns the keys of a map. | +| [mapMerge(mapField, secondMap, otherMaps)](./firestore_lite_pipelines.md#mapmerge_70a564b) | Creates an expression that merges multiple map values. | +| [mapRemove(mapField, key)](./firestore_lite_pipelines.md#mapremove_bd5726e) | Creates an expression that removes a key from the map at the specified field name. | +| [mapRemove(mapField, keyExpr)](./firestore_lite_pipelines.md#mapremove_8406d13) | Creates an expression that removes a key from the map at the specified field name. | +| [mapSet(mapField, key, value, moreKeyValues)](./firestore_lite_pipelines.md#mapset_baadc2a) | Creates an expression that returns a new map with the specified entries added or updated. | +| [mapValues(mapField)](./firestore_lite_pipelines.md#mapvalues_83ad836) | Creates an expression that returns the values of a map. | | function(name, ...) | -| [field(name)](./firestore_lite_pipelines.md#field_1eaaff4) | (Public Preview) Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). | +| [field(name)](./firestore_lite_pipelines.md#field_1eaaff4) | Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). | | function(path, ...) | -| [field(path)](./firestore_lite_pipelines.md#field_34ee07d) | (Public Preview) Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. | +| [field(path)](./firestore_lite_pipelines.md#field_34ee07d) | Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. | | function(pipeline, ...) | -| [execute(pipeline)](./firestore_lite_pipelines.md#execute_01df620) | (Public Preview) Executes this pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:

    • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
    • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
    • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
    | +| [execute(pipeline)](./firestore_lite_pipelines.md#execute_01df620) | Executes this pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:
    • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
    • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
    • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
    | | function(stringExpression, ...) | -| [charLength(stringExpression)](./firestore_lite_pipelines.md#charlength_c25a54a) | (Public Preview) Creates an expression that calculates the character length of a string expression in UTF-8. | -| [endsWith(stringExpression, suffix)](./firestore_lite_pipelines.md#endswith_0a0b889) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. | -| [endsWith(stringExpression, suffix)](./firestore_lite_pipelines.md#endswith_13aee0d) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. | -| [like(stringExpression, pattern)](./firestore_lite_pipelines.md#like_a84c581) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. | -| [like(stringExpression, pattern)](./firestore_lite_pipelines.md#like_b534848) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. | -| [regexContains(stringExpression, pattern)](./firestore_lite_pipelines.md#regexcontains_a84c581) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. | -| [regexContains(stringExpression, pattern)](./firestore_lite_pipelines.md#regexcontains_b534848) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. | -| [regexFind(stringExpression, pattern)](./firestore_lite_pipelines.md#regexfind_a84c581) | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFind(stringExpression, pattern)](./firestore_lite_pipelines.md#regexfind_b534848) | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFindAll(stringExpression, pattern)](./firestore_lite_pipelines.md#regexfindall_a84c581) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFindAll(stringExpression, pattern)](./firestore_lite_pipelines.md#regexfindall_b534848) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexMatch(stringExpression, pattern)](./firestore_lite_pipelines.md#regexmatch_a84c581) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. | -| [regexMatch(stringExpression, pattern)](./firestore_lite_pipelines.md#regexmatch_b534848) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. | -| [reverse(stringExpression)](./firestore_lite_pipelines.md#reverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. | -| [startsWith(stringExpression, prefix)](./firestore_lite_pipelines.md#startswith_75c3dbb) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. | -| [startsWith(stringExpression, prefix)](./firestore_lite_pipelines.md#startswith_52f218a) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. | -| [stringContains(stringExpression, substring)](./firestore_lite_pipelines.md#stringcontains_3e9ff32) | (Public Preview) Creates an expression that checks if a string expression contains a specified substring. | -| [stringContains(stringExpression, substring)](./firestore_lite_pipelines.md#stringcontains_cc6ee02) | (Public Preview) Creates an expression that checks if a string expression contains a substring specified by another expression. | -| [stringReverse(stringExpression)](./firestore_lite_pipelines.md#stringreverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. | -| [toLower(stringExpression)](./firestore_lite_pipelines.md#tolower_c25a54a) | (Public Preview) Creates an expression that converts a string expression to lowercase. | -| [toUpper(stringExpression)](./firestore_lite_pipelines.md#toupper_c25a54a) | (Public Preview) Creates an expression that converts a string expression to uppercase. | -| [trim(stringExpression, valueToTrim)](./firestore_lite_pipelines.md#trim_dd54322) | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array expression. | +| [charLength(stringExpression)](./firestore_lite_pipelines.md#charlength_c25a54a) | Creates an expression that calculates the character length of a string expression in UTF-8. | +| [endsWith(stringExpression, suffix)](./firestore_lite_pipelines.md#endswith_0a0b889) | Creates an expression that checks if a string expression ends with a given postfix. | +| [endsWith(stringExpression, suffix)](./firestore_lite_pipelines.md#endswith_13aee0d) | Creates an expression that checks if a string expression ends with a given postfix. | +| [like(stringExpression, pattern)](./firestore_lite_pipelines.md#like_a84c581) | Creates an expression that performs a case-sensitive wildcard string comparison. | +| [like(stringExpression, pattern)](./firestore_lite_pipelines.md#like_b534848) | Creates an expression that performs a case-sensitive wildcard string comparison. | +| [regexContains(stringExpression, pattern)](./firestore_lite_pipelines.md#regexcontains_a84c581) | Creates an expression that checks if a string expression contains a specified regular expression as a substring. | +| [regexContains(stringExpression, pattern)](./firestore_lite_pipelines.md#regexcontains_b534848) | Creates an expression that checks if a string expression contains a specified regular expression as a substring. | +| [regexFind(stringExpression, pattern)](./firestore_lite_pipelines.md#regexfind_a84c581) | Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFind(stringExpression, pattern)](./firestore_lite_pipelines.md#regexfind_b534848) | Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(stringExpression, pattern)](./firestore_lite_pipelines.md#regexfindall_a84c581) | Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(stringExpression, pattern)](./firestore_lite_pipelines.md#regexfindall_b534848) | Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexMatch(stringExpression, pattern)](./firestore_lite_pipelines.md#regexmatch_a84c581) | Creates an expression that checks if a string expression matches a specified regular expression. | +| [regexMatch(stringExpression, pattern)](./firestore_lite_pipelines.md#regexmatch_b534848) | Creates an expression that checks if a string expression matches a specified regular expression. | +| [reverse(stringExpression)](./firestore_lite_pipelines.md#reverse_c25a54a) | Creates an expression that reverses a string. | +| [startsWith(stringExpression, prefix)](./firestore_lite_pipelines.md#startswith_75c3dbb) | Creates an expression that checks if a string expression starts with a given prefix. | +| [startsWith(stringExpression, prefix)](./firestore_lite_pipelines.md#startswith_52f218a) | Creates an expression that checks if a string expression starts with a given prefix. | +| [stringContains(stringExpression, substring)](./firestore_lite_pipelines.md#stringcontains_3e9ff32) | Creates an expression that checks if a string expression contains a specified substring. | +| [stringContains(stringExpression, substring)](./firestore_lite_pipelines.md#stringcontains_cc6ee02) | Creates an expression that checks if a string expression contains a substring specified by another expression. | +| [stringReverse(stringExpression)](./firestore_lite_pipelines.md#stringreverse_c25a54a) | Creates an expression that reverses a string. | +| [toLower(stringExpression)](./firestore_lite_pipelines.md#tolower_c25a54a) | Creates an expression that converts a string expression to lowercase. | +| [toUpper(stringExpression)](./firestore_lite_pipelines.md#toupper_c25a54a) | Creates an expression that converts a string expression to uppercase. | +| [trim(stringExpression, valueToTrim)](./firestore_lite_pipelines.md#trim_dd54322) | Creates an expression that removes leading and trailing characters from a string or byte array expression. | | function(timestamp, ...) | -| [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_98418f9) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | -| [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_06ef927) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | -| [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_98418f9) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | -| [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_06ef927) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | +| [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_98418f9) | Creates an expression that adds a specified amount of time to a timestamp. | +| [timestampAdd(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampadd_06ef927) | Creates an expression that adds a specified amount of time to a timestamp. | +| [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_98418f9) | Creates an expression that subtracts a specified amount of time from a timestamp. | +| [timestampSubtract(timestamp, unit, amount)](./firestore_lite_pipelines.md#timestampsubtract_06ef927) | Creates an expression that subtracts a specified amount of time from a timestamp. | | function(timestampExpression, ...) | -| [timestampExtract(timestampExpression, part, timezone)](./firestore_lite_pipelines.md#timestampextract_b2f8f48) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | -| [timestampExtract(timestampExpression, part, timezone)](./firestore_lite_pipelines.md#timestampextract_73e0311) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | -| [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_ad5d843) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_d6ab2a4) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampExtract(timestampExpression, part, timezone)](./firestore_lite_pipelines.md#timestampextract_b2f8f48) | Creates an expression that extracts a specified part from a timestamp. | +| [timestampExtract(timestampExpression, part, timezone)](./firestore_lite_pipelines.md#timestampextract_73e0311) | Creates an expression that extracts a specified part from a timestamp. | +| [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_ad5d843) | Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_lite_pipelines.md#timestamptruncate_d6ab2a4) | Creates an expression that truncates a timestamp to a specified granularity. | | function(tryExpr, ...) | -| [ifError(tryExpr, catchExpr)](./firestore_lite_pipelines.md#iferror_a99a327) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation.This overload is useful when a BooleanExpression is required. | -| [ifError(tryExpr, catchExpr)](./firestore_lite_pipelines.md#iferror_756c12e) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. | -| [ifError(tryExpr, catchValue)](./firestore_lite_pipelines.md#iferror_dc532f9) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. | +| [ifError(tryExpr, catchExpr)](./firestore_lite_pipelines.md#iferror_a99a327) | Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation.This overload is useful when a BooleanExpression is required. | +| [ifError(tryExpr, catchExpr)](./firestore_lite_pipelines.md#iferror_756c12e) | Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. | +| [ifError(tryExpr, catchValue)](./firestore_lite_pipelines.md#iferror_dc532f9) | Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. | | function(value, ...) | -| [constant(value)](./firestore_lite_pipelines.md#constant_0c00f91) | (Public Preview) Creates a Constant instance for a number value. | -| [constant(value)](./firestore_lite_pipelines.md#constant_6dac335) | (Public Preview) Creates a Constant instance for a VectorValue value. | -| [constant(value)](./firestore_lite_pipelines.md#constant_7c807cd) | (Public Preview) Creates a Constant instance for a string value. | -| [constant(value)](./firestore_lite_pipelines.md#constant_b2e4f8d) | (Public Preview) Creates a BooleanExpression instance for a boolean value. | -| [constant(value)](./firestore_lite_pipelines.md#constant_73ebd84) | (Public Preview) Creates a Constant instance for a null value. | -| [constant(value)](./firestore_lite_pipelines.md#constant_72a76cb) | (Public Preview) Creates a Constant instance for a GeoPoint value. | -| [constant(value)](./firestore_lite_pipelines.md#constant_000477d) | (Public Preview) Creates a Constant instance for a Timestamp value. | -| [constant(value)](./firestore_lite_pipelines.md#constant_5131bf7) | (Public Preview) Creates a Constant instance for a Date value. | -| [constant(value)](./firestore_lite_pipelines.md#constant_fdf565d) | (Public Preview) Creates a Constant instance for a Bytes value. | -| [constant(value)](./firestore_lite_pipelines.md#constant_bcd2b0b) | (Public Preview) Creates a Constant instance for a DocumentReference value. | -| [exists(value)](./firestore_lite_pipelines.md#exists_f3daf14) | (Public Preview) Creates an expression that checks if a field exists. | -| [isAbsent(value)](./firestore_lite_pipelines.md#isabsent_f3daf14) | (Public Preview) Creates an expression that returns true if a value is absent. Otherwise, returns false even if the value is null. | -| [isError(value)](./firestore_lite_pipelines.md#iserror_f3daf14) | (Public Preview) Creates an expression that checks if a given expression produces an error. | +| [constant(value)](./firestore_lite_pipelines.md#constant_0c00f91) | Creates a Constant instance for a number value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_6dac335) | Creates a Constant instance for a VectorValue value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_7c807cd) | Creates a Constant instance for a string value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_b2e4f8d) | Creates a BooleanExpression instance for a boolean value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_73ebd84) | Creates a Constant instance for a null value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_72a76cb) | Creates a Constant instance for a GeoPoint value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_000477d) | Creates a Constant instance for a Timestamp value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_5131bf7) | Creates a Constant instance for a Date value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_fdf565d) | Creates a Constant instance for a Bytes value. | +| [constant(value)](./firestore_lite_pipelines.md#constant_bcd2b0b) | Creates a Constant instance for a DocumentReference value. | +| [exists(value)](./firestore_lite_pipelines.md#exists_f3daf14) | Creates an expression that checks if a field exists. | +| [isAbsent(value)](./firestore_lite_pipelines.md#isabsent_f3daf14) | Creates an expression that returns true if a value is absent. Otherwise, returns false even if the value is null. | +| [isError(value)](./firestore_lite_pipelines.md#iserror_f3daf14) | Creates an expression that checks if a given expression produces an error. | | function(vectorExpression, ...) | -| [cosineDistance(vectorExpression, vector)](./firestore_lite_pipelines.md#cosinedistance_3a80317) | (Public Preview) Calculates the Cosine distance between a vector expression and a vector literal. | -| [cosineDistance(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#cosinedistance_17b5bcc) | (Public Preview) Calculates the Cosine distance between two vector expressions. | -| [dotProduct(vectorExpression, vector)](./firestore_lite_pipelines.md#dotproduct_3a80317) | (Public Preview) Calculates the dot product between a vector expression and a double array. | -| [dotProduct(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#dotproduct_17b5bcc) | (Public Preview) Calculates the dot product between two vector expressions. | -| [euclideanDistance(vectorExpression, vector)](./firestore_lite_pipelines.md#euclideandistance_3a80317) | (Public Preview) Calculates the Euclidean distance between a vector expression and a double array. | -| [euclideanDistance(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#euclideandistance_17b5bcc) | (Public Preview) Calculates the Euclidean distance between two vector expressions. | -| [vectorLength(vectorExpression)](./firestore_lite_pipelines.md#vectorlength_58a039b) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector. | +| [cosineDistance(vectorExpression, vector)](./firestore_lite_pipelines.md#cosinedistance_3a80317) | Calculates the Cosine distance between a vector expression and a vector literal. | +| [cosineDistance(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#cosinedistance_17b5bcc) | Calculates the Cosine distance between two vector expressions. | +| [dotProduct(vectorExpression, vector)](./firestore_lite_pipelines.md#dotproduct_3a80317) | Calculates the dot product between a vector expression and a double array. | +| [dotProduct(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#dotproduct_17b5bcc) | Calculates the dot product between two vector expressions. | +| [euclideanDistance(vectorExpression, vector)](./firestore_lite_pipelines.md#euclideandistance_3a80317) | Calculates the Euclidean distance between a vector expression and a double array. | +| [euclideanDistance(vectorExpression, otherVectorExpression)](./firestore_lite_pipelines.md#euclideandistance_17b5bcc) | Calculates the Euclidean distance between two vector expressions. | +| [vectorLength(vectorExpression)](./firestore_lite_pipelines.md#vectorlength_58a039b) | Creates an expression that calculates the length of a Firestore Vector. | ## Classes | Class | Description | | --- | --- | -| [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) | (Public Preview) A class that represents an aggregate function. | -| [AliasedAggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregate_class) | (Public Preview) An AggregateFunction with alias. | -| [AliasedExpression](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpression_class) | (Public Preview) | -| [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | (Public Preview) An interface that represents a filter condition. | +| [AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class) | A class that represents an aggregate function. | +| [AliasedAggregate](./firestore_lite_pipelines.aliasedaggregate.md#aliasedaggregate_class) | An AggregateFunction with alias. | +| [AliasedExpression](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpression_class) | | +| [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | An interface that represents a filter condition. | | [Bytes](./firestore_lite_pipelines.bytes.md#bytes_class) | An immutable object representing an array of bytes. | | [CollectionReference](./firestore_lite_pipelines.collectionreference.md#collectionreference_class) | A CollectionReference object can be used for adding documents, getting document references, and querying for documents (using [query()](./firestore_.md#query_9f7b0f4)). | | [DocumentReference](./firestore_lite_pipelines.documentreference.md#documentreference_class) | A DocumentReference refers to a document location in a Firestore database and can be used to write, read, or listen to the location. The document at the referenced location may or may not exist. | | [DocumentSnapshot](./firestore_lite_pipelines.documentsnapshot.md#documentsnapshot_class) | A DocumentSnapshot contains data read from a document in your Firestore database. The data can be extracted with .data() or .get(<field>) to get a specific field.For a DocumentSnapshot that points to a non-existing document, any data access will return 'undefined'. You can use the exists() method to explicitly verify a document's existence. | -| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | (Public Preview) Represents an expression that can be evaluated to a value within the execution of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class).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. | -| [Field](./firestore_lite_pipelines.field.md#field_class) | (Public Preview) Represents a reference to a field in a Firestore document, or outputs of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) stage.

    Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines.

    You can create a Field instance using the static method: | +| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Represents an expression that can be evaluated to a value within the execution of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class).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. | +| [Field](./firestore_lite_pipelines.field.md#field_class) | Represents a reference to a field in a Firestore document, or outputs of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) stage.

    Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines.

    You can create a Field instance using the static method: | | [FieldPath](./firestore_lite_pipelines.fieldpath.md#fieldpath_class) | A FieldPath refers to a field in a document. The path may consist of a single field name (referring to a top-level field in the document), or a list of field names (referring to a nested field in the document).Create a FieldPath by providing field names. If more than one field name is provided, the path will point to a nested field in a document. | | [FieldValue](./firestore_lite_pipelines.fieldvalue.md#fieldvalue_class) | Sentinel values that can be used when writing document fields with set() or update(). | | [Firestore](./firestore_lite_pipelines.firestore.md#firestore_class) | The Cloud Firestore service interface.Do not call this constructor directly. Instead, use [getFirestore()](./firestore_.md#getfirestore). | -| [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) | (Public Preview) This class defines the base class for Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) functions, which can be evaluated within pipeline execution.Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_pipelines.md#and_e0c48bd), [equal()](./firestore_pipelines.md#equal_b3c3382), or the methods on [Expression](./firestore_pipelines.expression.md#expression_class) ([Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), etc.) to construct new Function instances. | +| [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) | This class defines the base class for Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) functions, which can be evaluated within pipeline execution.Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_pipelines.md#and_e0c48bd), [equal()](./firestore_pipelines.md#equal_b3c3382), or the methods on [Expression](./firestore_pipelines.expression.md#expression_class) ([Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), etc.) to construct new Function instances. | | [GeoPoint](./firestore_lite_pipelines.geopoint.md#geopoint_class) | An immutable object representing a geographic location in Firestore. The location is represented as latitude/longitude pair.Latitude values are in the range of \[-90, 90\]. Longitude values are in the range of \[-180, 180\]. | -| [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) | (Public Preview) Represents an ordering criterion for sorting documents in a Firestore pipeline.You create Ordering instances using the ascending and descending helper functions. | -| [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) | (Public Preview) The Pipeline class provides a flexible and expressive framework for building complex data transformation and query pipelines for Firestore.A pipeline takes data sources, such as Firestore collections or collection groups, and applies a series of stages that are chained together. Each stage takes the output from the previous stage (or the data source) and produces an output for the next stage (or as the final output of the pipeline).Expressions can be used within each stage to filter and transform data through the stage.NOTE: The chained stages do not prescribe exactly how Firestore will execute the pipeline. Instead, Firestore only guarantees that the result is the same as if the chained stages were executed in order.Usage Examples: | -| [PipelineResult](./firestore_lite_pipelines.pipelineresult.md#pipelineresult_class) | (Public Preview) A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the [PipelineResult.data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) or [PipelineResult.get()](./firestore_pipelines.pipelineresult.md#pipelineresultget) methods.

    If the PipelineResult represents a non-document result, ref will return a undefined value. | -| [PipelineSnapshot](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) | (Public Preview) Represents the results of a Firestore pipeline execution.A PipelineSnapshot contains zero or more [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. | -| [PipelineSource](./firestore_lite_pipelines.pipelinesource.md#pipelinesource_class) | (Public Preview) Provides the entry point for defining the data source of a Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class).Use the methods of this class (e.g., [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection), [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup), [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase), or [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments)) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. | +| [Ordering](./firestore_lite_pipelines.ordering.md#ordering_class) | Represents an ordering criterion for sorting documents in a Firestore pipeline.You create Ordering instances using the ascending and descending helper functions. | +| [Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) | The Pipeline class provides a flexible and expressive framework for building complex data transformation and query pipelines for Firestore.A pipeline takes data sources, such as Firestore collections or collection groups, and applies a series of stages that are chained together. Each stage takes the output from the previous stage (or the data source) and produces an output for the next stage (or as the final output of the pipeline).Expressions can be used within each stage to filter and transform data through the stage.NOTE: The chained stages do not prescribe exactly how Firestore will execute the pipeline. Instead, Firestore only guarantees that the result is the same as if the chained stages were executed in order.Usage Examples: | +| [PipelineResult](./firestore_lite_pipelines.pipelineresult.md#pipelineresult_class) | A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the [PipelineResult.data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) or [PipelineResult.get()](./firestore_pipelines.pipelineresult.md#pipelineresultget) methods.

    If the PipelineResult represents a non-document result, ref will return a undefined value. | +| [PipelineSnapshot](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) | Represents the results of a Firestore pipeline execution.A PipelineSnapshot contains zero or more [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. | +| [PipelineSource](./firestore_lite_pipelines.pipelinesource.md#pipelinesource_class) | Provides the entry point for defining the data source of a Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class).Use the methods of this class (e.g., [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection), [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup), [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase), or [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments)) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. | | [Query](./firestore_lite_pipelines.query.md#query_class) | A Query refers to a query which you can read or listen to. You can also construct refined Query objects by adding filters and ordering. | | [QueryDocumentSnapshot](./firestore_lite_pipelines.querydocumentsnapshot.md#querydocumentsnapshot_class) | A QueryDocumentSnapshot contains data read from a document in your Firestore database as part of a query. The document is guaranteed to exist and its data can be extracted with .data() or .get(<field>) to get a specific field.A QueryDocumentSnapshot offers the same API surface as a DocumentSnapshot. Since query results contain only existing documents, the exists property will always be true and data() will never return 'undefined'. | | [Timestamp](./firestore_lite_pipelines.timestamp.md#timestamp_class) | A Timestamp represents a point in time independent of any time zone or calendar, represented as seconds and fractions of seconds at nanosecond resolution in UTC Epoch time.It is encoded using the Proleptic Gregorian Calendar which extends the Gregorian calendar backwards to year one. It is encoded assuming all minutes are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.For examples and further specifications, refer to the [Timestamp definition](https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto). | @@ -435,49 +435,46 @@ https://github.com/firebase/firebase-js-sdk | --- | --- | | [DocumentData](./firestore_lite_pipelines.documentdata.md#documentdata_interface) | Document data (for use with [setDoc()](./firestore_lite.md#setdoc_ee215ad)) consists of fields mapped to values. | | [FirestoreDataConverter](./firestore_lite_pipelines.firestoredataconverter.md#firestoredataconverter_interface) | Converter used by withConverter() to transform user objects of type AppModelType into Firestore data of type DbModelType.Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore.In this context, an "AppModel" is a class that is used in an application to package together related information and functionality. Such a class could, for example, have properties with complex, nested data types, properties used for memoization, properties of types not supported by Firestore (such as symbol and bigint), and helper functions that perform compound operations. Such classes are not suitable and/or possible to store into a Firestore database. Instead, instances of such classes need to be converted to "plain old JavaScript objects" (POJOs) with exclusively primitive properties, potentially nested inside other POJOs or arrays of POJOs. In this context, this type is referred to as the "DbModel" and would be an object suitable for persisting into Firestore. For convenience, applications can implement FirestoreDataConverter and register the converter with Firestore objects, such as DocumentReference or Query, to automatically convert AppModel to DbModel when storing into Firestore, and convert DbModel to AppModel when retrieving from Firestore. | -| [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) | (Public Preview) An interface that represents a selectable expression. | -| [StageOptions](./firestore_lite_pipelines.stageoptions.md#stageoptions_interface) | (Public Preview) Options defining how a Stage is evaluated. | +| [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) | An interface that represents a selectable expression. | +| [StageOptions](./firestore_lite_pipelines.stageoptions.md#stageoptions_interface) | Options defining how a Stage is evaluated. | ## Type Aliases | Type Alias | Description | | --- | --- | -| [AddFieldsStageOptions](./firestore_lite_pipelines.md#addfieldsstageoptions) | (Public Preview) Options defining how an AddFieldsStage is evaluated. See [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields). | -| [AggregateStageOptions](./firestore_lite_pipelines.md#aggregatestageoptions) | (Public Preview) Options defining how an AggregateStage is evaluated. See [Pipeline.aggregate()](./firestore_pipelines.pipeline.md#pipelineaggregate). | -| [CollectionGroupStageOptions](./firestore_lite_pipelines.md#collectiongroupstageoptions) | (Public Preview) Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution.See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. | -| [CollectionStageOptions](./firestore_lite_pipelines.md#collectionstageoptions) | (Public Preview) Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). | -| [DatabaseStageOptions](./firestore_lite_pipelines.md#databasestageoptions) | (Public Preview) Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). | -| [DistinctStageOptions](./firestore_lite_pipelines.md#distinctstageoptions) | (Public Preview) Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). | -| [DocumentsStageOptions](./firestore_lite_pipelines.md#documentsstageoptions) | (Public Preview) Options defining how a DocumentsStage is evaluated. See [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments). | -| [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | (Public Preview) An enumeration of the different types of expressions. | -| [FindNearestStageOptions](./firestore_lite_pipelines.md#findneareststageoptions) | (Public Preview) Options defining how a FindNearestStage is evaluated. See [Pipeline.findNearest()](./firestore_pipelines.pipeline.md#pipelinefindnearest). | -| [LimitStageOptions](./firestore_lite_pipelines.md#limitstageoptions) | (Public Preview) Options defining how a LimitStage is evaluated. See [Pipeline.limit()](./firestore_pipelines.pipeline.md#pipelinelimit). | -| [OffsetStageOptions](./firestore_lite_pipelines.md#offsetstageoptions) | (Public Preview) Options defining how an OffsetStage is evaluated. See [Pipeline.offset()](./firestore_pipelines.pipeline.md#pipelineoffset). | -| [OneOf](./firestore_lite_pipelines.md#oneof) | (Public Preview) Utility type to create an type that only allows one property of the Type param T to be set. | +| [AddFieldsStageOptions](./firestore_lite_pipelines.md#addfieldsstageoptions) | Options defining how an AddFieldsStage is evaluated. See [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields). | +| [AggregateStageOptions](./firestore_lite_pipelines.md#aggregatestageoptions) | Options defining how an AggregateStage is evaluated. See [Pipeline.aggregate()](./firestore_pipelines.pipeline.md#pipelineaggregate). | +| [CollectionGroupStageOptions](./firestore_lite_pipelines.md#collectiongroupstageoptions) | Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution.See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. | +| [CollectionStageOptions](./firestore_lite_pipelines.md#collectionstageoptions) | Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). | +| [DatabaseStageOptions](./firestore_lite_pipelines.md#databasestageoptions) | Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). | +| [DistinctStageOptions](./firestore_lite_pipelines.md#distinctstageoptions) | Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). | +| [DocumentsStageOptions](./firestore_lite_pipelines.md#documentsstageoptions) | Options defining how a DocumentsStage is evaluated. See [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments). | +| [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | An enumeration of the different types of expressions. | +| [FindNearestStageOptions](./firestore_lite_pipelines.md#findneareststageoptions) | Options defining how a FindNearestStage is evaluated. See [Pipeline.findNearest()](./firestore_pipelines.pipeline.md#pipelinefindnearest). | +| [LimitStageOptions](./firestore_lite_pipelines.md#limitstageoptions) | Options defining how a LimitStage is evaluated. See [Pipeline.limit()](./firestore_pipelines.pipeline.md#pipelinelimit). | +| [OffsetStageOptions](./firestore_lite_pipelines.md#offsetstageoptions) | Options defining how an OffsetStage is evaluated. See [Pipeline.offset()](./firestore_pipelines.pipeline.md#pipelineoffset). | +| [OneOf](./firestore_lite_pipelines.md#oneof) | Utility type to create an type that only allows one property of the Type param T to be set. | | [PartialWithFieldValue](./firestore_lite_pipelines.md#partialwithfieldvalue) | Similar to TypeScript's Partial<T>, but allows nested fields to be omitted and FieldValues to be passed in as property values. | | [Primitive](./firestore_lite_pipelines.md#primitive) | Primitive types. | -| [RemoveFieldsStageOptions](./firestore_lite_pipelines.md#removefieldsstageoptions) | (Public Preview) Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). | -| [ReplaceWithStageOptions](./firestore_lite_pipelines.md#replacewithstageoptions) | (Public Preview) Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). | -| [SampleStageOptions](./firestore_lite_pipelines.md#samplestageoptions) | (Public Preview) Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied.See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. | -| [SelectStageOptions](./firestore_lite_pipelines.md#selectstageoptions) | (Public Preview) Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). | +| [RemoveFieldsStageOptions](./firestore_lite_pipelines.md#removefieldsstageoptions) | Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). | +| [ReplaceWithStageOptions](./firestore_lite_pipelines.md#replacewithstageoptions) | Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). | +| [SampleStageOptions](./firestore_lite_pipelines.md#samplestageoptions) | Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied.See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. | +| [SelectStageOptions](./firestore_lite_pipelines.md#selectstageoptions) | Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). | | [SetOptions](./firestore_lite_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | -| [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | -| [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | (Public Preview) Specify time granularity for expressions. | -| [TimePart](./firestore_lite_pipelines.md#timepart) | (Public Preview) Specify time parts for timestampExtract expressions. | -| [TimeUnit](./firestore_lite_pipelines.md#timeunit) | (Public Preview) Specify time units for expressions. | -| [Type](./firestore_lite_pipelines.md#type) | (Public Preview) An enumeration of the different types generated by the Firestore backend.

    • Numerics evaluate directly to backend representation (int64 or float64), not JS number.
    • JavaScript Date and firestore Timestamp objects strictly evaluate to 'timestamp'.
    • Advanced configurations parsing backend types (such as decimal128, max_key or min_key from BSON) are also incorporated in this union string type. Note that decimal128 is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    | -| [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | -| [UnnestStageOptions](./firestore_lite_pipelines.md#unneststageoptions) | (Public Preview) Represents the specific options available for configuring an UnnestStage within a pipeline. | -| [WhereStageOptions](./firestore_lite_pipelines.md#wherestageoptions) | (Public Preview) Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). | +| [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | +| [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | Specify time granularity for expressions. | +| [TimePart](./firestore_lite_pipelines.md#timepart) | Specify time parts for timestampExtract expressions. | +| [TimeUnit](./firestore_lite_pipelines.md#timeunit) | Specify time units for expressions. | +| [Type](./firestore_lite_pipelines.md#type) | An enumeration of the different types generated by the Firestore backend.
    • Numerics evaluate directly to backend representation (int64 or float64), not JS number.
    • JavaScript Date and firestore Timestamp objects strictly evaluate to 'timestamp'.
    • Advanced configurations parsing backend types (such as decimal128, max_key or min_key from BSON) are also incorporated in this union string type. Note that decimal128 is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    | +| [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | +| [UnnestStageOptions](./firestore_lite_pipelines.md#unneststageoptions) | Represents the specific options available for configuring an UnnestStage within a pipeline. | +| [WhereStageOptions](./firestore_lite_pipelines.md#wherestageoptions) | Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). | | [WithFieldValue](./firestore_lite_pipelines.md#withfieldvalue) | Allows FieldValues to be passed in as a property value while maintaining type safety. | ## function() ### countAll() {:#countall} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the total number of stage inputs. Signature: @@ -502,9 +499,6 @@ countAll().as("totalDocument"); ### currentTimestamp() {:#currenttimestamp} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to the current server timestamp. Signature: @@ -529,9 +523,6 @@ currentTimestamp() ### rand() {:#rand} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. Signature: @@ -558,9 +549,6 @@ rand(); ### arrayContains(array, element) {:#arraycontains_a00ea48} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array expression contains a specific element. Signature: @@ -593,9 +581,6 @@ arrayContains(field("colors"), field("selectedColor")); ### arrayContains(array, element) {:#arraycontains_7328608} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array expression contains a specific element. Signature: @@ -628,9 +613,6 @@ arrayContains(field("colors"), "red"); ### arrayContainsAll(array, values) {:#arraycontainsall_c658ad5} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array expression contains all the specified elements. Signature: @@ -663,9 +645,6 @@ arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]) ### arrayContainsAll(array, arrayExpression) {:#arraycontainsall_7b535db} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array expression contains all the specified elements. Signature: @@ -698,9 +677,6 @@ arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]) ### arrayContainsAny(array, values) {:#arraycontainsany_c658ad5} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array expression contains any of the specified elements. Signature: @@ -733,9 +709,6 @@ arrayContainsAny(field("categories"), [field("cate1"), "Science"]); ### arrayContainsAny(array, values) {:#arraycontainsany_c381a96} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array expression contains any of the specified elements. Signature: @@ -768,9 +741,6 @@ arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); ### arrayLength(array) {:#arraylength_195e339} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of an array expression. Signature: @@ -804,9 +774,6 @@ arrayLength(field("cart")); ### arrayFirst(arrayExpression) {:#arrayfirst_f574e12} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first element of an array. Signature: @@ -838,9 +805,6 @@ arrayFirst(field("tags")); ### arrayFirstN(arrayExpression, n) {:#arrayfirstn_bff7f91} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first `n` elements of an array. Signature: @@ -873,9 +837,6 @@ arrayFirstN(field("tags"), 3); ### arrayFirstN(arrayExpression, n) {:#arrayfirstn_19b4ef8} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first `n` elements of an array. Signature: @@ -908,9 +869,6 @@ arrayFirstN(field("tags"), field("count")); ### arrayGet(arrayExpression, offset) {:#arrayget_f2e27cc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: @@ -943,9 +901,6 @@ arrayGet(field('tags'), 1); ### arrayGet(arrayExpression, offsetExpr) {:#arrayget_484550d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: @@ -979,9 +934,6 @@ arrayGet(field('tags'), field('favoriteTag')); ### arrayIndexOf(arrayExpression, search) {:#arrayindexof_694a0b4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. Signature: @@ -1014,9 +966,6 @@ arrayIndexOf(field("tags"), "politics"); ### arrayIndexOfAll(arrayExpression, search) {:#arrayindexofall_694a0b4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns all indices of the search value in an array. Signature: @@ -1049,9 +998,6 @@ arrayIndexOfAll(field("scores"), 5); ### arrayLast(arrayExpression) {:#arraylast_f574e12} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last element of an array. Signature: @@ -1083,9 +1029,6 @@ arrayLast(field("tags")); ### arrayLastIndexOf(arrayExpression, search) {:#arraylastindexof_694a0b4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. Signature: @@ -1118,9 +1061,6 @@ arrayLastIndexOf(field("tags"), "politics"); ### arrayLastN(arrayExpression, n) {:#arraylastn_bff7f91} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last `n` elements of an array. Signature: @@ -1153,9 +1093,6 @@ arrayLastN(field("tags"), 3); ### arrayLastN(arrayExpression, n) {:#arraylastn_19b4ef8} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last `n` elements of an array. Signature: @@ -1188,9 +1125,6 @@ arrayLastN(field("tags"), field("count")); ### arrayMaximum(arrayExpression) {:#arraymaximum_f574e12} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the maximum value in an array. Signature: @@ -1222,9 +1156,6 @@ arrayMaximum(field("scores")); ### arrayMaximumN(arrayExpression, n) {:#arraymaximumn_bff7f91} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the largest `n` elements of an array. Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1259,9 +1190,6 @@ arrayMaximumN(field("scores"), 3); ### arrayMaximumN(arrayExpression, n) {:#arraymaximumn_19b4ef8} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the largest `n` elements of an array. Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1296,9 +1224,6 @@ arrayMaximumN(field("scores"), field("count")); ### arrayMinimum(arrayExpression) {:#arrayminimum_f574e12} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the minimum value in an array. Signature: @@ -1330,9 +1255,6 @@ arrayMinimum(field("scores")); ### arrayMinimumN(arrayExpression, n) {:#arrayminimumn_bff7f91} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smallest `n` elements of an array. Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1367,9 +1289,6 @@ arrayMinimumN(field("scores"), 3); ### arrayMinimumN(arrayExpression, n) {:#arrayminimumn_19b4ef8} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smallest `n` elements of an array. Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1404,9 +1323,6 @@ arrayMinimumN(field("scores"), field("count")); ### join(arrayExpression, delimiterExpression) {:#join_313e6aa} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that joins the elements of an array into a string. Signature: @@ -1439,9 +1355,6 @@ join(array(['foo', 'bar']), field("separator")) ### join(arrayExpression, delimiter) {:#join_d088d29} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that joins the elements of an array into a string. Signature: @@ -1476,9 +1389,6 @@ join(field("tags"), ", ") ### arrayGet(arrayField, offset) {:#arrayget_3f58471} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: @@ -1511,9 +1421,6 @@ arrayGet('tags', 1); ### arrayGet(arrayField, offsetExpr) {:#arrayget_1904c9a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: @@ -1549,9 +1456,6 @@ arrayGet('tags', field('favoriteTag')); ### join(arrayFieldName, delimiter) {:#join_478ef36} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that joins the elements of an array into a string. Signature: @@ -1584,9 +1488,6 @@ join("tags", ", ") ### join(arrayFieldName, delimiterExpression) {:#join_829294c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that joins the elements of an array into a string. Signature: @@ -1621,9 +1522,6 @@ join('tags', field("separator")) ### pow(base, exponent) {:#pow_e4a9e64} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the value of the base expression raised to the power of the exponent expression. Signature: @@ -1656,9 +1554,6 @@ pow(field("base"), field("exponent")); ### pow(base, exponent) {:#pow_93eae7f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the value of the base expression raised to the power of the exponent. Signature: @@ -1691,9 +1586,6 @@ pow(field("base"), 2); ### pow(base, exponent) {:#pow_a237721} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the value of the base field raised to the power of the exponent expression. Signature: @@ -1726,9 +1618,6 @@ pow("base", field("exponent")); ### pow(base, exponent) {:#pow_f4d7908} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the value of the base field raised to the power of the exponent. Signature: @@ -1763,9 +1652,6 @@ pow("base", 2); ### countIf(booleanExpr) {:#countif_c5b8fb1} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. Signature: @@ -1797,9 +1683,6 @@ countIf(field("is_active").equal(true)).as("numActiveDocuments"); ### not(booleanExpr) {:#not_c5b8fb1} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that negates a filter condition. Signature: @@ -1833,9 +1716,6 @@ not(equal("completed", true)); ### conditional(condition, thenExpr, elseExpr) {:#conditional_07a206d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. Signature: @@ -1870,9 +1750,6 @@ conditional( ### switchOn(condition, result, others) {:#switchon_02b8caf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to the result corresponding to the first true condition. This function behaves like a `switch` statement. It accepts an alternating sequence of conditions and their corresponding results. If an odd number of arguments is provided, the final argument serves as a default fallback result. If no default is provided and no condition evaluates to true, it throws an error. @@ -1915,9 +1792,6 @@ switchOn( ### documentId(documentPath) {:#documentid_cef293c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the document ID from a path. Signature: @@ -1951,9 +1825,6 @@ documentId(myDocumentReference); ### documentId(documentPathExpr) {:#documentid_9a69021} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the document ID from a path. Signature: @@ -1987,9 +1858,6 @@ documentId(field("__path__")); ### notEqualAny(element, values) {:#notequalany_c2c5bcb} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is not equal to any of the provided values or expressions. Signature: @@ -2022,9 +1890,6 @@ notEqualAny(field("status"), ["pending", field("rejectedStatus")]); ### notEqualAny(element, arrayExpression) {:#notequalany_16b2851} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is not equal to any of the provided values or expressions. Signature: @@ -2059,9 +1924,6 @@ notEqualAny(field("status"), ["pending", field("rejectedStatus")]); ### array(elements) {:#array_7d853aa} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that creates a Firestore array value from an input array. Signature: @@ -2093,9 +1955,6 @@ array(['bar', field('baz')]).as('foo'); ### map(elements) {:#map_ce5dee1} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that creates a Firestore map value from an input object. Signature: @@ -2129,9 +1988,6 @@ map({foo: 'bar', baz: field('baz')}).as('data'); ### timestampDiff(endExpression, startFieldName, unit) {:#timestampdiff_4370feb} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the difference between two timestamps. Signature: @@ -2165,9 +2021,6 @@ timestampDiff(field('endTime'), 'startTime', 'day') ### timestampDiff(endExpression, startExpression, unit) {:#timestampdiff_bc0830f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the difference between two timestamps. Signature: @@ -2203,9 +2056,6 @@ timestampDiff(field('endTime'), field('startTime'), 'day') ### timestampDiff(endFieldName, startFieldName, unit) {:#timestampdiff_f60102c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the difference between two timestamps. Signature: @@ -2239,9 +2089,6 @@ timestampDiff('endTime', 'startTime', 'day') ### timestampDiff(endFieldName, startExpression, unit) {:#timestampdiff_6e54d92} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the difference between two timestamps. Signature: @@ -2277,9 +2124,6 @@ timestampDiff('endTime', field('startTime'), 'day') ### abs(expr) {:#abs_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the absolute value of a numeric value. Signature: @@ -2302,9 +2146,6 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ### ascending(expr) {:#ascending_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. Signature: @@ -2337,9 +2178,6 @@ firestore.pipeline().collection("users") ### byteLength(expr) {:#bytelength_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. Signature: @@ -2371,9 +2209,6 @@ byteLength(field("myString")); ### countDistinct(expr) {:#countdistinct_3c28b08} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the number of distinct values of a field. Signature: @@ -2396,9 +2231,6 @@ A new `AggregateFunction` representing the 'count\_distinct' aggregation. ### descending(expr) {:#descending_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. Signature: @@ -2431,9 +2263,6 @@ firestore.pipeline().collection("users") ### floor(expr) {:#floor_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the floor of a numeric value. Signature: @@ -2456,9 +2285,6 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ### timestampToUnixMicros(expr) {:#timestamptounixmicros_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -2490,9 +2316,6 @@ timestampToUnixMicros(field("timestamp")); ### timestampToUnixMillis(expr) {:#timestamptounixmillis_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -2524,9 +2347,6 @@ timestampToUnixMillis(field("timestamp")); ### timestampToUnixSeconds(expr) {:#timestamptounixseconds_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -2558,9 +2378,6 @@ timestampToUnixSeconds(field("timestamp")); ### unixMicrosToTimestamp(expr) {:#unixmicrostotimestamp_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. Signature: @@ -2592,9 +2409,6 @@ unixMicrosToTimestamp(field("microseconds")); ### unixMillisToTimestamp(expr) {:#unixmillistotimestamp_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. Signature: @@ -2626,9 +2440,6 @@ unixMillisToTimestamp(field("milliseconds")); ### unixSecondsToTimestamp(expr) {:#unixsecondstotimestamp_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. Signature: @@ -2662,9 +2473,6 @@ unixSecondsToTimestamp(field("seconds")); ### arrayAgg(expression) {:#arrayagg_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. 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. @@ -2698,9 +2506,6 @@ arrayAgg(field("tags")).as("allTags"); ### arrayAggDistinct(expression) {:#arrayaggdistinct_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. 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. @@ -2734,9 +2539,6 @@ arrayAggDistinct(field("tags")).as("allDistinctTags"); ### arraySum(expression) {:#arraysum_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the sum of the elements in an array. Signature: @@ -2768,9 +2570,6 @@ arraySum(field("scores")); ### average(expression) {:#average_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. Signature: @@ -2802,9 +2601,6 @@ average(field("age")).as("averageAge"); ### ceil(expression) {:#ceil_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the ceiling of a numeric value. Signature: @@ -2836,9 +2632,6 @@ ceil(field("price")); ### coalesce(expression, replacement, others) {:#coalesce_00859cb} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. Signature: @@ -2873,9 +2666,6 @@ coalesce(field("preferredName"), field("fullName"), constant("Anonymous")) ### collectionId(expression) {:#collectionid_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the collection ID from a path. Signature: @@ -2907,9 +2697,6 @@ collectionId(field("__name__")); ### count(expression) {:#count_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. Signature: @@ -2941,9 +2728,6 @@ count(field("price").greaterThan(10)).as("expensiveItemCount"); ### divide(expression, value) {:#divide_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that divides an expression by a constant value. Signature: @@ -2976,9 +2760,6 @@ divide(field("value"), 10); ### equal(expression, value) {:#equal_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is equal to a constant value. Signature: @@ -3011,9 +2792,6 @@ equal(field("age"), 21); ### equalAny(expression, values) {:#equalany_7e759b5} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. Signature: @@ -3046,9 +2824,6 @@ equalAny(field("category"), [constant("Electronics"), field("primaryType")]); ### equalAny(expression, arrayExpression) {:#equalany_214ce68} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is equal to any of the provided values. Signature: @@ -3081,9 +2856,6 @@ equalAny(field("category"), field('disabledCategories')); ### exp(expression) {:#exp_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes e to the power of the expression's result. Signature: @@ -3115,9 +2887,6 @@ exp(constant(2)); ### first(expression) {:#first_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the first value of an expression across multiple stage inputs. Signature: @@ -3149,9 +2918,6 @@ first(field("rating")).as("firstRating"); ### greaterThan(expression, value) {:#greaterthan_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is greater than a constant value. Signature: @@ -3184,9 +2950,6 @@ greaterThan(field("age"), 18); ### greaterThanOrEqual(expression, value) {:#greaterthanorequal_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is greater than or equal to a constant value. Signature: @@ -3219,9 +2982,6 @@ greaterThanOrEqual(field("quantity"), 10); ### isType(expression, type) {:#istype_27398ce} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the result of an expression is of the given type. Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. @@ -3256,9 +3016,6 @@ isType(add('count', 1), 'number') ### last(expression) {:#last_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the last value of an expression across multiple stage inputs. Signature: @@ -3290,9 +3047,6 @@ last(field("rating")).as("lastRating"); ### length\_2(expression) {:#length_2_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of a string, array, map, vector, or bytes. Signature: @@ -3327,9 +3081,6 @@ length(field("cart")); ### lessThan(expression, value) {:#lessthan_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is less than a constant value. Signature: @@ -3362,9 +3113,6 @@ lessThan(field("age"), 30); ### lessThanOrEqual(expression, value) {:#lessthanorequal_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is less than or equal to a constant value. Signature: @@ -3397,9 +3145,6 @@ lessThan(field("quantity"), 20); ### ln(expression) {:#ln_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the natural logarithm of a numeric value. Signature: @@ -3431,9 +3176,6 @@ ln(field("value")); ### log(expression, base) {:#log_ac183e2} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the logarithm of an expression to a given base. Signature: @@ -3466,9 +3208,6 @@ log(field("value"), 10); ### log(expression, base) {:#log_1894737} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the logarithm of an expression to a given base. Signature: @@ -3501,9 +3240,6 @@ log(field("value"), field("base")); ### log10(expression) {:#log10_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the base-10 logarithm of a numeric value. Signature: @@ -3535,9 +3271,6 @@ log10(field("value")); ### ltrim(expression, valueToTrim) {:#ltrim_775e2f2} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. Signature: @@ -3573,9 +3306,6 @@ ltrim(field("userInput"), '"'); ### maximum(expression) {:#maximum_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. Signature: @@ -3607,9 +3337,6 @@ maximum(field("score")).as("highestScore"); ### minimum(expression) {:#minimum_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. Signature: @@ -3641,9 +3368,6 @@ minimum(field("price")).as("lowestPrice"); ### mod(expression, value) {:#mod_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. Signature: @@ -3676,9 +3400,6 @@ mod(field("field1"), 5); ### notEqual(expression, value) {:#notequal_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is not equal to a constant value. Signature: @@ -3711,9 +3432,6 @@ notEqual(field("status"), "completed"); ### round(expression) {:#round_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the nearest whole number. Signature: @@ -3745,9 +3463,6 @@ round(field("price")); ### round(expression, decimalPlaces) {:#round_a3a92d0} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the specified number of decimal places. Signature: @@ -3780,9 +3495,6 @@ round(field("price"), constant(2)); ### rtrim(expression, valueToTrim) {:#rtrim_775e2f2} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. Signature: @@ -3818,9 +3530,6 @@ rtrim(field("userInput"), '"'); ### split(expression, delimiter) {:#split_5b5612b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that splits a string into an array of substrings based on the provided delimiter. Signature: @@ -3853,9 +3562,6 @@ split(field('scoresCsv'), ',') ### split(expression, delimiter) {:#split_5a171ed} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that splits a string into an array of substrings based on the provided delimiter. Signature: @@ -3888,9 +3594,6 @@ split(field('scores'), conditional(field('format').equal('csv'), constant(','), ### sqrt(expression) {:#sqrt_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the square root of a numeric value. Signature: @@ -3922,9 +3625,6 @@ sqrt(field("value")); ### stringIndexOf(expression, search) {:#stringindexof_6dfca5f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that finds the index of the first occurrence of a substring or byte sequence. Signature: @@ -3957,9 +3657,6 @@ stringIndexOf(field("text"), "foo"); ### stringRepeat(expression, repetitions) {:#stringrepeat_a55ba16} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that repeats a string or byte array a specified number of times. Signature: @@ -3992,9 +3689,6 @@ stringRepeat(field("label"), 3); ### stringReplaceAll(expression, find, replacement) {:#stringreplaceall_197ecbe} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. Signature: @@ -4028,9 +3722,6 @@ stringReplaceAll(field("text"), "foo", "bar"); ### stringReplaceOne(expression, find, replacement) {:#stringreplaceone_197ecbe} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. Signature: @@ -4064,9 +3755,6 @@ stringReplaceOne(field("text"), "foo", "bar"); ### subtract(expression, value) {:#subtract_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a constant value from an expression. Signature: @@ -4099,9 +3787,6 @@ subtract(field("value"), 2); ### sum(expression) {:#sum_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. Signature: @@ -4133,9 +3818,6 @@ sum(field("orderAmount")).as("totalRevenue"); ### trunc(expression) {:#trunc_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates the numeric value of an expression to an integer. Signature: @@ -4167,9 +3849,6 @@ trunc(field("rating")); ### trunc(expression, decimalPlaces) {:#trunc_a3a92d0} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a numeric value to the specified number of decimal places. Signature: @@ -4202,9 +3881,6 @@ trunc(field("rating"), constant(2)); ### type(expression) {:#type_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the data type of an expression's result. Signature: @@ -4238,9 +3914,6 @@ type(conditional(exists('foo'), constant(1), constant(true))) ### isAbsent(field) {:#isabsent_0fb8cd4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns `true` if a field is absent. Otherwise, returns `false` even if the field value is `null`. Signature: @@ -4272,9 +3945,6 @@ isAbsent("value"); ### reverse(field) {:#reverse_0fb8cd4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses a string value in the specified field. Signature: @@ -4306,9 +3976,6 @@ reverse("myString"); ### stringReverse(field) {:#stringreverse_0fb8cd4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses a string value in the specified field. Signature: @@ -4340,9 +4007,6 @@ stringReverse("myString"); ### substring(field, position, length) {:#substring_0d9573a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a substring of a string or byte array. Signature: @@ -4365,9 +4029,6 @@ export declare function substring(field: string, position: number, length?: numb ### substring(field, position, length) {:#substring_05cb14e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a substring of a string or byte array. Signature: @@ -4392,9 +4053,6 @@ export declare function substring(field: string, position: Expression, length?: ### abs(fieldName) {:#abs_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the absolute value of a numeric value. Signature: @@ -4417,9 +4075,6 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ### add(fieldName, second) {:#add_b75bb8b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds a field's value to an expression. Signature: @@ -4452,9 +4107,6 @@ add("quantity", field("reserve")); ### arrayAgg(fieldName) {:#arrayagg_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that collects all values of a field across multiple stage inputs into an array. 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. @@ -4488,9 +4140,6 @@ arrayAgg("tags").as("allTags"); ### arrayAggDistinct(fieldName) {:#arrayaggdistinct_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. 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. @@ -4524,9 +4173,6 @@ arrayAggDistinct("tags").as("allDistinctTags"); ### arrayContains(fieldName, element) {:#arraycontains_aaace4a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's array value contains a specific element. Signature: @@ -4559,9 +4205,6 @@ arrayContains("colors", field("selectedColor")); ### arrayContains(fieldName, element) {:#arraycontains_999590f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's array value contains a specific value. Signature: @@ -4594,9 +4237,6 @@ arrayContains("colors", "red"); ### arrayContainsAll(fieldName, values) {:#arraycontainsall_8060b23} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's array value contains all the specified values or expressions. Signature: @@ -4629,9 +4269,6 @@ arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); ### arrayContainsAll(fieldName, arrayExpression) {:#arraycontainsall_48da8d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's array value contains all the specified values or expressions. Signature: @@ -4664,9 +4301,6 @@ arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); ### arrayContainsAny(fieldName, values) {:#arraycontainsany_8060b23} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's array value contains any of the specified elements. Signature: @@ -4700,9 +4334,6 @@ arrayContainsAny("categories", [field("cate1"), "Science"]); ### arrayContainsAny(fieldName, values) {:#arraycontainsany_1b4f7cd} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's array value contains any of the specified elements. Signature: @@ -4736,9 +4367,6 @@ arrayContainsAny("categories", array([field("cate1"), "Science"])); ### arrayFirst(fieldName) {:#arrayfirst_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first element of an array. Signature: @@ -4770,9 +4398,6 @@ arrayFirst("tags"); ### arrayFirstN(fieldName, n) {:#arrayfirstn_597a4d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first `n` elements of an array. Signature: @@ -4805,9 +4430,6 @@ arrayFirstN("tags", 3); ### arrayFirstN(fieldName, n) {:#arrayfirstn_1a86a2c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first `n` elements of an array. Signature: @@ -4840,9 +4462,6 @@ arrayFirstN("tags", field("count")); ### arrayIndexOf(fieldName, search) {:#arrayindexof_5e4c2c3} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. Signature: @@ -4875,9 +4494,6 @@ arrayIndexOf("tags", "politics"); ### arrayIndexOfAll(fieldName, search) {:#arrayindexofall_5e4c2c3} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns all indices of the search value in an array. Signature: @@ -4910,9 +4526,6 @@ arrayIndexOfAll("scores", 5); ### arrayLast(fieldName) {:#arraylast_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last element of an array. Signature: @@ -4944,9 +4557,6 @@ arrayLast("tags"); ### arrayLastIndexOf(fieldName, search) {:#arraylastindexof_5e4c2c3} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. Signature: @@ -4979,9 +4589,6 @@ arrayLastIndexOf("tags", "politics"); ### arrayLastN(fieldName, n) {:#arraylastn_597a4d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last `n` elements of an array. Signature: @@ -5014,9 +4621,6 @@ arrayLastN("tags", 3); ### arrayLastN(fieldName, n) {:#arraylastn_1a86a2c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last `n` elements of an array. Signature: @@ -5049,9 +4653,6 @@ arrayLastN("tags", field("count")); ### arrayLength(fieldName) {:#arraylength_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of an array in a specified field. Signature: @@ -5083,9 +4684,6 @@ arrayLength('cart'); ### arrayMaximum(fieldName) {:#arraymaximum_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the maximum value in an array. Signature: @@ -5117,9 +4715,6 @@ arrayMaximum("scores"); ### arrayMaximumN(fieldName, n) {:#arraymaximumn_597a4d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the largest `n` elements of an array. Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -5154,9 +4749,6 @@ arrayMaximumN("scores", 3); ### arrayMaximumN(fieldName, n) {:#arraymaximumn_1a86a2c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the largest `n` elements of an array. Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -5191,9 +4783,6 @@ arrayMaximumN("scores", field("count")); ### arrayMinimum(fieldName) {:#arrayminimum_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the minimum value in an array. Signature: @@ -5225,9 +4814,6 @@ arrayMinimum("scores"); ### arrayMinimumN(fieldName, n) {:#arrayminimumn_597a4d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smallest `n` elements of an array. Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -5262,9 +4848,6 @@ arrayMinimumN("scores", 3); ### arrayMinimumN(fieldName, n) {:#arrayminimumn_1a86a2c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smallest `n` elements of an array. Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -5299,9 +4882,6 @@ arrayMinimumN(field("scores"), field("count")); ### arraySum(fieldName) {:#arraysum_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the sum of the elements in an array. Signature: @@ -5333,9 +4913,6 @@ arraySum("scores"); ### ascending(fieldName) {:#ascending_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. Signature: @@ -5368,9 +4945,6 @@ firestore.pipeline().collection("users") ### average(fieldName) {:#average_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. Signature: @@ -5402,9 +4976,6 @@ average("age").as("averageAge"); ### byteLength(fieldName) {:#bytelength_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. Signature: @@ -5436,9 +5007,6 @@ byteLength("myString"); ### ceil(fieldName) {:#ceil_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the ceiling of a numeric value. Signature: @@ -5470,9 +5038,6 @@ ceil("price"); ### charLength(fieldName) {:#charlength_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the character length of a string field in UTF8. Signature: @@ -5504,9 +5069,6 @@ charLength("name"); ### coalesce(fieldName, replacement, others) {:#coalesce_249958e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. Signature: @@ -5541,9 +5103,6 @@ coalesce("preferredName", field("fullName"), constant("Anonymous")) ### collectionId(fieldName) {:#collectionid_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the collection ID from a path. Signature: @@ -5575,9 +5134,6 @@ collectionId("__name__"); ### concat(fieldName, second, others) {:#concat_828272e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. Signature: @@ -5611,9 +5167,6 @@ concat(field("firstName"), "Doe") ### cosineDistance(fieldName, vector) {:#cosinedistance_463a23e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Cosine distance between a field's vector value and a literal vector value. Signature: @@ -5646,9 +5199,6 @@ cosineDistance("location", [37.7749, -122.4194]); ### cosineDistance(fieldName, vectorExpression) {:#cosinedistance_ed766a1} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Cosine distance between a field's vector value and a vector expression. Signature: @@ -5681,9 +5231,6 @@ cosineDistance("userVector", field("itemVector")); ### count(fieldName) {:#count_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the number of stage inputs where the input field exists. Signature: @@ -5715,9 +5262,6 @@ count("productId").as("totalProducts"); ### descending(fieldName) {:#descending_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on a field. Signature: @@ -5750,9 +5294,6 @@ firestore.pipeline().collection("users") ### divide(fieldName, expressions) {:#divide_cf36e43} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that divides a field's value by an expression. Signature: @@ -5785,9 +5326,6 @@ divide("total", field("count")); ### divide(fieldName, value) {:#divide_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that divides a field's value by a constant value. Signature: @@ -5820,9 +5358,6 @@ divide("value", 10); ### dotProduct(fieldName, vector) {:#dotproduct_463a23e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the dot product between a field's vector value and a double array. Signature: @@ -5855,9 +5390,6 @@ dotProduct("features", [0.5, 0.8, 0.2]); ### dotProduct(fieldName, vectorExpression) {:#dotproduct_ed766a1} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the dot product between a field's vector value and a vector expression. Signature: @@ -5890,9 +5422,6 @@ dotProduct("docVector1", field("docVector2")); ### endsWith(fieldName, suffix) {:#endswith_05ca3b0} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value ends with a given postfix. Signature: @@ -5925,9 +5454,6 @@ endsWith("filename", ".txt"); ### endsWith(fieldName, suffix) {:#endswith_8fc0ebc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value ends with a given postfix. Signature: @@ -5960,9 +5486,6 @@ endsWith("url", field("extension")); ### equal(fieldName, expression) {:#equal_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is equal to an expression. Signature: @@ -5995,9 +5518,6 @@ equal("age", field("limit")); ### equal(fieldName, value) {:#equal_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is equal to a constant value. Signature: @@ -6030,9 +5550,6 @@ equal("city", "London"); ### equalAny(fieldName, values) {:#equalany_8060b23} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is equal to any of the provided values or expressions. Signature: @@ -6065,9 +5582,6 @@ equalAny("category", [constant("Electronics"), field("primaryType")]); ### equalAny(fieldName, arrayExpression) {:#equalany_48da8d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is equal to any of the provided values or expressions. Signature: @@ -6100,9 +5614,6 @@ equalAny("category", ["Electronics", field("primaryType")]); ### euclideanDistance(fieldName, vector) {:#euclideandistance_463a23e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Euclidean distance between a field's vector value and a double array. Signature: @@ -6135,9 +5646,6 @@ euclideanDistance("location", [37.7749, -122.4194]); ### euclideanDistance(fieldName, vectorExpression) {:#euclideandistance_ed766a1} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Euclidean distance between a field's vector value and a vector expression. Signature: @@ -6170,9 +5678,6 @@ euclideanDistance("pointA", field("pointB")); ### exists(fieldName) {:#exists_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field exists. Signature: @@ -6204,9 +5709,6 @@ exists("phoneNumber"); ### exp(fieldName) {:#exp_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes e to the power of the expression's result. Signature: @@ -6238,9 +5740,6 @@ exp('value'); ### first(fieldName) {:#first_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the first value of a field across multiple stage inputs. Signature: @@ -6272,9 +5771,6 @@ first("rating").as("firstRating"); ### floor(fieldName) {:#floor_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the floor of a numeric value. Signature: @@ -6297,9 +5793,6 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ### greaterThan(fieldName, expression) {:#greaterthan_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is greater than an expression. Signature: @@ -6332,9 +5825,6 @@ greaterThan("age", field("limit")); ### greaterThan(fieldName, value) {:#greaterthan_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is greater than a constant value. Signature: @@ -6367,9 +5857,6 @@ greaterThan("price", 100); ### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_2e16acb} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is greater than or equal to an expression. Signature: @@ -6402,9 +5889,6 @@ greaterThanOrEqual("age", field("limit")); ### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is greater than or equal to a constant value. Signature: @@ -6437,9 +5921,6 @@ greaterThanOrEqual("score", 80); ### isType(fieldName, type) {:#istype_5da287e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the value in the specified field is of the given type. Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. @@ -6474,9 +5955,6 @@ isType('price', 'float64'); ### last(fieldName) {:#last_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the last value of a field across multiple stage inputs. Signature: @@ -6508,9 +5986,6 @@ last("rating").as("lastRating"); ### length\_2(fieldName) {:#length_2_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of a string, array, map, vector, or bytes. Signature: @@ -6545,9 +6020,6 @@ length("cart"); ### lessThan(fieldName, expression) {:#lessthan_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is less than an expression. Signature: @@ -6580,9 +6052,6 @@ lessThan("age", field("limit")); ### lessThan(fieldName, value) {:#lessthan_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is less than a constant value. Signature: @@ -6615,9 +6084,6 @@ lessThan("price", 50); ### lessThanOrEqual(fieldName, expression) {:#lessthanorequal_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is less than or equal to an expression. Signature: @@ -6650,9 +6116,6 @@ lessThan("quantity", field("limit")); ### lessThanOrEqual(fieldName, value) {:#lessthanorequal_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is less than or equal to a constant value. Signature: @@ -6685,9 +6148,6 @@ lessThan("score", 70); ### like(fieldName, pattern) {:#like_67f7432} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a case-sensitive wildcard string comparison against a field. Signature: @@ -6720,9 +6180,6 @@ like("title", "%guide%"); ### like(fieldName, pattern) {:#like_cb1318d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a case-sensitive wildcard string comparison against a field. Signature: @@ -6755,9 +6212,6 @@ like("title", field("pattern")); ### ln(fieldName) {:#ln_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the natural logarithm of a numeric value. Signature: @@ -6789,9 +6243,6 @@ ln("value"); ### log(fieldName, base) {:#log_a89e21b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the logarithm of a field to a given base. Signature: @@ -6824,9 +6275,6 @@ log("value", 10); ### log(fieldName, base) {:#log_805b11f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the logarithm of a field to a given base. Signature: @@ -6859,9 +6307,6 @@ log("value", field("base")); ### log10(fieldName) {:#log10_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the base-10 logarithm of a numeric value. Signature: @@ -6893,9 +6338,6 @@ log10("value"); ### logicalMaximum(fieldName, second, others) {:#logicalmaximum_828272e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. Signature: @@ -6930,9 +6372,6 @@ logicalMaximum("field1", field("field2"), 1000); ### logicalMinimum(fieldName, second, others) {:#logicalminimum_828272e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. Signature: @@ -6967,9 +6406,6 @@ logicalMinimum("field1", field("field2"), 1000); ### ltrim(fieldName, valueToTrim) {:#ltrim_c0e3211} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. Signature: @@ -7005,9 +6441,6 @@ ltrim(field("userInput"), '"'); ### mapGet(fieldName, subField) {:#mapget_06663cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Accesses a value from a map (object) field using the provided key. Signature: @@ -7040,9 +6473,6 @@ mapGet("address", "city"); ### maximum(fieldName) {:#maximum_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the maximum value of a field across multiple stage inputs. Signature: @@ -7074,9 +6504,6 @@ maximum("score").as("highestScore"); ### minimum(fieldName) {:#minimum_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the minimum value of a field across multiple stage inputs. Signature: @@ -7108,9 +6535,6 @@ minimum("price").as("lowestPrice"); ### mod(fieldName, expression) {:#mod_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. Signature: @@ -7143,9 +6567,6 @@ mod("field1", field("field2")); ### mod(fieldName, value) {:#mod_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. Signature: @@ -7178,9 +6599,6 @@ mod("field1", 5); ### multiply(fieldName, second) {:#multiply_b75bb8b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that multiplies a field's value by an expression. Signature: @@ -7213,9 +6631,6 @@ multiply("quantity", field("price")); ### notEqual(fieldName, expression) {:#notequal_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is not equal to an expression. Signature: @@ -7248,9 +6663,6 @@ notEqual("status", field("expectedStatus")); ### notEqual(fieldName, value) {:#notequal_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is not equal to a constant value. Signature: @@ -7283,9 +6695,6 @@ notEqual("country", "USA"); ### notEqualAny(fieldName, values) {:#notequalany_8060b23} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. Signature: @@ -7318,9 +6727,6 @@ notEqualAny("status", [constant("pending"), field("rejectedStatus")]); ### notEqualAny(fieldName, arrayExpression) {:#notequalany_48da8d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. Signature: @@ -7353,9 +6759,6 @@ notEqualAny("status", field("rejectedStatuses")); ### regexContains(fieldName, pattern) {:#regexcontains_67f7432} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string field contains a specified regular expression as a substring. Signature: @@ -7388,9 +6791,6 @@ regexContains("description", "(?i)example"); ### regexContains(fieldName, pattern) {:#regexcontains_cb1318d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string field contains a specified regular expression as a substring. Signature: @@ -7423,9 +6823,6 @@ regexContains("description", field("pattern")); ### regexFind(fieldName, pattern) {:#regexfind_67f7432} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first substring of a string field that matches a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -7460,9 +6857,6 @@ regexFind("email", "@[A-Za-z0-9.-]+"); ### regexFind(fieldName, pattern) {:#regexfind_cb1318d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first substring of a string field that matches a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -7497,9 +6891,6 @@ regexFind("email", field("pattern")); ### regexFindAll(fieldName, pattern) {:#regexfindall_67f7432} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -7534,9 +6925,6 @@ regexFindAll("content", "#[A-Za-z0-9_]+"); ### regexFindAll(fieldName, pattern) {:#regexfindall_cb1318d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -7571,9 +6959,6 @@ regexFindAll("content", field("pattern")); ### regexMatch(fieldName, pattern) {:#regexmatch_67f7432} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string field matches a specified regular expression. Signature: @@ -7606,9 +6991,6 @@ regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); ### regexMatch(fieldName, pattern) {:#regexmatch_cb1318d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string field matches a specified regular expression. Signature: @@ -7641,9 +7023,6 @@ regexMatch("email", field("pattern")); ### round(fieldName) {:#round_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the nearest whole number. Signature: @@ -7675,9 +7054,6 @@ round("price"); ### round(fieldName, decimalPlaces) {:#round_07d0cf0} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the specified number of decimal places. Signature: @@ -7710,9 +7086,6 @@ round("price", 2); ### rtrim(fieldName, valueToTrim) {:#rtrim_c0e3211} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. Signature: @@ -7748,9 +7121,6 @@ rtrim(field("userInput"), '"'); ### split(fieldName, delimiter) {:#split_2cfdd37} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that splits the value of a field on the provided delimiter. Signature: @@ -7783,9 +7153,6 @@ split('scoresCsv', ',') ### split(fieldName, delimiter) {:#split_f4fe06a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that splits the value of a field on the provided delimiter. Signature: @@ -7818,9 +7185,6 @@ split('scores', conditional(field('format').equal('csv'), constant(','), constan ### sqrt(fieldName) {:#sqrt_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the square root of a numeric value. Signature: @@ -7852,9 +7216,6 @@ sqrt("value"); ### startsWith(fieldName, prefix) {:#startswith_89325cc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value starts with a given prefix. Signature: @@ -7887,9 +7248,6 @@ startsWith("name", "Mr."); ### startsWith(fieldName, prefix) {:#startswith_266c338} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value starts with a given prefix. Signature: @@ -7922,9 +7280,6 @@ startsWith("fullName", field("firstName")); ### stringConcat(fieldName, secondString, otherStrings) {:#stringconcat_d80077e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates string functions, fields or constants together. Signature: @@ -7958,9 +7313,6 @@ stringConcat("firstName", " ", field("lastName")); ### stringContains(fieldName, substring) {:#stringcontains_5b94cfe} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string field contains a specified substring. Signature: @@ -7993,9 +7345,6 @@ stringContains("description", "example"); ### stringContains(fieldName, substring) {:#stringcontains_ac3ba47} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string field contains a substring specified by an expression. Signature: @@ -8028,9 +7377,6 @@ stringContains("description", field("keyword")); ### stringIndexOf(fieldName, search) {:#stringindexof_6c4650e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that finds the index of the first occurrence of a substring or byte sequence. Signature: @@ -8063,9 +7409,6 @@ stringIndexOf("text", "foo"); ### stringRepeat(fieldName, repetitions) {:#stringrepeat_e144a59} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that repeats a string or byte array a specified number of times. Signature: @@ -8098,9 +7441,6 @@ stringRepeat("label", 3); ### stringReplaceAll(fieldName, find, replacement) {:#stringreplaceall_b0db15f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. Signature: @@ -8134,9 +7474,6 @@ stringReplaceAll("text", "foo", "bar"); ### stringReplaceOne(fieldName, find, replacement) {:#stringreplaceone_b0db15f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. Signature: @@ -8170,9 +7507,6 @@ stringReplaceOne("text", "foo", "bar"); ### subtract(fieldName, expression) {:#subtract_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts an expression from a field's value. Signature: @@ -8205,9 +7539,6 @@ subtract("price", field("discount")); ### subtract(fieldName, value) {:#subtract_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a constant value from a field's value. Signature: @@ -8240,9 +7571,6 @@ subtract("total", 20); ### sum(fieldName) {:#sum_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. Signature: @@ -8274,9 +7602,6 @@ sum("orderAmount").as("totalRevenue"); ### timestampAdd(fieldName, unit, amount) {:#timestampadd_3b0a297} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds a specified amount of time to a timestamp represented by a field. Signature: @@ -8310,9 +7635,6 @@ timestampAdd("timestamp", "day", 1); ### timestampExtract(fieldName, part, timezone) {:#timestampextract_a51c205} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that extracts a specified part from a timestamp. Signature: @@ -8346,9 +7668,6 @@ timestampExtract('createdAt', 'year') ### timestampExtract(fieldName, part, timezone) {:#timestampextract_2d51eac} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that extracts a specified part from a timestamp. Signature: @@ -8382,9 +7701,6 @@ timestampExtract('createdAt', field('part')) ### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_3b0a297} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. Signature: @@ -8418,9 +7734,6 @@ timestampSubtract("timestamp", "day", 1); ### timestampToUnixMicros(fieldName) {:#timestamptounixmicros_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -8452,9 +7765,6 @@ timestampToUnixMicros("timestamp"); ### timestampToUnixMillis(fieldName) {:#timestamptounixmillis_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -8486,9 +7796,6 @@ timestampToUnixMillis("timestamp"); ### timestampToUnixSeconds(fieldName) {:#timestamptounixseconds_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -8520,9 +7827,6 @@ timestampToUnixSeconds("timestamp"); ### timestampTruncate(fieldName, granularity, timezone) {:#timestamptruncate_b6c7512} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a timestamp to a specified granularity. Signature: @@ -8556,9 +7860,6 @@ timestampTruncate('createdAt', 'day') ### timestampTruncate(fieldName, granularity, timezone) {:#timestamptruncate_ed83d46} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a timestamp to a specified granularity. Signature: @@ -8592,9 +7893,6 @@ timestampTruncate('createdAt', field('granularity')) ### toLower(fieldName) {:#tolower_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a string field to lowercase. Signature: @@ -8626,9 +7924,6 @@ toLower("name"); ### toUpper(fieldName) {:#toupper_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a string field to uppercase. Signature: @@ -8660,9 +7955,6 @@ toUpper("title"); ### trim(fieldName, valueToTrim) {:#trim_c9f90ee} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes leading and trailing whitespace from a string or byte array. Signature: @@ -8698,9 +7990,6 @@ trim("userInput", '"'); ### trunc(fieldName) {:#trunc_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates the numeric value of a field to an integer. Signature: @@ -8732,9 +8021,6 @@ trunc("rating"); ### trunc(fieldName, decimalPlaces) {:#trunc_07d0cf0} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a numeric expression to the specified number of decimal places. Signature: @@ -8767,9 +8053,6 @@ trunc("rating", 2); ### type(fieldName) {:#type_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the data type of the data in the specified field. String inputs passed iteratively to this global function act as `field()` path lookups. If you wish to pass a string literal value, it must be wrapped: `type(constant("my_string"))`. @@ -8803,9 +8086,6 @@ type('title') ### unixMicrosToTimestamp(fieldName) {:#unixmicrostotimestamp_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. Signature: @@ -8837,9 +8117,6 @@ unixMicrosToTimestamp("microseconds"); ### unixMillisToTimestamp(fieldName) {:#unixmillistotimestamp_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. Signature: @@ -8871,9 +8148,6 @@ unixMillisToTimestamp("milliseconds"); ### unixSecondsToTimestamp(fieldName) {:#unixsecondstotimestamp_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. Signature: @@ -8905,9 +8179,6 @@ unixSecondsToTimestamp("seconds"); ### vectorLength(fieldName) {:#vectorlength_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of a Firestore Vector represented by a field. Signature: @@ -8941,9 +8212,6 @@ vectorLength("embedding"); ### add(first, second) {:#add_846ca1b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds two expressions together. Signature: @@ -8976,9 +8244,6 @@ add(field("quantity"), field("reserve")); ### and(first, second, more) {:#and_e0c48bd} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a logical 'AND' operation on multiple filter conditions. Signature: @@ -9013,9 +8278,6 @@ const condition = and(greaterThan("age", 18), equal("city", "London"), equal("st ### concat(first, second, others) {:#concat_83be015} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. Signature: @@ -9049,9 +8311,6 @@ concat(field("firstName"), " ", field("lastName")) ### logicalMaximum(first, second, others) {:#logicalmaximum_83be015} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. Signature: @@ -9086,9 +8345,6 @@ logicalMaximum(field("field1"), field("field2"), 1000); ### logicalMinimum(first, second, others) {:#logicalminimum_83be015} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. Signature: @@ -9123,9 +8379,6 @@ logicalMinimum(field("field1"), field("field2"), 1000); ### multiply(first, second) {:#multiply_846ca1b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that multiplies two expressions together. Signature: @@ -9158,9 +8411,6 @@ multiply(field("quantity"), field("price")); ### nor(first, second, more) {:#nor_e0c48bd} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a logical 'NOR' operation on multiple filter conditions. Signature: @@ -9197,9 +8447,6 @@ const condition = nor( ### or(first, second, more) {:#or_e0c48bd} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a logical 'OR' operation on multiple filter conditions. Signature: @@ -9234,9 +8481,6 @@ const condition = or(greaterThan("age", 18), equal("city", "London"), equal("sta ### xor(first, second, additionalConditions) {:#xor_8197113} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. Signature: @@ -9276,9 +8520,6 @@ const condition = xor( ### arrayConcat(firstArray, secondArray, otherArrays) {:#arrayconcat_c00d5d7} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates an array expression with other arrays. Signature: @@ -9314,9 +8555,6 @@ arrayConcat(field("items"), [field("newItems"), field("otherItems")]); ### arrayConcat(firstArrayField, secondArray, otherArrays) {:#arrayconcat_f92063d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates a field's array value with other arrays. Signature: @@ -9352,9 +8590,6 @@ arrayConcat("items", [field("newItems"), field("otherItems")]); ### mapMerge(firstMap, secondMap, otherMaps) {:#mapmerge_cfe77ce} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that merges multiple map values. Signature: @@ -9389,9 +8624,6 @@ mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { a ### stringConcat(firstString, secondString, otherStrings) {:#stringconcat_8a8d1b6} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates string expressions together. Signature: @@ -9427,9 +8659,6 @@ stringConcat(field("firstName"), " ", field("lastName")); ### ifAbsent(ifExpr, elseExpr) {:#ifabsent_0e6d161} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseExpr` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. Signature: @@ -9463,9 +8692,6 @@ ifAbsent(field("optional_field"), constant("default_value")) ### ifAbsent(ifExpr, elseValue) {:#ifabsent_c34e5ed} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. Signature: @@ -9499,9 +8725,6 @@ ifAbsent(field("optional_field"), "default_value") ### ifNull(ifExpr, elseExpr) {:#ifnull_0e6d161} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseExpr` argument if `ifExpr` is null, else return the result of the `ifExpr` argument evaluation. This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. @@ -9536,9 +8759,6 @@ ifNull(field("preferredName"), field("fullName")) ### ifNull(ifExpr, elseValue) {:#ifnull_c34e5ed} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if `ifExpr` is null, else return the result of the `ifExpr` argument evaluation. This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. @@ -9575,9 +8795,6 @@ ifNull(field("displayName"), "Anonymous") ### ifAbsent(ifFieldName, elseExpr) {:#ifabsent_e6dabea} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseExpr` argument if `ifFieldName` is absent, else return the value of the field. Signature: @@ -9611,9 +8828,6 @@ ifAbsent("optional_field", field("default_field")) ### ifAbsent(ifFieldName, elseValue) {:#ifabsent_d8f2823} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if `ifFieldName` is absent, else return the value of the field. Signature: @@ -9647,9 +8861,6 @@ ifAbsent("optional_field", "default_value") ### ifNull(ifFieldName, elseExpr) {:#ifnull_e6dabea} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseExpr` argument if `ifFieldName` field is null, else return the value of the field. This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. @@ -9684,9 +8895,6 @@ ifNull("preferredName", field("fullName")) ### ifNull(ifFieldName, elseValue) {:#ifnull_587c2f0} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if `ifFieldName` field is null, else return the value of the field. This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. @@ -9723,9 +8931,6 @@ ifNull("displayName", "Anonymous") ### substring(input, position, length) {:#substring_e6e0aa3} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a substring of a string or byte array. Signature: @@ -9748,9 +8953,6 @@ export declare function substring(input: Expression, position: number, length?: ### substring(input, position, length) {:#substring_ab56dc6} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a substring of a string or byte array. Signature: @@ -9775,9 +8977,6 @@ export declare function substring(input: Expression, position: Expression, lengt ### divide(left, right) {:#divide_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that divides two expressions. Signature: @@ -9810,9 +9009,6 @@ divide(field("total"), field("count")); ### equal(left, right) {:#equal_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if two expressions are equal. Signature: @@ -9845,9 +9041,6 @@ equal(field("age"), field("minAge").add(10)); ### greaterThan(left, right) {:#greaterthan_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the first expression is greater than the second expression. Signature: @@ -9880,9 +9073,6 @@ greaterThan(field("age"), constant(9).add(9)); ### greaterThanOrEqual(left, right) {:#greaterthanorequal_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the first expression is greater than or equal to the second expression. Signature: @@ -9915,9 +9105,6 @@ greaterThanOrEqual(field("quantity"), field("threshold")); ### lessThan(left, right) {:#lessthan_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the first expression is less than the second expression. Signature: @@ -9950,9 +9137,6 @@ lessThan(field("age"), field("limit")); ### lessThanOrEqual(left, right) {:#lessthanorequal_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the first expression is less than or equal to the second expression. Signature: @@ -9985,9 +9169,6 @@ lessThan(field("quantity"), field("limit")); ### mod(left, right) {:#mod_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the modulo (remainder) of dividing two expressions. Signature: @@ -10020,9 +9201,6 @@ mod(field("field1"), field("field2")); ### notEqual(left, right) {:#notequal_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if two expressions are not equal. Signature: @@ -10055,9 +9233,6 @@ notEqual(field("status"), field("finalState")); ### subtract(left, right) {:#subtract_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts two expressions. Signature: @@ -10092,9 +9267,6 @@ subtract(field("price"), field("discount")); ### mapRemove(mapExpr, key) {:#mapremove_23c7d51} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes a key from the map produced by evaluating an expression. Signature: @@ -10126,9 +9298,6 @@ mapRemove(map({foo: 'bar', baz: true}), 'baz'); ### mapRemove(mapExpr, keyExpr) {:#mapremove_9fbcaa3} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes a key from the map produced by evaluating an expression. Signature: @@ -10162,9 +9331,6 @@ mapRemove(map({foo: 'bar', baz: true}), constant('baz')); ### mapEntries(mapExpression) {:#mapentries_9cf124c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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" }, ...]`. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -10198,9 +9364,6 @@ mapEntries(map({"city": "San Francisco"})); ### mapGet(mapExpression, subField) {:#mapget_688c050} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Accesses a value from a map (object) expression using the provided key. Signature: @@ -10233,9 +9396,6 @@ mapGet(field("address"), "city"); ### mapKeys(mapExpression) {:#mapkeys_9cf124c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the keys of a map. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -10269,9 +9429,6 @@ mapKeys(map({"city": "San Francisco"})); ### mapSet(mapExpression, key, value, moreKeyValues) {:#mapset_45b48ff} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a new map with the specified entries added or updated. This 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`. @@ -10308,9 +9465,6 @@ mapSet(map({"state": "California"}), "city", "San Francisco"); ### mapValues(mapExpression) {:#mapvalues_9cf124c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the values of a map. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -10346,9 +9500,6 @@ mapValues(map({"city": "San Francisco"})); ### mapEntries(mapField) {:#mapentries_83ad836} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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" }, ...]`. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -10382,9 +9533,6 @@ mapEntries("address"); ### mapKeys(mapField) {:#mapkeys_83ad836} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the keys of a map. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -10418,9 +9566,6 @@ mapKeys("address"); ### mapMerge(mapField, secondMap, otherMaps) {:#mapmerge_70a564b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that merges multiple map values. Signature: @@ -10453,9 +9598,6 @@ mapMerge('settings', { enabled: true }, conditional(field('isAdmin'), { admin: t ### mapRemove(mapField, key) {:#mapremove_bd5726e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes a key from the map at the specified field name. Signature: @@ -10486,9 +9628,6 @@ mapRemove('address', 'city'); ### mapRemove(mapField, keyExpr) {:#mapremove_8406d13} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes a key from the map at the specified field name. Signature: @@ -10519,9 +9658,6 @@ mapRemove('address', constant('city')); ### mapSet(mapField, key, value, moreKeyValues) {:#mapset_baadc2a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a new map with the specified entries added or updated. This 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`. @@ -10558,9 +9694,6 @@ mapSet("address", "city", "San Francisco"); ### mapValues(mapField) {:#mapvalues_83ad836} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the values of a map. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -10596,9 +9729,6 @@ mapValues("address"); ### field(name) {:#field_1eaaff4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). @@ -10637,9 +9767,6 @@ const authorFirstNameField = field("author.firstName"); ### field(path) {:#field_34ee07d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. Signature: @@ -10664,9 +9791,6 @@ A new [Field](./firestore_pipelines.field.md#field_class) instance representing ### execute(pipeline) {:#execute_01df620} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Executes this pipeline and returns a Promise to represent the asynchronous operation. The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously. @@ -10709,9 +9833,6 @@ const results: PipelineResults = snapshot.results; ### charLength(stringExpression) {:#charlength_c25a54a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the character length of a string expression in UTF-8. Signature: @@ -10743,9 +9864,6 @@ charLength(field("name")); ### endsWith(stringExpression, suffix) {:#endswith_0a0b889} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression ends with a given postfix. Signature: @@ -10778,9 +9896,6 @@ endsWith(field("fullName"), "Jr."); ### endsWith(stringExpression, suffix) {:#endswith_13aee0d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression ends with a given postfix. Signature: @@ -10813,9 +9928,6 @@ endsWith(field("fullName"), constant("Jr.")); ### like(stringExpression, pattern) {:#like_a84c581} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a case-sensitive wildcard string comparison. Signature: @@ -10848,9 +9960,6 @@ like(field("title"), "%guide%"); ### like(stringExpression, pattern) {:#like_b534848} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a case-sensitive wildcard string comparison. Signature: @@ -10883,9 +9992,6 @@ like(field("title"), field("pattern")); ### regexContains(stringExpression, pattern) {:#regexcontains_a84c581} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression contains a specified regular expression as a substring. Signature: @@ -10918,9 +10024,6 @@ regexContains(field("description"), "(?i)example"); ### regexContains(stringExpression, pattern) {:#regexcontains_b534848} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression contains a specified regular expression as a substring. Signature: @@ -10953,9 +10056,6 @@ regexContains(field("description"), field("pattern")); ### regexFind(stringExpression, pattern) {:#regexfind_a84c581} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first substring of a string expression that matches a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -10990,9 +10090,6 @@ regexFind(field("email"), "@[A-Za-z0-9.-]+"); ### regexFind(stringExpression, pattern) {:#regexfind_b534848} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first substring of a string expression that matches a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -11027,9 +10124,6 @@ regexFind(field("email"), field("pattern")); ### regexFindAll(stringExpression, pattern) {:#regexfindall_a84c581} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -11064,9 +10158,6 @@ regexFindAll(field("comment"), "@[A-Za-z0-9_]+"); ### regexFindAll(stringExpression, pattern) {:#regexfindall_b534848} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -11101,9 +10192,6 @@ regexFindAll(field("comment"), field("pattern")); ### regexMatch(stringExpression, pattern) {:#regexmatch_a84c581} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression matches a specified regular expression. Signature: @@ -11136,9 +10224,6 @@ regexMatch(field("email"), "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); ### regexMatch(stringExpression, pattern) {:#regexmatch_b534848} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression matches a specified regular expression. Signature: @@ -11171,9 +10256,6 @@ regexMatch(field("email"), field("pattern")); ### reverse(stringExpression) {:#reverse_c25a54a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses a string. Signature: @@ -11205,9 +10287,6 @@ reverse(field("myString")); ### startsWith(stringExpression, prefix) {:#startswith_75c3dbb} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression starts with a given prefix. Signature: @@ -11240,9 +10319,6 @@ startsWith(field("fullName"), "Mr."); ### startsWith(stringExpression, prefix) {:#startswith_52f218a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression starts with a given prefix. Signature: @@ -11275,9 +10351,6 @@ startsWith(field("fullName"), field("prefix")); ### stringContains(stringExpression, substring) {:#stringcontains_3e9ff32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression contains a specified substring. Signature: @@ -11310,9 +10383,6 @@ stringContains(field("description"), "example"); ### stringContains(stringExpression, substring) {:#stringcontains_cc6ee02} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression contains a substring specified by another expression. Signature: @@ -11345,9 +10415,6 @@ stringContains(field("description"), field("keyword")); ### stringReverse(stringExpression) {:#stringreverse_c25a54a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses a string. Signature: @@ -11379,9 +10446,6 @@ stringReverse(field("myString")); ### toLower(stringExpression) {:#tolower_c25a54a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a string expression to lowercase. Signature: @@ -11413,9 +10477,6 @@ toLower(field("name")); ### toUpper(stringExpression) {:#toupper_c25a54a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a string expression to uppercase. Signature: @@ -11447,9 +10508,6 @@ toUpper(field("title")); ### trim(stringExpression, valueToTrim) {:#trim_dd54322} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes leading and trailing characters from a string or byte array expression. Signature: @@ -11487,9 +10545,6 @@ trim(field("userInput"), '"'); ### timestampAdd(timestamp, unit, amount) {:#timestampadd_98418f9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds a specified amount of time to a timestamp. Signature: @@ -11523,9 +10578,6 @@ timestampAdd(field("timestamp"), field("unit"), field("amount")); ### timestampAdd(timestamp, unit, amount) {:#timestampadd_06ef927} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds a specified amount of time to a timestamp. Signature: @@ -11559,9 +10611,6 @@ timestampAdd(field("timestamp"), "day", 1); ### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_98418f9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a specified amount of time from a timestamp. Signature: @@ -11595,9 +10644,6 @@ timestampSubtract(field("timestamp"), field("unit"), field("amount")); ### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_06ef927} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a specified amount of time from a timestamp. Signature: @@ -11633,9 +10679,6 @@ timestampSubtract(field("timestamp"), "day", 1); ### timestampExtract(timestampExpression, part, timezone) {:#timestampextract_b2f8f48} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that extracts a specified part from a timestamp. Signature: @@ -11669,9 +10712,6 @@ timestampExtract(field('createdAt'), 'year') ### timestampExtract(timestampExpression, part, timezone) {:#timestampextract_73e0311} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that extracts a specified part from a timestamp. Signature: @@ -11705,9 +10745,6 @@ timestampExtract(field('createdAt'), field('part')) ### timestampTruncate(timestampExpression, granularity, timezone) {:#timestamptruncate_ad5d843} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a timestamp to a specified granularity. Signature: @@ -11741,9 +10778,6 @@ timestampTruncate(field('createdAt'), 'day') ### timestampTruncate(timestampExpression, granularity, timezone) {:#timestamptruncate_d6ab2a4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a timestamp to a specified granularity. Signature: @@ -11779,9 +10813,6 @@ timestampTruncate(field('createdAt'), field('granularity')) ### ifError(tryExpr, catchExpr) {:#iferror_a99a327} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. This overload is useful when a BooleanExpression is required. @@ -11817,9 +10848,6 @@ ifError(constant(50).divide(field('length')).greaterThan(1), constant(false)); ### ifError(tryExpr, catchExpr) {:#iferror_756c12e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. Signature: @@ -11853,9 +10881,6 @@ ifError(field("title").arrayGet(0), field("title")); ### ifError(tryExpr, catchValue) {:#iferror_dc532f9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. Signature: @@ -11891,9 +10916,6 @@ ifError(field("title").arrayGet(0), "Default Title"); ### constant(value) {:#constant_0c00f91} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a number value. Signature: @@ -11916,9 +10938,6 @@ A new `Constant` instance. ### constant(value) {:#constant_6dac335} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a VectorValue value. Signature: @@ -11941,9 +10960,6 @@ A new `Constant` instance. ### constant(value) {:#constant_7c807cd} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a string value. Signature: @@ -11966,9 +10982,6 @@ A new `Constant` instance. ### constant(value) {:#constant_b2e4f8d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `BooleanExpression` instance for a boolean value. Signature: @@ -11991,9 +11004,6 @@ A new `Constant` instance. ### constant(value) {:#constant_73ebd84} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a null value. Signature: @@ -12016,9 +11026,6 @@ A new `Constant` instance. ### constant(value) {:#constant_72a76cb} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a GeoPoint value. Signature: @@ -12041,9 +11048,6 @@ A new `Constant` instance. ### constant(value) {:#constant_000477d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a Timestamp value. Signature: @@ -12066,9 +11070,6 @@ A new `Constant` instance. ### constant(value) {:#constant_5131bf7} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a Date value. Signature: @@ -12091,9 +11092,6 @@ A new `Constant` instance. ### constant(value) {:#constant_fdf565d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a Bytes value. Signature: @@ -12116,9 +11114,6 @@ A new `Constant` instance. ### constant(value) {:#constant_bcd2b0b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a DocumentReference value. Signature: @@ -12141,9 +11136,6 @@ A new `Constant` instance. ### exists(value) {:#exists_f3daf14} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field exists. Signature: @@ -12175,9 +11167,6 @@ exists(field("phoneNumber")); ### isAbsent(value) {:#isabsent_f3daf14} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns `true` if a value is absent. Otherwise, returns `false` even if the value is `null`. Signature: @@ -12209,9 +11198,6 @@ isAbsent(field("value")); ### isError(value) {:#iserror_f3daf14} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a given expression produces an error. Signature: @@ -12245,9 +11231,6 @@ isError(field("title").arrayContains(1)); ### cosineDistance(vectorExpression, vector) {:#cosinedistance_3a80317} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Cosine distance between a vector expression and a vector literal. Signature: @@ -12280,9 +11263,6 @@ cosineDistance(field("location"), [37.7749, -122.4194]); ### cosineDistance(vectorExpression, otherVectorExpression) {:#cosinedistance_17b5bcc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Cosine distance between two vector expressions. Signature: @@ -12315,9 +11295,6 @@ cosineDistance(field("userVector"), field("itemVector")); ### dotProduct(vectorExpression, vector) {:#dotproduct_3a80317} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the dot product between a vector expression and a double array. Signature: @@ -12350,9 +11327,6 @@ dotProduct(field("features"), [0.5, 0.8, 0.2]); ### dotProduct(vectorExpression, otherVectorExpression) {:#dotproduct_17b5bcc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the dot product between two vector expressions. Signature: @@ -12385,9 +11359,6 @@ dotProduct(field("docVector1"), field("docVector2")); ### euclideanDistance(vectorExpression, vector) {:#euclideandistance_3a80317} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Euclidean distance between a vector expression and a double array. Signature: @@ -12421,9 +11392,6 @@ euclideanDistance(field("location"), [37.7749, -122.4194]); ### euclideanDistance(vectorExpression, otherVectorExpression) {:#euclideandistance_17b5bcc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Euclidean distance between two vector expressions. Signature: @@ -12456,9 +11424,6 @@ euclideanDistance(field("pointA"), field("pointB")); ### vectorLength(vectorExpression) {:#vectorlength_58a039b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of a Firestore Vector. Signature: @@ -12490,9 +11455,6 @@ vectorLength(field("embedding")); ## AddFieldsStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how an AddFieldsStage is evaluated. See [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields). Signature: @@ -12505,9 +11467,6 @@ export declare type AddFieldsStageOptions = StageOptions & { ## AggregateStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how an AggregateStage is evaluated. See [Pipeline.aggregate()](./firestore_pipelines.pipeline.md#pipelineaggregate). Signature: @@ -12521,9 +11480,6 @@ export declare type AggregateStageOptions = StageOptions & { ## CollectionGroupStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution. See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. @@ -12539,9 +11495,6 @@ export declare type CollectionGroupStageOptions = StageOptions & { ## CollectionStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). Signature: @@ -12555,9 +11508,6 @@ export declare type CollectionStageOptions = StageOptions & { ## DatabaseStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). Signature: @@ -12568,9 +11518,6 @@ export declare type DatabaseStageOptions = StageOptions & {}; ## DistinctStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). Signature: @@ -12583,9 +11530,6 @@ export declare type DistinctStageOptions = StageOptions & { ## DocumentsStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a DocumentsStage is evaluated. See [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments). Signature: @@ -12598,9 +11542,6 @@ export declare type DocumentsStageOptions = StageOptions & { ## ExpressionType -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An enumeration of the different types of expressions. Signature: @@ -12611,9 +11552,6 @@ export declare type ExpressionType = 'Field' | 'Constant' | 'Function' | 'Aggreg ## FindNearestStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a FindNearestStage is evaluated. See [Pipeline.findNearest()](./firestore_pipelines.pipeline.md#pipelinefindnearest). Signature: @@ -12630,9 +11568,6 @@ export declare type FindNearestStageOptions = StageOptions & { ## LimitStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a LimitStage is evaluated. See [Pipeline.limit()](./firestore_pipelines.pipeline.md#pipelinelimit). Signature: @@ -12645,9 +11580,6 @@ export declare type LimitStageOptions = StageOptions & { ## OffsetStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how an OffsetStage is evaluated. See [Pipeline.offset()](./firestore_pipelines.pipeline.md#pipelineoffset). Signature: @@ -12660,9 +11592,6 @@ export declare type OffsetStageOptions = StageOptions & { ## OneOf -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Utility type to create an type that only allows one property of the Type param T to be set. Signature: @@ -12710,9 +11639,6 @@ export declare type Primitive = string | number | boolean | undefined | null; ## RemoveFieldsStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). Signature: @@ -12725,9 +11651,6 @@ export declare type RemoveFieldsStageOptions = StageOptions & { ## ReplaceWithStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). Signature: @@ -12740,9 +11663,6 @@ export declare type ReplaceWithStageOptions = StageOptions & { ## SampleStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied. See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. @@ -12758,9 +11678,6 @@ export declare type SampleStageOptions = StageOptions & OneOf<{ ## SelectStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). Signature: @@ -12787,9 +11704,6 @@ export declare type SetOptions = { ## SortStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). Signature: @@ -12802,9 +11716,6 @@ export declare type SortStageOptions = StageOptions & { ## TimeGranularity -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Specify time granularity for expressions. Signature: @@ -12815,9 +11726,6 @@ export declare type TimeGranularity = TimeUnit | 'week' | 'week(monday)' | 'week ## TimePart -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Specify time parts for `timestampExtract` expressions. Signature: @@ -12828,9 +11736,6 @@ export declare type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; ## TimeUnit -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Specify time units for expressions. Signature: @@ -12841,9 +11746,6 @@ export declare type TimeUnit = 'microsecond' | 'millisecond' | 'second' | 'minut ## Type -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An enumeration of the different types generated by the Firestore backend.
    • Numerics evaluate directly to backend representation (`int64` or `float64`), not JS `number`.
    • JavaScript `Date` and firestore `Timestamp` objects strictly evaluate to `'timestamp'`.
    • Advanced configurations parsing backend types (such as `decimal128`, `max_key` or `min_key` from BSON) are also incorporated in this union string type. Note that `decimal128` is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    @@ -12856,9 +11758,6 @@ export declare type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' ## UnionStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). Signature: @@ -12871,9 +11770,6 @@ export declare type UnionStageOptions = StageOptions & { ## UnnestStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents the specific options available for configuring an `UnnestStage` within a pipeline. Signature: @@ -12887,9 +11783,6 @@ export declare type UnnestStageOptions = StageOptions & { ## WhereStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). Signature: diff --git a/docs-devsite/firestore_lite_pipelines.ordering.md b/docs-devsite/firestore_lite_pipelines.ordering.md index 2af9efcd91..bbc697fde8 100644 --- a/docs-devsite/firestore_lite_pipelines.ordering.md +++ b/docs-devsite/firestore_lite_pipelines.ordering.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # Ordering class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents an ordering criterion for sorting documents in a Firestore pipeline. You create `Ordering` instances using the `ascending` and `descending` helper functions. @@ -27,20 +24,17 @@ export declare class Ordering | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(expr, direction, \_methodName)](./firestore_lite_pipelines.ordering.md#orderingconstructor) | | (Public Preview) Constructs a new instance of the Ordering class | +| [(constructor)(expr, direction, \_methodName)](./firestore_lite_pipelines.ordering.md#orderingconstructor) | | Constructs a new instance of the Ordering class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [direction](./firestore_lite_pipelines.ordering.md#orderingdirection) | | 'ascending' \| 'descending' | (Public Preview) | -| [expr](./firestore_lite_pipelines.ordering.md#orderingexpr) | | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | (Public Preview) | +| [direction](./firestore_lite_pipelines.ordering.md#orderingdirection) | | 'ascending' \| 'descending' | | +| [expr](./firestore_lite_pipelines.ordering.md#orderingexpr) | | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | ## Ordering.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `Ordering` class Signature: @@ -59,9 +53,6 @@ constructor(expr: Expression, direction: 'ascending' | 'descending', _methodName ## Ordering.direction -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -70,9 +61,6 @@ readonly direction: 'ascending' | 'descending'; ## Ordering.expr -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/firestore_lite_pipelines.pipeline.md b/docs-devsite/firestore_lite_pipelines.pipeline.md index 0936e483bc..85e7d8c15d 100644 --- a/docs-devsite/firestore_lite_pipelines.pipeline.md +++ b/docs-devsite/firestore_lite_pipelines.pipeline.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # Pipeline class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The Pipeline class provides a flexible and expressive framework for building complex data transformation and query pipelines for Firestore. A pipeline takes data sources, such as Firestore collections or collection groups, and applies a series of stages that are chained together. Each stage takes the output from the previous stage (or the data source) and produces an output for the next stage (or as the final output of the pipeline). @@ -33,13 +30,13 @@ export declare class Pipeline | Method | Modifiers | Description | | --- | --- | --- | -| [addFields(field, additionalFields)](./firestore_lite_pipelines.pipeline.md#pipelineaddfields) | | (Public Preview) Adds new fields to outputs from previous stages.This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps).The added fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s, which can be:- [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [Expression](./firestore_pipelines.expression.md#expression_class): Either a literal value (see [constant()](./firestore_pipelines.md#constant_0c00f91)) or a computed value with an assigned alias using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | -| [addFields(options)](./firestore_lite_pipelines.pipeline.md#pipelineaddfields) | | (Public Preview) Adds new fields to outputs from previous stages.This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps).The added fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s, which can be:- [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [Expression](./firestore_pipelines.expression.md#expression_class): Either a literal value (see [constant()](./firestore_pipelines.md#constant_0c00f91)) or a computed value with an assigned alias using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | -| [aggregate(accumulator, additionalAccumulators)](./firestore_lite_pipelines.pipeline.md#pipelineaggregate) | | (Public Preview) Performs aggregation operations on the documents from previous stages.

    This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions which are typically results of calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances.

    Example: | -| [aggregate(options)](./firestore_lite_pipelines.pipeline.md#pipelineaggregate) | | (Public Preview) Performs optionally grouped aggregation operations on the documents from previous stages.

    This stage allows you to calculate aggregate values over a set of documents, optionally grouped by one or more fields or functions. You can specify:

    • \*\*Grouping Fields or Functions:\*\* One or more fields or functions to group the documents by. For each distinct combination of values in these fields, a separate group is created. If no grouping fields are provided, a single group containing all documents is used. Not specifying groups is the same as putting the entire inputs into one group.
    • \*\*Accumulators:\*\* One or more accumulation operations to perform within each group. These are defined using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions, which are typically created by calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances. Each aggregation calculates a value (e.g., sum, average, count) based on the documents within its group.

    Example: | -| [distinct(group, additionalGroups)](./firestore_lite_pipelines.pipeline.md#pipelinedistinct) | | (Public Preview) Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc).The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings:- string: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | -| [distinct(options)](./firestore_lite_pipelines.pipeline.md#pipelinedistinct) | | (Public Preview) Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc).The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings:- string: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | -| [findNearest(options)](./firestore_lite_pipelines.pipeline.md#pipelinefindnearest) | | (Public Preview) Performs a vector proximity search on the documents from the previous stage, returning the K-nearest documents based on the specified query vectorValue and distanceMeasure. The returned documents will be sorted in order from nearest to furthest from the query vectorValue.

    Example: +| [addFields(field, additionalFields)](./firestore_lite_pipelines.pipeline.md#pipelineaddfields) | | Adds new fields to outputs from previous stages.This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps).The added fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s, which can be:- [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [Expression](./firestore_pipelines.expression.md#expression_class): Either a literal value (see [constant()](./firestore_pipelines.md#constant_0c00f91)) or a computed value with an assigned alias using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | +| [addFields(options)](./firestore_lite_pipelines.pipeline.md#pipelineaddfields) | | Adds new fields to outputs from previous stages.This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps).The added fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s, which can be:- [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [Expression](./firestore_pipelines.expression.md#expression_class): Either a literal value (see [constant()](./firestore_pipelines.md#constant_0c00f91)) or a computed value with an assigned alias using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | +| [aggregate(accumulator, additionalAccumulators)](./firestore_lite_pipelines.pipeline.md#pipelineaggregate) | | Performs aggregation operations on the documents from previous stages.

    This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions which are typically results of calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances.

    Example: | +| [aggregate(options)](./firestore_lite_pipelines.pipeline.md#pipelineaggregate) | | Performs optionally grouped aggregation operations on the documents from previous stages.

    This stage allows you to calculate aggregate values over a set of documents, optionally grouped by one or more fields or functions. You can specify:

    • \*\*Grouping Fields or Functions:\*\* One or more fields or functions to group the documents by. For each distinct combination of values in these fields, a separate group is created. If no grouping fields are provided, a single group containing all documents is used. Not specifying groups is the same as putting the entire inputs into one group.
    • \*\*Accumulators:\*\* One or more accumulation operations to perform within each group. These are defined using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions, which are typically created by calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances. Each aggregation calculates a value (e.g., sum, average, count) based on the documents within its group.

    Example: | +| [distinct(group, additionalGroups)](./firestore_lite_pipelines.pipeline.md#pipelinedistinct) | | Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc).The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings:- string: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | +| [distinct(options)](./firestore_lite_pipelines.pipeline.md#pipelinedistinct) | | Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc).The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings:- string: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | +| [findNearest(options)](./firestore_lite_pipelines.pipeline.md#pipelinefindnearest) | | Performs a vector proximity search on the documents from the previous stage, returning the K-nearest documents based on the specified query vectorValue and distanceMeasure. The returned documents will be sorted in order from nearest to furthest from the query vectorValue.

    Example: ```typescript // Find the 10 most similar books based on the book description. const bookDescription = "Lorem ipsum..."; @@ -56,34 +53,31 @@ firestore.pipeline().collection("books") ``` | -| [limit(limit)](./firestore_lite_pipelines.pipeline.md#pipelinelimit) | | (Public Preview) Limits the maximum number of documents returned by previous stages to limit.

    This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for:

    • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
    • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.

    Example: | -| [limit(options)](./firestore_lite_pipelines.pipeline.md#pipelinelimit) | | (Public Preview) Limits the maximum number of documents returned by previous stages to limit.

    This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for:

    • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
    • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.

    Example: | -| [offset(offset)](./firestore_lite_pipelines.pipeline.md#pipelineoffset) | | (Public Preview) Skips the first offset number of documents from the results of previous stages.

    This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page.

    Example: | -| [offset(options)](./firestore_lite_pipelines.pipeline.md#pipelineoffset) | | (Public Preview) Skips the first offset number of documents from the results of previous stages.

    This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page.

    Example: | -| [rawStage(name, params, options)](./firestore_lite_pipelines.pipeline.md#pipelinerawstage) | | (Public Preview) Adds a raw stage to the pipeline.

    This method provides a flexible way to extend the pipeline's functionality by adding custom stages. Each raw stage is defined by a unique name and a set of params that control its behavior.

    Example (Assuming there is no 'where' stage available in SDK): | -| [removeFields(fieldValue, additionalFields)](./firestore_lite_pipelines.pipeline.md#pipelineremovefields) | | (Public Preview) Remove fields from outputs of previous stages.Example: | -| [removeFields(options)](./firestore_lite_pipelines.pipeline.md#pipelineremovefields) | | (Public Preview) Remove fields from outputs of previous stages.Example: | -| [replaceWith(fieldName)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) Fully overwrites all fields in a document with those coming from a nested map.

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

    Example: | -| [replaceWith(expr)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) Fully overwrites all fields in a document with those coming from a map.

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

    Example: | -| [replaceWith(options)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) Fully overwrites all fields in a document with those coming from a map.

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

    Example: | -| [sample(documents)](./firestore_lite_pipelines.pipeline.md#pipelinesample) | | (Public Preview) Performs a pseudo-random sampling of the documents from the previous stage.

    This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned.

    Examples: | -| [sample(options)](./firestore_lite_pipelines.pipeline.md#pipelinesample) | | (Public Preview) Performs a pseudo-random sampling of the documents from the previous stage.

    This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) for more information. | -| [select(selection, additionalSelections)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | (Public Preview) Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

    • string : Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

    Example: | -| [select(options)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | (Public Preview) Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

    • string: Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

    Example: | -| [sort(ordering, additionalOrderings)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | (Public Preview) Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

    Example: | -| [sort(options)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | (Public Preview) Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

    Example: | -| [union(other)](./firestore_lite_pipelines.pipeline.md#pipelineunion) | | (Public Preview) Performs union of all documents from two pipelines, including duplicates.

    This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined.

    Example: | -| [union(options)](./firestore_lite_pipelines.pipeline.md#pipelineunion) | | (Public Preview) Performs union of all documents from two pipelines, including duplicates.

    This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined.

    Example: | -| [unnest(selectable, indexField)](./firestore_lite_pipelines.pipeline.md#pipelineunnest) | | (Public Preview) Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: | -| [unnest(options)](./firestore_lite_pipelines.pipeline.md#pipelineunnest) | | (Public Preview) Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: | -| [where(condition)](./firestore_lite_pipelines.pipeline.md#pipelinewhere) | | (Public Preview) Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class).

    This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to:

    • field comparators: [Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), [Expression.greaterThan()](./firestore_pipelines.expression.md#expressiongreaterthan), etc.
    • logical operators: , , , etc.
    • advanced functions: [Expression.regexMatch()](./firestore_pipelines.expression.md#expressionregexmatch), [Expression.arrayContains()](./firestore_pipelines.expression.md#expressionarraycontains), etc.

    Example: | -| [where(options)](./firestore_lite_pipelines.pipeline.md#pipelinewhere) | | (Public Preview) Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class).

    This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to:

    • field comparators: , (less than), [Expression.greaterThan()](./firestore_pipelines.expression.md#expressiongreaterthan), etc.
    • logical operators: , , , etc.
    • advanced functions: [Expression.regexMatch()](./firestore_pipelines.expression.md#expressionregexmatch), [Expression.arrayContains()](./firestore_pipelines.expression.md#expressionarraycontains), etc.

    Example: | +| [limit(limit)](./firestore_lite_pipelines.pipeline.md#pipelinelimit) | | Limits the maximum number of documents returned by previous stages to limit.

    This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for:

    • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
    • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.

    Example: | +| [limit(options)](./firestore_lite_pipelines.pipeline.md#pipelinelimit) | | Limits the maximum number of documents returned by previous stages to limit.

    This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for:

    • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
    • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.

    Example: | +| [offset(offset)](./firestore_lite_pipelines.pipeline.md#pipelineoffset) | | Skips the first offset number of documents from the results of previous stages.

    This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page.

    Example: | +| [offset(options)](./firestore_lite_pipelines.pipeline.md#pipelineoffset) | | Skips the first offset number of documents from the results of previous stages.

    This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page.

    Example: | +| [rawStage(name, params, options)](./firestore_lite_pipelines.pipeline.md#pipelinerawstage) | | Adds a raw stage to the pipeline.

    This method provides a flexible way to extend the pipeline's functionality by adding custom stages. Each raw stage is defined by a unique name and a set of params that control its behavior.

    Example (Assuming there is no 'where' stage available in SDK): | +| [removeFields(fieldValue, additionalFields)](./firestore_lite_pipelines.pipeline.md#pipelineremovefields) | | Remove fields from outputs of previous stages.Example: | +| [removeFields(options)](./firestore_lite_pipelines.pipeline.md#pipelineremovefields) | | Remove fields from outputs of previous stages.Example: | +| [replaceWith(fieldName)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | Fully overwrites all fields in a document with those coming from a nested map.

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

    Example: | +| [replaceWith(expr)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | Fully overwrites all fields in a document with those coming from a map.

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

    Example: | +| [replaceWith(options)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | Fully overwrites all fields in a document with those coming from a map.

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

    Example: | +| [sample(documents)](./firestore_lite_pipelines.pipeline.md#pipelinesample) | | Performs a pseudo-random sampling of the documents from the previous stage.

    This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned.

    Examples: | +| [sample(options)](./firestore_lite_pipelines.pipeline.md#pipelinesample) | | Performs a pseudo-random sampling of the documents from the previous stage.

    This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) for more information. | +| [select(selection, additionalSelections)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

    • string : Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

    Example: | +| [select(options)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

    • string: Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

    Example: | +| [sort(ordering, additionalOrderings)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

    Example: | +| [sort(options)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

    Example: | +| [union(other)](./firestore_lite_pipelines.pipeline.md#pipelineunion) | | Performs union of all documents from two pipelines, including duplicates.

    This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined.

    Example: | +| [union(options)](./firestore_lite_pipelines.pipeline.md#pipelineunion) | | Performs union of all documents from two pipelines, including duplicates.

    This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined.

    Example: | +| [unnest(selectable, indexField)](./firestore_lite_pipelines.pipeline.md#pipelineunnest) | | Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: | +| [unnest(options)](./firestore_lite_pipelines.pipeline.md#pipelineunnest) | | Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: | +| [where(condition)](./firestore_lite_pipelines.pipeline.md#pipelinewhere) | | Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class).

    This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to:

    • field comparators: [Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), [Expression.greaterThan()](./firestore_pipelines.expression.md#expressiongreaterthan), etc.
    • logical operators: , , , etc.
    • advanced functions: [Expression.regexMatch()](./firestore_pipelines.expression.md#expressionregexmatch), [Expression.arrayContains()](./firestore_pipelines.expression.md#expressionarraycontains), etc.

    Example: | +| [where(options)](./firestore_lite_pipelines.pipeline.md#pipelinewhere) | | Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class).

    This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to:

    • field comparators: , (less than), [Expression.greaterThan()](./firestore_pipelines.expression.md#expressiongreaterthan), etc.
    • logical operators: , , , etc.
    • advanced functions: [Expression.regexMatch()](./firestore_pipelines.expression.md#expressionregexmatch), [Expression.arrayContains()](./firestore_pipelines.expression.md#expressionarraycontains), etc.

    Example: | ## Pipeline.addFields() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Adds new fields to outputs from previous stages. This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps). @@ -127,9 +121,6 @@ firestore.pipeline().collection("books") ## Pipeline.addFields() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Adds new fields to outputs from previous stages. This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps). @@ -172,9 +163,6 @@ firestore.pipeline().collection("books") ## Pipeline.aggregate() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Performs aggregation operations on the documents from previous stages.

    This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions which are typically results of calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances. @@ -215,9 +203,6 @@ firestore.pipeline().collection("books") ## Pipeline.aggregate() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Performs optionally grouped aggregation operations on the documents from previous stages.

    This stage allows you to calculate aggregate values over a set of documents, optionally grouped by one or more fields or functions. You can specify: @@ -259,9 +244,6 @@ firestore.pipeline().collection("books") ## Pipeline.distinct() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns a set of distinct values from the inputs to this stage. This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc). @@ -304,9 +286,6 @@ firestore.pipeline().collection("books") ## Pipeline.distinct() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns a set of distinct values from the inputs to this stage. This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc). @@ -348,9 +327,6 @@ firestore.pipeline().collection("books") ## Pipeline.findNearest() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Performs a vector proximity search on the documents from the previous stage, returning the K-nearest documents based on the specified query `vectorValue` and `distanceMeasure`. The returned documents will be sorted in order from nearest to furthest from the query `vectorValue`.

    Example: @@ -391,9 +367,6 @@ A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with t ## Pipeline.limit() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Limits the maximum number of documents returned by previous stages to `limit`.

    This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for: @@ -433,9 +406,6 @@ firestore.pipeline().collection('books') ## Pipeline.limit() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Limits the maximum number of documents returned by previous stages to `limit`.

    This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for: @@ -475,9 +445,6 @@ firestore.pipeline().collection('books') ## Pipeline.offset() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Skips the first `offset` number of documents from the results of previous stages.

    This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page. @@ -516,9 +483,6 @@ firestore.pipeline().collection('books') ## Pipeline.offset() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Skips the first `offset` number of documents from the results of previous stages.

    This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page. @@ -557,9 +521,6 @@ firestore.pipeline().collection('books') ## Pipeline.rawStage() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Adds a raw stage to the pipeline.

    This method provides a flexible way to extend the pipeline's functionality by adding custom stages. Each raw stage is defined by a unique `name` and a set of `params` that control its behavior. @@ -601,9 +562,6 @@ firestore.pipeline().collection('books') ## Pipeline.removeFields() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Remove fields from outputs of previous stages. Example: @@ -642,9 +600,6 @@ firestore.pipeline().collection('books') ## Pipeline.removeFields() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Remove fields from outputs of previous stages. Example: @@ -682,9 +637,6 @@ firestore.pipeline().collection('books') ## Pipeline.replaceWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Fully overwrites all fields in a document with those coming from a nested map.

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value. @@ -735,9 +687,6 @@ firestore.pipeline().collection('people').replaceWith('parents'); ## Pipeline.replaceWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Fully overwrites all fields in a document with those coming from a map.

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value. @@ -793,9 +742,6 @@ firestore.pipeline().collection('people').replaceWith(map({ ## Pipeline.replaceWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Fully overwrites all fields in a document with those coming from a map.

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value. @@ -851,9 +797,6 @@ firestore.pipeline().collection('people').replaceWith(map({ ## Pipeline.sample() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Performs a pseudo-random sampling of the documents from the previous stage.

    This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned. @@ -890,9 +833,6 @@ firestore.pipeline().collection('books') ## Pipeline.sample() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Performs a pseudo-random sampling of the documents from the previous stage.

    This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) for more information. @@ -931,9 +871,6 @@ firestore.pipeline().collection("books") ## Pipeline.select() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be: @@ -978,9 +915,6 @@ db.pipeline().collection("books") ## Pipeline.select() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be: @@ -1024,9 +958,6 @@ db.pipeline().collection("books") ## Pipeline.sort() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified. @@ -1068,9 +999,6 @@ firestore.pipeline().collection("books") ## Pipeline.sort() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified. @@ -1111,9 +1039,6 @@ firestore.pipeline().collection("books") ## Pipeline.union() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Performs union of all documents from two pipelines, including duplicates.

    This stage will pass through documents from previous stage, and also pass through documents from previous stage of the `other` [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined. @@ -1150,9 +1075,6 @@ firestore.pipeline().collection('books') ## Pipeline.union() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Performs union of all documents from two pipelines, including duplicates.

    This stage will pass through documents from previous stage, and also pass through documents from previous stage of the `other` [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined. @@ -1189,9 +1111,6 @@ firestore.pipeline().collection('books') ## Pipeline.unnest() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Produces a document for each element in an input array. For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the `selectable` parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the `alias` field with the array element value. @@ -1241,9 +1160,6 @@ firestore.pipeline().collection("books") ## Pipeline.unnest() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Produces a document for each element in an input array. For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the `selectable` parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the `alias` field with the array element value. @@ -1292,9 +1208,6 @@ firestore.pipeline().collection("books") ## Pipeline.where() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class).

    This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to: @@ -1337,9 +1250,6 @@ firestore.pipeline().collection("books") ## Pipeline.where() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class).

    This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to: diff --git a/docs-devsite/firestore_lite_pipelines.pipelineresult.md b/docs-devsite/firestore_lite_pipelines.pipelineresult.md index 7dde1ef068..ad59f7d598 100644 --- a/docs-devsite/firestore_lite_pipelines.pipelineresult.md +++ b/docs-devsite/firestore_lite_pipelines.pipelineresult.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # PipelineResult class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the [PipelineResult.data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) or [PipelineResult.get()](./firestore_pipelines.pipelineresult.md#pipelineresultget) methods.

    If the PipelineResult represents a non-document result, `ref` will return a undefined value. @@ -27,23 +24,20 @@ export declare class PipelineResult | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [createTime](./firestore_lite_pipelines.pipelineresult.md#pipelineresultcreatetime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was created. Undefined if this result is not a document. | -| [id](./firestore_lite_pipelines.pipelineresult.md#pipelineresultid) | | string \| undefined | (Public Preview) The ID of the document for which this PipelineResult contains data, if it is a document; otherwise undefined. | -| [ref](./firestore_lite_pipelines.pipelineresult.md#pipelineresultref) | | [DocumentReference](./firestore_lite.documentreference.md#documentreference_class) \| undefined | (Public Preview) The reference of the document, if it is a document; otherwise undefined. | -| [updateTime](./firestore_lite_pipelines.pipelineresult.md#pipelineresultupdatetime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. | +| [createTime](./firestore_lite_pipelines.pipelineresult.md#pipelineresultcreatetime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) \| undefined | The time the document was created. Undefined if this result is not a document. | +| [id](./firestore_lite_pipelines.pipelineresult.md#pipelineresultid) | | string \| undefined | The ID of the document for which this PipelineResult contains data, if it is a document; otherwise undefined. | +| [ref](./firestore_lite_pipelines.pipelineresult.md#pipelineresultref) | | [DocumentReference](./firestore_lite.documentreference.md#documentreference_class) \| undefined | The reference of the document, if it is a document; otherwise undefined. | +| [updateTime](./firestore_lite_pipelines.pipelineresult.md#pipelineresultupdatetime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) \| undefined | The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. | ## Methods | Method | Modifiers | Description | | --- | --- | --- | -| [data()](./firestore_lite_pipelines.pipelineresult.md#pipelineresultdata) | | (Public Preview) Retrieves all fields in the result as an object. | -| [get(fieldPath)](./firestore_lite_pipelines.pipelineresult.md#pipelineresultget) | | (Public Preview) Retrieves the field specified by field. | +| [data()](./firestore_lite_pipelines.pipelineresult.md#pipelineresultdata) | | Retrieves all fields in the result as an object. | +| [get(fieldPath)](./firestore_lite_pipelines.pipelineresult.md#pipelineresultget) | | Retrieves the field specified by field. | ## PipelineResult.createTime -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The time the document was created. Undefined if this result is not a document. Signature: @@ -54,9 +48,6 @@ get createTime(): Timestamp | undefined; ## PipelineResult.id -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The ID of the document for which this PipelineResult contains data, if it is a document; otherwise `undefined`. Signature: @@ -67,9 +58,6 @@ get id(): string | undefined; ## PipelineResult.ref -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The reference of the document, if it is a document; otherwise `undefined`. Signature: @@ -80,9 +68,6 @@ get ref(): DocumentReference | undefined; ## PipelineResult.updateTime -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. Signature: @@ -93,9 +78,6 @@ get updateTime(): Timestamp | undefined; ## PipelineResult.data() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Retrieves all fields in the result as an object. Signature: @@ -124,9 +106,6 @@ p.execute().then(results => { ## PipelineResult.get() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Retrieves the field specified by `field`. Signature: diff --git a/docs-devsite/firestore_lite_pipelines.pipelinesnapshot.md b/docs-devsite/firestore_lite_pipelines.pipelinesnapshot.md index d8e2f8f5bf..9999f6a45c 100644 --- a/docs-devsite/firestore_lite_pipelines.pipelinesnapshot.md +++ b/docs-devsite/firestore_lite_pipelines.pipelinesnapshot.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # PipelineSnapshot class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents the results of a Firestore pipeline execution. A `PipelineSnapshot` contains zero or more [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. @@ -27,20 +24,17 @@ export declare class PipelineSnapshot | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(pipeline, results, executionTime)](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshotconstructor) | | (Public Preview) Constructs a new instance of the PipelineSnapshot class | +| [(constructor)(pipeline, results, executionTime)](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshotconstructor) | | Constructs a new instance of the PipelineSnapshot class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [executionTime](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshotexecutiontime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) | (Public Preview) The time at which the pipeline producing this result is executed. | -| [results](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshotresults) | | [PipelineResult](./firestore_lite_pipelines.pipelineresult.md#pipelineresult_class)\[\] | (Public Preview) An array of all the results in the PipelineSnapshot. | +| [executionTime](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshotexecutiontime) | | [Timestamp](./firestore_lite.timestamp.md#timestamp_class) | The time at which the pipeline producing this result is executed. | +| [results](./firestore_lite_pipelines.pipelinesnapshot.md#pipelinesnapshotresults) | | [PipelineResult](./firestore_lite_pipelines.pipelineresult.md#pipelineresult_class)\[\] | An array of all the results in the PipelineSnapshot. | ## PipelineSnapshot.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `PipelineSnapshot` class Signature: @@ -59,9 +53,6 @@ constructor(pipeline: Pipeline, results: PipelineResult[], executionTime?: Times ## PipelineSnapshot.executionTime -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The time at which the pipeline producing this result is executed. Signature: @@ -72,9 +63,6 @@ get executionTime(): Timestamp; ## PipelineSnapshot.results -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An array of all the results in the `PipelineSnapshot`. Signature: diff --git a/docs-devsite/firestore_lite_pipelines.pipelinesource.md b/docs-devsite/firestore_lite_pipelines.pipelinesource.md index e42b7b66ec..f4559820b0 100644 --- a/docs-devsite/firestore_lite_pipelines.pipelinesource.md +++ b/docs-devsite/firestore_lite_pipelines.pipelinesource.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # PipelineSource class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Provides the entry point for defining the data source of a Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class). Use the methods of this class (e.g., [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection), [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup), [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase), or [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments)) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. @@ -27,21 +24,18 @@ export declare class PipelineSource | Method | Modifiers | Description | | --- | --- | --- | -| [collection(collection)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecollection) | | (Public Preview) Returns all documents from the entire collection. The collection can be nested. | -| [collection(options)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecollection) | | (Public Preview) Returns all documents from the entire collection. The collection can be nested. | -| [collectionGroup(collectionId)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) | | (Public Preview) Returns all documents from a collection ID regardless of the parent. | -| [collectionGroup(options)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) | | (Public Preview) Returns all documents from a collection ID regardless of the parent. | -| [createFrom(query)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecreatefrom) | | (Public Preview) Convert the given Query into an equivalent Pipeline. | -| [database()](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcedatabase) | | (Public Preview) Returns all documents from the entire database. | -| [database(options)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcedatabase) | | (Public Preview) Returns all documents from the entire database. | -| [documents(docs)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcedocuments) | | (Public Preview) Set the pipeline's source to the documents specified by the given paths and DocumentReferences. | -| [documents(options)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcedocuments) | | (Public Preview) Set the pipeline's source to the documents specified by the given paths and DocumentReferences. | +| [collection(collection)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecollection) | | Returns all documents from the entire collection. The collection can be nested. | +| [collection(options)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecollection) | | Returns all documents from the entire collection. The collection can be nested. | +| [collectionGroup(collectionId)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) | | Returns all documents from a collection ID regardless of the parent. | +| [collectionGroup(options)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) | | Returns all documents from a collection ID regardless of the parent. | +| [createFrom(query)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcecreatefrom) | | Convert the given Query into an equivalent Pipeline. | +| [database()](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcedatabase) | | Returns all documents from the entire database. | +| [database(options)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcedatabase) | | Returns all documents from the entire database. | +| [documents(docs)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcedocuments) | | Set the pipeline's source to the documents specified by the given paths and DocumentReferences. | +| [documents(options)](./firestore_lite_pipelines.pipelinesource.md#pipelinesourcedocuments) | | Set the pipeline's source to the documents specified by the given paths and DocumentReferences. | ## PipelineSource.collection() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all documents from the entire collection. The collection can be nested. Signature: @@ -62,9 +56,6 @@ PipelineType ## PipelineSource.collection() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all documents from the entire collection. The collection can be nested. Signature: @@ -85,9 +76,6 @@ PipelineType ## PipelineSource.collectionGroup() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all documents from a collection ID regardless of the parent. Signature: @@ -108,9 +96,6 @@ PipelineType ## PipelineSource.collectionGroup() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all documents from a collection ID regardless of the parent. Signature: @@ -131,9 +116,6 @@ PipelineType ## PipelineSource.createFrom() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Convert the given Query into an equivalent Pipeline. Signature: @@ -158,9 +140,6 @@ createFrom(query: Query): Pipeline; ## PipelineSource.database() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all documents from the entire database. Signature: @@ -174,9 +153,6 @@ PipelineType ## PipelineSource.database() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all documents from the entire database. Signature: @@ -197,9 +173,6 @@ PipelineType ## PipelineSource.documents() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Set the pipeline's source to the documents specified by the given paths and DocumentReferences. Signature: @@ -224,9 +197,6 @@ PipelineType ## PipelineSource.documents() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Set the pipeline's source to the documents specified by the given paths and DocumentReferences. Signature: diff --git a/docs-devsite/firestore_lite_pipelines.selectable.md b/docs-devsite/firestore_lite_pipelines.selectable.md index 555b613577..1b8bf06261 100644 --- a/docs-devsite/firestore_lite_pipelines.selectable.md +++ b/docs-devsite/firestore_lite_pipelines.selectable.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # Selectable interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An interface that represents a selectable expression. Signature: @@ -25,13 +22,10 @@ export declare interface Selectable | Property | Type | Description | | --- | --- | --- | -| [selectable](./firestore_lite_pipelines.selectable.md#selectableselectable) | true | (Public Preview) | +| [selectable](./firestore_lite_pipelines.selectable.md#selectableselectable) | true | | ## Selectable.selectable -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/firestore_lite_pipelines.stageoptions.md b/docs-devsite/firestore_lite_pipelines.stageoptions.md index b751cfaa7f..597d446a80 100644 --- a/docs-devsite/firestore_lite_pipelines.stageoptions.md +++ b/docs-devsite/firestore_lite_pipelines.stageoptions.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # StageOptions interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a Stage is evaluated. Signature: @@ -25,13 +22,10 @@ export declare interface StageOptions | Property | Type | Description | | --- | --- | --- | -| [rawOptions](./firestore_lite_pipelines.stageoptions.md#stageoptionsrawoptions) | { \[name: string\]: unknown; } | (Public Preview) An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Raw option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK.rawOptions supports dot notation, if you want to override a nested option. | +| [rawOptions](./firestore_lite_pipelines.stageoptions.md#stageoptionsrawoptions) | { \[name: string\]: unknown; } | An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Raw option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK.rawOptions supports dot notation, if you want to override a nested option. | ## StageOptions.rawOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK. The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name). diff --git a/docs-devsite/firestore_pipelines.aggregatefunction.md b/docs-devsite/firestore_pipelines.aggregatefunction.md index 37b927d28d..c00c146ad1 100644 --- a/docs-devsite/firestore_pipelines.aggregatefunction.md +++ b/docs-devsite/firestore_pipelines.aggregatefunction.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # AggregateFunction class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - A class that represents an aggregate function. Signature: @@ -25,25 +22,22 @@ export declare class AggregateFunction | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(name, params)](./firestore_pipelines.aggregatefunction.md#aggregatefunctionconstructor) | | (Public Preview) Constructs a new instance of the AggregateFunction class | +| [(constructor)(name, params)](./firestore_pipelines.aggregatefunction.md#aggregatefunctionconstructor) | | Constructs a new instance of the AggregateFunction class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [exprType](./firestore_pipelines.aggregatefunction.md#aggregatefunctionexprtype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) | +| [exprType](./firestore_pipelines.aggregatefunction.md#aggregatefunctionexprtype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | | ## Methods | Method | Modifiers | Description | | --- | --- | --- | -| [as(name)](./firestore_pipelines.aggregatefunction.md#aggregatefunctionas) | | (Public Preview) Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. | +| [as(name)](./firestore_pipelines.aggregatefunction.md#aggregatefunctionas) | | Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. | ## AggregateFunction.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `AggregateFunction` class Signature: @@ -61,9 +55,6 @@ constructor(name: string, params: Expression[]); ## AggregateFunction.exprType -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -72,9 +63,6 @@ exprType: ExpressionType; ## AggregateFunction.as() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Assigns an alias to this AggregateFunction. The alias specifies the name that the aggregated value will have in the output document. Signature: diff --git a/docs-devsite/firestore_pipelines.aliasedaggregate.md b/docs-devsite/firestore_pipelines.aliasedaggregate.md index 39826b83b6..8b443f44e4 100644 --- a/docs-devsite/firestore_pipelines.aliasedaggregate.md +++ b/docs-devsite/firestore_pipelines.aliasedaggregate.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # AliasedAggregate class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An AggregateFunction with alias. Signature: @@ -25,20 +22,17 @@ export declare class AliasedAggregate | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(aggregate, alias, \_methodName)](./firestore_pipelines.aliasedaggregate.md#aliasedaggregateconstructor) | | (Public Preview) Constructs a new instance of the AliasedAggregate class | +| [(constructor)(aggregate, alias, \_methodName)](./firestore_pipelines.aliasedaggregate.md#aliasedaggregateconstructor) | | Constructs a new instance of the AliasedAggregate class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [aggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregateaggregate) | | [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) | (Public Preview) | -| [alias](./firestore_pipelines.aliasedaggregate.md#aliasedaggregatealias) | | string | (Public Preview) | +| [aggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregateaggregate) | | [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) | | +| [alias](./firestore_pipelines.aliasedaggregate.md#aliasedaggregatealias) | | string | | ## AliasedAggregate.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `AliasedAggregate` class Signature: @@ -57,9 +51,6 @@ constructor(aggregate: AggregateFunction, alias: string, _methodName: string | u ## AliasedAggregate.aggregate -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -68,9 +59,6 @@ readonly aggregate: AggregateFunction; ## AliasedAggregate.alias -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/firestore_pipelines.aliasedexpression.md b/docs-devsite/firestore_pipelines.aliasedexpression.md index 6a602a9e44..657bd7e2e7 100644 --- a/docs-devsite/firestore_pipelines.aliasedexpression.md +++ b/docs-devsite/firestore_pipelines.aliasedexpression.md @@ -10,10 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # AliasedExpression class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - - Signature: ```typescript @@ -25,22 +21,19 @@ export declare class AliasedExpression implements Selectable | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(expr, alias, \_methodName)](./firestore_pipelines.aliasedexpression.md#aliasedexpressionconstructor) | | (Public Preview) Constructs a new instance of the AliasedExpression class | +| [(constructor)(expr, alias, \_methodName)](./firestore_pipelines.aliasedexpression.md#aliasedexpressionconstructor) | | Constructs a new instance of the AliasedExpression class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [alias](./firestore_pipelines.aliasedexpression.md#aliasedexpressionalias) | | string | (Public Preview) | -| [expr](./firestore_pipelines.aliasedexpression.md#aliasedexpressionexpr) | | [Expression](./firestore_pipelines.expression.md#expression_class) | (Public Preview) | -| [exprType](./firestore_pipelines.aliasedexpression.md#aliasedexpressionexprtype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) | -| [selectable](./firestore_pipelines.aliasedexpression.md#aliasedexpressionselectable) | | true | (Public Preview) | +| [alias](./firestore_pipelines.aliasedexpression.md#aliasedexpressionalias) | | string | | +| [expr](./firestore_pipelines.aliasedexpression.md#aliasedexpressionexpr) | | [Expression](./firestore_pipelines.expression.md#expression_class) | | +| [exprType](./firestore_pipelines.aliasedexpression.md#aliasedexpressionexprtype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | | +| [selectable](./firestore_pipelines.aliasedexpression.md#aliasedexpressionselectable) | | true | | ## AliasedExpression.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `AliasedExpression` class Signature: @@ -59,9 +52,6 @@ constructor(expr: Expression, alias: string, _methodName: string | undefined); ## AliasedExpression.alias -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -70,9 +60,6 @@ readonly alias: string; ## AliasedExpression.expr -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -81,9 +68,6 @@ readonly expr: Expression; ## AliasedExpression.exprType -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -92,9 +76,6 @@ exprType: ExpressionType; ## AliasedExpression.selectable -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/firestore_pipelines.booleanexpression.md b/docs-devsite/firestore_pipelines.booleanexpression.md index a5d0f86f12..c9b0df409c 100644 --- a/docs-devsite/firestore_pipelines.booleanexpression.md +++ b/docs-devsite/firestore_pipelines.booleanexpression.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # BooleanExpression class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An interface that represents a filter condition. Signature: @@ -26,19 +23,16 @@ export declare abstract class BooleanExpression extends Expression | Method | Modifiers | Description | | --- | --- | --- | -| [conditional(thenExpr, elseExpr)](./firestore_pipelines.booleanexpression.md#booleanexpressionconditional) | | (Public Preview) Creates a conditional expression that evaluates to the 'then' expression if this expression evaluates to true, or evaluates to the 'else' expression if this expressions evaluates false. | -| [countIf()](./firestore_pipelines.booleanexpression.md#booleanexpressioncountif) | | (Public Preview) Creates an aggregation that finds the count of input documents satisfying this boolean expression. | -| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | -| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | -| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | -| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | -| [not()](./firestore_pipelines.booleanexpression.md#booleanexpressionnot) | | (Public Preview) Creates an expression that negates this boolean expression. | +| [conditional(thenExpr, elseExpr)](./firestore_pipelines.booleanexpression.md#booleanexpressionconditional) | | Creates a conditional expression that evaluates to the 'then' expression if this expression evaluates to true, or evaluates to the 'else' expression if this expressions evaluates false. | +| [countIf()](./firestore_pipelines.booleanexpression.md#booleanexpressioncountif) | | Creates an aggregation that finds the count of input documents satisfying this boolean expression. | +| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_pipelines.booleanexpression.md#booleanexpressioniferror) | | Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [not()](./firestore_pipelines.booleanexpression.md#booleanexpressionnot) | | Creates an expression that negates this boolean expression. | ## BooleanExpression.conditional() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a conditional expression that evaluates to the 'then' expression if `this` expression evaluates to `true`, or evaluates to the 'else' expression if `this` expressions evaluates `false`. Signature: @@ -71,9 +65,6 @@ field("age").greaterThanOrEqual(18).conditional(constant("Adult"), constant("Min ## BooleanExpression.countIf() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the count of input documents satisfying this boolean expression. Signature: @@ -98,9 +89,6 @@ field("score").greaterThan(90).countIf().as("highestScore"); ## BooleanExpression.ifError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. Signature: @@ -133,9 +121,6 @@ constant(50).divide(field('length')).greaterThan(1).ifError(constant(false)); ## BooleanExpression.ifError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. Signature: @@ -168,9 +153,6 @@ constant(50).divide(field('length')).greaterThan(1).ifError(false); ## BooleanExpression.ifError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. Signature: @@ -202,9 +184,6 @@ constant(50).divide(field('length')).greaterThan(1).ifError(constant(0)); ## BooleanExpression.ifError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. Signature: @@ -236,9 +215,6 @@ constant(50).divide(field('length')).greaterThan(1).ifError(0); ## BooleanExpression.not() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that negates this boolean expression. Signature: diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 9d8d72df89..07fca7c58d 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # Expression class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents an expression that can be evaluated to a value within the execution of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class). Expressions are the building blocks for creating complex queries and transformations in Firestore pipelines. They can represent: @@ -31,186 +28,183 @@ export declare abstract class Expression | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [expressionType](./firestore_pipelines.expression.md#expressionexpressiontype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) | +| [expressionType](./firestore_pipelines.expression.md#expressionexpressiontype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | | ## Methods | Method | Modifiers | Description | | --- | --- | --- | -| [abs()](./firestore_pipelines.expression.md#expressionabs) | | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | -| [add(second)](./firestore_pipelines.expression.md#expressionadd) | | (Public Preview) Creates an expression that adds this expression to another expression. | -| [arrayAgg()](./firestore_pipelines.expression.md#expressionarrayagg) | | (Public Preview) Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. | -| [arrayAggDistinct()](./firestore_pipelines.expression.md#expressionarrayaggdistinct) | | (Public Preview) Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. | -| [arrayConcat(secondArray, otherArrays)](./firestore_pipelines.expression.md#expressionarrayconcat) | | (Public Preview) Creates an expression that concatenates an array expression with one or more other arrays. | -| [arrayContains(expression)](./firestore_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific element. | -| [arrayContains(value)](./firestore_pipelines.expression.md#expressionarraycontains) | | (Public Preview) Creates an expression that checks if an array contains a specific value. | -| [arrayContainsAll(values)](./firestore_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. | -| [arrayContainsAll(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsall) | | (Public Preview) Creates an expression that checks if an array contains all the specified elements. | -| [arrayContainsAny(values)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. | -| [arrayContainsAny(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | (Public Preview) Creates an expression that checks if an array contains any of the specified elements. | -| [arrayFirst()](./firestore_pipelines.expression.md#expressionarrayfirst) | | (Public Preview) Returns the first element of the array. | -| [arrayFirstN(n)](./firestore_pipelines.expression.md#expressionarrayfirstn) | | (Public Preview) Returns the first n elements of the array. | -| [arrayFirstN(n)](./firestore_pipelines.expression.md#expressionarrayfirstn) | | (Public Preview) Returns the first n elements of the array. | -| [arrayGet(offset)](./firestore_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | -| [arrayGet(offsetExpr)](./firestore_pipelines.expression.md#expressionarrayget) | | (Public Preview) Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | -| [arrayIndexOf(search)](./firestore_pipelines.expression.md#expressionarrayindexof) | | (Public Preview) Returns the first index of the search value in the array, or -1 if not found. | -| [arrayIndexOf(search)](./firestore_pipelines.expression.md#expressionarrayindexof) | | (Public Preview) Returns the first index of the search value in the array, or -1 if not found. | -| [arrayIndexOfAll(search)](./firestore_pipelines.expression.md#expressionarrayindexofall) | | (Public Preview) Returns all indices of the search value in the array. | -| [arrayIndexOfAll(search)](./firestore_pipelines.expression.md#expressionarrayindexofall) | | (Public Preview) Returns all indices of the search value in the array. | -| [arrayLast()](./firestore_pipelines.expression.md#expressionarraylast) | | (Public Preview) Returns the last element of the array. | -| [arrayLastIndexOf(search)](./firestore_pipelines.expression.md#expressionarraylastindexof) | | (Public Preview) Returns the last index of the search value in the array, or -1 if not found. | -| [arrayLastIndexOf(search)](./firestore_pipelines.expression.md#expressionarraylastindexof) | | (Public Preview) Returns the last index of the search value in the array, or -1 if not found. | -| [arrayLastN(n)](./firestore_pipelines.expression.md#expressionarraylastn) | | (Public Preview) Returns the last n elements of the array. | -| [arrayLastN(n)](./firestore_pipelines.expression.md#expressionarraylastn) | | (Public Preview) Returns the last n elements of the array. | -| [arrayLength()](./firestore_pipelines.expression.md#expressionarraylength) | | (Public Preview) Creates an expression that calculates the length of an array. | -| [arrayMaximum()](./firestore_pipelines.expression.md#expressionarraymaximum) | | (Public Preview) Returns the maximum value in the array. | -| [arrayMaximumN(n)](./firestore_pipelines.expression.md#expressionarraymaximumn) | | (Public Preview) Returns the largest n elements of the array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMaximumN(n)](./firestore_pipelines.expression.md#expressionarraymaximumn) | | (Public Preview) Returns the largest n elements of the array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMinimum()](./firestore_pipelines.expression.md#expressionarrayminimum) | | (Public Preview) Returns the minimum value in the array. | -| [arrayMinimumN(n)](./firestore_pipelines.expression.md#expressionarrayminimumn) | | (Public Preview) Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMinimumN(n)](./firestore_pipelines.expression.md#expressionarrayminimumn) | | (Public Preview) Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayReverse()](./firestore_pipelines.expression.md#expressionarrayreverse) | | (Public Preview) Creates an expression that reverses an array. | -| [arraySum()](./firestore_pipelines.expression.md#expressionarraysum) | | (Public Preview) Creates an expression that computes the sum of the elements in an array. | -| [as(name)](./firestore_pipelines.expression.md#expressionas) | | (Public Preview) 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. | -| [asBoolean()](./firestore_pipelines.expression.md#expressionasboolean) | | (Public Preview) Wraps the expression in a \[BooleanExpression\]. | -| [ascending()](./firestore_pipelines.expression.md#expressionascending) | | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on this expression. | -| [average()](./firestore_pipelines.expression.md#expressionaverage) | | (Public Preview) Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. | -| [byteLength()](./firestore_pipelines.expression.md#expressionbytelength) | | (Public Preview) Creates an expression that calculates the length of this string expression in bytes. | -| [ceil()](./firestore_pipelines.expression.md#expressionceil) | | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | -| [charLength()](./firestore_pipelines.expression.md#expressioncharlength) | | (Public Preview) Creates an expression that calculates the character length of a string in UTF-8. | -| [coalesce(replacement, others)](./firestore_pipelines.expression.md#expressioncoalesce) | | (Public Preview) Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | -| [collectionId()](./firestore_pipelines.expression.md#expressioncollectionid) | | (Public Preview) Creates an expression that returns the collection ID from a path. | -| [concat(second, others)](./firestore_pipelines.expression.md#expressionconcat) | | (Public Preview) Creates an expression that concatenates expression results together. | -| [cosineDistance(vectorExpression)](./firestore_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the cosine distance between two vectors. | -| [cosineDistance(vector)](./firestore_pipelines.expression.md#expressioncosinedistance) | | (Public Preview) Calculates the Cosine distance between two vectors. | -| [count()](./firestore_pipelines.expression.md#expressioncount) | | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. | -| [countDistinct()](./firestore_pipelines.expression.md#expressioncountdistinct) | | (Public Preview) Creates an aggregation that counts the number of distinct values of the expression or field. | -| [descending()](./firestore_pipelines.expression.md#expressiondescending) | | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on this expression. | -| [divide(divisor)](./firestore_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by another expression. | -| [divide(divisor)](./firestore_pipelines.expression.md#expressiondivide) | | (Public Preview) Creates an expression that divides this expression by a constant value. | -| [documentId()](./firestore_pipelines.expression.md#expressiondocumentid) | | (Public Preview) Creates an expression that returns the document ID from a path. | -| [dotProduct(vectorExpression)](./firestore_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. | -| [dotProduct(vector)](./firestore_pipelines.expression.md#expressiondotproduct) | | (Public Preview) Calculates the dot product between two vectors. | -| [endsWith(suffix)](./firestore_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix. | -| [endsWith(suffix)](./firestore_pipelines.expression.md#expressionendswith) | | (Public Preview) Creates an expression that checks if a string ends with a given postfix (represented as an expression). | -| [equal(expression)](./firestore_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to another expression. | -| [equal(value)](./firestore_pipelines.expression.md#expressionequal) | | (Public Preview) Creates an expression that checks if this expression is equal to a constant value. | -| [equalAny(values)](./firestore_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. | -| [equalAny(arrayExpression)](./firestore_pipelines.expression.md#expressionequalany) | | (Public Preview) Creates an expression that checks if this expression is equal to any of the provided values or expressions. | -| [euclideanDistance(vectorExpression)](./firestore_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. | -| [euclideanDistance(vector)](./firestore_pipelines.expression.md#expressioneuclideandistance) | | (Public Preview) Calculates the Euclidean distance between two vectors. | -| [exists()](./firestore_pipelines.expression.md#expressionexists) | | (Public Preview) Creates an expression that checks if a field exists in the document. | -| [exp()](./firestore_pipelines.expression.md#expressionexp) | | (Public Preview) Creates an expression that computes e to the power of this expression. | -| [first()](./firestore_pipelines.expression.md#expressionfirst) | | (Public Preview) Creates an aggregation that finds the first value of an expression across multiple stage inputs. | -| [floor()](./firestore_pipelines.expression.md#expressionfloor) | | (Public Preview) Creates an expression that computes the floor of a numeric value. | -| [greaterThan(expression)](./firestore_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than another expression. | -| [greaterThan(value)](./firestore_pipelines.expression.md#expressiongreaterthan) | | (Public Preview) Creates an expression that checks if this expression is greater than a constant value. | -| [greaterThanOrEqual(expression)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to another expression. | -| [greaterThanOrEqual(value)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | (Public Preview) Creates an expression that checks if this expression is greater than or equal to a constant value. | -| [ifAbsent(elseValue)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | -| [ifAbsent(elseExpression)](./firestore_pipelines.expression.md#expressionifabsent) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | -| [ifError(catchExpr)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. | -| [ifError(catchValue)](./firestore_pipelines.expression.md#expressioniferror) | | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | -| [ifNull(elseExpression)](./firestore_pipelines.expression.md#expressionifnull) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression evaluates to null, else return the result of this expression evaluation. | -| [ifNull(elseValue)](./firestore_pipelines.expression.md#expressionifnull) | | (Public Preview) Creates an expression that returns the elseValue argument if this expression evaluates to null, else return the result of this expression evaluation. | -| [isAbsent()](./firestore_pipelines.expression.md#expressionisabsent) | | (Public Preview) Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. | -| [isError()](./firestore_pipelines.expression.md#expressioniserror) | | (Public Preview) Creates an expression that checks if a given expression produces an error. | -| [isType(type)](./firestore_pipelines.expression.md#expressionistype) | | (Public Preview) Creates an expression that checks if the result of this expression is of the given type. | -| [join(delimiterExpression)](./firestore_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array into a string. | -| [join(delimiter)](./firestore_pipelines.expression.md#expressionjoin) | | (Public Preview) Creates an expression that joins the elements of an array field into a string. | -| [last()](./firestore_pipelines.expression.md#expressionlast) | | (Public Preview) Creates an aggregation that finds the last value of an expression across multiple stage inputs. | -| [length()](./firestore_pipelines.expression.md#expressionlength) | | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | -| [lessThan(experession)](./firestore_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than another expression. | -| [lessThan(value)](./firestore_pipelines.expression.md#expressionlessthan) | | (Public Preview) Creates an expression that checks if this expression is less than a constant value. | -| [lessThanOrEqual(expression)](./firestore_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to another expression. | -| [lessThanOrEqual(value)](./firestore_pipelines.expression.md#expressionlessthanorequal) | | (Public Preview) Creates an expression that checks if this expression is less than or equal to a constant value. | -| [like(pattern)](./firestore_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. | -| [like(pattern)](./firestore_pipelines.expression.md#expressionlike) | | (Public Preview) Creates an expression that performs a case-sensitive string comparison. | -| [ln()](./firestore_pipelines.expression.md#expressionln) | | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. | -| [log10()](./firestore_pipelines.expression.md#expressionlog10) | | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | -| [logicalMaximum(second, others)](./firestore_pipelines.expression.md#expressionlogicalmaximum) | | (Public Preview) Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. | -| [logicalMinimum(second, others)](./firestore_pipelines.expression.md#expressionlogicalminimum) | | (Public Preview) Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. | -| [ltrim(valueToTrim)](./firestore_pipelines.expression.md#expressionltrim) | | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | -| [mapEntries()](./firestore_pipelines.expression.md#expressionmapentries) | | (Public Preview) 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" }, ...]. | -| [mapGet(subfield)](./firestore_pipelines.expression.md#expressionmapget) | | (Public Preview) Accesses a value from a map (object) field using the provided key. | -| [mapKeys()](./firestore_pipelines.expression.md#expressionmapkeys) | | (Public Preview) Creates an expression that returns the keys of a map. | -| [mapMerge(secondMap, otherMaps)](./firestore_pipelines.expression.md#expressionmapmerge) | | (Public Preview) Creates an expression that merges multiple map values. | -| [mapRemove(key)](./firestore_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | -| [mapRemove(keyExpr)](./firestore_pipelines.expression.md#expressionmapremove) | | (Public Preview) Creates an expression that removes a key from the map produced by evaluating this expression. | -| [mapSet(key, value, moreKeyValues)](./firestore_pipelines.expression.md#expressionmapset) | | (Public Preview) Creates an expression that returns a new map with the specified entries added or updated. | -| [mapValues()](./firestore_pipelines.expression.md#expressionmapvalues) | | (Public Preview) Creates an expression that returns the values of a map. | -| [maximum()](./firestore_pipelines.expression.md#expressionmaximum) | | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | -| [minimum()](./firestore_pipelines.expression.md#expressionminimum) | | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | -| [mod(expression)](./firestore_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. | -| [mod(value)](./firestore_pipelines.expression.md#expressionmod) | | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. | -| [multiply(second)](./firestore_pipelines.expression.md#expressionmultiply) | | (Public Preview) Creates an expression that multiplies this expression by another expression. | -| [notEqual(expression)](./firestore_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to another expression. | -| [notEqual(value)](./firestore_pipelines.expression.md#expressionnotequal) | | (Public Preview) Creates an expression that checks if this expression is not equal to a constant value. | -| [notEqualAny(values)](./firestore_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the provided values or expressions. | -| [notEqualAny(arrayExpression)](./firestore_pipelines.expression.md#expressionnotequalany) | | (Public Preview) Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. | -| [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of another expression. | -| [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | (Public Preview) Creates an expression that returns the value of this expression raised to the power of a constant value. | -| [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. | -| [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified regular expression as a substring. | -| [regexFind(pattern)](./firestore_pipelines.expression.md#expressionregexfind) | | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFind(pattern)](./firestore_pipelines.expression.md#expressionregexfind) | | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFindAll(pattern)](./firestore_pipelines.expression.md#expressionregexfindall) | | (Public Preview) Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFindAll(pattern)](./firestore_pipelines.expression.md#expressionregexfindall) | | (Public Preview) Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexMatch(pattern)](./firestore_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. | -| [regexMatch(pattern)](./firestore_pipelines.expression.md#expressionregexmatch) | | (Public Preview) Creates an expression that checks if a string matches a specified regular expression. | -| [reverse()](./firestore_pipelines.expression.md#expressionreverse) | | (Public Preview) Creates an expression that reverses this string expression. | -| [round()](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | -| [round(decimalPlaces)](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | -| [round(decimalPlaces)](./firestore_pipelines.expression.md#expressionround) | | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | -| [rtrim(valueToTrim)](./firestore_pipelines.expression.md#expressionrtrim) | | (Public Preview) Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | -| [split(delimiter)](./firestore_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | -| [split(delimiter)](./firestore_pipelines.expression.md#expressionsplit) | | (Public Preview) Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | -| [sqrt()](./firestore_pipelines.expression.md#expressionsqrt) | | (Public Preview) Creates an expression that computes the square root of a numeric value. | -| [startsWith(prefix)](./firestore_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix. | -| [startsWith(prefix)](./firestore_pipelines.expression.md#expressionstartswith) | | (Public Preview) Creates an expression that checks if a string starts with a given prefix (represented as an expression). | -| [stringConcat(secondString, otherStrings)](./firestore_pipelines.expression.md#expressionstringconcat) | | (Public Preview) Creates an expression that concatenates string expressions together. | -| [stringContains(substring)](./firestore_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains a specified substring. | -| [stringContains(expr)](./firestore_pipelines.expression.md#expressionstringcontains) | | (Public Preview) Creates an expression that checks if a string contains the string represented by another expression. | -| [stringIndexOf(search)](./firestore_pipelines.expression.md#expressionstringindexof) | | (Public Preview) Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | -| [stringRepeat(repetitions)](./firestore_pipelines.expression.md#expressionstringrepeat) | | (Public Preview) Creates an expression that repeats a string or byte array a specified number of times. | -| [stringReplaceAll(find, replacement)](./firestore_pipelines.expression.md#expressionstringreplaceall) | | (Public Preview) Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | -| [stringReplaceOne(find, replacement)](./firestore_pipelines.expression.md#expressionstringreplaceone) | | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | -| [stringReverse()](./firestore_pipelines.expression.md#expressionstringreverse) | | (Public Preview) Creates an expression that reverses a string. | -| [substring(position, length)](./firestore_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | -| [substring(position, length)](./firestore_pipelines.expression.md#expressionsubstring) | | (Public Preview) Creates an expression that returns a substring of the results of this expression. | -| [subtract(subtrahend)](./firestore_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts another expression from this expression. | -| [subtract(subtrahend)](./firestore_pipelines.expression.md#expressionsubtract) | | (Public Preview) Creates an expression that subtracts a constant value from this expression. | -| [sum()](./firestore_pipelines.expression.md#expressionsum) | | (Public Preview) Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. | -| [timestampAdd(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. | -| [timestampAdd(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampadd) | | (Public Preview) Creates an expression that adds a specified amount of time to this timestamp expression. | -| [timestampDiff(start, unit)](./firestore_pipelines.expression.md#expressiontimestampdiff) | | (Public Preview) Creates an expression that calculates the difference between this timestamp and another timestamp. | -| [timestampDiff(start, unit)](./firestore_pipelines.expression.md#expressiontimestampdiff) | | (Public Preview) Creates an expression that calculates the difference between this timestamp and another timestamp. | -| [timestampExtract(part, timezone)](./firestore_pipelines.expression.md#expressiontimestampextract) | | (Public Preview) Creates an expression that extracts a specified part from this timestamp expression. | -| [timestampExtract(part, timezone)](./firestore_pipelines.expression.md#expressiontimestampextract) | | (Public Preview) Creates an expression that extracts a specified part from this timestamp expression. | -| [timestampSubtract(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. | -| [timestampSubtract(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampsubtract) | | (Public Preview) Creates an expression that subtracts a specified amount of time from this timestamp expression. | -| [timestampToUnixMicros()](./firestore_pipelines.expression.md#expressiontimestamptounixmicros) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampToUnixMillis()](./firestore_pipelines.expression.md#expressiontimestamptounixmillis) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampToUnixSeconds()](./firestore_pipelines.expression.md#expressiontimestamptounixseconds) | | (Public Preview) Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampTruncate(granularity, timezone)](./firestore_pipelines.expression.md#expressiontimestamptruncate) | | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [timestampTruncate(granularity, timezone)](./firestore_pipelines.expression.md#expressiontimestamptruncate) | | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [toLower()](./firestore_pipelines.expression.md#expressiontolower) | | (Public Preview) Creates an expression that converts a string to lowercase. | -| [toUpper()](./firestore_pipelines.expression.md#expressiontoupper) | | (Public Preview) Creates an expression that converts a string to uppercase. | -| [trim(valueToTrim)](./firestore_pipelines.expression.md#expressiontrim) | | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array. | -| [trunc()](./firestore_pipelines.expression.md#expressiontrunc) | | (Public Preview) Creates an expression that truncates the numeric value to an integer. | -| [trunc(decimalPlaces)](./firestore_pipelines.expression.md#expressiontrunc) | | (Public Preview) Creates an expression that truncates a numeric value to the specified number of decimal places. | -| [trunc(decimalPlaces)](./firestore_pipelines.expression.md#expressiontrunc) | | (Public Preview) Creates an expression that truncates a numeric value to the specified number of decimal places. | -| [type()](./firestore_pipelines.expression.md#expressiontype) | | (Public Preview) Creates an expression that returns the data type of this expression's result, as a string. | -| [unixMicrosToTimestamp()](./firestore_pipelines.expression.md#expressionunixmicrostotimestamp) | | (Public Preview) 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. | -| [unixMillisToTimestamp()](./firestore_pipelines.expression.md#expressionunixmillistotimestamp) | | (Public Preview) 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. | -| [unixSecondsToTimestamp()](./firestore_pipelines.expression.md#expressionunixsecondstotimestamp) | | (Public Preview) 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. | -| [vectorLength()](./firestore_pipelines.expression.md#expressionvectorlength) | | (Public Preview) Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. | +| [abs()](./firestore_pipelines.expression.md#expressionabs) | | Creates an expression that computes the absolute value of a numeric value. | +| [add(second)](./firestore_pipelines.expression.md#expressionadd) | | Creates an expression that adds this expression to another expression. | +| [arrayAgg()](./firestore_pipelines.expression.md#expressionarrayagg) | | Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. | +| [arrayAggDistinct()](./firestore_pipelines.expression.md#expressionarrayaggdistinct) | | Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. | +| [arrayConcat(secondArray, otherArrays)](./firestore_pipelines.expression.md#expressionarrayconcat) | | Creates an expression that concatenates an array expression with one or more other arrays. | +| [arrayContains(expression)](./firestore_pipelines.expression.md#expressionarraycontains) | | Creates an expression that checks if an array contains a specific element. | +| [arrayContains(value)](./firestore_pipelines.expression.md#expressionarraycontains) | | Creates an expression that checks if an array contains a specific value. | +| [arrayContainsAll(values)](./firestore_pipelines.expression.md#expressionarraycontainsall) | | Creates an expression that checks if an array contains all the specified elements. | +| [arrayContainsAll(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsall) | | Creates an expression that checks if an array contains all the specified elements. | +| [arrayContainsAny(values)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | Creates an expression that checks if an array contains any of the specified elements. | +| [arrayContainsAny(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | Creates an expression that checks if an array contains any of the specified elements. | +| [arrayFirst()](./firestore_pipelines.expression.md#expressionarrayfirst) | | Returns the first element of the array. | +| [arrayFirstN(n)](./firestore_pipelines.expression.md#expressionarrayfirstn) | | Returns the first n elements of the array. | +| [arrayFirstN(n)](./firestore_pipelines.expression.md#expressionarrayfirstn) | | Returns the first n elements of the array. | +| [arrayGet(offset)](./firestore_pipelines.expression.md#expressionarrayget) | | Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(offsetExpr)](./firestore_pipelines.expression.md#expressionarrayget) | | Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayIndexOf(search)](./firestore_pipelines.expression.md#expressionarrayindexof) | | Returns the first index of the search value in the array, or -1 if not found. | +| [arrayIndexOf(search)](./firestore_pipelines.expression.md#expressionarrayindexof) | | Returns the first index of the search value in the array, or -1 if not found. | +| [arrayIndexOfAll(search)](./firestore_pipelines.expression.md#expressionarrayindexofall) | | Returns all indices of the search value in the array. | +| [arrayIndexOfAll(search)](./firestore_pipelines.expression.md#expressionarrayindexofall) | | Returns all indices of the search value in the array. | +| [arrayLast()](./firestore_pipelines.expression.md#expressionarraylast) | | Returns the last element of the array. | +| [arrayLastIndexOf(search)](./firestore_pipelines.expression.md#expressionarraylastindexof) | | Returns the last index of the search value in the array, or -1 if not found. | +| [arrayLastIndexOf(search)](./firestore_pipelines.expression.md#expressionarraylastindexof) | | Returns the last index of the search value in the array, or -1 if not found. | +| [arrayLastN(n)](./firestore_pipelines.expression.md#expressionarraylastn) | | Returns the last n elements of the array. | +| [arrayLastN(n)](./firestore_pipelines.expression.md#expressionarraylastn) | | Returns the last n elements of the array. | +| [arrayLength()](./firestore_pipelines.expression.md#expressionarraylength) | | Creates an expression that calculates the length of an array. | +| [arrayMaximum()](./firestore_pipelines.expression.md#expressionarraymaximum) | | Returns the maximum value in the array. | +| [arrayMaximumN(n)](./firestore_pipelines.expression.md#expressionarraymaximumn) | | Returns the largest n elements of the array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMaximumN(n)](./firestore_pipelines.expression.md#expressionarraymaximumn) | | Returns the largest n elements of the array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimum()](./firestore_pipelines.expression.md#expressionarrayminimum) | | Returns the minimum value in the array. | +| [arrayMinimumN(n)](./firestore_pipelines.expression.md#expressionarrayminimumn) | | Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimumN(n)](./firestore_pipelines.expression.md#expressionarrayminimumn) | | Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayReverse()](./firestore_pipelines.expression.md#expressionarrayreverse) | | Creates an expression that reverses an array. | +| [arraySum()](./firestore_pipelines.expression.md#expressionarraysum) | | Creates an expression that computes the sum of the elements in an array. | +| [as(name)](./firestore_pipelines.expression.md#expressionas) | | 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. | +| [asBoolean()](./firestore_pipelines.expression.md#expressionasboolean) | | Wraps the expression in a \[BooleanExpression\]. | +| [ascending()](./firestore_pipelines.expression.md#expressionascending) | | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on this expression. | +| [average()](./firestore_pipelines.expression.md#expressionaverage) | | Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. | +| [byteLength()](./firestore_pipelines.expression.md#expressionbytelength) | | Creates an expression that calculates the length of this string expression in bytes. | +| [ceil()](./firestore_pipelines.expression.md#expressionceil) | | Creates an expression that computes the ceiling of a numeric value. | +| [charLength()](./firestore_pipelines.expression.md#expressioncharlength) | | Creates an expression that calculates the character length of a string in UTF-8. | +| [coalesce(replacement, others)](./firestore_pipelines.expression.md#expressioncoalesce) | | Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | +| [collectionId()](./firestore_pipelines.expression.md#expressioncollectionid) | | Creates an expression that returns the collection ID from a path. | +| [concat(second, others)](./firestore_pipelines.expression.md#expressionconcat) | | Creates an expression that concatenates expression results together. | +| [cosineDistance(vectorExpression)](./firestore_pipelines.expression.md#expressioncosinedistance) | | Calculates the cosine distance between two vectors. | +| [cosineDistance(vector)](./firestore_pipelines.expression.md#expressioncosinedistance) | | Calculates the Cosine distance between two vectors. | +| [count()](./firestore_pipelines.expression.md#expressioncount) | | Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. | +| [countDistinct()](./firestore_pipelines.expression.md#expressioncountdistinct) | | Creates an aggregation that counts the number of distinct values of the expression or field. | +| [descending()](./firestore_pipelines.expression.md#expressiondescending) | | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on this expression. | +| [divide(divisor)](./firestore_pipelines.expression.md#expressiondivide) | | Creates an expression that divides this expression by another expression. | +| [divide(divisor)](./firestore_pipelines.expression.md#expressiondivide) | | Creates an expression that divides this expression by a constant value. | +| [documentId()](./firestore_pipelines.expression.md#expressiondocumentid) | | Creates an expression that returns the document ID from a path. | +| [dotProduct(vectorExpression)](./firestore_pipelines.expression.md#expressiondotproduct) | | Calculates the dot product between two vectors. | +| [dotProduct(vector)](./firestore_pipelines.expression.md#expressiondotproduct) | | Calculates the dot product between two vectors. | +| [endsWith(suffix)](./firestore_pipelines.expression.md#expressionendswith) | | Creates an expression that checks if a string ends with a given postfix. | +| [endsWith(suffix)](./firestore_pipelines.expression.md#expressionendswith) | | Creates an expression that checks if a string ends with a given postfix (represented as an expression). | +| [equal(expression)](./firestore_pipelines.expression.md#expressionequal) | | Creates an expression that checks if this expression is equal to another expression. | +| [equal(value)](./firestore_pipelines.expression.md#expressionequal) | | Creates an expression that checks if this expression is equal to a constant value. | +| [equalAny(values)](./firestore_pipelines.expression.md#expressionequalany) | | Creates an expression that checks if this expression is equal to any of the provided values or expressions. | +| [equalAny(arrayExpression)](./firestore_pipelines.expression.md#expressionequalany) | | Creates an expression that checks if this expression is equal to any of the provided values or expressions. | +| [euclideanDistance(vectorExpression)](./firestore_pipelines.expression.md#expressioneuclideandistance) | | Calculates the Euclidean distance between two vectors. | +| [euclideanDistance(vector)](./firestore_pipelines.expression.md#expressioneuclideandistance) | | Calculates the Euclidean distance between two vectors. | +| [exists()](./firestore_pipelines.expression.md#expressionexists) | | Creates an expression that checks if a field exists in the document. | +| [exp()](./firestore_pipelines.expression.md#expressionexp) | | Creates an expression that computes e to the power of this expression. | +| [first()](./firestore_pipelines.expression.md#expressionfirst) | | Creates an aggregation that finds the first value of an expression across multiple stage inputs. | +| [floor()](./firestore_pipelines.expression.md#expressionfloor) | | Creates an expression that computes the floor of a numeric value. | +| [greaterThan(expression)](./firestore_pipelines.expression.md#expressiongreaterthan) | | Creates an expression that checks if this expression is greater than another expression. | +| [greaterThan(value)](./firestore_pipelines.expression.md#expressiongreaterthan) | | Creates an expression that checks if this expression is greater than a constant value. | +| [greaterThanOrEqual(expression)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | Creates an expression that checks if this expression is greater than or equal to another expression. | +| [greaterThanOrEqual(value)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | Creates an expression that checks if this expression is greater than or equal to a constant value. | +| [ifAbsent(elseValue)](./firestore_pipelines.expression.md#expressionifabsent) | | Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | +| [ifAbsent(elseExpression)](./firestore_pipelines.expression.md#expressionifabsent) | | Creates an expression that returns the elseValue argument if this expression results in an absent value, else return the result of this expression evaluation. | +| [ifError(catchExpr)](./firestore_pipelines.expression.md#expressioniferror) | | Creates an expression that returns the result of the catchExpr argument if there is an error, else return the result of this expression. | +| [ifError(catchValue)](./firestore_pipelines.expression.md#expressioniferror) | | Creates an expression that returns the catch argument if there is an error, else return the result of this expression. | +| [ifNull(elseExpression)](./firestore_pipelines.expression.md#expressionifnull) | | Creates an expression that returns the elseValue argument if this expression evaluates to null, else return the result of this expression evaluation. | +| [ifNull(elseValue)](./firestore_pipelines.expression.md#expressionifnull) | | Creates an expression that returns the elseValue argument if this expression evaluates to null, else return the result of this expression evaluation. | +| [isAbsent()](./firestore_pipelines.expression.md#expressionisabsent) | | Creates an expression that returns true if the result of this expression is absent. Otherwise, returns false even if the value is null. | +| [isError()](./firestore_pipelines.expression.md#expressioniserror) | | Creates an expression that checks if a given expression produces an error. | +| [isType(type)](./firestore_pipelines.expression.md#expressionistype) | | Creates an expression that checks if the result of this expression is of the given type. | +| [join(delimiterExpression)](./firestore_pipelines.expression.md#expressionjoin) | | Creates an expression that joins the elements of an array into a string. | +| [join(delimiter)](./firestore_pipelines.expression.md#expressionjoin) | | Creates an expression that joins the elements of an array field into a string. | +| [last()](./firestore_pipelines.expression.md#expressionlast) | | Creates an aggregation that finds the last value of an expression across multiple stage inputs. | +| [length()](./firestore_pipelines.expression.md#expressionlength) | | Creates an expression that calculates the length of a string, array, map, vector, or bytes. | +| [lessThan(experession)](./firestore_pipelines.expression.md#expressionlessthan) | | Creates an expression that checks if this expression is less than another expression. | +| [lessThan(value)](./firestore_pipelines.expression.md#expressionlessthan) | | Creates an expression that checks if this expression is less than a constant value. | +| [lessThanOrEqual(expression)](./firestore_pipelines.expression.md#expressionlessthanorequal) | | Creates an expression that checks if this expression is less than or equal to another expression. | +| [lessThanOrEqual(value)](./firestore_pipelines.expression.md#expressionlessthanorequal) | | Creates an expression that checks if this expression is less than or equal to a constant value. | +| [like(pattern)](./firestore_pipelines.expression.md#expressionlike) | | Creates an expression that performs a case-sensitive string comparison. | +| [like(pattern)](./firestore_pipelines.expression.md#expressionlike) | | Creates an expression that performs a case-sensitive string comparison. | +| [ln()](./firestore_pipelines.expression.md#expressionln) | | Creates an expression that computes the natural logarithm of a numeric value. | +| [log10()](./firestore_pipelines.expression.md#expressionlog10) | | Creates an expression that computes the base-10 logarithm of a numeric value. | +| [logicalMaximum(second, others)](./firestore_pipelines.expression.md#expressionlogicalmaximum) | | Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. | +| [logicalMinimum(second, others)](./firestore_pipelines.expression.md#expressionlogicalminimum) | | Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. | +| [ltrim(valueToTrim)](./firestore_pipelines.expression.md#expressionltrim) | | Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | +| [mapEntries()](./firestore_pipelines.expression.md#expressionmapentries) | | 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" }, ...]. | +| [mapGet(subfield)](./firestore_pipelines.expression.md#expressionmapget) | | Accesses a value from a map (object) field using the provided key. | +| [mapKeys()](./firestore_pipelines.expression.md#expressionmapkeys) | | Creates an expression that returns the keys of a map. | +| [mapMerge(secondMap, otherMaps)](./firestore_pipelines.expression.md#expressionmapmerge) | | Creates an expression that merges multiple map values. | +| [mapRemove(key)](./firestore_pipelines.expression.md#expressionmapremove) | | Creates an expression that removes a key from the map produced by evaluating this expression. | +| [mapRemove(keyExpr)](./firestore_pipelines.expression.md#expressionmapremove) | | Creates an expression that removes a key from the map produced by evaluating this expression. | +| [mapSet(key, value, moreKeyValues)](./firestore_pipelines.expression.md#expressionmapset) | | Creates an expression that returns a new map with the specified entries added or updated. | +| [mapValues()](./firestore_pipelines.expression.md#expressionmapvalues) | | Creates an expression that returns the values of a map. | +| [maximum()](./firestore_pipelines.expression.md#expressionmaximum) | | Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | +| [minimum()](./firestore_pipelines.expression.md#expressionminimum) | | Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | +| [mod(expression)](./firestore_pipelines.expression.md#expressionmod) | | Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. | +| [mod(value)](./firestore_pipelines.expression.md#expressionmod) | | Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. | +| [multiply(second)](./firestore_pipelines.expression.md#expressionmultiply) | | Creates an expression that multiplies this expression by another expression. | +| [notEqual(expression)](./firestore_pipelines.expression.md#expressionnotequal) | | Creates an expression that checks if this expression is not equal to another expression. | +| [notEqual(value)](./firestore_pipelines.expression.md#expressionnotequal) | | Creates an expression that checks if this expression is not equal to a constant value. | +| [notEqualAny(values)](./firestore_pipelines.expression.md#expressionnotequalany) | | Creates an expression that checks if this expression is not equal to any of the provided values or expressions. | +| [notEqualAny(arrayExpression)](./firestore_pipelines.expression.md#expressionnotequalany) | | Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. | +| [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | Creates an expression that returns the value of this expression raised to the power of another expression. | +| [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | Creates an expression that returns the value of this expression raised to the power of a constant value. | +| [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | Creates an expression that checks if a string contains a specified regular expression as a substring. | +| [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | Creates an expression that checks if a string contains a specified regular expression as a substring. | +| [regexFind(pattern)](./firestore_pipelines.expression.md#expressionregexfind) | | Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFind(pattern)](./firestore_pipelines.expression.md#expressionregexfind) | | Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(pattern)](./firestore_pipelines.expression.md#expressionregexfindall) | | Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(pattern)](./firestore_pipelines.expression.md#expressionregexfindall) | | Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexMatch(pattern)](./firestore_pipelines.expression.md#expressionregexmatch) | | Creates an expression that checks if a string matches a specified regular expression. | +| [regexMatch(pattern)](./firestore_pipelines.expression.md#expressionregexmatch) | | Creates an expression that checks if a string matches a specified regular expression. | +| [reverse()](./firestore_pipelines.expression.md#expressionreverse) | | Creates an expression that reverses this string expression. | +| [round()](./firestore_pipelines.expression.md#expressionround) | | Creates an expression that rounds a numeric value to the nearest whole number. | +| [round(decimalPlaces)](./firestore_pipelines.expression.md#expressionround) | | Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [round(decimalPlaces)](./firestore_pipelines.expression.md#expressionround) | | Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [rtrim(valueToTrim)](./firestore_pipelines.expression.md#expressionrtrim) | | Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | +| [split(delimiter)](./firestore_pipelines.expression.md#expressionsplit) | | Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | +| [split(delimiter)](./firestore_pipelines.expression.md#expressionsplit) | | Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. | +| [sqrt()](./firestore_pipelines.expression.md#expressionsqrt) | | Creates an expression that computes the square root of a numeric value. | +| [startsWith(prefix)](./firestore_pipelines.expression.md#expressionstartswith) | | Creates an expression that checks if a string starts with a given prefix. | +| [startsWith(prefix)](./firestore_pipelines.expression.md#expressionstartswith) | | Creates an expression that checks if a string starts with a given prefix (represented as an expression). | +| [stringConcat(secondString, otherStrings)](./firestore_pipelines.expression.md#expressionstringconcat) | | Creates an expression that concatenates string expressions together. | +| [stringContains(substring)](./firestore_pipelines.expression.md#expressionstringcontains) | | Creates an expression that checks if a string contains a specified substring. | +| [stringContains(expr)](./firestore_pipelines.expression.md#expressionstringcontains) | | Creates an expression that checks if a string contains the string represented by another expression. | +| [stringIndexOf(search)](./firestore_pipelines.expression.md#expressionstringindexof) | | Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | +| [stringRepeat(repetitions)](./firestore_pipelines.expression.md#expressionstringrepeat) | | Creates an expression that repeats a string or byte array a specified number of times. | +| [stringReplaceAll(find, replacement)](./firestore_pipelines.expression.md#expressionstringreplaceall) | | Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | +| [stringReplaceOne(find, replacement)](./firestore_pipelines.expression.md#expressionstringreplaceone) | | Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | +| [stringReverse()](./firestore_pipelines.expression.md#expressionstringreverse) | | Creates an expression that reverses a string. | +| [substring(position, length)](./firestore_pipelines.expression.md#expressionsubstring) | | Creates an expression that returns a substring of the results of this expression. | +| [substring(position, length)](./firestore_pipelines.expression.md#expressionsubstring) | | Creates an expression that returns a substring of the results of this expression. | +| [subtract(subtrahend)](./firestore_pipelines.expression.md#expressionsubtract) | | Creates an expression that subtracts another expression from this expression. | +| [subtract(subtrahend)](./firestore_pipelines.expression.md#expressionsubtract) | | Creates an expression that subtracts a constant value from this expression. | +| [sum()](./firestore_pipelines.expression.md#expressionsum) | | Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. | +| [timestampAdd(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampadd) | | Creates an expression that adds a specified amount of time to this timestamp expression. | +| [timestampAdd(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampadd) | | Creates an expression that adds a specified amount of time to this timestamp expression. | +| [timestampDiff(start, unit)](./firestore_pipelines.expression.md#expressiontimestampdiff) | | Creates an expression that calculates the difference between this timestamp and another timestamp. | +| [timestampDiff(start, unit)](./firestore_pipelines.expression.md#expressiontimestampdiff) | | Creates an expression that calculates the difference between this timestamp and another timestamp. | +| [timestampExtract(part, timezone)](./firestore_pipelines.expression.md#expressiontimestampextract) | | Creates an expression that extracts a specified part from this timestamp expression. | +| [timestampExtract(part, timezone)](./firestore_pipelines.expression.md#expressiontimestampextract) | | Creates an expression that extracts a specified part from this timestamp expression. | +| [timestampSubtract(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampsubtract) | | Creates an expression that subtracts a specified amount of time from this timestamp expression. | +| [timestampSubtract(unit, amount)](./firestore_pipelines.expression.md#expressiontimestampsubtract) | | Creates an expression that subtracts a specified amount of time from this timestamp expression. | +| [timestampToUnixMicros()](./firestore_pipelines.expression.md#expressiontimestamptounixmicros) | | Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixMillis()](./firestore_pipelines.expression.md#expressiontimestamptounixmillis) | | Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixSeconds()](./firestore_pipelines.expression.md#expressiontimestamptounixseconds) | | Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampTruncate(granularity, timezone)](./firestore_pipelines.expression.md#expressiontimestamptruncate) | | Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(granularity, timezone)](./firestore_pipelines.expression.md#expressiontimestamptruncate) | | Creates an expression that truncates a timestamp to a specified granularity. | +| [toLower()](./firestore_pipelines.expression.md#expressiontolower) | | Creates an expression that converts a string to lowercase. | +| [toUpper()](./firestore_pipelines.expression.md#expressiontoupper) | | Creates an expression that converts a string to uppercase. | +| [trim(valueToTrim)](./firestore_pipelines.expression.md#expressiontrim) | | Creates an expression that removes leading and trailing characters from a string or byte array. | +| [trunc()](./firestore_pipelines.expression.md#expressiontrunc) | | Creates an expression that truncates the numeric value to an integer. | +| [trunc(decimalPlaces)](./firestore_pipelines.expression.md#expressiontrunc) | | Creates an expression that truncates a numeric value to the specified number of decimal places. | +| [trunc(decimalPlaces)](./firestore_pipelines.expression.md#expressiontrunc) | | Creates an expression that truncates a numeric value to the specified number of decimal places. | +| [type()](./firestore_pipelines.expression.md#expressiontype) | | Creates an expression that returns the data type of this expression's result, as a string. | +| [unixMicrosToTimestamp()](./firestore_pipelines.expression.md#expressionunixmicrostotimestamp) | | 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. | +| [unixMillisToTimestamp()](./firestore_pipelines.expression.md#expressionunixmillistotimestamp) | | 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. | +| [unixSecondsToTimestamp()](./firestore_pipelines.expression.md#expressionunixsecondstotimestamp) | | 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. | +| [vectorLength()](./firestore_pipelines.expression.md#expressionvectorlength) | | Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. | ## Expression.expressionType -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -219,9 +213,6 @@ abstract readonly expressionType: ExpressionType; ## Expression.abs() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the absolute value of a numeric value. Signature: @@ -246,9 +237,6 @@ field("price").abs(); ## Expression.add() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds this expression to another expression. Signature: @@ -280,9 +268,6 @@ field("quantity").add(field("reserve")); ## Expression.arrayAgg() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. 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. @@ -309,9 +294,6 @@ field("tags").arrayAgg().as("allTags"); ## Expression.arrayAggDistinct() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. 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. @@ -338,9 +320,6 @@ field("tags").arrayAggDistinct().as("allDistinctTags"); ## Expression.arrayConcat() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates an array expression with one or more other arrays. Signature: @@ -373,9 +352,6 @@ field("items").arrayConcat(field("otherItems")); ## Expression.arrayContains() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array contains a specific element. Signature: @@ -407,9 +383,6 @@ field("sizes").arrayContains(field("selectedSize")); ## Expression.arrayContains() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array contains a specific value. Signature: @@ -441,9 +414,6 @@ field("colors").arrayContains("red"); ## Expression.arrayContainsAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array contains all the specified elements. Signature: @@ -475,9 +445,6 @@ field("tags").arrayContainsAll([field("tag1"), "tag2"]); ## Expression.arrayContainsAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array contains all the specified elements. Signature: @@ -509,9 +476,6 @@ field("tags").arrayContainsAll(array([field("tag1"), "tag2"])); ## Expression.arrayContainsAny() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array contains any of the specified elements. Signature: @@ -543,9 +507,6 @@ field("categories").arrayContainsAny([field("cate1"), field("cate2")]); ## Expression.arrayContainsAny() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array contains any of the specified elements. Signature: @@ -578,9 +539,6 @@ field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); ## Expression.arrayFirst() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the first element of the array. Signature: @@ -605,9 +563,6 @@ field("myArray").arrayFirst(); ## Expression.arrayFirstN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the first `n` elements of the array. Signature: @@ -639,9 +594,6 @@ field("myArray").arrayFirstN(3); ## Expression.arrayFirstN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the first `n` elements of the array. Signature: @@ -673,9 +625,6 @@ field("myArray").arrayFirstN(field("count")); ## Expression.arrayGet() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: @@ -707,9 +656,6 @@ field('tags').arrayGet(1); ## Expression.arrayGet() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that indexes into an array from the beginning or end and returns the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: @@ -742,9 +688,6 @@ field('tags').arrayGet(field('favoriteTag')); ## Expression.arrayIndexOf() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the first index of the search value in the array, or -1 if not found. Signature: @@ -776,9 +719,6 @@ field("myArray").arrayIndexOf(3); ## Expression.arrayIndexOf() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the first index of the search value in the array, or -1 if not found. Signature: @@ -810,9 +750,6 @@ field("myArray").arrayIndexOf(field("searchVal")); ## Expression.arrayIndexOfAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all indices of the search value in the array. Signature: @@ -844,9 +781,6 @@ field("myArray").arrayIndexOfAll(3); ## Expression.arrayIndexOfAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all indices of the search value in the array. Signature: @@ -878,9 +812,6 @@ field("myArray").arrayIndexOfAll(field("searchVal")); ## Expression.arrayLast() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the last element of the array. Signature: @@ -905,9 +836,6 @@ field("myArray").arrayLast(); ## Expression.arrayLastIndexOf() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the last index of the search value in the array, or -1 if not found. Signature: @@ -939,9 +867,6 @@ field("myArray").arrayLastIndexOf(3); ## Expression.arrayLastIndexOf() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the last index of the search value in the array, or -1 if not found. Signature: @@ -973,9 +898,6 @@ field("myArray").arrayLastIndexOf(field("searchVal")); ## Expression.arrayLastN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the last `n` elements of the array. Signature: @@ -1007,9 +929,6 @@ field("myArray").arrayLastN(3); ## Expression.arrayLastN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the last `n` elements of the array. Signature: @@ -1041,9 +960,6 @@ field("myArray").arrayLastN(field("count")); ## Expression.arrayLength() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of an array. Signature: @@ -1068,9 +984,6 @@ field("cart").arrayLength(); ## Expression.arrayMaximum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the maximum value in the array. Signature: @@ -1095,9 +1008,6 @@ field("myArray").arrayMaximum(); ## Expression.arrayMaximumN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the largest `n` elements of the array. Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1131,9 +1041,6 @@ field("myArray").arrayMaximumN(3); ## Expression.arrayMaximumN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the largest `n` elements of the array. Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1167,9 +1074,6 @@ field("myArray").arrayMaximumN(field("count")); ## Expression.arrayMinimum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the minimum value in the array. Signature: @@ -1194,9 +1098,6 @@ field("myArray").arrayMinimum(); ## Expression.arrayMinimumN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the smallest `n` elements of the array. Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1230,9 +1131,6 @@ field("myArray").arrayMinimumN(3); ## Expression.arrayMinimumN() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns the smallest `n` elements of the array. Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1266,9 +1164,6 @@ field("myArray").arrayMinimumN(field("count")); ## Expression.arrayReverse() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses an array. Signature: @@ -1293,9 +1188,6 @@ field("myArray").arrayReverse(); ## Expression.arraySum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the sum of the elements in an array. Signature: @@ -1320,9 +1212,6 @@ field("scores").arraySum(); ## Expression.as() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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. @@ -1357,9 +1246,6 @@ firestore.pipeline().collection("items") ## Expression.asBoolean() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Wraps the expression in a \[BooleanExpression\]. Signature: @@ -1375,9 +1261,6 @@ A \[BooleanExpression\] representing the same expression. ## Expression.ascending() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on this expression. Signature: @@ -1403,9 +1286,6 @@ firestore.pipeline().collection("users") ## Expression.average() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that calculates the average (mean) of a numeric field across multiple stage inputs. Signature: @@ -1430,9 +1310,6 @@ field("age").average().as("averageAge"); ## Expression.byteLength() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of this string expression in bytes. Signature: @@ -1457,9 +1334,6 @@ field("myString").byteLength(); ## Expression.ceil() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the ceiling of a numeric value. Signature: @@ -1484,9 +1358,6 @@ field("price").ceil(); ## Expression.charLength() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the character length of a string in UTF-8. Signature: @@ -1511,9 +1382,6 @@ field("name").charLength(); ## Expression.coalesce() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. Signature: @@ -1547,9 +1415,6 @@ field("preferredName").coalesce(field("fullName"), "Anonymous"); ## Expression.collectionId() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the collection ID from a path. Signature: @@ -1574,9 +1439,6 @@ field("__path__").collectionId(); ## Expression.concat() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates expression results together. Signature: @@ -1609,9 +1471,6 @@ field("firstName").concat(constant(" "), field("lastName")); ## Expression.cosineDistance() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the cosine distance between two vectors. Signature: @@ -1643,9 +1502,6 @@ field("userVector").cosineDistance(field("itemVector")); ## Expression.cosineDistance() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Cosine distance between two vectors. Signature: @@ -1677,9 +1533,6 @@ field("location").cosineDistance(new VectorValue([37.7749, -122.4194])); ## Expression.count() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the number of stage inputs with valid evaluations of the expression or field. Signature: @@ -1704,9 +1557,6 @@ field("productId").count().as("totalProducts"); ## Expression.countDistinct() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the number of distinct values of the expression or field. Signature: @@ -1731,9 +1581,6 @@ field("productId").countDistinct().as("distinctProducts"); ## Expression.descending() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on this expression. Signature: @@ -1759,9 +1606,6 @@ firestore.pipeline().collection("users") ## Expression.divide() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that divides this expression by another expression. Signature: @@ -1793,9 +1637,6 @@ field("total").divide(field("count")); ## Expression.divide() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that divides this expression by a constant value. Signature: @@ -1827,9 +1668,6 @@ field("value").divide(10); ## Expression.documentId() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the document ID from a path. Signature: @@ -1854,9 +1692,6 @@ field("__path__").documentId(); ## Expression.dotProduct() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the dot product between two vectors. Signature: @@ -1888,9 +1723,6 @@ field("features").dotProduct([0.5, 0.8, 0.2]); ## Expression.dotProduct() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the dot product between two vectors. Signature: @@ -1922,9 +1754,6 @@ field("features").dotProduct(new VectorValue([0.5, 0.8, 0.2])); ## Expression.endsWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string ends with a given postfix. Signature: @@ -1956,9 +1785,6 @@ field("filename").endsWith(".txt"); ## Expression.endsWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string ends with a given postfix (represented as an expression). Signature: @@ -1990,9 +1816,6 @@ field("url").endsWith(field("extension")); ## Expression.equal() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is equal to another expression. Signature: @@ -2024,9 +1847,6 @@ field("age").equal(21); ## Expression.equal() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is equal to a constant value. Signature: @@ -2058,9 +1878,6 @@ field("city").equal("London"); ## Expression.equalAny() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is equal to any of the provided values or expressions. Signature: @@ -2092,9 +1909,6 @@ field("category").equalAny(["Electronics", field("primaryType")]); ## Expression.equalAny() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is equal to any of the provided values or expressions. Signature: @@ -2126,9 +1940,6 @@ field("category").equalAny(array(["Electronics", field("primaryType")])); ## Expression.euclideanDistance() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Euclidean distance between two vectors. Signature: @@ -2160,9 +1971,6 @@ field("location").euclideanDistance([37.7749, -122.4194]); ## Expression.euclideanDistance() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Euclidean distance between two vectors. Signature: @@ -2194,9 +2002,6 @@ field("location").euclideanDistance(new VectorValue([37.7749, -122.4194])); ## Expression.exists() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field exists in the document. Signature: @@ -2221,9 +2026,6 @@ field("phoneNumber").exists(); ## Expression.exp() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes e to the power of this expression. Signature: @@ -2248,9 +2050,6 @@ field("value").exp(); ## Expression.first() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the first value of an expression across multiple stage inputs. Signature: @@ -2275,9 +2074,6 @@ field("rating").first().as("firstRating"); ## Expression.floor() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the floor of a numeric value. Signature: @@ -2302,9 +2098,6 @@ field("price").floor(); ## Expression.greaterThan() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is greater than another expression. Signature: @@ -2336,9 +2129,6 @@ field("age").greaterThan(field("limit")); ## Expression.greaterThan() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is greater than a constant value. Signature: @@ -2370,9 +2160,6 @@ field("price").greaterThan(100); ## Expression.greaterThanOrEqual() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is greater than or equal to another expression. Signature: @@ -2404,9 +2191,6 @@ field("quantity").greaterThanOrEqual(field('requirement').add(1)); ## Expression.greaterThanOrEqual() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is greater than or equal to a constant value. Signature: @@ -2438,9 +2222,6 @@ field("score").greaterThanOrEqual(80); ## Expression.ifAbsent() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of this expression evaluation. Signature: @@ -2473,9 +2254,6 @@ field("optional_field").ifAbsent("default_value") ## Expression.ifAbsent() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else return the result of this expression evaluation. Signature: @@ -2508,9 +2286,6 @@ field("optional_field").ifAbsent(field('default_field')) ## Expression.ifError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the result of the `catchExpr` argument if there is an error, else return the result of this expression. Signature: @@ -2543,9 +2318,6 @@ field("title").arrayGet(0).ifError(field("title")); ## Expression.ifError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of this expression. Signature: @@ -2578,9 +2350,6 @@ field("title").arrayGet(0).ifError("Default Title"); ## Expression.ifNull() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if this expression evaluates to null, else return the result of this expression evaluation. This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. @@ -2614,9 +2383,6 @@ field("preferredName").ifNull(field("fullName")) ## Expression.ifNull() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if this expression evaluates to null, else return the result of this expression evaluation. This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. @@ -2650,9 +2416,6 @@ field("displayName").ifNull("Anonymous") ## Expression.isAbsent() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns `true` if the result of this expression is absent. Otherwise, returns `false` even if the value is `null`. Signature: @@ -2677,9 +2440,6 @@ field("value").isAbsent(); ## Expression.isError() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a given expression produces an error. Signature: @@ -2704,9 +2464,6 @@ field("title").arrayContains(1).isError(); ## Expression.isType() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the result of this expression is of the given type. Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. @@ -2740,9 +2497,6 @@ field('price').isType('int64'); ## Expression.join() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that joins the elements of an array into a string. Signature: @@ -2774,9 +2528,6 @@ field("tags").join(field("separator")) ## Expression.join() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that joins the elements of an array field into a string. Signature: @@ -2808,9 +2559,6 @@ field("tags").join(", ") ## Expression.last() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the last value of an expression across multiple stage inputs. Signature: @@ -2835,9 +2583,6 @@ field("rating").last().as("lastRating"); ## Expression.length() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of a string, array, map, vector, or bytes. Signature: @@ -2865,9 +2610,6 @@ field("cart").length(); ## Expression.lessThan() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is less than another expression. Signature: @@ -2899,9 +2641,6 @@ field("age").lessThan(field('limit')); ## Expression.lessThan() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is less than a constant value. Signature: @@ -2933,9 +2672,6 @@ field("price").lessThan(50); ## Expression.lessThanOrEqual() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is less than or equal to another expression. Signature: @@ -2967,9 +2703,6 @@ field("quantity").lessThan(constant(20)); ## Expression.lessThanOrEqual() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is less than or equal to a constant value. Signature: @@ -3001,9 +2734,6 @@ field("score").lessThan(70); ## Expression.like() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a case-sensitive string comparison. Signature: @@ -3035,9 +2765,6 @@ field("title").like("%guide%"); ## Expression.like() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a case-sensitive string comparison. Signature: @@ -3069,9 +2796,6 @@ field("title").like("%guide%"); ## Expression.ln() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the natural logarithm of a numeric value. Signature: @@ -3096,9 +2820,6 @@ field("value").ln(); ## Expression.log10() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the base-10 logarithm of a numeric value. Signature: @@ -3123,9 +2844,6 @@ field("value").log10(); ## Expression.logicalMaximum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. Signature: @@ -3158,9 +2876,6 @@ field("timestamp").logicalMaximum(currentTimestamp()); ## Expression.logicalMinimum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. Signature: @@ -3193,9 +2908,6 @@ field("timestamp").logicalMinimum(currentTimestamp()); ## Expression.ltrim() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. Signature: @@ -3230,9 +2942,6 @@ field("userInput").ltrim('"'); ## Expression.mapEntries() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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" }, ...]`. Signature: @@ -3257,9 +2966,6 @@ field("address").mapEntries(); ## Expression.mapGet() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Accesses a value from a map (object) field using the provided key. Signature: @@ -3291,9 +2997,6 @@ field("address").mapGet("city"); ## Expression.mapKeys() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the keys of a map. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -3320,9 +3023,6 @@ field("address").mapKeys(); ## Expression.mapMerge() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that merges multiple map values. Signature: @@ -3356,9 +3056,6 @@ field('settings').mapMerge({ enabled: true }, conditional(field('isAdmin'), { ad ## Expression.mapRemove() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes a key from the map produced by evaluating this expression. Signature: @@ -3390,9 +3087,6 @@ map({foo: 'bar', baz: true}).mapRemove('baz'); ## Expression.mapRemove() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes a key from the map produced by evaluating this expression. Signature: @@ -3425,9 +3119,6 @@ map({foo: 'bar', baz: true}).mapRemove(constant('baz')); ## Expression.mapSet() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a new map with the specified entries added or updated. 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`. @@ -3463,9 +3154,6 @@ field("address").mapSet("city", "San Francisco"); ## Expression.mapValues() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the values of a map. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -3492,9 +3180,6 @@ field("address").mapValues(); ## Expression.maximum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the maximum value of a field across multiple stage inputs. Signature: @@ -3519,9 +3204,6 @@ field("score").maximum().as("highestScore"); ## Expression.minimum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the minimum value of a field across multiple stage inputs. Signature: @@ -3546,9 +3228,6 @@ field("price").minimum().as("lowestPrice"); ## Expression.mod() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. Signature: @@ -3580,9 +3259,6 @@ field("value").mod(field("divisor")); ## Expression.mod() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. Signature: @@ -3614,9 +3290,6 @@ field("value").mod(10); ## Expression.multiply() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that multiplies this expression by another expression. Signature: @@ -3648,9 +3321,6 @@ field("quantity").multiply(field("price")); ## Expression.notEqual() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is not equal to another expression. Signature: @@ -3682,9 +3352,6 @@ field("status").notEqual("completed"); ## Expression.notEqual() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is not equal to a constant value. Signature: @@ -3716,9 +3383,6 @@ field("country").notEqual("USA"); ## Expression.notEqualAny() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is not equal to any of the provided values or expressions. Signature: @@ -3750,9 +3414,6 @@ field("status").notEqualAny(["pending", field("rejectedStatus")]); ## Expression.notEqualAny() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. Signature: @@ -3784,9 +3445,6 @@ field("status").notEqualAny(field('rejectedStatuses')); ## Expression.pow() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the value of this expression raised to the power of another expression. Signature: @@ -3818,9 +3476,6 @@ field("base").pow(field("exponent")); ## Expression.pow() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the value of this expression raised to the power of a constant value. Signature: @@ -3852,9 +3507,6 @@ field("base").pow(2); ## Expression.regexContains() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string contains a specified regular expression as a substring. Signature: @@ -3886,9 +3538,6 @@ field("description").regexContains("(?i)example"); ## Expression.regexContains() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string contains a specified regular expression as a substring. Signature: @@ -3920,9 +3569,6 @@ field("description").regexContains(field("regex")); ## Expression.regexFind() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first substring of a string expression that matches a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -3956,9 +3602,6 @@ field("email").regexFind("@.+") ## Expression.regexFind() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first substring of a string expression that matches a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -3992,9 +3635,6 @@ field("email").regexFind(field("domain")) ## Expression.regexFindAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -4028,9 +3668,6 @@ field("content").regexFindAll("#[A-Za-z0-9_]+") ## Expression.regexFindAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to a list of all substrings in this string expression that match a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -4064,9 +3701,6 @@ field("content").regexFindAll(field("names")) ## Expression.regexMatch() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string matches a specified regular expression. Signature: @@ -4098,9 +3732,6 @@ field("email").regexMatch("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); ## Expression.regexMatch() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string matches a specified regular expression. Signature: @@ -4132,9 +3763,6 @@ field("email").regexMatch(field("regex")); ## Expression.reverse() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses this string expression. Signature: @@ -4159,9 +3787,6 @@ field("myString").reverse(); ## Expression.round() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the nearest whole number. Signature: @@ -4186,9 +3811,6 @@ field("price").round(); ## Expression.round() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the specified number of decimal places. Signature: @@ -4220,9 +3842,6 @@ field("price").round(2); ## Expression.round() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the specified number of decimal places. Signature: @@ -4254,9 +3873,6 @@ field("price").round(constant(2)); ## Expression.rtrim() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. Signature: @@ -4291,9 +3907,6 @@ field("userInput").rtrim('"'); ## Expression.split() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. Signature: @@ -4325,9 +3938,6 @@ field('scoresCsv').split(',') ## Expression.split() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that splits the result of this expression into an array of substrings based on the provided delimiter. Signature: @@ -4359,9 +3969,6 @@ field('scores').split(conditional(field('format').equal('csv'), constant(','), c ## Expression.sqrt() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the square root of a numeric value. Signature: @@ -4386,9 +3993,6 @@ field("value").sqrt(); ## Expression.startsWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string starts with a given prefix. Signature: @@ -4420,9 +4024,6 @@ field("name").startsWith("Mr."); ## Expression.startsWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string starts with a given prefix (represented as an expression). Signature: @@ -4454,9 +4055,6 @@ field("fullName").startsWith(field("firstName")); ## Expression.stringConcat() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates string expressions together. Signature: @@ -4489,9 +4087,6 @@ field("firstName").stringConcat(constant(" "), field("lastName")); ## Expression.stringContains() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string contains a specified substring. Signature: @@ -4523,9 +4118,6 @@ field("description").stringContains("example"); ## Expression.stringContains() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string contains the string represented by another expression. Signature: @@ -4557,9 +4149,6 @@ field("description").stringContains(field("keyword")); ## Expression.stringIndexOf() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that finds the index of the first occurrence of a substring or byte sequence. Signature: @@ -4591,9 +4180,6 @@ field("text").stringIndexOf("foo"); ## Expression.stringRepeat() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that repeats a string or byte array a specified number of times. Signature: @@ -4625,9 +4211,6 @@ field("label").stringRepeat(3); ## Expression.stringReplaceAll() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. Signature: @@ -4660,9 +4243,6 @@ field("text").stringReplaceAll("foo", "bar"); ## Expression.stringReplaceOne() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. Signature: @@ -4695,9 +4275,6 @@ field("text").stringReplaceOne("foo", "bar"); ## Expression.stringReverse() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses a string. Signature: @@ -4722,9 +4299,6 @@ field("myString").stringReverse(); ## Expression.substring() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a substring of the results of this expression. Signature: @@ -4746,9 +4320,6 @@ substring(position: number, length?: number): FunctionExpression; ## Expression.substring() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a substring of the results of this expression. Signature: @@ -4770,9 +4341,6 @@ substring(position: Expression, length?: Expression): FunctionExpression; ## Expression.subtract() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts another expression from this expression. Signature: @@ -4804,9 +4372,6 @@ field("price").subtract(field("discount")); ## Expression.subtract() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a constant value from this expression. Signature: @@ -4838,9 +4403,6 @@ field("total").subtract(20); ## Expression.sum() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. Signature: @@ -4865,9 +4427,6 @@ field("orderAmount").sum().as("totalRevenue"); ## Expression.timestampAdd() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds a specified amount of time to this timestamp expression. Signature: @@ -4900,9 +4459,6 @@ field("timestamp").timestampAdd(field("unit"), field("amount")); ## Expression.timestampAdd() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds a specified amount of time to this timestamp expression. Signature: @@ -4935,9 +4491,6 @@ field("timestamp").timestampAdd("day", 1); ## Expression.timestampDiff() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the difference between this timestamp and another timestamp. Signature: @@ -4970,9 +4523,6 @@ field("endTime").timestampDiff(field("startTime"), field("unit")); ## Expression.timestampDiff() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the difference between this timestamp and another timestamp. Signature: @@ -5005,9 +4555,6 @@ field("endTime").timestampDiff("startTime", "day"); ## Expression.timestampExtract() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that extracts a specified part from this timestamp expression. Signature: @@ -5040,9 +4587,6 @@ field('createdAt').timestampExtract('year') ## Expression.timestampExtract() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that extracts a specified part from this timestamp expression. Signature: @@ -5075,9 +4619,6 @@ field('createdAt').timestampExtract(field('extractionPart')) ## Expression.timestampSubtract() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a specified amount of time from this timestamp expression. Signature: @@ -5110,9 +4651,6 @@ field("timestamp").timestampSubtract(field("unit"), field("amount")); ## Expression.timestampSubtract() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a specified amount of time from this timestamp expression. Signature: @@ -5145,9 +4683,6 @@ field("timestamp").timestampSubtract("day", 1); ## Expression.timestampToUnixMicros() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -5172,9 +4707,6 @@ field("timestamp").timestampToUnixMicros(); ## Expression.timestampToUnixMillis() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -5199,9 +4731,6 @@ field("timestamp").timestampToUnixMillis(); ## Expression.timestampToUnixSeconds() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -5226,9 +4755,6 @@ field("timestamp").timestampToUnixSeconds(); ## Expression.timestampTruncate() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a timestamp to a specified granularity. Signature: @@ -5261,9 +4787,6 @@ field('createdAt').timestampTruncate('day') ## Expression.timestampTruncate() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a timestamp to a specified granularity. Signature: @@ -5296,9 +4819,6 @@ field('createdAt').timestampTruncate(field('granularity')) ## Expression.toLower() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a string to lowercase. Signature: @@ -5323,9 +4843,6 @@ field("name").toLower(); ## Expression.toUpper() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a string to uppercase. Signature: @@ -5350,9 +4867,6 @@ field("title").toUpper(); ## Expression.trim() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes leading and trailing characters from a string or byte array. Signature: @@ -5387,9 +4901,6 @@ field("userInput").trim('"'); ## Expression.trunc() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates the numeric value to an integer. Signature: @@ -5414,9 +4925,6 @@ field("rating").trunc(); ## Expression.trunc() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a numeric value to the specified number of decimal places. Signature: @@ -5448,9 +4956,6 @@ field("rating").trunc(2); ## Expression.trunc() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a numeric value to the specified number of decimal places. Signature: @@ -5482,9 +4987,6 @@ field("rating").trunc(constant(2)); ## Expression.type() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the data type of this expression's result, as a string. This is evaluated on the backend. This means: 1. Generic typed elements (like `array`) 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"`. @@ -5511,9 +5013,6 @@ field('title').type() ## Expression.unixMicrosToTimestamp() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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. Signature: @@ -5538,9 +5037,6 @@ field("microseconds").unixMicrosToTimestamp(); ## Expression.unixMillisToTimestamp() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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. Signature: @@ -5565,9 +5061,6 @@ field("milliseconds").unixMillisToTimestamp(); ## Expression.unixSecondsToTimestamp() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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. Signature: @@ -5592,9 +5085,6 @@ field("seconds").unixSecondsToTimestamp(); ## Expression.vectorLength() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. Signature: diff --git a/docs-devsite/firestore_pipelines.field.md b/docs-devsite/firestore_pipelines.field.md index 3a0a4aa75b..2a56e5ea4d 100644 --- a/docs-devsite/firestore_pipelines.field.md +++ b/docs-devsite/firestore_pipelines.field.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # Field class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents a reference to a field in a Firestore document, or outputs of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) stage.

    Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines. @@ -32,17 +29,14 @@ export declare class Field extends Expression implements Selectable | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [alias](./firestore_pipelines.field.md#fieldalias) | | string | (Public Preview) | -| [expr](./firestore_pipelines.field.md#fieldexpr) | | [Expression](./firestore_pipelines.expression.md#expression_class) | (Public Preview) | -| [expressionType](./firestore_pipelines.field.md#fieldexpressiontype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) | -| [fieldName](./firestore_pipelines.field.md#fieldfieldname) | | string | (Public Preview) | -| [selectable](./firestore_pipelines.field.md#fieldselectable) | | true | (Public Preview) | +| [alias](./firestore_pipelines.field.md#fieldalias) | | string | | +| [expr](./firestore_pipelines.field.md#fieldexpr) | | [Expression](./firestore_pipelines.expression.md#expression_class) | | +| [expressionType](./firestore_pipelines.field.md#fieldexpressiontype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | | +| [fieldName](./firestore_pipelines.field.md#fieldfieldname) | | string | | +| [selectable](./firestore_pipelines.field.md#fieldselectable) | | true | | ## Field.alias -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -51,9 +45,6 @@ get alias(): string; ## Field.expr -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -62,9 +53,6 @@ get expr(): Expression; ## Field.expressionType -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -73,9 +61,6 @@ readonly expressionType: ExpressionType; ## Field.fieldName -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -84,9 +69,6 @@ get fieldName(): string; ## Field.selectable -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/firestore_pipelines.functionexpression.md b/docs-devsite/firestore_pipelines.functionexpression.md index 2783f8168e..3715f684b7 100644 --- a/docs-devsite/firestore_pipelines.functionexpression.md +++ b/docs-devsite/firestore_pipelines.functionexpression.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # FunctionExpression class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - This class defines the base class for Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) functions, which can be evaluated within pipeline execution. Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_pipelines.md#and_e0c48bd), [equal()](./firestore_pipelines.md#equal_b3c3382), or the methods on [Expression](./firestore_pipelines.expression.md#expression_class) ([Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), etc.) to construct new Function instances. @@ -28,20 +25,17 @@ export declare class FunctionExpression extends Expression | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(name, params)](./firestore_pipelines.functionexpression.md#functionexpressionconstructor) | | (Public Preview) Constructs a new instance of the FunctionExpression class | -| [(constructor)(name, params, \_methodName)](./firestore_pipelines.functionexpression.md#functionexpressionconstructor) | | (Public Preview) Constructs a new instance of the FunctionExpression class | +| [(constructor)(name, params)](./firestore_pipelines.functionexpression.md#functionexpressionconstructor) | | Constructs a new instance of the FunctionExpression class | +| [(constructor)(name, params, \_methodName)](./firestore_pipelines.functionexpression.md#functionexpressionconstructor) | | Constructs a new instance of the FunctionExpression class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [expressionType](./firestore_pipelines.functionexpression.md#functionexpressionexpressiontype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) | +| [expressionType](./firestore_pipelines.functionexpression.md#functionexpressionexpressiontype) | | [ExpressionType](./firestore_pipelines.md#expressiontype) | | ## FunctionExpression.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `FunctionExpression` class Signature: @@ -59,9 +53,6 @@ constructor(name: string, params: Expression[]); ## FunctionExpression.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `FunctionExpression` class Signature: @@ -80,9 +71,6 @@ constructor(name: string, params: Expression[], _methodName: string | undefined) ## FunctionExpression.expressionType -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 889f0fbc9f..dc6dc893c6 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -16,417 +16,417 @@ https://github.com/firebase/firebase-js-sdk | Function | Description | | --- | --- | | function() | -| [countAll()](./firestore_pipelines.md#countall) | (Public Preview) Creates an aggregation that counts the total number of stage inputs. | -| [currentTimestamp()](./firestore_pipelines.md#currenttimestamp) | (Public Preview) Creates an expression that evaluates to the current server timestamp. | -| [rand()](./firestore_pipelines.md#rand) | (Public Preview) Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. | +| [countAll()](./firestore_pipelines.md#countall) | Creates an aggregation that counts the total number of stage inputs. | +| [currentTimestamp()](./firestore_pipelines.md#currenttimestamp) | Creates an expression that evaluates to the current server timestamp. | +| [rand()](./firestore_pipelines.md#rand) | Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. | | function(array, ...) | -| [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_a00ea48) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. | -| [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_7328608) | (Public Preview) Creates an expression that checks if an array expression contains a specific element. | -| [arrayContainsAll(array, values)](./firestore_pipelines.md#arraycontainsall_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. | -| [arrayContainsAll(array, arrayExpression)](./firestore_pipelines.md#arraycontainsall_7b535db) | (Public Preview) Creates an expression that checks if an array expression contains all the specified elements. | -| [arrayContainsAny(array, values)](./firestore_pipelines.md#arraycontainsany_c658ad5) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. | -| [arrayContainsAny(array, values)](./firestore_pipelines.md#arraycontainsany_c381a96) | (Public Preview) Creates an expression that checks if an array expression contains any of the specified elements. | -| [arrayLength(array)](./firestore_pipelines.md#arraylength_195e339) | (Public Preview) Creates an expression that calculates the length of an array expression. | +| [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_a00ea48) | Creates an expression that checks if an array expression contains a specific element. | +| [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_7328608) | Creates an expression that checks if an array expression contains a specific element. | +| [arrayContainsAll(array, values)](./firestore_pipelines.md#arraycontainsall_c658ad5) | Creates an expression that checks if an array expression contains all the specified elements. | +| [arrayContainsAll(array, arrayExpression)](./firestore_pipelines.md#arraycontainsall_7b535db) | Creates an expression that checks if an array expression contains all the specified elements. | +| [arrayContainsAny(array, values)](./firestore_pipelines.md#arraycontainsany_c658ad5) | Creates an expression that checks if an array expression contains any of the specified elements. | +| [arrayContainsAny(array, values)](./firestore_pipelines.md#arraycontainsany_c381a96) | Creates an expression that checks if an array expression contains any of the specified elements. | +| [arrayLength(array)](./firestore_pipelines.md#arraylength_195e339) | Creates an expression that calculates the length of an array expression. | | function(arrayExpression, ...) | -| [arrayFirst(arrayExpression)](./firestore_pipelines.md#arrayfirst_f574e12) | (Public Preview) Creates an expression that returns the first element of an array. | -| [arrayFirstN(arrayExpression, n)](./firestore_pipelines.md#arrayfirstn_bff7f91) | (Public Preview) Creates an expression that returns the first n elements of an array. | -| [arrayFirstN(arrayExpression, n)](./firestore_pipelines.md#arrayfirstn_19b4ef8) | (Public Preview) Creates an expression that returns the first n elements of an array. | -| [arrayGet(arrayExpression, offset)](./firestore_pipelines.md#arrayget_f2e27cc) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | -| [arrayGet(arrayExpression, offsetExpr)](./firestore_pipelines.md#arrayget_484550d) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | -| [arrayIndexOf(arrayExpression, search)](./firestore_pipelines.md#arrayindexof_694a0b4) | (Public Preview) Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. | -| [arrayIndexOfAll(arrayExpression, search)](./firestore_pipelines.md#arrayindexofall_694a0b4) | (Public Preview) Creates an expression that returns all indices of the search value in an array. | -| [arrayLast(arrayExpression)](./firestore_pipelines.md#arraylast_f574e12) | (Public Preview) Creates an expression that returns the last element of an array. | -| [arrayLastIndexOf(arrayExpression, search)](./firestore_pipelines.md#arraylastindexof_694a0b4) | (Public Preview) Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. | -| [arrayLastN(arrayExpression, n)](./firestore_pipelines.md#arraylastn_bff7f91) | (Public Preview) Creates an expression that returns the last n elements of an array. | -| [arrayLastN(arrayExpression, n)](./firestore_pipelines.md#arraylastn_19b4ef8) | (Public Preview) Creates an expression that returns the last n elements of an array. | -| [arrayMaximum(arrayExpression)](./firestore_pipelines.md#arraymaximum_f574e12) | (Public Preview) Creates an expression that returns the maximum value in an array. | -| [arrayMaximumN(arrayExpression, n)](./firestore_pipelines.md#arraymaximumn_bff7f91) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMaximumN(arrayExpression, n)](./firestore_pipelines.md#arraymaximumn_19b4ef8) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMinimum(arrayExpression)](./firestore_pipelines.md#arrayminimum_f574e12) | (Public Preview) Creates an expression that returns the minimum value in an array. | -| [arrayMinimumN(arrayExpression, n)](./firestore_pipelines.md#arrayminimumn_bff7f91) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMinimumN(arrayExpression, n)](./firestore_pipelines.md#arrayminimumn_19b4ef8) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [join(arrayExpression, delimiterExpression)](./firestore_pipelines.md#join_313e6aa) | (Public Preview) Creates an expression that joins the elements of an array into a string. | -| [join(arrayExpression, delimiter)](./firestore_pipelines.md#join_d088d29) | (Public Preview) Creates an expression that joins the elements of an array into a string. | +| [arrayFirst(arrayExpression)](./firestore_pipelines.md#arrayfirst_f574e12) | Creates an expression that returns the first element of an array. | +| [arrayFirstN(arrayExpression, n)](./firestore_pipelines.md#arrayfirstn_bff7f91) | Creates an expression that returns the first n elements of an array. | +| [arrayFirstN(arrayExpression, n)](./firestore_pipelines.md#arrayfirstn_19b4ef8) | Creates an expression that returns the first n elements of an array. | +| [arrayGet(arrayExpression, offset)](./firestore_pipelines.md#arrayget_f2e27cc) | Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(arrayExpression, offsetExpr)](./firestore_pipelines.md#arrayget_484550d) | Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayIndexOf(arrayExpression, search)](./firestore_pipelines.md#arrayindexof_694a0b4) | Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. | +| [arrayIndexOfAll(arrayExpression, search)](./firestore_pipelines.md#arrayindexofall_694a0b4) | Creates an expression that returns all indices of the search value in an array. | +| [arrayLast(arrayExpression)](./firestore_pipelines.md#arraylast_f574e12) | Creates an expression that returns the last element of an array. | +| [arrayLastIndexOf(arrayExpression, search)](./firestore_pipelines.md#arraylastindexof_694a0b4) | Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. | +| [arrayLastN(arrayExpression, n)](./firestore_pipelines.md#arraylastn_bff7f91) | Creates an expression that returns the last n elements of an array. | +| [arrayLastN(arrayExpression, n)](./firestore_pipelines.md#arraylastn_19b4ef8) | Creates an expression that returns the last n elements of an array. | +| [arrayMaximum(arrayExpression)](./firestore_pipelines.md#arraymaximum_f574e12) | Creates an expression that returns the maximum value in an array. | +| [arrayMaximumN(arrayExpression, n)](./firestore_pipelines.md#arraymaximumn_bff7f91) | Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMaximumN(arrayExpression, n)](./firestore_pipelines.md#arraymaximumn_19b4ef8) | Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimum(arrayExpression)](./firestore_pipelines.md#arrayminimum_f574e12) | Creates an expression that returns the minimum value in an array. | +| [arrayMinimumN(arrayExpression, n)](./firestore_pipelines.md#arrayminimumn_bff7f91) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimumN(arrayExpression, n)](./firestore_pipelines.md#arrayminimumn_19b4ef8) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [join(arrayExpression, delimiterExpression)](./firestore_pipelines.md#join_313e6aa) | Creates an expression that joins the elements of an array into a string. | +| [join(arrayExpression, delimiter)](./firestore_pipelines.md#join_d088d29) | Creates an expression that joins the elements of an array into a string. | | function(arrayField, ...) | -| [arrayGet(arrayField, offset)](./firestore_pipelines.md#arrayget_3f58471) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | -| [arrayGet(arrayField, offsetExpr)](./firestore_pipelines.md#arrayget_1904c9a) | (Public Preview) Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(arrayField, offset)](./firestore_pipelines.md#arrayget_3f58471) | Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | +| [arrayGet(arrayField, offsetExpr)](./firestore_pipelines.md#arrayget_1904c9a) | Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. | | function(arrayFieldName, ...) | -| [join(arrayFieldName, delimiter)](./firestore_pipelines.md#join_478ef36) | (Public Preview) Creates an expression that joins the elements of an array into a string. | -| [join(arrayFieldName, delimiterExpression)](./firestore_pipelines.md#join_829294c) | (Public Preview) Creates an expression that joins the elements of an array into a string. | +| [join(arrayFieldName, delimiter)](./firestore_pipelines.md#join_478ef36) | Creates an expression that joins the elements of an array into a string. | +| [join(arrayFieldName, delimiterExpression)](./firestore_pipelines.md#join_829294c) | Creates an expression that joins the elements of an array into a string. | | function(base, ...) | -| [pow(base, exponent)](./firestore_pipelines.md#pow_e4a9e64) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent expression. | -| [pow(base, exponent)](./firestore_pipelines.md#pow_93eae7f) | (Public Preview) Creates an expression that returns the value of the base expression raised to the power of the exponent. | -| [pow(base, exponent)](./firestore_pipelines.md#pow_a237721) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent expression. | -| [pow(base, exponent)](./firestore_pipelines.md#pow_f4d7908) | (Public Preview) Creates an expression that returns the value of the base field raised to the power of the exponent. | +| [pow(base, exponent)](./firestore_pipelines.md#pow_e4a9e64) | Creates an expression that returns the value of the base expression raised to the power of the exponent expression. | +| [pow(base, exponent)](./firestore_pipelines.md#pow_93eae7f) | Creates an expression that returns the value of the base expression raised to the power of the exponent. | +| [pow(base, exponent)](./firestore_pipelines.md#pow_a237721) | Creates an expression that returns the value of the base field raised to the power of the exponent expression. | +| [pow(base, exponent)](./firestore_pipelines.md#pow_f4d7908) | Creates an expression that returns the value of the base field raised to the power of the exponent. | | function(booleanExpr, ...) | -| [countIf(booleanExpr)](./firestore_pipelines.md#countif_c5b8fb1) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. | -| [not(booleanExpr)](./firestore_pipelines.md#not_c5b8fb1) | (Public Preview) Creates an expression that negates a filter condition. | +| [countIf(booleanExpr)](./firestore_pipelines.md#countif_c5b8fb1) | Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. | +| [not(booleanExpr)](./firestore_pipelines.md#not_c5b8fb1) | Creates an expression that negates a filter condition. | | function(condition, ...) | -| [conditional(condition, thenExpr, elseExpr)](./firestore_pipelines.md#conditional_07a206d) | (Public Preview) Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. | -| [switchOn(condition, result, others)](./firestore_pipelines.md#switchon_02b8caf) | (Public Preview) Creates an expression that evaluates to the result corresponding to the first true condition. | +| [conditional(condition, thenExpr, elseExpr)](./firestore_pipelines.md#conditional_07a206d) | Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. | +| [switchOn(condition, result, others)](./firestore_pipelines.md#switchon_02b8caf) | Creates an expression that evaluates to the result corresponding to the first true condition. | | function(documentPath, ...) | -| [documentId(documentPath)](./firestore_pipelines.md#documentid_cef293c) | (Public Preview) Creates an expression that returns the document ID from a path. | +| [documentId(documentPath)](./firestore_pipelines.md#documentid_cef293c) | Creates an expression that returns the document ID from a path. | | function(documentPathExpr, ...) | -| [documentId(documentPathExpr)](./firestore_pipelines.md#documentid_9a69021) | (Public Preview) Creates an expression that returns the document ID from a path. | +| [documentId(documentPathExpr)](./firestore_pipelines.md#documentid_9a69021) | Creates an expression that returns the document ID from a path. | | function(element, ...) | -| [notEqualAny(element, values)](./firestore_pipelines.md#notequalany_c2c5bcb) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | -| [notEqualAny(element, arrayExpression)](./firestore_pipelines.md#notequalany_16b2851) | (Public Preview) Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | +| [notEqualAny(element, values)](./firestore_pipelines.md#notequalany_c2c5bcb) | Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | +| [notEqualAny(element, arrayExpression)](./firestore_pipelines.md#notequalany_16b2851) | Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | | function(elements, ...) | -| [array(elements)](./firestore_pipelines.md#array_7d853aa) | (Public Preview) Creates an expression that creates a Firestore array value from an input array. | -| [map(elements)](./firestore_pipelines.md#map_ce5dee1) | (Public Preview) Creates an expression that creates a Firestore map value from an input object. | +| [array(elements)](./firestore_pipelines.md#array_7d853aa) | Creates an expression that creates a Firestore array value from an input array. | +| [map(elements)](./firestore_pipelines.md#map_ce5dee1) | Creates an expression that creates a Firestore map value from an input object. | | function(endExpression, ...) | -| [timestampDiff(endExpression, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_4370feb) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | -| [timestampDiff(endExpression, startExpression, unit)](./firestore_pipelines.md#timestampdiff_bc0830f) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endExpression, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_4370feb) | Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endExpression, startExpression, unit)](./firestore_pipelines.md#timestampdiff_bc0830f) | Creates an expression that calculates the difference between two timestamps. | | function(endFieldName, ...) | -| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_f60102c) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | -| [timestampDiff(endFieldName, startExpression, unit)](./firestore_pipelines.md#timestampdiff_6e54d92) | (Public Preview) Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_f60102c) | Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endFieldName, startExpression, unit)](./firestore_pipelines.md#timestampdiff_6e54d92) | Creates an expression that calculates the difference between two timestamps. | | function(expr, ...) | -| [abs(expr)](./firestore_pipelines.md#abs_005f3d4) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | -| [ascending(expr)](./firestore_pipelines.md#ascending_005f3d4) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. | -| [byteLength(expr)](./firestore_pipelines.md#bytelength_005f3d4) | (Public Preview) Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. | -| [countDistinct(expr)](./firestore_pipelines.md#countdistinct_3c28b08) | (Public Preview) Creates an aggregation that counts the number of distinct values of a field. | -| [descending(expr)](./firestore_pipelines.md#descending_005f3d4) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. | -| [floor(expr)](./firestore_pipelines.md#floor_005f3d4) | (Public Preview) Creates an expression that computes the floor of a numeric value. | -| [timestampToUnixMicros(expr)](./firestore_pipelines.md#timestamptounixmicros_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampToUnixMillis(expr)](./firestore_pipelines.md#timestamptounixmillis_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampToUnixSeconds(expr)](./firestore_pipelines.md#timestamptounixseconds_005f3d4) | (Public Preview) Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [unixMicrosToTimestamp(expr)](./firestore_pipelines.md#unixmicrostotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | -| [unixMillisToTimestamp(expr)](./firestore_pipelines.md#unixmillistotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | -| [unixSecondsToTimestamp(expr)](./firestore_pipelines.md#unixsecondstotimestamp_005f3d4) | (Public Preview) Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [abs(expr)](./firestore_pipelines.md#abs_005f3d4) | Creates an expression that computes the absolute value of a numeric value. | +| [ascending(expr)](./firestore_pipelines.md#ascending_005f3d4) | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. | +| [byteLength(expr)](./firestore_pipelines.md#bytelength_005f3d4) | Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. | +| [countDistinct(expr)](./firestore_pipelines.md#countdistinct_3c28b08) | Creates an aggregation that counts the number of distinct values of a field. | +| [descending(expr)](./firestore_pipelines.md#descending_005f3d4) | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. | +| [floor(expr)](./firestore_pipelines.md#floor_005f3d4) | Creates an expression that computes the floor of a numeric value. | +| [timestampToUnixMicros(expr)](./firestore_pipelines.md#timestamptounixmicros_005f3d4) | Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixMillis(expr)](./firestore_pipelines.md#timestamptounixmillis_005f3d4) | Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixSeconds(expr)](./firestore_pipelines.md#timestamptounixseconds_005f3d4) | Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [unixMicrosToTimestamp(expr)](./firestore_pipelines.md#unixmicrostotimestamp_005f3d4) | Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixMillisToTimestamp(expr)](./firestore_pipelines.md#unixmillistotimestamp_005f3d4) | Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixSecondsToTimestamp(expr)](./firestore_pipelines.md#unixsecondstotimestamp_005f3d4) | Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | | function(expression, ...) | -| [arrayAgg(expression)](./firestore_pipelines.md#arrayagg_1138a27) | (Public Preview) Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. | -| [arrayAggDistinct(expression)](./firestore_pipelines.md#arrayaggdistinct_1138a27) | (Public Preview) Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. | -| [arraySum(expression)](./firestore_pipelines.md#arraysum_1138a27) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | -| [average(expression)](./firestore_pipelines.md#average_1138a27) | (Public Preview) Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. | -| [ceil(expression)](./firestore_pipelines.md#ceil_1138a27) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | -| [coalesce(expression, replacement, others)](./firestore_pipelines.md#coalesce_00859cb) | (Public Preview) Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | -| [collectionId(expression)](./firestore_pipelines.md#collectionid_1138a27) | (Public Preview) Creates an expression that returns the collection ID from a path. | -| [count(expression)](./firestore_pipelines.md#count_1138a27) | (Public Preview) Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. | -| [divide(expression, value)](./firestore_pipelines.md#divide_01df3cf) | (Public Preview) Creates an expression that divides an expression by a constant value. | -| [equal(expression, value)](./firestore_pipelines.md#equal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is equal to a constant value. | -| [equalAny(expression, values)](./firestore_pipelines.md#equalany_7e759b5) | (Public Preview) Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. | -| [equalAny(expression, arrayExpression)](./firestore_pipelines.md#equalany_214ce68) | (Public Preview) Creates an expression that checks if an expression is equal to any of the provided values. | -| [exp(expression)](./firestore_pipelines.md#exp_1138a27) | (Public Preview) Creates an expression that computes e to the power of the expression's result. | -| [first(expression)](./firestore_pipelines.md#first_1138a27) | (Public Preview) Creates an aggregation that finds the first value of an expression across multiple stage inputs. | -| [greaterThan(expression, value)](./firestore_pipelines.md#greaterthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than a constant value. | -| [greaterThanOrEqual(expression, value)](./firestore_pipelines.md#greaterthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is greater than or equal to a constant value. | -| [isType(expression, type)](./firestore_pipelines.md#istype_27398ce) | (Public Preview) Creates an expression that checks if the result of an expression is of the given type. | -| [last(expression)](./firestore_pipelines.md#last_1138a27) | (Public Preview) Creates an aggregation that finds the last value of an expression across multiple stage inputs. | -| [length\_2(expression)](./firestore_pipelines.md#length_2_1138a27) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | -| [lessThan(expression, value)](./firestore_pipelines.md#lessthan_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than a constant value. | -| [lessThanOrEqual(expression, value)](./firestore_pipelines.md#lessthanorequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is less than or equal to a constant value. | -| [ln(expression)](./firestore_pipelines.md#ln_1138a27) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. | -| [log(expression, base)](./firestore_pipelines.md#log_ac183e2) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. | -| [log(expression, base)](./firestore_pipelines.md#log_1894737) | (Public Preview) Creates an expression that computes the logarithm of an expression to a given base. | -| [log10(expression)](./firestore_pipelines.md#log10_1138a27) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | -| [ltrim(expression, valueToTrim)](./firestore_pipelines.md#ltrim_775e2f2) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | -| [maximum(expression)](./firestore_pipelines.md#maximum_1138a27) | (Public Preview) Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. | -| [minimum(expression)](./firestore_pipelines.md#minimum_1138a27) | (Public Preview) Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. | -| [mod(expression, value)](./firestore_pipelines.md#mod_01df3cf) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. | -| [notEqual(expression, value)](./firestore_pipelines.md#notequal_01df3cf) | (Public Preview) Creates an expression that checks if an expression is not equal to a constant value. | -| [round(expression)](./firestore_pipelines.md#round_1138a27) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | -| [round(expression, decimalPlaces)](./firestore_pipelines.md#round_a3a92d0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | -| [rtrim(expression, valueToTrim)](./firestore_pipelines.md#rtrim_775e2f2) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | -| [split(expression, delimiter)](./firestore_pipelines.md#split_5b5612b) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | -| [split(expression, delimiter)](./firestore_pipelines.md#split_5a171ed) | (Public Preview) Creates an expression that splits a string into an array of substrings based on the provided delimiter. | -| [sqrt(expression)](./firestore_pipelines.md#sqrt_1138a27) | (Public Preview) Creates an expression that computes the square root of a numeric value. | -| [stringIndexOf(expression, search)](./firestore_pipelines.md#stringindexof_6dfca5f) | (Public Preview) Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | -| [stringRepeat(expression, repetitions)](./firestore_pipelines.md#stringrepeat_a55ba16) | (Public Preview) Creates an expression that repeats a string or byte array a specified number of times. | -| [stringReplaceAll(expression, find, replacement)](./firestore_pipelines.md#stringreplaceall_197ecbe) | (Public Preview) Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | -| [stringReplaceOne(expression, find, replacement)](./firestore_pipelines.md#stringreplaceone_197ecbe) | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | -| [subtract(expression, value)](./firestore_pipelines.md#subtract_01df3cf) | (Public Preview) Creates an expression that subtracts a constant value from an expression. | -| [sum(expression)](./firestore_pipelines.md#sum_1138a27) | (Public Preview) Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. | -| [trunc(expression)](./firestore_pipelines.md#trunc_1138a27) | (Public Preview) Creates an expression that truncates the numeric value of an expression to an integer. | -| [trunc(expression, decimalPlaces)](./firestore_pipelines.md#trunc_a3a92d0) | (Public Preview) Creates an expression that truncates a numeric value to the specified number of decimal places. | -| [type(expression)](./firestore_pipelines.md#type_1138a27) | (Public Preview) Creates an expression that returns the data type of an expression's result. | +| [arrayAgg(expression)](./firestore_pipelines.md#arrayagg_1138a27) | Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. | +| [arrayAggDistinct(expression)](./firestore_pipelines.md#arrayaggdistinct_1138a27) | Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. | +| [arraySum(expression)](./firestore_pipelines.md#arraysum_1138a27) | Creates an expression that computes the sum of the elements in an array. | +| [average(expression)](./firestore_pipelines.md#average_1138a27) | Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. | +| [ceil(expression)](./firestore_pipelines.md#ceil_1138a27) | Creates an expression that computes the ceiling of a numeric value. | +| [coalesce(expression, replacement, others)](./firestore_pipelines.md#coalesce_00859cb) | Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | +| [collectionId(expression)](./firestore_pipelines.md#collectionid_1138a27) | Creates an expression that returns the collection ID from a path. | +| [count(expression)](./firestore_pipelines.md#count_1138a27) | Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. | +| [divide(expression, value)](./firestore_pipelines.md#divide_01df3cf) | Creates an expression that divides an expression by a constant value. | +| [equal(expression, value)](./firestore_pipelines.md#equal_01df3cf) | Creates an expression that checks if an expression is equal to a constant value. | +| [equalAny(expression, values)](./firestore_pipelines.md#equalany_7e759b5) | Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. | +| [equalAny(expression, arrayExpression)](./firestore_pipelines.md#equalany_214ce68) | Creates an expression that checks if an expression is equal to any of the provided values. | +| [exp(expression)](./firestore_pipelines.md#exp_1138a27) | Creates an expression that computes e to the power of the expression's result. | +| [first(expression)](./firestore_pipelines.md#first_1138a27) | Creates an aggregation that finds the first value of an expression across multiple stage inputs. | +| [greaterThan(expression, value)](./firestore_pipelines.md#greaterthan_01df3cf) | Creates an expression that checks if an expression is greater than a constant value. | +| [greaterThanOrEqual(expression, value)](./firestore_pipelines.md#greaterthanorequal_01df3cf) | Creates an expression that checks if an expression is greater than or equal to a constant value. | +| [isType(expression, type)](./firestore_pipelines.md#istype_27398ce) | Creates an expression that checks if the result of an expression is of the given type. | +| [last(expression)](./firestore_pipelines.md#last_1138a27) | Creates an aggregation that finds the last value of an expression across multiple stage inputs. | +| [length\_2(expression)](./firestore_pipelines.md#length_2_1138a27) | Creates an expression that calculates the length of a string, array, map, vector, or bytes. | +| [lessThan(expression, value)](./firestore_pipelines.md#lessthan_01df3cf) | Creates an expression that checks if an expression is less than a constant value. | +| [lessThanOrEqual(expression, value)](./firestore_pipelines.md#lessthanorequal_01df3cf) | Creates an expression that checks if an expression is less than or equal to a constant value. | +| [ln(expression)](./firestore_pipelines.md#ln_1138a27) | Creates an expression that computes the natural logarithm of a numeric value. | +| [log(expression, base)](./firestore_pipelines.md#log_ac183e2) | Creates an expression that computes the logarithm of an expression to a given base. | +| [log(expression, base)](./firestore_pipelines.md#log_1894737) | Creates an expression that computes the logarithm of an expression to a given base. | +| [log10(expression)](./firestore_pipelines.md#log10_1138a27) | Creates an expression that computes the base-10 logarithm of a numeric value. | +| [ltrim(expression, valueToTrim)](./firestore_pipelines.md#ltrim_775e2f2) | Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | +| [maximum(expression)](./firestore_pipelines.md#maximum_1138a27) | Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. | +| [minimum(expression)](./firestore_pipelines.md#minimum_1138a27) | Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. | +| [mod(expression, value)](./firestore_pipelines.md#mod_01df3cf) | Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. | +| [notEqual(expression, value)](./firestore_pipelines.md#notequal_01df3cf) | Creates an expression that checks if an expression is not equal to a constant value. | +| [round(expression)](./firestore_pipelines.md#round_1138a27) | Creates an expression that rounds a numeric value to the nearest whole number. | +| [round(expression, decimalPlaces)](./firestore_pipelines.md#round_a3a92d0) | Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [rtrim(expression, valueToTrim)](./firestore_pipelines.md#rtrim_775e2f2) | Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | +| [split(expression, delimiter)](./firestore_pipelines.md#split_5b5612b) | Creates an expression that splits a string into an array of substrings based on the provided delimiter. | +| [split(expression, delimiter)](./firestore_pipelines.md#split_5a171ed) | Creates an expression that splits a string into an array of substrings based on the provided delimiter. | +| [sqrt(expression)](./firestore_pipelines.md#sqrt_1138a27) | Creates an expression that computes the square root of a numeric value. | +| [stringIndexOf(expression, search)](./firestore_pipelines.md#stringindexof_6dfca5f) | Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | +| [stringRepeat(expression, repetitions)](./firestore_pipelines.md#stringrepeat_a55ba16) | Creates an expression that repeats a string or byte array a specified number of times. | +| [stringReplaceAll(expression, find, replacement)](./firestore_pipelines.md#stringreplaceall_197ecbe) | Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | +| [stringReplaceOne(expression, find, replacement)](./firestore_pipelines.md#stringreplaceone_197ecbe) | Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | +| [subtract(expression, value)](./firestore_pipelines.md#subtract_01df3cf) | Creates an expression that subtracts a constant value from an expression. | +| [sum(expression)](./firestore_pipelines.md#sum_1138a27) | Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. | +| [trunc(expression)](./firestore_pipelines.md#trunc_1138a27) | Creates an expression that truncates the numeric value of an expression to an integer. | +| [trunc(expression, decimalPlaces)](./firestore_pipelines.md#trunc_a3a92d0) | Creates an expression that truncates a numeric value to the specified number of decimal places. | +| [type(expression)](./firestore_pipelines.md#type_1138a27) | Creates an expression that returns the data type of an expression's result. | | function(field, ...) | -| [isAbsent(field)](./firestore_pipelines.md#isabsent_0fb8cd4) | (Public Preview) Creates an expression that returns true if a field is absent. Otherwise, returns false even if the field value is null. | -| [reverse(field)](./firestore_pipelines.md#reverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. | -| [stringReverse(field)](./firestore_pipelines.md#stringreverse_0fb8cd4) | (Public Preview) Creates an expression that reverses a string value in the specified field. | -| [substring(field, position, length)](./firestore_pipelines.md#substring_0d9573a) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | -| [substring(field, position, length)](./firestore_pipelines.md#substring_05cb14e) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| [isAbsent(field)](./firestore_pipelines.md#isabsent_0fb8cd4) | Creates an expression that returns true if a field is absent. Otherwise, returns false even if the field value is null. | +| [reverse(field)](./firestore_pipelines.md#reverse_0fb8cd4) | Creates an expression that reverses a string value in the specified field. | +| [stringReverse(field)](./firestore_pipelines.md#stringreverse_0fb8cd4) | Creates an expression that reverses a string value in the specified field. | +| [substring(field, position, length)](./firestore_pipelines.md#substring_0d9573a) | Creates an expression that returns a substring of a string or byte array. | +| [substring(field, position, length)](./firestore_pipelines.md#substring_05cb14e) | Creates an expression that returns a substring of a string or byte array. | | function(fieldName, ...) | -| [abs(fieldName)](./firestore_pipelines.md#abs_e5b0480) | (Public Preview) Creates an expression that computes the absolute value of a numeric value. | -| [add(fieldName, second)](./firestore_pipelines.md#add_b75bb8b) | (Public Preview) Creates an expression that adds a field's value to an expression. | -| [arrayAgg(fieldName)](./firestore_pipelines.md#arrayagg_e5b0480) | (Public Preview) Creates an aggregation that collects all values of a field across multiple stage inputs into an array. | -| [arrayAggDistinct(fieldName)](./firestore_pipelines.md#arrayaggdistinct_e5b0480) | (Public Preview) Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. | -| [arrayContains(fieldName, element)](./firestore_pipelines.md#arraycontains_aaace4a) | (Public Preview) Creates an expression that checks if a field's array value contains a specific element. | -| [arrayContains(fieldName, element)](./firestore_pipelines.md#arraycontains_999590f) | (Public Preview) Creates an expression that checks if a field's array value contains a specific value. | -| [arrayContainsAll(fieldName, values)](./firestore_pipelines.md#arraycontainsall_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. | -| [arrayContainsAll(fieldName, arrayExpression)](./firestore_pipelines.md#arraycontainsall_48da8d9) | (Public Preview) Creates an expression that checks if a field's array value contains all the specified values or expressions. | -| [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_8060b23) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. | -| [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_1b4f7cd) | (Public Preview) Creates an expression that checks if a field's array value contains any of the specified elements. | -| [arrayFirst(fieldName)](./firestore_pipelines.md#arrayfirst_e5b0480) | (Public Preview) Creates an expression that returns the first element of an array. | -| [arrayFirstN(fieldName, n)](./firestore_pipelines.md#arrayfirstn_597a4d9) | (Public Preview) Creates an expression that returns the first n elements of an array. | -| [arrayFirstN(fieldName, n)](./firestore_pipelines.md#arrayfirstn_1a86a2c) | (Public Preview) Creates an expression that returns the first n elements of an array. | -| [arrayIndexOf(fieldName, search)](./firestore_pipelines.md#arrayindexof_5e4c2c3) | (Public Preview) Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. | -| [arrayIndexOfAll(fieldName, search)](./firestore_pipelines.md#arrayindexofall_5e4c2c3) | (Public Preview) Creates an expression that returns all indices of the search value in an array. | -| [arrayLast(fieldName)](./firestore_pipelines.md#arraylast_e5b0480) | (Public Preview) Creates an expression that returns the last element of an array. | -| [arrayLastIndexOf(fieldName, search)](./firestore_pipelines.md#arraylastindexof_5e4c2c3) | (Public Preview) Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. | -| [arrayLastN(fieldName, n)](./firestore_pipelines.md#arraylastn_597a4d9) | (Public Preview) Creates an expression that returns the last n elements of an array. | -| [arrayLastN(fieldName, n)](./firestore_pipelines.md#arraylastn_1a86a2c) | (Public Preview) Creates an expression that returns the last n elements of an array. | -| [arrayLength(fieldName)](./firestore_pipelines.md#arraylength_e5b0480) | (Public Preview) Creates an expression that calculates the length of an array in a specified field. | -| [arrayMaximum(fieldName)](./firestore_pipelines.md#arraymaximum_e5b0480) | (Public Preview) Creates an expression that returns the maximum value in an array. | -| [arrayMaximumN(fieldName, n)](./firestore_pipelines.md#arraymaximumn_597a4d9) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMaximumN(fieldName, n)](./firestore_pipelines.md#arraymaximumn_1a86a2c) | (Public Preview) Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMinimum(fieldName)](./firestore_pipelines.md#arrayminimum_e5b0480) | (Public Preview) Creates an expression that returns the minimum value in an array. | -| [arrayMinimumN(fieldName, n)](./firestore_pipelines.md#arrayminimumn_597a4d9) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arrayMinimumN(fieldName, n)](./firestore_pipelines.md#arrayminimumn_1a86a2c) | (Public Preview) Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | -| [arraySum(fieldName)](./firestore_pipelines.md#arraysum_e5b0480) | (Public Preview) Creates an expression that computes the sum of the elements in an array. | -| [ascending(fieldName)](./firestore_pipelines.md#ascending_e5b0480) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. | -| [average(fieldName)](./firestore_pipelines.md#average_e5b0480) | (Public Preview) Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. | -| [byteLength(fieldName)](./firestore_pipelines.md#bytelength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. | -| [ceil(fieldName)](./firestore_pipelines.md#ceil_e5b0480) | (Public Preview) Creates an expression that computes the ceiling of a numeric value. | -| [charLength(fieldName)](./firestore_pipelines.md#charlength_e5b0480) | (Public Preview) Creates an expression that calculates the character length of a string field in UTF8. | -| [coalesce(fieldName, replacement, others)](./firestore_pipelines.md#coalesce_249958e) | (Public Preview) Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | -| [collectionId(fieldName)](./firestore_pipelines.md#collectionid_e5b0480) | (Public Preview) Creates an expression that returns the collection ID from a path. | -| [concat(fieldName, second, others)](./firestore_pipelines.md#concat_828272e) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | -| [cosineDistance(fieldName, vector)](./firestore_pipelines.md#cosinedistance_463a23e) | (Public Preview) Calculates the Cosine distance between a field's vector value and a literal vector value. | -| [cosineDistance(fieldName, vectorExpression)](./firestore_pipelines.md#cosinedistance_ed766a1) | (Public Preview) Calculates the Cosine distance between a field's vector value and a vector expression. | -| [count(fieldName)](./firestore_pipelines.md#count_e5b0480) | (Public Preview) Creates an aggregation that counts the number of stage inputs where the input field exists. | -| [descending(fieldName)](./firestore_pipelines.md#descending_e5b0480) | (Public Preview) Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on a field. | -| [divide(fieldName, expressions)](./firestore_pipelines.md#divide_cf36e43) | (Public Preview) Creates an expression that divides a field's value by an expression. | -| [divide(fieldName, value)](./firestore_pipelines.md#divide_65e2f32) | (Public Preview) Creates an expression that divides a field's value by a constant value. | -| [dotProduct(fieldName, vector)](./firestore_pipelines.md#dotproduct_463a23e) | (Public Preview) Calculates the dot product between a field's vector value and a double array. | -| [dotProduct(fieldName, vectorExpression)](./firestore_pipelines.md#dotproduct_ed766a1) | (Public Preview) Calculates the dot product between a field's vector value and a vector expression. | -| [endsWith(fieldName, suffix)](./firestore_pipelines.md#endswith_05ca3b0) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. | -| [endsWith(fieldName, suffix)](./firestore_pipelines.md#endswith_8fc0ebc) | (Public Preview) Creates an expression that checks if a field's value ends with a given postfix. | -| [equal(fieldName, expression)](./firestore_pipelines.md#equal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is equal to an expression. | -| [equal(fieldName, value)](./firestore_pipelines.md#equal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is equal to a constant value. | -| [equalAny(fieldName, values)](./firestore_pipelines.md#equalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. | -| [equalAny(fieldName, arrayExpression)](./firestore_pipelines.md#equalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is equal to any of the provided values or expressions. | -| [euclideanDistance(fieldName, vector)](./firestore_pipelines.md#euclideandistance_463a23e) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a double array. | -| [euclideanDistance(fieldName, vectorExpression)](./firestore_pipelines.md#euclideandistance_ed766a1) | (Public Preview) Calculates the Euclidean distance between a field's vector value and a vector expression. | -| [exists(fieldName)](./firestore_pipelines.md#exists_e5b0480) | (Public Preview) Creates an expression that checks if a field exists. | -| [exp(fieldName)](./firestore_pipelines.md#exp_e5b0480) | (Public Preview) Creates an expression that computes e to the power of the expression's result. | -| [first(fieldName)](./firestore_pipelines.md#first_e5b0480) | (Public Preview) Creates an aggregation that finds the first value of a field across multiple stage inputs. | -| [floor(fieldName)](./firestore_pipelines.md#floor_e5b0480) | (Public Preview) Creates an expression that computes the floor of a numeric value. | -| [greaterThan(fieldName, expression)](./firestore_pipelines.md#greaterthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is greater than an expression. | -| [greaterThan(fieldName, value)](./firestore_pipelines.md#greaterthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than a constant value. | -| [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_2e16acb) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to an expression. | -| [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is greater than or equal to a constant value. | -| [isType(fieldName, type)](./firestore_pipelines.md#istype_5da287e) | (Public Preview) Creates an expression that checks if the value in the specified field is of the given type. | -| [last(fieldName)](./firestore_pipelines.md#last_e5b0480) | (Public Preview) Creates an aggregation that finds the last value of a field across multiple stage inputs. | -| [length\_2(fieldName)](./firestore_pipelines.md#length_2_e5b0480) | (Public Preview) Creates an expression that calculates the length of a string, array, map, vector, or bytes. | -| [lessThan(fieldName, expression)](./firestore_pipelines.md#lessthan_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than an expression. | -| [lessThan(fieldName, value)](./firestore_pipelines.md#lessthan_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than a constant value. | -| [lessThanOrEqual(fieldName, expression)](./firestore_pipelines.md#lessthanorequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to an expression. | -| [lessThanOrEqual(fieldName, value)](./firestore_pipelines.md#lessthanorequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is less than or equal to a constant value. | -| [like(fieldName, pattern)](./firestore_pipelines.md#like_67f7432) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. | -| [like(fieldName, pattern)](./firestore_pipelines.md#like_cb1318d) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison against a field. | -| [ln(fieldName)](./firestore_pipelines.md#ln_e5b0480) | (Public Preview) Creates an expression that computes the natural logarithm of a numeric value. | -| [log(fieldName, base)](./firestore_pipelines.md#log_a89e21b) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. | -| [log(fieldName, base)](./firestore_pipelines.md#log_805b11f) | (Public Preview) Creates an expression that computes the logarithm of a field to a given base. | -| [log10(fieldName)](./firestore_pipelines.md#log10_e5b0480) | (Public Preview) Creates an expression that computes the base-10 logarithm of a numeric value. | -| [logicalMaximum(fieldName, second, others)](./firestore_pipelines.md#logicalmaximum_828272e) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | -| [logicalMinimum(fieldName, second, others)](./firestore_pipelines.md#logicalminimum_828272e) | (Public Preview) Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. | -| [ltrim(fieldName, valueToTrim)](./firestore_pipelines.md#ltrim_c0e3211) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | -| [mapGet(fieldName, subField)](./firestore_pipelines.md#mapget_06663cf) | (Public Preview) Accesses a value from a map (object) field using the provided key. | -| [maximum(fieldName)](./firestore_pipelines.md#maximum_e5b0480) | (Public Preview) Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | -| [minimum(fieldName)](./firestore_pipelines.md#minimum_e5b0480) | (Public Preview) Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | -| [mod(fieldName, expression)](./firestore_pipelines.md#mod_1e91657) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. | -| [mod(fieldName, value)](./firestore_pipelines.md#mod_65e2f32) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. | -| [multiply(fieldName, second)](./firestore_pipelines.md#multiply_b75bb8b) | (Public Preview) Creates an expression that multiplies a field's value by an expression. | -| [notEqual(fieldName, expression)](./firestore_pipelines.md#notequal_1e91657) | (Public Preview) Creates an expression that checks if a field's value is not equal to an expression. | -| [notEqual(fieldName, value)](./firestore_pipelines.md#notequal_65e2f32) | (Public Preview) Creates an expression that checks if a field's value is not equal to a constant value. | -| [notEqualAny(fieldName, values)](./firestore_pipelines.md#notequalany_8060b23) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. | -| [notEqualAny(fieldName, arrayExpression)](./firestore_pipelines.md#notequalany_48da8d9) | (Public Preview) Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. | -| [regexContains(fieldName, pattern)](./firestore_pipelines.md#regexcontains_67f7432) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. | -| [regexContains(fieldName, pattern)](./firestore_pipelines.md#regexcontains_cb1318d) | (Public Preview) Creates an expression that checks if a string field contains a specified regular expression as a substring. | -| [regexFind(fieldName, pattern)](./firestore_pipelines.md#regexfind_67f7432) | (Public Preview) Creates an expression that returns the first substring of a string field that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFind(fieldName, pattern)](./firestore_pipelines.md#regexfind_cb1318d) | (Public Preview) Creates an expression that returns the first substring of a string field that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFindAll(fieldName, pattern)](./firestore_pipelines.md#regexfindall_67f7432) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFindAll(fieldName, pattern)](./firestore_pipelines.md#regexfindall_cb1318d) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_67f7432) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | -| [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_cb1318d) | (Public Preview) Creates an expression that checks if a string field matches a specified regular expression. | -| [round(fieldName)](./firestore_pipelines.md#round_e5b0480) | (Public Preview) Creates an expression that rounds a numeric value to the nearest whole number. | -| [round(fieldName, decimalPlaces)](./firestore_pipelines.md#round_07d0cf0) | (Public Preview) Creates an expression that rounds a numeric value to the specified number of decimal places. | -| [rtrim(fieldName, valueToTrim)](./firestore_pipelines.md#rtrim_c0e3211) | (Public Preview) Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | -| [split(fieldName, delimiter)](./firestore_pipelines.md#split_2cfdd37) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | -| [split(fieldName, delimiter)](./firestore_pipelines.md#split_f4fe06a) | (Public Preview) Creates an expression that splits the value of a field on the provided delimiter. | -| [sqrt(fieldName)](./firestore_pipelines.md#sqrt_e5b0480) | (Public Preview) Creates an expression that computes the square root of a numeric value. | -| [startsWith(fieldName, prefix)](./firestore_pipelines.md#startswith_89325cc) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. | -| [startsWith(fieldName, prefix)](./firestore_pipelines.md#startswith_266c338) | (Public Preview) Creates an expression that checks if a field's value starts with a given prefix. | -| [stringConcat(fieldName, secondString, otherStrings)](./firestore_pipelines.md#stringconcat_d80077e) | (Public Preview) Creates an expression that concatenates string functions, fields or constants together. | -| [stringContains(fieldName, substring)](./firestore_pipelines.md#stringcontains_5b94cfe) | (Public Preview) Creates an expression that checks if a string field contains a specified substring. | -| [stringContains(fieldName, substring)](./firestore_pipelines.md#stringcontains_ac3ba47) | (Public Preview) Creates an expression that checks if a string field contains a substring specified by an expression. | -| [stringIndexOf(fieldName, search)](./firestore_pipelines.md#stringindexof_6c4650e) | (Public Preview) Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | -| [stringRepeat(fieldName, repetitions)](./firestore_pipelines.md#stringrepeat_e144a59) | (Public Preview) Creates an expression that repeats a string or byte array a specified number of times. | -| [stringReplaceAll(fieldName, find, replacement)](./firestore_pipelines.md#stringreplaceall_b0db15f) | (Public Preview) Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | -| [stringReplaceOne(fieldName, find, replacement)](./firestore_pipelines.md#stringreplaceone_b0db15f) | (Public Preview) Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | -| [subtract(fieldName, expression)](./firestore_pipelines.md#subtract_1e91657) | (Public Preview) Creates an expression that subtracts an expression from a field's value. | -| [subtract(fieldName, value)](./firestore_pipelines.md#subtract_65e2f32) | (Public Preview) Creates an expression that subtracts a constant value from a field's value. | -| [sum(fieldName)](./firestore_pipelines.md#sum_e5b0480) | (Public Preview) Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. | -| [timestampAdd(fieldName, unit, amount)](./firestore_pipelines.md#timestampadd_3b0a297) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp represented by a field. | -| [timestampExtract(fieldName, part, timezone)](./firestore_pipelines.md#timestampextract_a51c205) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | -| [timestampExtract(fieldName, part, timezone)](./firestore_pipelines.md#timestampextract_2d51eac) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | -| [timestampSubtract(fieldName, unit, amount)](./firestore_pipelines.md#timestampsubtract_3b0a297) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. | -| [timestampToUnixMicros(fieldName)](./firestore_pipelines.md#timestamptounixmicros_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampToUnixMillis(fieldName)](./firestore_pipelines.md#timestamptounixmillis_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampToUnixSeconds(fieldName)](./firestore_pipelines.md#timestamptounixseconds_e5b0480) | (Public Preview) Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | -| [timestampTruncate(fieldName, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_b6c7512) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [timestampTruncate(fieldName, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_ed83d46) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [toLower(fieldName)](./firestore_pipelines.md#tolower_e5b0480) | (Public Preview) Creates an expression that converts a string field to lowercase. | -| [toUpper(fieldName)](./firestore_pipelines.md#toupper_e5b0480) | (Public Preview) Creates an expression that converts a string field to uppercase. | -| [trim(fieldName, valueToTrim)](./firestore_pipelines.md#trim_c9f90ee) | (Public Preview) Creates an expression that removes leading and trailing whitespace from a string or byte array. | -| [trunc(fieldName)](./firestore_pipelines.md#trunc_e5b0480) | (Public Preview) Creates an expression that truncates the numeric value of a field to an integer. | -| [trunc(fieldName, decimalPlaces)](./firestore_pipelines.md#trunc_07d0cf0) | (Public Preview) Creates an expression that truncates a numeric expression to the specified number of decimal places. | -| [type(fieldName)](./firestore_pipelines.md#type_e5b0480) | (Public Preview) Creates an expression that returns the data type of the data in the specified field. | -| [unixMicrosToTimestamp(fieldName)](./firestore_pipelines.md#unixmicrostotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | -| [unixMillisToTimestamp(fieldName)](./firestore_pipelines.md#unixmillistotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | -| [unixSecondsToTimestamp(fieldName)](./firestore_pipelines.md#unixsecondstotimestamp_e5b0480) | (Public Preview) Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | -| [vectorLength(fieldName)](./firestore_pipelines.md#vectorlength_e5b0480) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector represented by a field. | +| [abs(fieldName)](./firestore_pipelines.md#abs_e5b0480) | Creates an expression that computes the absolute value of a numeric value. | +| [add(fieldName, second)](./firestore_pipelines.md#add_b75bb8b) | Creates an expression that adds a field's value to an expression. | +| [arrayAgg(fieldName)](./firestore_pipelines.md#arrayagg_e5b0480) | Creates an aggregation that collects all values of a field across multiple stage inputs into an array. | +| [arrayAggDistinct(fieldName)](./firestore_pipelines.md#arrayaggdistinct_e5b0480) | Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. | +| [arrayContains(fieldName, element)](./firestore_pipelines.md#arraycontains_aaace4a) | Creates an expression that checks if a field's array value contains a specific element. | +| [arrayContains(fieldName, element)](./firestore_pipelines.md#arraycontains_999590f) | Creates an expression that checks if a field's array value contains a specific value. | +| [arrayContainsAll(fieldName, values)](./firestore_pipelines.md#arraycontainsall_8060b23) | Creates an expression that checks if a field's array value contains all the specified values or expressions. | +| [arrayContainsAll(fieldName, arrayExpression)](./firestore_pipelines.md#arraycontainsall_48da8d9) | Creates an expression that checks if a field's array value contains all the specified values or expressions. | +| [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_8060b23) | Creates an expression that checks if a field's array value contains any of the specified elements. | +| [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_1b4f7cd) | Creates an expression that checks if a field's array value contains any of the specified elements. | +| [arrayFirst(fieldName)](./firestore_pipelines.md#arrayfirst_e5b0480) | Creates an expression that returns the first element of an array. | +| [arrayFirstN(fieldName, n)](./firestore_pipelines.md#arrayfirstn_597a4d9) | Creates an expression that returns the first n elements of an array. | +| [arrayFirstN(fieldName, n)](./firestore_pipelines.md#arrayfirstn_1a86a2c) | Creates an expression that returns the first n elements of an array. | +| [arrayIndexOf(fieldName, search)](./firestore_pipelines.md#arrayindexof_5e4c2c3) | Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. | +| [arrayIndexOfAll(fieldName, search)](./firestore_pipelines.md#arrayindexofall_5e4c2c3) | Creates an expression that returns all indices of the search value in an array. | +| [arrayLast(fieldName)](./firestore_pipelines.md#arraylast_e5b0480) | Creates an expression that returns the last element of an array. | +| [arrayLastIndexOf(fieldName, search)](./firestore_pipelines.md#arraylastindexof_5e4c2c3) | Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. | +| [arrayLastN(fieldName, n)](./firestore_pipelines.md#arraylastn_597a4d9) | Creates an expression that returns the last n elements of an array. | +| [arrayLastN(fieldName, n)](./firestore_pipelines.md#arraylastn_1a86a2c) | Creates an expression that returns the last n elements of an array. | +| [arrayLength(fieldName)](./firestore_pipelines.md#arraylength_e5b0480) | Creates an expression that calculates the length of an array in a specified field. | +| [arrayMaximum(fieldName)](./firestore_pipelines.md#arraymaximum_e5b0480) | Creates an expression that returns the maximum value in an array. | +| [arrayMaximumN(fieldName, n)](./firestore_pipelines.md#arraymaximumn_597a4d9) | Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMaximumN(fieldName, n)](./firestore_pipelines.md#arraymaximumn_1a86a2c) | Creates an expression that returns the largest n elements of an array.Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimum(fieldName)](./firestore_pipelines.md#arrayminimum_e5b0480) | Creates an expression that returns the minimum value in an array. | +| [arrayMinimumN(fieldName, n)](./firestore_pipelines.md#arrayminimumn_597a4d9) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arrayMinimumN(fieldName, n)](./firestore_pipelines.md#arrayminimumn_1a86a2c) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arraySum(fieldName)](./firestore_pipelines.md#arraysum_e5b0480) | Creates an expression that computes the sum of the elements in an array. | +| [ascending(fieldName)](./firestore_pipelines.md#ascending_e5b0480) | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. | +| [average(fieldName)](./firestore_pipelines.md#average_e5b0480) | Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. | +| [byteLength(fieldName)](./firestore_pipelines.md#bytelength_e5b0480) | Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. | +| [ceil(fieldName)](./firestore_pipelines.md#ceil_e5b0480) | Creates an expression that computes the ceiling of a numeric value. | +| [charLength(fieldName)](./firestore_pipelines.md#charlength_e5b0480) | Creates an expression that calculates the character length of a string field in UTF8. | +| [coalesce(fieldName, replacement, others)](./firestore_pipelines.md#coalesce_249958e) | Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. | +| [collectionId(fieldName)](./firestore_pipelines.md#collectionid_e5b0480) | Creates an expression that returns the collection ID from a path. | +| [concat(fieldName, second, others)](./firestore_pipelines.md#concat_828272e) | Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | +| [cosineDistance(fieldName, vector)](./firestore_pipelines.md#cosinedistance_463a23e) | Calculates the Cosine distance between a field's vector value and a literal vector value. | +| [cosineDistance(fieldName, vectorExpression)](./firestore_pipelines.md#cosinedistance_ed766a1) | Calculates the Cosine distance between a field's vector value and a vector expression. | +| [count(fieldName)](./firestore_pipelines.md#count_e5b0480) | Creates an aggregation that counts the number of stage inputs where the input field exists. | +| [descending(fieldName)](./firestore_pipelines.md#descending_e5b0480) | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on a field. | +| [divide(fieldName, expressions)](./firestore_pipelines.md#divide_cf36e43) | Creates an expression that divides a field's value by an expression. | +| [divide(fieldName, value)](./firestore_pipelines.md#divide_65e2f32) | Creates an expression that divides a field's value by a constant value. | +| [dotProduct(fieldName, vector)](./firestore_pipelines.md#dotproduct_463a23e) | Calculates the dot product between a field's vector value and a double array. | +| [dotProduct(fieldName, vectorExpression)](./firestore_pipelines.md#dotproduct_ed766a1) | Calculates the dot product between a field's vector value and a vector expression. | +| [endsWith(fieldName, suffix)](./firestore_pipelines.md#endswith_05ca3b0) | Creates an expression that checks if a field's value ends with a given postfix. | +| [endsWith(fieldName, suffix)](./firestore_pipelines.md#endswith_8fc0ebc) | Creates an expression that checks if a field's value ends with a given postfix. | +| [equal(fieldName, expression)](./firestore_pipelines.md#equal_1e91657) | Creates an expression that checks if a field's value is equal to an expression. | +| [equal(fieldName, value)](./firestore_pipelines.md#equal_65e2f32) | Creates an expression that checks if a field's value is equal to a constant value. | +| [equalAny(fieldName, values)](./firestore_pipelines.md#equalany_8060b23) | Creates an expression that checks if a field's value is equal to any of the provided values or expressions. | +| [equalAny(fieldName, arrayExpression)](./firestore_pipelines.md#equalany_48da8d9) | Creates an expression that checks if a field's value is equal to any of the provided values or expressions. | +| [euclideanDistance(fieldName, vector)](./firestore_pipelines.md#euclideandistance_463a23e) | Calculates the Euclidean distance between a field's vector value and a double array. | +| [euclideanDistance(fieldName, vectorExpression)](./firestore_pipelines.md#euclideandistance_ed766a1) | Calculates the Euclidean distance between a field's vector value and a vector expression. | +| [exists(fieldName)](./firestore_pipelines.md#exists_e5b0480) | Creates an expression that checks if a field exists. | +| [exp(fieldName)](./firestore_pipelines.md#exp_e5b0480) | Creates an expression that computes e to the power of the expression's result. | +| [first(fieldName)](./firestore_pipelines.md#first_e5b0480) | Creates an aggregation that finds the first value of a field across multiple stage inputs. | +| [floor(fieldName)](./firestore_pipelines.md#floor_e5b0480) | Creates an expression that computes the floor of a numeric value. | +| [greaterThan(fieldName, expression)](./firestore_pipelines.md#greaterthan_1e91657) | Creates an expression that checks if a field's value is greater than an expression. | +| [greaterThan(fieldName, value)](./firestore_pipelines.md#greaterthan_65e2f32) | Creates an expression that checks if a field's value is greater than a constant value. | +| [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_2e16acb) | Creates an expression that checks if a field's value is greater than or equal to an expression. | +| [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_65e2f32) | Creates an expression that checks if a field's value is greater than or equal to a constant value. | +| [isType(fieldName, type)](./firestore_pipelines.md#istype_5da287e) | Creates an expression that checks if the value in the specified field is of the given type. | +| [last(fieldName)](./firestore_pipelines.md#last_e5b0480) | Creates an aggregation that finds the last value of a field across multiple stage inputs. | +| [length\_2(fieldName)](./firestore_pipelines.md#length_2_e5b0480) | Creates an expression that calculates the length of a string, array, map, vector, or bytes. | +| [lessThan(fieldName, expression)](./firestore_pipelines.md#lessthan_1e91657) | Creates an expression that checks if a field's value is less than an expression. | +| [lessThan(fieldName, value)](./firestore_pipelines.md#lessthan_65e2f32) | Creates an expression that checks if a field's value is less than a constant value. | +| [lessThanOrEqual(fieldName, expression)](./firestore_pipelines.md#lessthanorequal_1e91657) | Creates an expression that checks if a field's value is less than or equal to an expression. | +| [lessThanOrEqual(fieldName, value)](./firestore_pipelines.md#lessthanorequal_65e2f32) | Creates an expression that checks if a field's value is less than or equal to a constant value. | +| [like(fieldName, pattern)](./firestore_pipelines.md#like_67f7432) | Creates an expression that performs a case-sensitive wildcard string comparison against a field. | +| [like(fieldName, pattern)](./firestore_pipelines.md#like_cb1318d) | Creates an expression that performs a case-sensitive wildcard string comparison against a field. | +| [ln(fieldName)](./firestore_pipelines.md#ln_e5b0480) | Creates an expression that computes the natural logarithm of a numeric value. | +| [log(fieldName, base)](./firestore_pipelines.md#log_a89e21b) | Creates an expression that computes the logarithm of a field to a given base. | +| [log(fieldName, base)](./firestore_pipelines.md#log_805b11f) | Creates an expression that computes the logarithm of a field to a given base. | +| [log10(fieldName)](./firestore_pipelines.md#log10_e5b0480) | Creates an expression that computes the base-10 logarithm of a numeric value. | +| [logicalMaximum(fieldName, second, others)](./firestore_pipelines.md#logicalmaximum_828272e) | Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | +| [logicalMinimum(fieldName, second, others)](./firestore_pipelines.md#logicalminimum_828272e) | Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. | +| [ltrim(fieldName, valueToTrim)](./firestore_pipelines.md#ltrim_c0e3211) | Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. | +| [mapGet(fieldName, subField)](./firestore_pipelines.md#mapget_06663cf) | Accesses a value from a map (object) field using the provided key. | +| [maximum(fieldName)](./firestore_pipelines.md#maximum_e5b0480) | Creates an aggregation that finds the maximum value of a field across multiple stage inputs. | +| [minimum(fieldName)](./firestore_pipelines.md#minimum_e5b0480) | Creates an aggregation that finds the minimum value of a field across multiple stage inputs. | +| [mod(fieldName, expression)](./firestore_pipelines.md#mod_1e91657) | Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. | +| [mod(fieldName, value)](./firestore_pipelines.md#mod_65e2f32) | Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. | +| [multiply(fieldName, second)](./firestore_pipelines.md#multiply_b75bb8b) | Creates an expression that multiplies a field's value by an expression. | +| [notEqual(fieldName, expression)](./firestore_pipelines.md#notequal_1e91657) | Creates an expression that checks if a field's value is not equal to an expression. | +| [notEqual(fieldName, value)](./firestore_pipelines.md#notequal_65e2f32) | Creates an expression that checks if a field's value is not equal to a constant value. | +| [notEqualAny(fieldName, values)](./firestore_pipelines.md#notequalany_8060b23) | Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. | +| [notEqualAny(fieldName, arrayExpression)](./firestore_pipelines.md#notequalany_48da8d9) | Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. | +| [regexContains(fieldName, pattern)](./firestore_pipelines.md#regexcontains_67f7432) | Creates an expression that checks if a string field contains a specified regular expression as a substring. | +| [regexContains(fieldName, pattern)](./firestore_pipelines.md#regexcontains_cb1318d) | Creates an expression that checks if a string field contains a specified regular expression as a substring. | +| [regexFind(fieldName, pattern)](./firestore_pipelines.md#regexfind_67f7432) | Creates an expression that returns the first substring of a string field that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFind(fieldName, pattern)](./firestore_pipelines.md#regexfind_cb1318d) | Creates an expression that returns the first substring of a string field that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(fieldName, pattern)](./firestore_pipelines.md#regexfindall_67f7432) | Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(fieldName, pattern)](./firestore_pipelines.md#regexfindall_cb1318d) | Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_67f7432) | Creates an expression that checks if a string field matches a specified regular expression. | +| [regexMatch(fieldName, pattern)](./firestore_pipelines.md#regexmatch_cb1318d) | Creates an expression that checks if a string field matches a specified regular expression. | +| [round(fieldName)](./firestore_pipelines.md#round_e5b0480) | Creates an expression that rounds a numeric value to the nearest whole number. | +| [round(fieldName, decimalPlaces)](./firestore_pipelines.md#round_07d0cf0) | Creates an expression that rounds a numeric value to the specified number of decimal places. | +| [rtrim(fieldName, valueToTrim)](./firestore_pipelines.md#rtrim_c0e3211) | Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. | +| [split(fieldName, delimiter)](./firestore_pipelines.md#split_2cfdd37) | Creates an expression that splits the value of a field on the provided delimiter. | +| [split(fieldName, delimiter)](./firestore_pipelines.md#split_f4fe06a) | Creates an expression that splits the value of a field on the provided delimiter. | +| [sqrt(fieldName)](./firestore_pipelines.md#sqrt_e5b0480) | Creates an expression that computes the square root of a numeric value. | +| [startsWith(fieldName, prefix)](./firestore_pipelines.md#startswith_89325cc) | Creates an expression that checks if a field's value starts with a given prefix. | +| [startsWith(fieldName, prefix)](./firestore_pipelines.md#startswith_266c338) | Creates an expression that checks if a field's value starts with a given prefix. | +| [stringConcat(fieldName, secondString, otherStrings)](./firestore_pipelines.md#stringconcat_d80077e) | Creates an expression that concatenates string functions, fields or constants together. | +| [stringContains(fieldName, substring)](./firestore_pipelines.md#stringcontains_5b94cfe) | Creates an expression that checks if a string field contains a specified substring. | +| [stringContains(fieldName, substring)](./firestore_pipelines.md#stringcontains_ac3ba47) | Creates an expression that checks if a string field contains a substring specified by an expression. | +| [stringIndexOf(fieldName, search)](./firestore_pipelines.md#stringindexof_6c4650e) | Creates an expression that finds the index of the first occurrence of a substring or byte sequence. | +| [stringRepeat(fieldName, repetitions)](./firestore_pipelines.md#stringrepeat_e144a59) | Creates an expression that repeats a string or byte array a specified number of times. | +| [stringReplaceAll(fieldName, find, replacement)](./firestore_pipelines.md#stringreplaceall_b0db15f) | Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. | +| [stringReplaceOne(fieldName, find, replacement)](./firestore_pipelines.md#stringreplaceone_b0db15f) | Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. | +| [subtract(fieldName, expression)](./firestore_pipelines.md#subtract_1e91657) | Creates an expression that subtracts an expression from a field's value. | +| [subtract(fieldName, value)](./firestore_pipelines.md#subtract_65e2f32) | Creates an expression that subtracts a constant value from a field's value. | +| [sum(fieldName)](./firestore_pipelines.md#sum_e5b0480) | Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. | +| [timestampAdd(fieldName, unit, amount)](./firestore_pipelines.md#timestampadd_3b0a297) | Creates an expression that adds a specified amount of time to a timestamp represented by a field. | +| [timestampExtract(fieldName, part, timezone)](./firestore_pipelines.md#timestampextract_a51c205) | Creates an expression that extracts a specified part from a timestamp. | +| [timestampExtract(fieldName, part, timezone)](./firestore_pipelines.md#timestampextract_2d51eac) | Creates an expression that extracts a specified part from a timestamp. | +| [timestampSubtract(fieldName, unit, amount)](./firestore_pipelines.md#timestampsubtract_3b0a297) | Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. | +| [timestampToUnixMicros(fieldName)](./firestore_pipelines.md#timestamptounixmicros_e5b0480) | Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixMillis(fieldName)](./firestore_pipelines.md#timestamptounixmillis_e5b0480) | Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampToUnixSeconds(fieldName)](./firestore_pipelines.md#timestamptounixseconds_e5b0480) | Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). | +| [timestampTruncate(fieldName, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_b6c7512) | Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(fieldName, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_ed83d46) | Creates an expression that truncates a timestamp to a specified granularity. | +| [toLower(fieldName)](./firestore_pipelines.md#tolower_e5b0480) | Creates an expression that converts a string field to lowercase. | +| [toUpper(fieldName)](./firestore_pipelines.md#toupper_e5b0480) | Creates an expression that converts a string field to uppercase. | +| [trim(fieldName, valueToTrim)](./firestore_pipelines.md#trim_c9f90ee) | Creates an expression that removes leading and trailing whitespace from a string or byte array. | +| [trunc(fieldName)](./firestore_pipelines.md#trunc_e5b0480) | Creates an expression that truncates the numeric value of a field to an integer. | +| [trunc(fieldName, decimalPlaces)](./firestore_pipelines.md#trunc_07d0cf0) | Creates an expression that truncates a numeric expression to the specified number of decimal places. | +| [type(fieldName)](./firestore_pipelines.md#type_e5b0480) | Creates an expression that returns the data type of the data in the specified field. | +| [unixMicrosToTimestamp(fieldName)](./firestore_pipelines.md#unixmicrostotimestamp_e5b0480) | Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixMillisToTimestamp(fieldName)](./firestore_pipelines.md#unixmillistotimestamp_e5b0480) | Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [unixSecondsToTimestamp(fieldName)](./firestore_pipelines.md#unixsecondstotimestamp_e5b0480) | Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. | +| [vectorLength(fieldName)](./firestore_pipelines.md#vectorlength_e5b0480) | Creates an expression that calculates the length of a Firestore Vector represented by a field. | | function(first, ...) | -| [add(first, second)](./firestore_pipelines.md#add_846ca1b) | (Public Preview) Creates an expression that adds two expressions together. | -| [and(first, second, more)](./firestore_pipelines.md#and_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'AND' operation on multiple filter conditions. | -| [concat(first, second, others)](./firestore_pipelines.md#concat_83be015) | (Public Preview) Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | -| [logicalMaximum(first, second, others)](./firestore_pipelines.md#logicalmaximum_83be015) | (Public Preview) Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | -| [logicalMinimum(first, second, others)](./firestore_pipelines.md#logicalminimum_83be015) | (Public Preview) Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. | -| [multiply(first, second)](./firestore_pipelines.md#multiply_846ca1b) | (Public Preview) Creates an expression that multiplies two expressions together. | -| [nor(first, second, more)](./firestore_pipelines.md#nor_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'NOR' operation on multiple filter conditions. | -| [or(first, second, more)](./firestore_pipelines.md#or_e0c48bd) | (Public Preview) Creates an expression that performs a logical 'OR' operation on multiple filter conditions. | -| [xor(first, second, additionalConditions)](./firestore_pipelines.md#xor_8197113) | (Public Preview) Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. | +| [add(first, second)](./firestore_pipelines.md#add_846ca1b) | Creates an expression that adds two expressions together. | +| [and(first, second, more)](./firestore_pipelines.md#and_e0c48bd) | Creates an expression that performs a logical 'AND' operation on multiple filter conditions. | +| [concat(first, second, others)](./firestore_pipelines.md#concat_83be015) | Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. | +| [logicalMaximum(first, second, others)](./firestore_pipelines.md#logicalmaximum_83be015) | Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. | +| [logicalMinimum(first, second, others)](./firestore_pipelines.md#logicalminimum_83be015) | Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. | +| [multiply(first, second)](./firestore_pipelines.md#multiply_846ca1b) | Creates an expression that multiplies two expressions together. | +| [nor(first, second, more)](./firestore_pipelines.md#nor_e0c48bd) | Creates an expression that performs a logical 'NOR' operation on multiple filter conditions. | +| [or(first, second, more)](./firestore_pipelines.md#or_e0c48bd) | Creates an expression that performs a logical 'OR' operation on multiple filter conditions. | +| [xor(first, second, additionalConditions)](./firestore_pipelines.md#xor_8197113) | Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. | | function(firstArray, ...) | -| [arrayConcat(firstArray, secondArray, otherArrays)](./firestore_pipelines.md#arrayconcat_c00d5d7) | (Public Preview) Creates an expression that concatenates an array expression with other arrays. | +| [arrayConcat(firstArray, secondArray, otherArrays)](./firestore_pipelines.md#arrayconcat_c00d5d7) | Creates an expression that concatenates an array expression with other arrays. | | function(firstArrayField, ...) | -| [arrayConcat(firstArrayField, secondArray, otherArrays)](./firestore_pipelines.md#arrayconcat_f92063d) | (Public Preview) Creates an expression that concatenates a field's array value with other arrays. | +| [arrayConcat(firstArrayField, secondArray, otherArrays)](./firestore_pipelines.md#arrayconcat_f92063d) | Creates an expression that concatenates a field's array value with other arrays. | | function(firstMap, ...) | -| [mapMerge(firstMap, secondMap, otherMaps)](./firestore_pipelines.md#mapmerge_cfe77ce) | (Public Preview) Creates an expression that merges multiple map values. | +| [mapMerge(firstMap, secondMap, otherMaps)](./firestore_pipelines.md#mapmerge_cfe77ce) | Creates an expression that merges multiple map values. | | function(firstString, ...) | -| [stringConcat(firstString, secondString, otherStrings)](./firestore_pipelines.md#stringconcat_8a8d1b6) | (Public Preview) Creates an expression that concatenates string expressions together. | +| [stringConcat(firstString, secondString, otherStrings)](./firestore_pipelines.md#stringconcat_8a8d1b6) | Creates an expression that concatenates string expressions together. | | function(ifExpr, ...) | -| [ifAbsent(ifExpr, elseExpr)](./firestore_pipelines.md#ifabsent_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | -| [ifAbsent(ifExpr, elseValue)](./firestore_pipelines.md#ifabsent_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | -| [ifNull(ifExpr, elseExpr)](./firestore_pipelines.md#ifnull_0e6d161) | (Public Preview) Creates an expression that returns the elseExpr argument if ifExpr is null, else return the result of the ifExpr argument evaluation. | -| [ifNull(ifExpr, elseValue)](./firestore_pipelines.md#ifnull_c34e5ed) | (Public Preview) Creates an expression that returns the elseValue argument if ifExpr is null, else return the result of the ifExpr argument evaluation. | +| [ifAbsent(ifExpr, elseExpr)](./firestore_pipelines.md#ifabsent_0e6d161) | Creates an expression that returns the elseExpr argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | +| [ifAbsent(ifExpr, elseValue)](./firestore_pipelines.md#ifabsent_c34e5ed) | Creates an expression that returns the elseValue argument if ifExpr is absent, else return the result of the ifExpr argument evaluation. | +| [ifNull(ifExpr, elseExpr)](./firestore_pipelines.md#ifnull_0e6d161) | Creates an expression that returns the elseExpr argument if ifExpr is null, else return the result of the ifExpr argument evaluation. | +| [ifNull(ifExpr, elseValue)](./firestore_pipelines.md#ifnull_c34e5ed) | Creates an expression that returns the elseValue argument if ifExpr is null, else return the result of the ifExpr argument evaluation. | | function(ifFieldName, ...) | -| [ifAbsent(ifFieldName, elseExpr)](./firestore_pipelines.md#ifabsent_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName is absent, else return the value of the field. | -| [ifAbsent(ifFieldName, elseValue)](./firestore_pipelines.md#ifabsent_d8f2823) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName is absent, else return the value of the field. | -| [ifNull(ifFieldName, elseExpr)](./firestore_pipelines.md#ifnull_e6dabea) | (Public Preview) Creates an expression that returns the elseExpr argument if ifFieldName field is null, else return the value of the field. | -| [ifNull(ifFieldName, elseValue)](./firestore_pipelines.md#ifnull_587c2f0) | (Public Preview) Creates an expression that returns the elseValue argument if ifFieldName field is null, else return the value of the field. | +| [ifAbsent(ifFieldName, elseExpr)](./firestore_pipelines.md#ifabsent_e6dabea) | Creates an expression that returns the elseExpr argument if ifFieldName is absent, else return the value of the field. | +| [ifAbsent(ifFieldName, elseValue)](./firestore_pipelines.md#ifabsent_d8f2823) | Creates an expression that returns the elseValue argument if ifFieldName is absent, else return the value of the field. | +| [ifNull(ifFieldName, elseExpr)](./firestore_pipelines.md#ifnull_e6dabea) | Creates an expression that returns the elseExpr argument if ifFieldName field is null, else return the value of the field. | +| [ifNull(ifFieldName, elseValue)](./firestore_pipelines.md#ifnull_587c2f0) | Creates an expression that returns the elseValue argument if ifFieldName field is null, else return the value of the field. | | function(input, ...) | -| [substring(input, position, length)](./firestore_pipelines.md#substring_e6e0aa3) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | -| [substring(input, position, length)](./firestore_pipelines.md#substring_ab56dc6) | (Public Preview) Creates an expression that returns a substring of a string or byte array. | +| [substring(input, position, length)](./firestore_pipelines.md#substring_e6e0aa3) | Creates an expression that returns a substring of a string or byte array. | +| [substring(input, position, length)](./firestore_pipelines.md#substring_ab56dc6) | Creates an expression that returns a substring of a string or byte array. | | function(left, ...) | -| [divide(left, right)](./firestore_pipelines.md#divide_b3c3382) | (Public Preview) Creates an expression that divides two expressions. | -| [equal(left, right)](./firestore_pipelines.md#equal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are equal. | -| [greaterThan(left, right)](./firestore_pipelines.md#greaterthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than the second expression. | -| [greaterThanOrEqual(left, right)](./firestore_pipelines.md#greaterthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is greater than or equal to the second expression. | -| [lessThan(left, right)](./firestore_pipelines.md#lessthan_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than the second expression. | -| [lessThanOrEqual(left, right)](./firestore_pipelines.md#lessthanorequal_b3c3382) | (Public Preview) Creates an expression that checks if the first expression is less than or equal to the second expression. | -| [mod(left, right)](./firestore_pipelines.md#mod_b3c3382) | (Public Preview) Creates an expression that calculates the modulo (remainder) of dividing two expressions. | -| [notEqual(left, right)](./firestore_pipelines.md#notequal_b3c3382) | (Public Preview) Creates an expression that checks if two expressions are not equal. | -| [pipelineResultEqual(left, right)](./firestore_pipelines.md#pipelineresultequal_707a755) | (Public Preview) Test equality of two PipelineResults. | -| [subtract(left, right)](./firestore_pipelines.md#subtract_b3c3382) | (Public Preview) Creates an expression that subtracts two expressions. | +| [divide(left, right)](./firestore_pipelines.md#divide_b3c3382) | Creates an expression that divides two expressions. | +| [equal(left, right)](./firestore_pipelines.md#equal_b3c3382) | Creates an expression that checks if two expressions are equal. | +| [greaterThan(left, right)](./firestore_pipelines.md#greaterthan_b3c3382) | Creates an expression that checks if the first expression is greater than the second expression. | +| [greaterThanOrEqual(left, right)](./firestore_pipelines.md#greaterthanorequal_b3c3382) | Creates an expression that checks if the first expression is greater than or equal to the second expression. | +| [lessThan(left, right)](./firestore_pipelines.md#lessthan_b3c3382) | Creates an expression that checks if the first expression is less than the second expression. | +| [lessThanOrEqual(left, right)](./firestore_pipelines.md#lessthanorequal_b3c3382) | Creates an expression that checks if the first expression is less than or equal to the second expression. | +| [mod(left, right)](./firestore_pipelines.md#mod_b3c3382) | Creates an expression that calculates the modulo (remainder) of dividing two expressions. | +| [notEqual(left, right)](./firestore_pipelines.md#notequal_b3c3382) | Creates an expression that checks if two expressions are not equal. | +| [pipelineResultEqual(left, right)](./firestore_pipelines.md#pipelineresultequal_707a755) | Test equality of two PipelineResults. | +| [subtract(left, right)](./firestore_pipelines.md#subtract_b3c3382) | Creates an expression that subtracts two expressions. | | function(mapExpr, ...) | -| [mapRemove(mapExpr, key)](./firestore_pipelines.md#mapremove_23c7d51) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. | -| [mapRemove(mapExpr, keyExpr)](./firestore_pipelines.md#mapremove_9fbcaa3) | (Public Preview) Creates an expression that removes a key from the map produced by evaluating an expression. | +| [mapRemove(mapExpr, key)](./firestore_pipelines.md#mapremove_23c7d51) | Creates an expression that removes a key from the map produced by evaluating an expression. | +| [mapRemove(mapExpr, keyExpr)](./firestore_pipelines.md#mapremove_9fbcaa3) | Creates an expression that removes a key from the map produced by evaluating an expression. | | function(mapExpression, ...) | -| [mapEntries(mapExpression)](./firestore_pipelines.md#mapentries_9cf124c) | (Public Preview) 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" }, ...]. | -| [mapGet(mapExpression, subField)](./firestore_pipelines.md#mapget_688c050) | (Public Preview) Accesses a value from a map (object) expression using the provided key. | -| [mapKeys(mapExpression)](./firestore_pipelines.md#mapkeys_9cf124c) | (Public Preview) Creates an expression that returns the keys of a map. | -| [mapSet(mapExpression, key, value, moreKeyValues)](./firestore_pipelines.md#mapset_45b48ff) | (Public Preview) Creates an expression that returns a new map with the specified entries added or updated. | -| [mapValues(mapExpression)](./firestore_pipelines.md#mapvalues_9cf124c) | (Public Preview) Creates an expression that returns the values of a map. | +| [mapEntries(mapExpression)](./firestore_pipelines.md#mapentries_9cf124c) | 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" }, ...]. | +| [mapGet(mapExpression, subField)](./firestore_pipelines.md#mapget_688c050) | Accesses a value from a map (object) expression using the provided key. | +| [mapKeys(mapExpression)](./firestore_pipelines.md#mapkeys_9cf124c) | Creates an expression that returns the keys of a map. | +| [mapSet(mapExpression, key, value, moreKeyValues)](./firestore_pipelines.md#mapset_45b48ff) | Creates an expression that returns a new map with the specified entries added or updated. | +| [mapValues(mapExpression)](./firestore_pipelines.md#mapvalues_9cf124c) | Creates an expression that returns the values of a map. | | function(mapField, ...) | -| [mapEntries(mapField)](./firestore_pipelines.md#mapentries_83ad836) | (Public Preview) 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" }, ...]. | -| [mapKeys(mapField)](./firestore_pipelines.md#mapkeys_83ad836) | (Public Preview) Creates an expression that returns the keys of a map. | -| [mapMerge(mapField, secondMap, otherMaps)](./firestore_pipelines.md#mapmerge_70a564b) | (Public Preview) Creates an expression that merges multiple map values. | -| [mapRemove(mapField, key)](./firestore_pipelines.md#mapremove_bd5726e) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. | -| [mapRemove(mapField, keyExpr)](./firestore_pipelines.md#mapremove_8406d13) | (Public Preview) Creates an expression that removes a key from the map at the specified field name. | -| [mapSet(mapField, key, value, moreKeyValues)](./firestore_pipelines.md#mapset_baadc2a) | (Public Preview) Creates an expression that returns a new map with the specified entries added or updated. | -| [mapValues(mapField)](./firestore_pipelines.md#mapvalues_83ad836) | (Public Preview) Creates an expression that returns the values of a map. | +| [mapEntries(mapField)](./firestore_pipelines.md#mapentries_83ad836) | 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" }, ...]. | +| [mapKeys(mapField)](./firestore_pipelines.md#mapkeys_83ad836) | Creates an expression that returns the keys of a map. | +| [mapMerge(mapField, secondMap, otherMaps)](./firestore_pipelines.md#mapmerge_70a564b) | Creates an expression that merges multiple map values. | +| [mapRemove(mapField, key)](./firestore_pipelines.md#mapremove_bd5726e) | Creates an expression that removes a key from the map at the specified field name. | +| [mapRemove(mapField, keyExpr)](./firestore_pipelines.md#mapremove_8406d13) | Creates an expression that removes a key from the map at the specified field name. | +| [mapSet(mapField, key, value, moreKeyValues)](./firestore_pipelines.md#mapset_baadc2a) | Creates an expression that returns a new map with the specified entries added or updated. | +| [mapValues(mapField)](./firestore_pipelines.md#mapvalues_83ad836) | Creates an expression that returns the values of a map. | | function(name, ...) | -| [field(name)](./firestore_pipelines.md#field_1eaaff4) | (Public Preview) Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). | +| [field(name)](./firestore_pipelines.md#field_1eaaff4) | Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). | | function(options, ...) | -| [execute(options)](./firestore_pipelines.md#execute_9e87e31) | (Public Preview) Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:

    • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
    • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
    • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
    | +| [execute(options)](./firestore_pipelines.md#execute_9e87e31) | Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:
    • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
    • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
    • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
    | | function(path, ...) | -| [field(path)](./firestore_pipelines.md#field_34ee07d) | (Public Preview) Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. | +| [field(path)](./firestore_pipelines.md#field_34ee07d) | Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. | | function(pipeline, ...) | -| [execute(pipeline)](./firestore_pipelines.md#execute_01df620) | (Public Preview) Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:
    • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
    • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
    • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
    | +| [execute(pipeline)](./firestore_pipelines.md#execute_01df620) | Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:
    • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
    • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
    • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
    | | function(stringExpression, ...) | -| [charLength(stringExpression)](./firestore_pipelines.md#charlength_c25a54a) | (Public Preview) Creates an expression that calculates the character length of a string expression in UTF-8. | -| [endsWith(stringExpression, suffix)](./firestore_pipelines.md#endswith_0a0b889) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. | -| [endsWith(stringExpression, suffix)](./firestore_pipelines.md#endswith_13aee0d) | (Public Preview) Creates an expression that checks if a string expression ends with a given postfix. | -| [like(stringExpression, pattern)](./firestore_pipelines.md#like_a84c581) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. | -| [like(stringExpression, pattern)](./firestore_pipelines.md#like_b534848) | (Public Preview) Creates an expression that performs a case-sensitive wildcard string comparison. | -| [regexContains(stringExpression, pattern)](./firestore_pipelines.md#regexcontains_a84c581) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. | -| [regexContains(stringExpression, pattern)](./firestore_pipelines.md#regexcontains_b534848) | (Public Preview) Creates an expression that checks if a string expression contains a specified regular expression as a substring. | -| [regexFind(stringExpression, pattern)](./firestore_pipelines.md#regexfind_a84c581) | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFind(stringExpression, pattern)](./firestore_pipelines.md#regexfind_b534848) | (Public Preview) Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFindAll(stringExpression, pattern)](./firestore_pipelines.md#regexfindall_a84c581) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexFindAll(stringExpression, pattern)](./firestore_pipelines.md#regexfindall_b534848) | (Public Preview) Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | -| [regexMatch(stringExpression, pattern)](./firestore_pipelines.md#regexmatch_a84c581) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. | -| [regexMatch(stringExpression, pattern)](./firestore_pipelines.md#regexmatch_b534848) | (Public Preview) Creates an expression that checks if a string expression matches a specified regular expression. | -| [reverse(stringExpression)](./firestore_pipelines.md#reverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. | -| [startsWith(stringExpression, prefix)](./firestore_pipelines.md#startswith_75c3dbb) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. | -| [startsWith(stringExpression, prefix)](./firestore_pipelines.md#startswith_52f218a) | (Public Preview) Creates an expression that checks if a string expression starts with a given prefix. | -| [stringContains(stringExpression, substring)](./firestore_pipelines.md#stringcontains_3e9ff32) | (Public Preview) Creates an expression that checks if a string expression contains a specified substring. | -| [stringContains(stringExpression, substring)](./firestore_pipelines.md#stringcontains_cc6ee02) | (Public Preview) Creates an expression that checks if a string expression contains a substring specified by another expression. | -| [stringReverse(stringExpression)](./firestore_pipelines.md#stringreverse_c25a54a) | (Public Preview) Creates an expression that reverses a string. | -| [toLower(stringExpression)](./firestore_pipelines.md#tolower_c25a54a) | (Public Preview) Creates an expression that converts a string expression to lowercase. | -| [toUpper(stringExpression)](./firestore_pipelines.md#toupper_c25a54a) | (Public Preview) Creates an expression that converts a string expression to uppercase. | -| [trim(stringExpression, valueToTrim)](./firestore_pipelines.md#trim_dd54322) | (Public Preview) Creates an expression that removes leading and trailing characters from a string or byte array expression. | +| [charLength(stringExpression)](./firestore_pipelines.md#charlength_c25a54a) | Creates an expression that calculates the character length of a string expression in UTF-8. | +| [endsWith(stringExpression, suffix)](./firestore_pipelines.md#endswith_0a0b889) | Creates an expression that checks if a string expression ends with a given postfix. | +| [endsWith(stringExpression, suffix)](./firestore_pipelines.md#endswith_13aee0d) | Creates an expression that checks if a string expression ends with a given postfix. | +| [like(stringExpression, pattern)](./firestore_pipelines.md#like_a84c581) | Creates an expression that performs a case-sensitive wildcard string comparison. | +| [like(stringExpression, pattern)](./firestore_pipelines.md#like_b534848) | Creates an expression that performs a case-sensitive wildcard string comparison. | +| [regexContains(stringExpression, pattern)](./firestore_pipelines.md#regexcontains_a84c581) | Creates an expression that checks if a string expression contains a specified regular expression as a substring. | +| [regexContains(stringExpression, pattern)](./firestore_pipelines.md#regexcontains_b534848) | Creates an expression that checks if a string expression contains a specified regular expression as a substring. | +| [regexFind(stringExpression, pattern)](./firestore_pipelines.md#regexfind_a84c581) | Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFind(stringExpression, pattern)](./firestore_pipelines.md#regexfind_b534848) | Creates an expression that returns the first substring of a string expression that matches a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(stringExpression, pattern)](./firestore_pipelines.md#regexfindall_a84c581) | Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexFindAll(stringExpression, pattern)](./firestore_pipelines.md#regexfindall_b534848) | Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression.This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. | +| [regexMatch(stringExpression, pattern)](./firestore_pipelines.md#regexmatch_a84c581) | Creates an expression that checks if a string expression matches a specified regular expression. | +| [regexMatch(stringExpression, pattern)](./firestore_pipelines.md#regexmatch_b534848) | Creates an expression that checks if a string expression matches a specified regular expression. | +| [reverse(stringExpression)](./firestore_pipelines.md#reverse_c25a54a) | Creates an expression that reverses a string. | +| [startsWith(stringExpression, prefix)](./firestore_pipelines.md#startswith_75c3dbb) | Creates an expression that checks if a string expression starts with a given prefix. | +| [startsWith(stringExpression, prefix)](./firestore_pipelines.md#startswith_52f218a) | Creates an expression that checks if a string expression starts with a given prefix. | +| [stringContains(stringExpression, substring)](./firestore_pipelines.md#stringcontains_3e9ff32) | Creates an expression that checks if a string expression contains a specified substring. | +| [stringContains(stringExpression, substring)](./firestore_pipelines.md#stringcontains_cc6ee02) | Creates an expression that checks if a string expression contains a substring specified by another expression. | +| [stringReverse(stringExpression)](./firestore_pipelines.md#stringreverse_c25a54a) | Creates an expression that reverses a string. | +| [toLower(stringExpression)](./firestore_pipelines.md#tolower_c25a54a) | Creates an expression that converts a string expression to lowercase. | +| [toUpper(stringExpression)](./firestore_pipelines.md#toupper_c25a54a) | Creates an expression that converts a string expression to uppercase. | +| [trim(stringExpression, valueToTrim)](./firestore_pipelines.md#trim_dd54322) | Creates an expression that removes leading and trailing characters from a string or byte array expression. | | function(timestamp, ...) | -| [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_98418f9) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | -| [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_06ef927) | (Public Preview) Creates an expression that adds a specified amount of time to a timestamp. | -| [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_98418f9) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | -| [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_06ef927) | (Public Preview) Creates an expression that subtracts a specified amount of time from a timestamp. | +| [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_98418f9) | Creates an expression that adds a specified amount of time to a timestamp. | +| [timestampAdd(timestamp, unit, amount)](./firestore_pipelines.md#timestampadd_06ef927) | Creates an expression that adds a specified amount of time to a timestamp. | +| [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_98418f9) | Creates an expression that subtracts a specified amount of time from a timestamp. | +| [timestampSubtract(timestamp, unit, amount)](./firestore_pipelines.md#timestampsubtract_06ef927) | Creates an expression that subtracts a specified amount of time from a timestamp. | | function(timestampExpression, ...) | -| [timestampExtract(timestampExpression, part, timezone)](./firestore_pipelines.md#timestampextract_b2f8f48) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | -| [timestampExtract(timestampExpression, part, timezone)](./firestore_pipelines.md#timestampextract_73e0311) | (Public Preview) Creates an expression that extracts a specified part from a timestamp. | -| [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_ad5d843) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | -| [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_d6ab2a4) | (Public Preview) Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampExtract(timestampExpression, part, timezone)](./firestore_pipelines.md#timestampextract_b2f8f48) | Creates an expression that extracts a specified part from a timestamp. | +| [timestampExtract(timestampExpression, part, timezone)](./firestore_pipelines.md#timestampextract_73e0311) | Creates an expression that extracts a specified part from a timestamp. | +| [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_ad5d843) | Creates an expression that truncates a timestamp to a specified granularity. | +| [timestampTruncate(timestampExpression, granularity, timezone)](./firestore_pipelines.md#timestamptruncate_d6ab2a4) | Creates an expression that truncates a timestamp to a specified granularity. | | function(tryExpr, ...) | -| [ifError(tryExpr, catchExpr)](./firestore_pipelines.md#iferror_a99a327) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation.This overload is useful when a BooleanExpression is required. | -| [ifError(tryExpr, catchExpr)](./firestore_pipelines.md#iferror_756c12e) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. | -| [ifError(tryExpr, catchValue)](./firestore_pipelines.md#iferror_dc532f9) | (Public Preview) Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. | +| [ifError(tryExpr, catchExpr)](./firestore_pipelines.md#iferror_a99a327) | Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation.This overload is useful when a BooleanExpression is required. | +| [ifError(tryExpr, catchExpr)](./firestore_pipelines.md#iferror_756c12e) | Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. | +| [ifError(tryExpr, catchValue)](./firestore_pipelines.md#iferror_dc532f9) | Creates an expression that returns the catch argument if there is an error, else return the result of the try argument evaluation. | | function(value, ...) | -| [constant(value)](./firestore_pipelines.md#constant_0c00f91) | (Public Preview) Creates a Constant instance for a number value. | -| [constant(value)](./firestore_pipelines.md#constant_6dac335) | (Public Preview) Creates a Constant instance for a VectorValue value. | -| [constant(value)](./firestore_pipelines.md#constant_7c807cd) | (Public Preview) Creates a Constant instance for a string value. | -| [constant(value)](./firestore_pipelines.md#constant_b2e4f8d) | (Public Preview) Creates a BooleanExpression instance for a boolean value. | -| [constant(value)](./firestore_pipelines.md#constant_73ebd84) | (Public Preview) Creates a Constant instance for a null value. | -| [constant(value)](./firestore_pipelines.md#constant_72a76cb) | (Public Preview) Creates a Constant instance for a GeoPoint value. | -| [constant(value)](./firestore_pipelines.md#constant_000477d) | (Public Preview) Creates a Constant instance for a Timestamp value. | -| [constant(value)](./firestore_pipelines.md#constant_5131bf7) | (Public Preview) Creates a Constant instance for a Date value. | -| [constant(value)](./firestore_pipelines.md#constant_fdf565d) | (Public Preview) Creates a Constant instance for a Bytes value. | -| [constant(value)](./firestore_pipelines.md#constant_bcd2b0b) | (Public Preview) Creates a Constant instance for a DocumentReference value. | -| [exists(value)](./firestore_pipelines.md#exists_f3daf14) | (Public Preview) Creates an expression that checks if a field exists. | -| [isAbsent(value)](./firestore_pipelines.md#isabsent_f3daf14) | (Public Preview) Creates an expression that returns true if a value is absent. Otherwise, returns false even if the value is null. | -| [isError(value)](./firestore_pipelines.md#iserror_f3daf14) | (Public Preview) Creates an expression that checks if a given expression produces an error. | +| [constant(value)](./firestore_pipelines.md#constant_0c00f91) | Creates a Constant instance for a number value. | +| [constant(value)](./firestore_pipelines.md#constant_6dac335) | Creates a Constant instance for a VectorValue value. | +| [constant(value)](./firestore_pipelines.md#constant_7c807cd) | Creates a Constant instance for a string value. | +| [constant(value)](./firestore_pipelines.md#constant_b2e4f8d) | Creates a BooleanExpression instance for a boolean value. | +| [constant(value)](./firestore_pipelines.md#constant_73ebd84) | Creates a Constant instance for a null value. | +| [constant(value)](./firestore_pipelines.md#constant_72a76cb) | Creates a Constant instance for a GeoPoint value. | +| [constant(value)](./firestore_pipelines.md#constant_000477d) | Creates a Constant instance for a Timestamp value. | +| [constant(value)](./firestore_pipelines.md#constant_5131bf7) | Creates a Constant instance for a Date value. | +| [constant(value)](./firestore_pipelines.md#constant_fdf565d) | Creates a Constant instance for a Bytes value. | +| [constant(value)](./firestore_pipelines.md#constant_bcd2b0b) | Creates a Constant instance for a DocumentReference value. | +| [exists(value)](./firestore_pipelines.md#exists_f3daf14) | Creates an expression that checks if a field exists. | +| [isAbsent(value)](./firestore_pipelines.md#isabsent_f3daf14) | Creates an expression that returns true if a value is absent. Otherwise, returns false even if the value is null. | +| [isError(value)](./firestore_pipelines.md#iserror_f3daf14) | Creates an expression that checks if a given expression produces an error. | | function(vectorExpression, ...) | -| [cosineDistance(vectorExpression, vector)](./firestore_pipelines.md#cosinedistance_3a80317) | (Public Preview) Calculates the Cosine distance between a vector expression and a vector literal. | -| [cosineDistance(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#cosinedistance_17b5bcc) | (Public Preview) Calculates the Cosine distance between two vector expressions. | -| [dotProduct(vectorExpression, vector)](./firestore_pipelines.md#dotproduct_3a80317) | (Public Preview) Calculates the dot product between a vector expression and a double array. | -| [dotProduct(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#dotproduct_17b5bcc) | (Public Preview) Calculates the dot product between two vector expressions. | -| [euclideanDistance(vectorExpression, vector)](./firestore_pipelines.md#euclideandistance_3a80317) | (Public Preview) Calculates the Euclidean distance between a vector expression and a double array. | -| [euclideanDistance(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#euclideandistance_17b5bcc) | (Public Preview) Calculates the Euclidean distance between two vector expressions. | -| [vectorLength(vectorExpression)](./firestore_pipelines.md#vectorlength_58a039b) | (Public Preview) Creates an expression that calculates the length of a Firestore Vector. | +| [cosineDistance(vectorExpression, vector)](./firestore_pipelines.md#cosinedistance_3a80317) | Calculates the Cosine distance between a vector expression and a vector literal. | +| [cosineDistance(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#cosinedistance_17b5bcc) | Calculates the Cosine distance between two vector expressions. | +| [dotProduct(vectorExpression, vector)](./firestore_pipelines.md#dotproduct_3a80317) | Calculates the dot product between a vector expression and a double array. | +| [dotProduct(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#dotproduct_17b5bcc) | Calculates the dot product between two vector expressions. | +| [euclideanDistance(vectorExpression, vector)](./firestore_pipelines.md#euclideandistance_3a80317) | Calculates the Euclidean distance between a vector expression and a double array. | +| [euclideanDistance(vectorExpression, otherVectorExpression)](./firestore_pipelines.md#euclideandistance_17b5bcc) | Calculates the Euclidean distance between two vector expressions. | +| [vectorLength(vectorExpression)](./firestore_pipelines.md#vectorlength_58a039b) | Creates an expression that calculates the length of a Firestore Vector. | ## Classes | Class | Description | | --- | --- | -| [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) | (Public Preview) A class that represents an aggregate function. | -| [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) | (Public Preview) An AggregateFunction with alias. | -| [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class) | (Public Preview) | -| [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | (Public Preview) An interface that represents a filter condition. | +| [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) | A class that represents an aggregate function. | +| [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) | An AggregateFunction with alias. | +| [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class) | | +| [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | An interface that represents a filter condition. | | [Bytes](./firestore_pipelines.bytes.md#bytes_class) | An immutable object representing an array of bytes. | | [CollectionReference](./firestore_pipelines.collectionreference.md#collectionreference_class) | A CollectionReference object can be used for adding documents, getting document references, and querying for documents (using [query()](./firestore_.md#query_9f7b0f4)). | | [DocumentReference](./firestore_pipelines.documentreference.md#documentreference_class) | A DocumentReference refers to a document location in a Firestore database and can be used to write, read, or listen to the location. The document at the referenced location may or may not exist. | | [DocumentSnapshot](./firestore_pipelines.documentsnapshot.md#documentsnapshot_class) | A DocumentSnapshot contains data read from a document in your Firestore database. The data can be extracted with .data() or .get(<field>) to get a specific field.For a DocumentSnapshot that points to a non-existing document, any data access will return 'undefined'. You can use the exists() method to explicitly verify a document's existence. | -| [Expression](./firestore_pipelines.expression.md#expression_class) | (Public Preview) Represents an expression that can be evaluated to a value within the execution of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class).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. | -| [Field](./firestore_pipelines.field.md#field_class) | (Public Preview) Represents a reference to a field in a Firestore document, or outputs of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) stage.

    Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines.

    You can create a Field instance using the static method: | +| [Expression](./firestore_pipelines.expression.md#expression_class) | Represents an expression that can be evaluated to a value within the execution of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class).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. | +| [Field](./firestore_pipelines.field.md#field_class) | Represents a reference to a field in a Firestore document, or outputs of a [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) stage.

    Field references are used to access document field values in expressions and to specify fields for sorting, filtering, and projecting data in Firestore pipelines.

    You can create a Field instance using the static method: | | [FieldPath](./firestore_pipelines.fieldpath.md#fieldpath_class) | A FieldPath refers to a field in a document. The path may consist of a single field name (referring to a top-level field in the document), or a list of field names (referring to a nested field in the document).Create a FieldPath by providing field names. If more than one field name is provided, the path will point to a nested field in a document. | | [FieldValue](./firestore_pipelines.fieldvalue.md#fieldvalue_class) | Sentinel values that can be used when writing document fields with set() or update(). | | [Firestore](./firestore_pipelines.firestore.md#firestore_class) | The Cloud Firestore service interface.Do not call this constructor directly. Instead, use [getFirestore()](./firestore_.md#getfirestore). | -| [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) | (Public Preview) This class defines the base class for Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) functions, which can be evaluated within pipeline execution.Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_pipelines.md#and_e0c48bd), [equal()](./firestore_pipelines.md#equal_b3c3382), or the methods on [Expression](./firestore_pipelines.expression.md#expression_class) ([Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), etc.) to construct new Function instances. | +| [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) | This class defines the base class for Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) functions, which can be evaluated within pipeline execution.Typically, you would not use this class or its children directly. Use either the functions like [and()](./firestore_pipelines.md#and_e0c48bd), [equal()](./firestore_pipelines.md#equal_b3c3382), or the methods on [Expression](./firestore_pipelines.expression.md#expression_class) ([Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), etc.) to construct new Function instances. | | [GeoPoint](./firestore_pipelines.geopoint.md#geopoint_class) | An immutable object representing a geographic location in Firestore. The location is represented as latitude/longitude pair.Latitude values are in the range of \[-90, 90\]. Longitude values are in the range of \[-180, 180\]. | -| [Ordering](./firestore_pipelines.ordering.md#ordering_class) | (Public Preview) Represents an ordering criterion for sorting documents in a Firestore pipeline.You create Ordering instances using the ascending and descending helper functions. | -| [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | (Public Preview) | -| [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) | (Public Preview) A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the [PipelineResult.data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) or [PipelineResult.get()](./firestore_pipelines.pipelineresult.md#pipelineresultget) methods.

    If the PipelineResult represents a non-document result, ref will return a undefined value. | -| [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) | (Public Preview) Represents the results of a Firestore pipeline execution.A PipelineSnapshot contains zero or more [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. | -| [PipelineSource](./firestore_pipelines.pipelinesource.md#pipelinesource_class) | (Public Preview) Provides the entry point for defining the data source of a Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class).Use the methods of this class (e.g., [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection), [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup), [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase), or [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments)) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. | +| [Ordering](./firestore_pipelines.ordering.md#ordering_class) | Represents an ordering criterion for sorting documents in a Firestore pipeline.You create Ordering instances using the ascending and descending helper functions. | +| [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | | +| [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) | A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the [PipelineResult.data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) or [PipelineResult.get()](./firestore_pipelines.pipelineresult.md#pipelineresultget) methods.

    If the PipelineResult represents a non-document result, ref will return a undefined value. | +| [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) | Represents the results of a Firestore pipeline execution.A PipelineSnapshot contains zero or more [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. | +| [PipelineSource](./firestore_pipelines.pipelinesource.md#pipelinesource_class) | Provides the entry point for defining the data source of a Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class).Use the methods of this class (e.g., [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection), [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup), [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase), or [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments)) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. | | [Query](./firestore_pipelines.query.md#query_class) | A Query refers to a query which you can read or listen to. You can also construct refined Query objects by adding filters and ordering. | | [QueryDocumentSnapshot](./firestore_pipelines.querydocumentsnapshot.md#querydocumentsnapshot_class) | A QueryDocumentSnapshot contains data read from a document in your Firestore database as part of a query. The document is guaranteed to exist and its data can be extracted with .data() or .get(<field>) to get a specific field.A QueryDocumentSnapshot offers the same API surface as a DocumentSnapshot. Since query results contain only existing documents, the exists property will always be true and data() will never return 'undefined'. | | [SnapshotMetadata](./firestore_pipelines.snapshotmetadata.md#snapshotmetadata_class) | Metadata about a snapshot, describing the state of the snapshot. | @@ -439,51 +439,48 @@ https://github.com/firebase/firebase-js-sdk | --- | --- | | [DocumentData](./firestore_pipelines.documentdata.md#documentdata_interface) | Document data (for use with [setDoc()](./firestore_lite.md#setdoc_ee215ad)) consists of fields mapped to values. | | [FirestoreDataConverter](./firestore_pipelines.firestoredataconverter.md#firestoredataconverter_interface) | Converter used by withConverter() to transform user objects of type AppModelType into Firestore data of type DbModelType.Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore.In this context, an "AppModel" is a class that is used in an application to package together related information and functionality. Such a class could, for example, have properties with complex, nested data types, properties used for memoization, properties of types not supported by Firestore (such as symbol and bigint), and helper functions that perform compound operations. Such classes are not suitable and/or possible to store into a Firestore database. Instead, instances of such classes need to be converted to "plain old JavaScript objects" (POJOs) with exclusively primitive properties, potentially nested inside other POJOs or arrays of POJOs. In this context, this type is referred to as the "DbModel" and would be an object suitable for persisting into Firestore. For convenience, applications can implement FirestoreDataConverter and register the converter with Firestore objects, such as DocumentReference or Query, to automatically convert AppModel to DbModel when storing into Firestore, and convert DbModel to AppModel when retrieving from Firestore. | -| [PipelineExecuteOptions](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptions_interface) | (Public Preview) Options defining Pipeline execution. | -| [Selectable](./firestore_pipelines.selectable.md#selectable_interface) | (Public Preview) An interface that represents a selectable expression. | +| [PipelineExecuteOptions](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptions_interface) | Options defining Pipeline execution. | +| [Selectable](./firestore_pipelines.selectable.md#selectable_interface) | An interface that represents a selectable expression. | | [SnapshotOptions](./firestore_pipelines.snapshotoptions.md#snapshotoptions_interface) | Options that configure how data is retrieved from a DocumentSnapshot (for example the desired behavior for server timestamps that have not yet been set to their final value). | -| [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) | (Public Preview) Options defining how a Stage is evaluated. | +| [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) | Options defining how a Stage is evaluated. | ## Type Aliases | Type Alias | Description | | --- | --- | -| [AddFieldsStageOptions](./firestore_pipelines.md#addfieldsstageoptions) | (Public Preview) Options defining how an AddFieldsStage is evaluated. See [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields). | -| [AggregateStageOptions](./firestore_pipelines.md#aggregatestageoptions) | (Public Preview) Options defining how an AggregateStage is evaluated. See [Pipeline.aggregate()](./firestore_pipelines.pipeline.md#pipelineaggregate). | -| [CollectionGroupStageOptions](./firestore_pipelines.md#collectiongroupstageoptions) | (Public Preview) Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution.See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. | -| [CollectionStageOptions](./firestore_pipelines.md#collectionstageoptions) | (Public Preview) Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). | -| [DatabaseStageOptions](./firestore_pipelines.md#databasestageoptions) | (Public Preview) Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). | -| [DistinctStageOptions](./firestore_pipelines.md#distinctstageoptions) | (Public Preview) Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). | -| [DocumentsStageOptions](./firestore_pipelines.md#documentsstageoptions) | (Public Preview) Options defining how a DocumentsStage is evaluated. See [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments). | -| [ExpressionType](./firestore_pipelines.md#expressiontype) | (Public Preview) An enumeration of the different types of expressions. | -| [FindNearestStageOptions](./firestore_pipelines.md#findneareststageoptions) | (Public Preview) Options defining how a FindNearestStage is evaluated. See [Pipeline.findNearest()](./firestore_pipelines.pipeline.md#pipelinefindnearest). | -| [LimitStageOptions](./firestore_pipelines.md#limitstageoptions) | (Public Preview) Options defining how a LimitStage is evaluated. See [Pipeline.limit()](./firestore_pipelines.pipeline.md#pipelinelimit). | -| [OffsetStageOptions](./firestore_pipelines.md#offsetstageoptions) | (Public Preview) Options defining how an OffsetStage is evaluated. See [Pipeline.offset()](./firestore_pipelines.pipeline.md#pipelineoffset). | -| [OneOf](./firestore_pipelines.md#oneof) | (Public Preview) Utility type to create an type that only allows one property of the Type param T to be set. | +| [AddFieldsStageOptions](./firestore_pipelines.md#addfieldsstageoptions) | Options defining how an AddFieldsStage is evaluated. See [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields). | +| [AggregateStageOptions](./firestore_pipelines.md#aggregatestageoptions) | Options defining how an AggregateStage is evaluated. See [Pipeline.aggregate()](./firestore_pipelines.pipeline.md#pipelineaggregate). | +| [CollectionGroupStageOptions](./firestore_pipelines.md#collectiongroupstageoptions) | Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution.See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. | +| [CollectionStageOptions](./firestore_pipelines.md#collectionstageoptions) | Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). | +| [DatabaseStageOptions](./firestore_pipelines.md#databasestageoptions) | Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). | +| [DistinctStageOptions](./firestore_pipelines.md#distinctstageoptions) | Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). | +| [DocumentsStageOptions](./firestore_pipelines.md#documentsstageoptions) | Options defining how a DocumentsStage is evaluated. See [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments). | +| [ExpressionType](./firestore_pipelines.md#expressiontype) | An enumeration of the different types of expressions. | +| [FindNearestStageOptions](./firestore_pipelines.md#findneareststageoptions) | Options defining how a FindNearestStage is evaluated. See [Pipeline.findNearest()](./firestore_pipelines.pipeline.md#pipelinefindnearest). | +| [LimitStageOptions](./firestore_pipelines.md#limitstageoptions) | Options defining how a LimitStage is evaluated. See [Pipeline.limit()](./firestore_pipelines.pipeline.md#pipelinelimit). | +| [OffsetStageOptions](./firestore_pipelines.md#offsetstageoptions) | Options defining how an OffsetStage is evaluated. See [Pipeline.offset()](./firestore_pipelines.pipeline.md#pipelineoffset). | +| [OneOf](./firestore_pipelines.md#oneof) | Utility type to create an type that only allows one property of the Type param T to be set. | | [PartialWithFieldValue](./firestore_pipelines.md#partialwithfieldvalue) | Similar to TypeScript's Partial<T>, but allows nested fields to be omitted and FieldValues to be passed in as property values. | | [Primitive](./firestore_pipelines.md#primitive) | Primitive types. | -| [RemoveFieldsStageOptions](./firestore_pipelines.md#removefieldsstageoptions) | (Public Preview) Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). | -| [ReplaceWithStageOptions](./firestore_pipelines.md#replacewithstageoptions) | (Public Preview) Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). | -| [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) | (Public Preview) Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied.See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. | -| [SelectStageOptions](./firestore_pipelines.md#selectstageoptions) | (Public Preview) Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). | +| [RemoveFieldsStageOptions](./firestore_pipelines.md#removefieldsstageoptions) | Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). | +| [ReplaceWithStageOptions](./firestore_pipelines.md#replacewithstageoptions) | Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). | +| [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) | Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied.See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. | +| [SelectStageOptions](./firestore_pipelines.md#selectstageoptions) | Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). | | [SetOptions](./firestore_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | -| [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | (Public Preview) Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | -| [TimeGranularity](./firestore_pipelines.md#timegranularity) | (Public Preview) Specify time granularity for expressions. | -| [TimePart](./firestore_pipelines.md#timepart) | (Public Preview) Specify time parts for timestampExtract expressions. | -| [TimeUnit](./firestore_pipelines.md#timeunit) | (Public Preview) Specify time units for expressions. | -| [Type](./firestore_pipelines.md#type) | (Public Preview) An enumeration of the different types generated by the Firestore backend.

    • Numerics evaluate directly to backend representation (int64 or float64), not JS number.
    • JavaScript Date and firestore Timestamp objects strictly evaluate to 'timestamp'.
    • Advanced configurations parsing backend types (such as decimal128, max_key or min_key from BSON) are also incorporated in this union string type. Note that decimal128 is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    | -| [UnionStageOptions](./firestore_pipelines.md#unionstageoptions) | (Public Preview) Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | -| [UnnestStageOptions](./firestore_pipelines.md#unneststageoptions) | (Public Preview) Represents the specific options available for configuring an UnnestStage within a pipeline. | -| [WhereStageOptions](./firestore_pipelines.md#wherestageoptions) | (Public Preview) Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). | +| [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | +| [TimeGranularity](./firestore_pipelines.md#timegranularity) | Specify time granularity for expressions. | +| [TimePart](./firestore_pipelines.md#timepart) | Specify time parts for timestampExtract expressions. | +| [TimeUnit](./firestore_pipelines.md#timeunit) | Specify time units for expressions. | +| [Type](./firestore_pipelines.md#type) | An enumeration of the different types generated by the Firestore backend.
    • Numerics evaluate directly to backend representation (int64 or float64), not JS number.
    • JavaScript Date and firestore Timestamp objects strictly evaluate to 'timestamp'.
    • Advanced configurations parsing backend types (such as decimal128, max_key or min_key from BSON) are also incorporated in this union string type. Note that decimal128 is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    | +| [UnionStageOptions](./firestore_pipelines.md#unionstageoptions) | Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | +| [UnnestStageOptions](./firestore_pipelines.md#unneststageoptions) | Represents the specific options available for configuring an UnnestStage within a pipeline. | +| [WhereStageOptions](./firestore_pipelines.md#wherestageoptions) | Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). | | [WithFieldValue](./firestore_pipelines.md#withfieldvalue) | Allows FieldValues to be passed in as a property value while maintaining type safety. | ## function() ### countAll() {:#countall} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the total number of stage inputs. Signature: @@ -508,9 +505,6 @@ countAll().as("totalDocument"); ### currentTimestamp() {:#currenttimestamp} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to the current server timestamp. Signature: @@ -535,9 +529,6 @@ currentTimestamp() ### rand() {:#rand} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. Signature: @@ -564,9 +555,6 @@ rand(); ### arrayContains(array, element) {:#arraycontains_a00ea48} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array expression contains a specific element. Signature: @@ -599,9 +587,6 @@ arrayContains(field("colors"), field("selectedColor")); ### arrayContains(array, element) {:#arraycontains_7328608} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array expression contains a specific element. Signature: @@ -634,9 +619,6 @@ arrayContains(field("colors"), "red"); ### arrayContainsAll(array, values) {:#arraycontainsall_c658ad5} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array expression contains all the specified elements. Signature: @@ -669,9 +651,6 @@ arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]) ### arrayContainsAll(array, arrayExpression) {:#arraycontainsall_7b535db} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array expression contains all the specified elements. Signature: @@ -704,9 +683,6 @@ arrayContainsAll(field("tags"), [field("tag1"), constant("SciFi"), "Adventure"]) ### arrayContainsAny(array, values) {:#arraycontainsany_c658ad5} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array expression contains any of the specified elements. Signature: @@ -739,9 +715,6 @@ arrayContainsAny(field("categories"), [field("cate1"), "Science"]); ### arrayContainsAny(array, values) {:#arraycontainsany_c381a96} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an array expression contains any of the specified elements. Signature: @@ -774,9 +747,6 @@ arrayContainsAny(field("categories"), array([field("cate1"), "Science"])); ### arrayLength(array) {:#arraylength_195e339} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of an array expression. Signature: @@ -810,9 +780,6 @@ arrayLength(field("cart")); ### arrayFirst(arrayExpression) {:#arrayfirst_f574e12} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first element of an array. Signature: @@ -844,9 +811,6 @@ arrayFirst(field("tags")); ### arrayFirstN(arrayExpression, n) {:#arrayfirstn_bff7f91} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first `n` elements of an array. Signature: @@ -879,9 +843,6 @@ arrayFirstN(field("tags"), 3); ### arrayFirstN(arrayExpression, n) {:#arrayfirstn_19b4ef8} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first `n` elements of an array. Signature: @@ -914,9 +875,6 @@ arrayFirstN(field("tags"), field("count")); ### arrayGet(arrayExpression, offset) {:#arrayget_f2e27cc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: @@ -949,9 +907,6 @@ arrayGet(field('tags'), 1); ### arrayGet(arrayExpression, offsetExpr) {:#arrayget_484550d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: @@ -985,9 +940,6 @@ arrayGet(field('tags'), field('favoriteTag')); ### arrayIndexOf(arrayExpression, search) {:#arrayindexof_694a0b4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. Signature: @@ -1020,9 +972,6 @@ arrayIndexOf(field("tags"), "politics"); ### arrayIndexOfAll(arrayExpression, search) {:#arrayindexofall_694a0b4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns all indices of the search value in an array. Signature: @@ -1055,9 +1004,6 @@ arrayIndexOfAll(field("scores"), 5); ### arrayLast(arrayExpression) {:#arraylast_f574e12} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last element of an array. Signature: @@ -1089,9 +1035,6 @@ arrayLast(field("tags")); ### arrayLastIndexOf(arrayExpression, search) {:#arraylastindexof_694a0b4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. Signature: @@ -1124,9 +1067,6 @@ arrayLastIndexOf(field("tags"), "politics"); ### arrayLastN(arrayExpression, n) {:#arraylastn_bff7f91} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last `n` elements of an array. Signature: @@ -1159,9 +1099,6 @@ arrayLastN(field("tags"), 3); ### arrayLastN(arrayExpression, n) {:#arraylastn_19b4ef8} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last `n` elements of an array. Signature: @@ -1194,9 +1131,6 @@ arrayLastN(field("tags"), field("count")); ### arrayMaximum(arrayExpression) {:#arraymaximum_f574e12} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the maximum value in an array. Signature: @@ -1228,9 +1162,6 @@ arrayMaximum(field("scores")); ### arrayMaximumN(arrayExpression, n) {:#arraymaximumn_bff7f91} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the largest `n` elements of an array. Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1265,9 +1196,6 @@ arrayMaximumN(field("scores"), 3); ### arrayMaximumN(arrayExpression, n) {:#arraymaximumn_19b4ef8} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the largest `n` elements of an array. Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1302,9 +1230,6 @@ arrayMaximumN(field("scores"), field("count")); ### arrayMinimum(arrayExpression) {:#arrayminimum_f574e12} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the minimum value in an array. Signature: @@ -1336,9 +1261,6 @@ arrayMinimum(field("scores")); ### arrayMinimumN(arrayExpression, n) {:#arrayminimumn_bff7f91} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smallest `n` elements of an array. Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1373,9 +1295,6 @@ arrayMinimumN(field("scores"), 3); ### arrayMinimumN(arrayExpression, n) {:#arrayminimumn_19b4ef8} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smallest `n` elements of an array. Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -1410,9 +1329,6 @@ arrayMinimumN(field("scores"), field("count")); ### join(arrayExpression, delimiterExpression) {:#join_313e6aa} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that joins the elements of an array into a string. Signature: @@ -1445,9 +1361,6 @@ join(array(['foo', 'bar']), field("separator")) ### join(arrayExpression, delimiter) {:#join_d088d29} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that joins the elements of an array into a string. Signature: @@ -1482,9 +1395,6 @@ join(field("tags"), ", ") ### arrayGet(arrayField, offset) {:#arrayget_3f58471} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: @@ -1517,9 +1427,6 @@ arrayGet('tags', 1); ### arrayGet(arrayField, offsetExpr) {:#arrayget_1904c9a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that indexes into an array from the beginning or end and return the element. If the offset exceeds the array length, an error is returned. A negative offset, starts from the end. Signature: @@ -1555,9 +1462,6 @@ arrayGet('tags', field('favoriteTag')); ### join(arrayFieldName, delimiter) {:#join_478ef36} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that joins the elements of an array into a string. Signature: @@ -1590,9 +1494,6 @@ join("tags", ", ") ### join(arrayFieldName, delimiterExpression) {:#join_829294c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that joins the elements of an array into a string. Signature: @@ -1627,9 +1528,6 @@ join('tags', field("separator")) ### pow(base, exponent) {:#pow_e4a9e64} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the value of the base expression raised to the power of the exponent expression. Signature: @@ -1662,9 +1560,6 @@ pow(field("base"), field("exponent")); ### pow(base, exponent) {:#pow_93eae7f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the value of the base expression raised to the power of the exponent. Signature: @@ -1697,9 +1592,6 @@ pow(field("base"), 2); ### pow(base, exponent) {:#pow_a237721} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the value of the base field raised to the power of the exponent expression. Signature: @@ -1732,9 +1624,6 @@ pow("base", field("exponent")); ### pow(base, exponent) {:#pow_f4d7908} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the value of the base field raised to the power of the exponent. Signature: @@ -1769,9 +1658,6 @@ pow("base", 2); ### countIf(booleanExpr) {:#countif_c5b8fb1} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the number of stage inputs where the provided boolean expression evaluates to true. Signature: @@ -1803,9 +1689,6 @@ countIf(field("is_active").equal(true)).as("numActiveDocuments"); ### not(booleanExpr) {:#not_c5b8fb1} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that negates a filter condition. Signature: @@ -1839,9 +1722,6 @@ not(equal("completed", true)); ### conditional(condition, thenExpr, elseExpr) {:#conditional_07a206d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a conditional expression that evaluates to a 'then' expression if a condition is true and an 'else' expression if the condition is false. Signature: @@ -1876,9 +1756,6 @@ conditional( ### switchOn(condition, result, others) {:#switchon_02b8caf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to the result corresponding to the first true condition. This function behaves like a `switch` statement. It accepts an alternating sequence of conditions and their corresponding results. If an odd number of arguments is provided, the final argument serves as a default fallback result. If no default is provided and no condition evaluates to true, it throws an error. @@ -1921,9 +1798,6 @@ switchOn( ### documentId(documentPath) {:#documentid_cef293c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the document ID from a path. Signature: @@ -1957,9 +1831,6 @@ documentId(myDocumentReference); ### documentId(documentPathExpr) {:#documentid_9a69021} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the document ID from a path. Signature: @@ -1993,9 +1864,6 @@ documentId(field("__path__")); ### notEqualAny(element, values) {:#notequalany_c2c5bcb} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is not equal to any of the provided values or expressions. Signature: @@ -2028,9 +1896,6 @@ notEqualAny(field("status"), ["pending", field("rejectedStatus")]); ### notEqualAny(element, arrayExpression) {:#notequalany_16b2851} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is not equal to any of the provided values or expressions. Signature: @@ -2065,9 +1930,6 @@ notEqualAny(field("status"), ["pending", field("rejectedStatus")]); ### array(elements) {:#array_7d853aa} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that creates a Firestore array value from an input array. Signature: @@ -2099,9 +1961,6 @@ array(['bar', field('baz')]).as('foo'); ### map(elements) {:#map_ce5dee1} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that creates a Firestore map value from an input object. Signature: @@ -2135,9 +1994,6 @@ map({foo: 'bar', baz: field('baz')}).as('data'); ### timestampDiff(endExpression, startFieldName, unit) {:#timestampdiff_4370feb} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the difference between two timestamps. Signature: @@ -2171,9 +2027,6 @@ timestampDiff(field('endTime'), 'startTime', 'day') ### timestampDiff(endExpression, startExpression, unit) {:#timestampdiff_bc0830f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the difference between two timestamps. Signature: @@ -2209,9 +2062,6 @@ timestampDiff(field('endTime'), field('startTime'), 'day') ### timestampDiff(endFieldName, startFieldName, unit) {:#timestampdiff_f60102c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the difference between two timestamps. Signature: @@ -2245,9 +2095,6 @@ timestampDiff('endTime', 'startTime', 'day') ### timestampDiff(endFieldName, startExpression, unit) {:#timestampdiff_6e54d92} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the difference between two timestamps. Signature: @@ -2283,9 +2130,6 @@ timestampDiff('endTime', field('startTime'), 'day') ### abs(expr) {:#abs_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the absolute value of a numeric value. Signature: @@ -2308,9 +2152,6 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ### ascending(expr) {:#ascending_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on an expression. Signature: @@ -2343,9 +2184,6 @@ firestore.pipeline().collection("users") ### byteLength(expr) {:#bytelength_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. Signature: @@ -2377,9 +2215,6 @@ byteLength(field("myString")); ### countDistinct(expr) {:#countdistinct_3c28b08} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the number of distinct values of a field. Signature: @@ -2402,9 +2237,6 @@ A new `AggregateFunction` representing the 'count\_distinct' aggregation. ### descending(expr) {:#descending_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on an expression. Signature: @@ -2437,9 +2269,6 @@ firestore.pipeline().collection("users") ### floor(expr) {:#floor_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the floor of a numeric value. Signature: @@ -2462,9 +2291,6 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ### timestampToUnixMicros(expr) {:#timestamptounixmicros_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -2496,9 +2322,6 @@ timestampToUnixMicros(field("timestamp")); ### timestampToUnixMillis(expr) {:#timestamptounixmillis_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -2530,9 +2353,6 @@ timestampToUnixMillis(field("timestamp")); ### timestampToUnixSeconds(expr) {:#timestamptounixseconds_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -2564,9 +2384,6 @@ timestampToUnixSeconds(field("timestamp")); ### unixMicrosToTimestamp(expr) {:#unixmicrostotimestamp_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. Signature: @@ -2598,9 +2415,6 @@ unixMicrosToTimestamp(field("microseconds")); ### unixMillisToTimestamp(expr) {:#unixmillistotimestamp_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. Signature: @@ -2632,9 +2446,6 @@ unixMillisToTimestamp(field("milliseconds")); ### unixSecondsToTimestamp(expr) {:#unixsecondstotimestamp_005f3d4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. Signature: @@ -2668,9 +2479,6 @@ unixSecondsToTimestamp(field("seconds")); ### arrayAgg(expression) {:#arrayagg_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. 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. @@ -2704,9 +2512,6 @@ arrayAgg(field("tags")).as("allTags"); ### arrayAggDistinct(expression) {:#arrayaggdistinct_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. 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. @@ -2740,9 +2545,6 @@ arrayAggDistinct(field("tags")).as("allDistinctTags"); ### arraySum(expression) {:#arraysum_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the sum of the elements in an array. Signature: @@ -2774,9 +2576,6 @@ arraySum(field("scores")); ### average(expression) {:#average_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that calculates the average (mean) of values from an expression across multiple stage inputs. Signature: @@ -2808,9 +2607,6 @@ average(field("age")).as("averageAge"); ### ceil(expression) {:#ceil_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the ceiling of a numeric value. Signature: @@ -2842,9 +2638,6 @@ ceil(field("price")); ### coalesce(expression, replacement, others) {:#coalesce_00859cb} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. Signature: @@ -2879,9 +2672,6 @@ coalesce(field("preferredName"), field("fullName"), constant("Anonymous")) ### collectionId(expression) {:#collectionid_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the collection ID from a path. Signature: @@ -2913,9 +2703,6 @@ collectionId(field("__name__")); ### count(expression) {:#count_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the number of stage inputs with valid evaluations of the provided expression. Signature: @@ -2947,9 +2734,6 @@ count(field("price").greaterThan(10)).as("expensiveItemCount"); ### divide(expression, value) {:#divide_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that divides an expression by a constant value. Signature: @@ -2982,9 +2766,6 @@ divide(field("value"), 10); ### equal(expression, value) {:#equal_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is equal to a constant value. Signature: @@ -3017,9 +2798,6 @@ equal(field("age"), 21); ### equalAny(expression, values) {:#equalany_7e759b5} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or expressions. Signature: @@ -3052,9 +2830,6 @@ equalAny(field("category"), [constant("Electronics"), field("primaryType")]); ### equalAny(expression, arrayExpression) {:#equalany_214ce68} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is equal to any of the provided values. Signature: @@ -3087,9 +2862,6 @@ equalAny(field("category"), field('disabledCategories')); ### exp(expression) {:#exp_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes e to the power of the expression's result. Signature: @@ -3121,9 +2893,6 @@ exp(constant(2)); ### first(expression) {:#first_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the first value of an expression across multiple stage inputs. Signature: @@ -3155,9 +2924,6 @@ first(field("rating")).as("firstRating"); ### greaterThan(expression, value) {:#greaterthan_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is greater than a constant value. Signature: @@ -3190,9 +2956,6 @@ greaterThan(field("age"), 18); ### greaterThanOrEqual(expression, value) {:#greaterthanorequal_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is greater than or equal to a constant value. Signature: @@ -3225,9 +2988,6 @@ greaterThanOrEqual(field("quantity"), 10); ### isType(expression, type) {:#istype_27398ce} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the result of an expression is of the given type. Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. @@ -3262,9 +3022,6 @@ isType(add('count', 1), 'number') ### last(expression) {:#last_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the last value of an expression across multiple stage inputs. Signature: @@ -3296,9 +3053,6 @@ last(field("rating")).as("lastRating"); ### length\_2(expression) {:#length_2_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of a string, array, map, vector, or bytes. Signature: @@ -3333,9 +3087,6 @@ length(field("cart")); ### lessThan(expression, value) {:#lessthan_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is less than a constant value. Signature: @@ -3368,9 +3119,6 @@ lessThan(field("age"), 30); ### lessThanOrEqual(expression, value) {:#lessthanorequal_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is less than or equal to a constant value. Signature: @@ -3403,9 +3151,6 @@ lessThan(field("quantity"), 20); ### ln(expression) {:#ln_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the natural logarithm of a numeric value. Signature: @@ -3437,9 +3182,6 @@ ln(field("value")); ### log(expression, base) {:#log_ac183e2} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the logarithm of an expression to a given base. Signature: @@ -3472,9 +3214,6 @@ log(field("value"), 10); ### log(expression, base) {:#log_1894737} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the logarithm of an expression to a given base. Signature: @@ -3507,9 +3246,6 @@ log(field("value"), field("base")); ### log10(expression) {:#log10_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the base-10 logarithm of a numeric value. Signature: @@ -3541,9 +3277,6 @@ log10(field("value")); ### ltrim(expression, valueToTrim) {:#ltrim_775e2f2} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. Signature: @@ -3579,9 +3312,6 @@ ltrim(field("userInput"), '"'); ### maximum(expression) {:#maximum_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the maximum value of an expression across multiple stage inputs. Signature: @@ -3613,9 +3343,6 @@ maximum(field("score")).as("highestScore"); ### minimum(expression) {:#minimum_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the minimum value of an expression across multiple stage inputs. Signature: @@ -3647,9 +3374,6 @@ minimum(field("price")).as("lowestPrice"); ### mod(expression, value) {:#mod_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. Signature: @@ -3682,9 +3406,6 @@ mod(field("field1"), 5); ### notEqual(expression, value) {:#notequal_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if an expression is not equal to a constant value. Signature: @@ -3717,9 +3438,6 @@ notEqual(field("status"), "completed"); ### round(expression) {:#round_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the nearest whole number. Signature: @@ -3751,9 +3469,6 @@ round(field("price")); ### round(expression, decimalPlaces) {:#round_a3a92d0} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the specified number of decimal places. Signature: @@ -3786,9 +3501,6 @@ round(field("price"), constant(2)); ### rtrim(expression, valueToTrim) {:#rtrim_775e2f2} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. Signature: @@ -3824,9 +3536,6 @@ rtrim(field("userInput"), '"'); ### split(expression, delimiter) {:#split_5b5612b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that splits a string into an array of substrings based on the provided delimiter. Signature: @@ -3859,9 +3568,6 @@ split(field('scoresCsv'), ',') ### split(expression, delimiter) {:#split_5a171ed} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that splits a string into an array of substrings based on the provided delimiter. Signature: @@ -3894,9 +3600,6 @@ split(field('scores'), conditional(field('format').equal('csv'), constant(','), ### sqrt(expression) {:#sqrt_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the square root of a numeric value. Signature: @@ -3928,9 +3631,6 @@ sqrt(field("value")); ### stringIndexOf(expression, search) {:#stringindexof_6dfca5f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that finds the index of the first occurrence of a substring or byte sequence. Signature: @@ -3963,9 +3663,6 @@ stringIndexOf(field("text"), "foo"); ### stringRepeat(expression, repetitions) {:#stringrepeat_a55ba16} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that repeats a string or byte array a specified number of times. Signature: @@ -3998,9 +3695,6 @@ stringRepeat(field("label"), 3); ### stringReplaceAll(expression, find, replacement) {:#stringreplaceall_197ecbe} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. Signature: @@ -4034,9 +3728,6 @@ stringReplaceAll(field("text"), "foo", "bar"); ### stringReplaceOne(expression, find, replacement) {:#stringreplaceone_197ecbe} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. Signature: @@ -4070,9 +3761,6 @@ stringReplaceOne(field("text"), "foo", "bar"); ### subtract(expression, value) {:#subtract_01df3cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a constant value from an expression. Signature: @@ -4105,9 +3793,6 @@ subtract(field("value"), 2); ### sum(expression) {:#sum_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that calculates the sum of values from an expression across multiple stage inputs. Signature: @@ -4139,9 +3824,6 @@ sum(field("orderAmount")).as("totalRevenue"); ### trunc(expression) {:#trunc_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates the numeric value of an expression to an integer. Signature: @@ -4173,9 +3855,6 @@ trunc(field("rating")); ### trunc(expression, decimalPlaces) {:#trunc_a3a92d0} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a numeric value to the specified number of decimal places. Signature: @@ -4208,9 +3887,6 @@ trunc(field("rating"), constant(2)); ### type(expression) {:#type_1138a27} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the data type of an expression's result. Signature: @@ -4244,9 +3920,6 @@ type(conditional(exists('foo'), constant(1), constant(true))) ### isAbsent(field) {:#isabsent_0fb8cd4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns `true` if a field is absent. Otherwise, returns `false` even if the field value is `null`. Signature: @@ -4278,9 +3951,6 @@ isAbsent("value"); ### reverse(field) {:#reverse_0fb8cd4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses a string value in the specified field. Signature: @@ -4312,9 +3982,6 @@ reverse("myString"); ### stringReverse(field) {:#stringreverse_0fb8cd4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses a string value in the specified field. Signature: @@ -4346,9 +4013,6 @@ stringReverse("myString"); ### substring(field, position, length) {:#substring_0d9573a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a substring of a string or byte array. Signature: @@ -4371,9 +4035,6 @@ export declare function substring(field: string, position: number, length?: numb ### substring(field, position, length) {:#substring_05cb14e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a substring of a string or byte array. Signature: @@ -4398,9 +4059,6 @@ export declare function substring(field: string, position: Expression, length?: ### abs(fieldName) {:#abs_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the absolute value of a numeric value. Signature: @@ -4423,9 +4081,6 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ### add(fieldName, second) {:#add_b75bb8b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds a field's value to an expression. Signature: @@ -4458,9 +4113,6 @@ add("quantity", field("reserve")); ### arrayAgg(fieldName) {:#arrayagg_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that collects all values of a field across multiple stage inputs into an array. 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. @@ -4494,9 +4146,6 @@ arrayAgg("tags").as("allTags"); ### arrayAggDistinct(fieldName) {:#arrayaggdistinct_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that collects all distinct values of a field across multiple stage inputs into an array. 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. @@ -4530,9 +4179,6 @@ arrayAggDistinct("tags").as("allDistinctTags"); ### arrayContains(fieldName, element) {:#arraycontains_aaace4a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's array value contains a specific element. Signature: @@ -4565,9 +4211,6 @@ arrayContains("colors", field("selectedColor")); ### arrayContains(fieldName, element) {:#arraycontains_999590f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's array value contains a specific value. Signature: @@ -4600,9 +4243,6 @@ arrayContains("colors", "red"); ### arrayContainsAll(fieldName, values) {:#arraycontainsall_8060b23} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's array value contains all the specified values or expressions. Signature: @@ -4635,9 +4275,6 @@ arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); ### arrayContainsAll(fieldName, arrayExpression) {:#arraycontainsall_48da8d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's array value contains all the specified values or expressions. Signature: @@ -4670,9 +4307,6 @@ arrayContainsAll("tags", [field("tag1"), "SciFi", "Adventure"]); ### arrayContainsAny(fieldName, values) {:#arraycontainsany_8060b23} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's array value contains any of the specified elements. Signature: @@ -4706,9 +4340,6 @@ arrayContainsAny("categories", [field("cate1"), "Science"]); ### arrayContainsAny(fieldName, values) {:#arraycontainsany_1b4f7cd} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's array value contains any of the specified elements. Signature: @@ -4742,9 +4373,6 @@ arrayContainsAny("categories", array([field("cate1"), "Science"])); ### arrayFirst(fieldName) {:#arrayfirst_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first element of an array. Signature: @@ -4776,9 +4404,6 @@ arrayFirst("tags"); ### arrayFirstN(fieldName, n) {:#arrayfirstn_597a4d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first `n` elements of an array. Signature: @@ -4811,9 +4436,6 @@ arrayFirstN("tags", 3); ### arrayFirstN(fieldName, n) {:#arrayfirstn_1a86a2c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first `n` elements of an array. Signature: @@ -4846,9 +4468,6 @@ arrayFirstN("tags", field("count")); ### arrayIndexOf(fieldName, search) {:#arrayindexof_5e4c2c3} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first index of the search value in an array. Returns -1 if the value is not found. Signature: @@ -4881,9 +4500,6 @@ arrayIndexOf("tags", "politics"); ### arrayIndexOfAll(fieldName, search) {:#arrayindexofall_5e4c2c3} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns all indices of the search value in an array. Signature: @@ -4916,9 +4532,6 @@ arrayIndexOfAll("scores", 5); ### arrayLast(fieldName) {:#arraylast_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last element of an array. Signature: @@ -4950,9 +4563,6 @@ arrayLast("tags"); ### arrayLastIndexOf(fieldName, search) {:#arraylastindexof_5e4c2c3} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last index of the search value in an array. Returns -1 if the value is not found. Signature: @@ -4985,9 +4595,6 @@ arrayLastIndexOf("tags", "politics"); ### arrayLastN(fieldName, n) {:#arraylastn_597a4d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last `n` elements of an array. Signature: @@ -5020,9 +4627,6 @@ arrayLastN("tags", 3); ### arrayLastN(fieldName, n) {:#arraylastn_1a86a2c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the last `n` elements of an array. Signature: @@ -5055,9 +4659,6 @@ arrayLastN("tags", field("count")); ### arrayLength(fieldName) {:#arraylength_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of an array in a specified field. Signature: @@ -5089,9 +4690,6 @@ arrayLength('cart'); ### arrayMaximum(fieldName) {:#arraymaximum_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the maximum value in an array. Signature: @@ -5123,9 +4721,6 @@ arrayMaximum("scores"); ### arrayMaximumN(fieldName, n) {:#arraymaximumn_597a4d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the largest `n` elements of an array. Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -5160,9 +4755,6 @@ arrayMaximumN("scores", 3); ### arrayMaximumN(fieldName, n) {:#arraymaximumn_1a86a2c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the largest `n` elements of an array. Note: Returns the n largest non-null elements in the array, in descending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -5197,9 +4789,6 @@ arrayMaximumN("scores", field("count")); ### arrayMinimum(fieldName) {:#arrayminimum_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the minimum value in an array. Signature: @@ -5231,9 +4820,6 @@ arrayMinimum("scores"); ### arrayMinimumN(fieldName, n) {:#arrayminimumn_597a4d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smallest `n` elements of an array. Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -5268,9 +4854,6 @@ arrayMinimumN("scores", 3); ### arrayMinimumN(fieldName, n) {:#arrayminimumn_1a86a2c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smallest `n` elements of an array. Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. @@ -5305,9 +4888,6 @@ arrayMinimumN(field("scores"), field("count")); ### arraySum(fieldName) {:#arraysum_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the sum of the elements in an array. Signature: @@ -5339,9 +4919,6 @@ arraySum("scores"); ### ascending(fieldName) {:#ascending_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. Signature: @@ -5374,9 +4951,6 @@ firestore.pipeline().collection("users") ### average(fieldName) {:#average_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. Signature: @@ -5408,9 +4982,6 @@ average("age").as("averageAge"); ### byteLength(fieldName) {:#bytelength_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. Signature: @@ -5442,9 +5013,6 @@ byteLength("myString"); ### ceil(fieldName) {:#ceil_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the ceiling of a numeric value. Signature: @@ -5476,9 +5044,6 @@ ceil("price"); ### charLength(fieldName) {:#charlength_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the character length of a string field in UTF8. Signature: @@ -5510,9 +5075,6 @@ charLength("name"); ### coalesce(fieldName, replacement, others) {:#coalesce_249958e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first non-null, non-absent argument, without evaluating the rest of the arguments. When all arguments are null or absent, returns the last argument. Signature: @@ -5547,9 +5109,6 @@ coalesce("preferredName", field("fullName"), constant("Anonymous")) ### collectionId(fieldName) {:#collectionid_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the collection ID from a path. Signature: @@ -5581,9 +5140,6 @@ collectionId("__name__"); ### concat(fieldName, second, others) {:#concat_828272e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. Signature: @@ -5617,9 +5173,6 @@ concat(field("firstName"), "Doe") ### cosineDistance(fieldName, vector) {:#cosinedistance_463a23e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Cosine distance between a field's vector value and a literal vector value. Signature: @@ -5652,9 +5205,6 @@ cosineDistance("location", [37.7749, -122.4194]); ### cosineDistance(fieldName, vectorExpression) {:#cosinedistance_ed766a1} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Cosine distance between a field's vector value and a vector expression. Signature: @@ -5687,9 +5237,6 @@ cosineDistance("userVector", field("itemVector")); ### count(fieldName) {:#count_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that counts the number of stage inputs where the input field exists. Signature: @@ -5721,9 +5268,6 @@ count("productId").as("totalProducts"); ### descending(fieldName) {:#descending_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in descending order based on a field. Signature: @@ -5756,9 +5300,6 @@ firestore.pipeline().collection("users") ### divide(fieldName, expressions) {:#divide_cf36e43} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that divides a field's value by an expression. Signature: @@ -5791,9 +5332,6 @@ divide("total", field("count")); ### divide(fieldName, value) {:#divide_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that divides a field's value by a constant value. Signature: @@ -5826,9 +5364,6 @@ divide("value", 10); ### dotProduct(fieldName, vector) {:#dotproduct_463a23e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the dot product between a field's vector value and a double array. Signature: @@ -5861,9 +5396,6 @@ dotProduct("features", [0.5, 0.8, 0.2]); ### dotProduct(fieldName, vectorExpression) {:#dotproduct_ed766a1} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the dot product between a field's vector value and a vector expression. Signature: @@ -5896,9 +5428,6 @@ dotProduct("docVector1", field("docVector2")); ### endsWith(fieldName, suffix) {:#endswith_05ca3b0} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value ends with a given postfix. Signature: @@ -5931,9 +5460,6 @@ endsWith("filename", ".txt"); ### endsWith(fieldName, suffix) {:#endswith_8fc0ebc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value ends with a given postfix. Signature: @@ -5966,9 +5492,6 @@ endsWith("url", field("extension")); ### equal(fieldName, expression) {:#equal_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is equal to an expression. Signature: @@ -6001,9 +5524,6 @@ equal("age", field("limit")); ### equal(fieldName, value) {:#equal_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is equal to a constant value. Signature: @@ -6036,9 +5556,6 @@ equal("city", "London"); ### equalAny(fieldName, values) {:#equalany_8060b23} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is equal to any of the provided values or expressions. Signature: @@ -6071,9 +5588,6 @@ equalAny("category", [constant("Electronics"), field("primaryType")]); ### equalAny(fieldName, arrayExpression) {:#equalany_48da8d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is equal to any of the provided values or expressions. Signature: @@ -6106,9 +5620,6 @@ equalAny("category", ["Electronics", field("primaryType")]); ### euclideanDistance(fieldName, vector) {:#euclideandistance_463a23e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Euclidean distance between a field's vector value and a double array. Signature: @@ -6141,9 +5652,6 @@ euclideanDistance("location", [37.7749, -122.4194]); ### euclideanDistance(fieldName, vectorExpression) {:#euclideandistance_ed766a1} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Euclidean distance between a field's vector value and a vector expression. Signature: @@ -6176,9 +5684,6 @@ euclideanDistance("pointA", field("pointB")); ### exists(fieldName) {:#exists_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field exists. Signature: @@ -6210,9 +5715,6 @@ exists("phoneNumber"); ### exp(fieldName) {:#exp_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes e to the power of the expression's result. Signature: @@ -6244,9 +5746,6 @@ exp('value'); ### first(fieldName) {:#first_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the first value of a field across multiple stage inputs. Signature: @@ -6278,9 +5777,6 @@ first("rating").as("firstRating"); ### floor(fieldName) {:#floor_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the floor of a numeric value. Signature: @@ -6303,9 +5799,6 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe ### greaterThan(fieldName, expression) {:#greaterthan_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is greater than an expression. Signature: @@ -6338,9 +5831,6 @@ greaterThan("age", field("limit")); ### greaterThan(fieldName, value) {:#greaterthan_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is greater than a constant value. Signature: @@ -6373,9 +5863,6 @@ greaterThan("price", 100); ### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_2e16acb} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is greater than or equal to an expression. Signature: @@ -6408,9 +5895,6 @@ greaterThanOrEqual("age", field("limit")); ### greaterThanOrEqual(fieldName, value) {:#greaterthanorequal_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is greater than or equal to a constant value. Signature: @@ -6443,9 +5927,6 @@ greaterThanOrEqual("score", 80); ### isType(fieldName, type) {:#istype_5da287e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the value in the specified field is of the given type. Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. @@ -6480,9 +5961,6 @@ isType('price', 'float64'); ### last(fieldName) {:#last_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the last value of a field across multiple stage inputs. Signature: @@ -6514,9 +5992,6 @@ last("rating").as("lastRating"); ### length\_2(fieldName) {:#length_2_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of a string, array, map, vector, or bytes. Signature: @@ -6551,9 +6026,6 @@ length("cart"); ### lessThan(fieldName, expression) {:#lessthan_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is less than an expression. Signature: @@ -6586,9 +6058,6 @@ lessThan("age", field("limit")); ### lessThan(fieldName, value) {:#lessthan_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is less than a constant value. Signature: @@ -6621,9 +6090,6 @@ lessThan("price", 50); ### lessThanOrEqual(fieldName, expression) {:#lessthanorequal_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is less than or equal to an expression. Signature: @@ -6656,9 +6122,6 @@ lessThan("quantity", field("limit")); ### lessThanOrEqual(fieldName, value) {:#lessthanorequal_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is less than or equal to a constant value. Signature: @@ -6691,9 +6154,6 @@ lessThan("score", 70); ### like(fieldName, pattern) {:#like_67f7432} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a case-sensitive wildcard string comparison against a field. Signature: @@ -6726,9 +6186,6 @@ like("title", "%guide%"); ### like(fieldName, pattern) {:#like_cb1318d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a case-sensitive wildcard string comparison against a field. Signature: @@ -6761,9 +6218,6 @@ like("title", field("pattern")); ### ln(fieldName) {:#ln_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the natural logarithm of a numeric value. Signature: @@ -6795,9 +6249,6 @@ ln("value"); ### log(fieldName, base) {:#log_a89e21b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the logarithm of a field to a given base. Signature: @@ -6830,9 +6281,6 @@ log("value", 10); ### log(fieldName, base) {:#log_805b11f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the logarithm of a field to a given base. Signature: @@ -6865,9 +6313,6 @@ log("value", field("base")); ### log10(fieldName) {:#log10_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the base-10 logarithm of a numeric value. Signature: @@ -6899,9 +6344,6 @@ log10("value"); ### logicalMaximum(fieldName, second, others) {:#logicalmaximum_828272e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. Signature: @@ -6936,9 +6378,6 @@ logicalMaximum("field1", field("field2"), 1000); ### logicalMinimum(fieldName, second, others) {:#logicalminimum_828272e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smallest value between a field's value and other input expressions or literal values. Based on Firestore's value type ordering. Signature: @@ -6973,9 +6412,6 @@ logicalMinimum("field1", field("field2"), 1000); ### ltrim(fieldName, valueToTrim) {:#ltrim_c0e3211} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. Signature: @@ -7011,9 +6447,6 @@ ltrim(field("userInput"), '"'); ### mapGet(fieldName, subField) {:#mapget_06663cf} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Accesses a value from a map (object) field using the provided key. Signature: @@ -7046,9 +6479,6 @@ mapGet("address", "city"); ### maximum(fieldName) {:#maximum_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the maximum value of a field across multiple stage inputs. Signature: @@ -7080,9 +6510,6 @@ maximum("score").as("highestScore"); ### minimum(fieldName) {:#minimum_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that finds the minimum value of a field across multiple stage inputs. Signature: @@ -7114,9 +6541,6 @@ minimum("price").as("lowestPrice"); ### mod(fieldName, expression) {:#mod_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. Signature: @@ -7149,9 +6573,6 @@ mod("field1", field("field2")); ### mod(fieldName, value) {:#mod_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. Signature: @@ -7184,9 +6605,6 @@ mod("field1", 5); ### multiply(fieldName, second) {:#multiply_b75bb8b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that multiplies a field's value by an expression. Signature: @@ -7219,9 +6637,6 @@ multiply("quantity", field("price")); ### notEqual(fieldName, expression) {:#notequal_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is not equal to an expression. Signature: @@ -7254,9 +6669,6 @@ notEqual("status", field("expectedStatus")); ### notEqual(fieldName, value) {:#notequal_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is not equal to a constant value. Signature: @@ -7289,9 +6701,6 @@ notEqual("country", "USA"); ### notEqualAny(fieldName, values) {:#notequalany_8060b23} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is not equal to any of the provided values or expressions. Signature: @@ -7324,9 +6733,6 @@ notEqualAny("status", [constant("pending"), field("rejectedStatus")]); ### notEqualAny(fieldName, arrayExpression) {:#notequalany_48da8d9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. Signature: @@ -7359,9 +6765,6 @@ notEqualAny("status", field("rejectedStatuses")); ### regexContains(fieldName, pattern) {:#regexcontains_67f7432} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string field contains a specified regular expression as a substring. Signature: @@ -7394,9 +6797,6 @@ regexContains("description", "(?i)example"); ### regexContains(fieldName, pattern) {:#regexcontains_cb1318d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string field contains a specified regular expression as a substring. Signature: @@ -7429,9 +6829,6 @@ regexContains("description", field("pattern")); ### regexFind(fieldName, pattern) {:#regexfind_67f7432} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first substring of a string field that matches a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -7466,9 +6863,6 @@ regexFind("email", "@[A-Za-z0-9.-]+"); ### regexFind(fieldName, pattern) {:#regexfind_cb1318d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first substring of a string field that matches a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -7503,9 +6897,6 @@ regexFind("email", field("pattern")); ### regexFindAll(fieldName, pattern) {:#regexfindall_67f7432} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -7540,9 +6931,6 @@ regexFindAll("content", "#[A-Za-z0-9_]+"); ### regexFindAll(fieldName, pattern) {:#regexfindall_cb1318d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to a list of all substrings in a string field that match a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -7577,9 +6965,6 @@ regexFindAll("content", field("pattern")); ### regexMatch(fieldName, pattern) {:#regexmatch_67f7432} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string field matches a specified regular expression. Signature: @@ -7612,9 +6997,6 @@ regexMatch("email", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); ### regexMatch(fieldName, pattern) {:#regexmatch_cb1318d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string field matches a specified regular expression. Signature: @@ -7647,9 +7029,6 @@ regexMatch("email", field("pattern")); ### round(fieldName) {:#round_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the nearest whole number. Signature: @@ -7681,9 +7060,6 @@ round("price"); ### round(fieldName, decimalPlaces) {:#round_07d0cf0} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that rounds a numeric value to the specified number of decimal places. Signature: @@ -7716,9 +7092,6 @@ round("price", 2); ### rtrim(fieldName, valueToTrim) {:#rtrim_c0e3211} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. Signature: @@ -7754,9 +7127,6 @@ rtrim(field("userInput"), '"'); ### split(fieldName, delimiter) {:#split_2cfdd37} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that splits the value of a field on the provided delimiter. Signature: @@ -7789,9 +7159,6 @@ split('scoresCsv', ',') ### split(fieldName, delimiter) {:#split_f4fe06a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that splits the value of a field on the provided delimiter. Signature: @@ -7824,9 +7191,6 @@ split('scores', conditional(field('format').equal('csv'), constant(','), constan ### sqrt(fieldName) {:#sqrt_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that computes the square root of a numeric value. Signature: @@ -7858,9 +7222,6 @@ sqrt("value"); ### startsWith(fieldName, prefix) {:#startswith_89325cc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value starts with a given prefix. Signature: @@ -7893,9 +7254,6 @@ startsWith("name", "Mr."); ### startsWith(fieldName, prefix) {:#startswith_266c338} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field's value starts with a given prefix. Signature: @@ -7928,9 +7286,6 @@ startsWith("fullName", field("firstName")); ### stringConcat(fieldName, secondString, otherStrings) {:#stringconcat_d80077e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates string functions, fields or constants together. Signature: @@ -7964,9 +7319,6 @@ stringConcat("firstName", " ", field("lastName")); ### stringContains(fieldName, substring) {:#stringcontains_5b94cfe} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string field contains a specified substring. Signature: @@ -7999,9 +7351,6 @@ stringContains("description", "example"); ### stringContains(fieldName, substring) {:#stringcontains_ac3ba47} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string field contains a substring specified by an expression. Signature: @@ -8034,9 +7383,6 @@ stringContains("description", field("keyword")); ### stringIndexOf(fieldName, search) {:#stringindexof_6c4650e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that finds the index of the first occurrence of a substring or byte sequence. Signature: @@ -8069,9 +7415,6 @@ stringIndexOf("text", "foo"); ### stringRepeat(fieldName, repetitions) {:#stringrepeat_e144a59} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that repeats a string or byte array a specified number of times. Signature: @@ -8104,9 +7447,6 @@ stringRepeat("label", 3); ### stringReplaceAll(fieldName, find, replacement) {:#stringreplaceall_b0db15f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. Signature: @@ -8140,9 +7480,6 @@ stringReplaceAll("text", "foo", "bar"); ### stringReplaceOne(fieldName, find, replacement) {:#stringreplaceone_b0db15f} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. Signature: @@ -8176,9 +7513,6 @@ stringReplaceOne("text", "foo", "bar"); ### subtract(fieldName, expression) {:#subtract_1e91657} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts an expression from a field's value. Signature: @@ -8211,9 +7545,6 @@ subtract("price", field("discount")); ### subtract(fieldName, value) {:#subtract_65e2f32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a constant value from a field's value. Signature: @@ -8246,9 +7577,6 @@ subtract("total", 20); ### sum(fieldName) {:#sum_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an aggregation that calculates the sum of a field's values across multiple stage inputs. Signature: @@ -8280,9 +7608,6 @@ sum("orderAmount").as("totalRevenue"); ### timestampAdd(fieldName, unit, amount) {:#timestampadd_3b0a297} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds a specified amount of time to a timestamp represented by a field. Signature: @@ -8316,9 +7641,6 @@ timestampAdd("timestamp", "day", 1); ### timestampExtract(fieldName, part, timezone) {:#timestampextract_a51c205} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that extracts a specified part from a timestamp. Signature: @@ -8352,9 +7674,6 @@ timestampExtract('createdAt', 'year') ### timestampExtract(fieldName, part, timezone) {:#timestampextract_2d51eac} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that extracts a specified part from a timestamp. Signature: @@ -8388,9 +7707,6 @@ timestampExtract('createdAt', field('part')) ### timestampSubtract(fieldName, unit, amount) {:#timestampsubtract_3b0a297} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. Signature: @@ -8424,9 +7740,6 @@ timestampSubtract("timestamp", "day", 1); ### timestampToUnixMicros(fieldName) {:#timestamptounixmicros_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -8458,9 +7771,6 @@ timestampToUnixMicros("timestamp"); ### timestampToUnixMillis(fieldName) {:#timestamptounixmillis_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -8492,9 +7802,6 @@ timestampToUnixMillis("timestamp"); ### timestampToUnixSeconds(fieldName) {:#timestamptounixseconds_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). Signature: @@ -8526,9 +7833,6 @@ timestampToUnixSeconds("timestamp"); ### timestampTruncate(fieldName, granularity, timezone) {:#timestamptruncate_b6c7512} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a timestamp to a specified granularity. Signature: @@ -8562,9 +7866,6 @@ timestampTruncate('createdAt', 'day') ### timestampTruncate(fieldName, granularity, timezone) {:#timestamptruncate_ed83d46} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a timestamp to a specified granularity. Signature: @@ -8598,9 +7899,6 @@ timestampTruncate('createdAt', field('granularity')) ### toLower(fieldName) {:#tolower_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a string field to lowercase. Signature: @@ -8632,9 +7930,6 @@ toLower("name"); ### toUpper(fieldName) {:#toupper_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a string field to uppercase. Signature: @@ -8666,9 +7961,6 @@ toUpper("title"); ### trim(fieldName, valueToTrim) {:#trim_c9f90ee} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes leading and trailing whitespace from a string or byte array. Signature: @@ -8704,9 +7996,6 @@ trim("userInput", '"'); ### trunc(fieldName) {:#trunc_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates the numeric value of a field to an integer. Signature: @@ -8738,9 +8027,6 @@ trunc("rating"); ### trunc(fieldName, decimalPlaces) {:#trunc_07d0cf0} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a numeric expression to the specified number of decimal places. Signature: @@ -8773,9 +8059,6 @@ trunc("rating", 2); ### type(fieldName) {:#type_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the data type of the data in the specified field. String inputs passed iteratively to this global function act as `field()` path lookups. If you wish to pass a string literal value, it must be wrapped: `type(constant("my_string"))`. @@ -8809,9 +8092,6 @@ type('title') ### unixMicrosToTimestamp(fieldName) {:#unixmicrostotimestamp_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. Signature: @@ -8843,9 +8123,6 @@ unixMicrosToTimestamp("microseconds"); ### unixMillisToTimestamp(fieldName) {:#unixmillistotimestamp_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. Signature: @@ -8877,9 +8154,6 @@ unixMillisToTimestamp("milliseconds"); ### unixSecondsToTimestamp(fieldName) {:#unixsecondstotimestamp_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) and returns a timestamp. Signature: @@ -8911,9 +8185,6 @@ unixSecondsToTimestamp("seconds"); ### vectorLength(fieldName) {:#vectorlength_e5b0480} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of a Firestore Vector represented by a field. Signature: @@ -8947,9 +8218,6 @@ vectorLength("embedding"); ### add(first, second) {:#add_846ca1b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds two expressions together. Signature: @@ -8982,9 +8250,6 @@ add(field("quantity"), field("reserve")); ### and(first, second, more) {:#and_e0c48bd} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a logical 'AND' operation on multiple filter conditions. Signature: @@ -9019,9 +8284,6 @@ const condition = and(greaterThan("age", 18), equal("city", "London"), equal("st ### concat(first, second, others) {:#concat_83be015} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. Signature: @@ -9055,9 +8317,6 @@ concat(field("firstName"), " ", field("lastName")) ### logicalMaximum(first, second, others) {:#logicalmaximum_83be015} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the largest value between multiple input expressions or literal values. Based on Firestore's value type ordering. Signature: @@ -9092,9 +8351,6 @@ logicalMaximum(field("field1"), field("field2"), 1000); ### logicalMinimum(first, second, others) {:#logicalminimum_83be015} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the smallest value between multiple input expressions and literal values. Based on Firestore's value type ordering. Signature: @@ -9129,9 +8385,6 @@ logicalMinimum(field("field1"), field("field2"), 1000); ### multiply(first, second) {:#multiply_846ca1b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that multiplies two expressions together. Signature: @@ -9164,9 +8417,6 @@ multiply(field("quantity"), field("price")); ### nor(first, second, more) {:#nor_e0c48bd} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a logical 'NOR' operation on multiple filter conditions. Signature: @@ -9203,9 +8453,6 @@ const condition = nor( ### or(first, second, more) {:#or_e0c48bd} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a logical 'OR' operation on multiple filter conditions. Signature: @@ -9240,9 +8487,6 @@ const condition = or(greaterThan("age", 18), equal("city", "London"), equal("sta ### xor(first, second, additionalConditions) {:#xor_8197113} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. Signature: @@ -9282,9 +8526,6 @@ const condition = xor( ### arrayConcat(firstArray, secondArray, otherArrays) {:#arrayconcat_c00d5d7} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates an array expression with other arrays. Signature: @@ -9320,9 +8561,6 @@ arrayConcat(field("items"), [field("newItems"), field("otherItems")]); ### arrayConcat(firstArrayField, secondArray, otherArrays) {:#arrayconcat_f92063d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates a field's array value with other arrays. Signature: @@ -9358,9 +8596,6 @@ arrayConcat("items", [field("newItems"), field("otherItems")]); ### mapMerge(firstMap, secondMap, otherMaps) {:#mapmerge_cfe77ce} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that merges multiple map values. Signature: @@ -9395,9 +8630,6 @@ mapMerge(field('settings'), { enabled: true }, conditional(field('isAdmin'), { a ### stringConcat(firstString, secondString, otherStrings) {:#stringconcat_8a8d1b6} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that concatenates string expressions together. Signature: @@ -9433,9 +8665,6 @@ stringConcat(field("firstName"), " ", field("lastName")); ### ifAbsent(ifExpr, elseExpr) {:#ifabsent_0e6d161} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseExpr` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. Signature: @@ -9469,9 +8698,6 @@ ifAbsent(field("optional_field"), constant("default_value")) ### ifAbsent(ifExpr, elseValue) {:#ifabsent_c34e5ed} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if `ifExpr` is absent, else return the result of the `ifExpr` argument evaluation. Signature: @@ -9505,9 +8731,6 @@ ifAbsent(field("optional_field"), "default_value") ### ifNull(ifExpr, elseExpr) {:#ifnull_0e6d161} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseExpr` argument if `ifExpr` is null, else return the result of the `ifExpr` argument evaluation. This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. @@ -9542,9 +8765,6 @@ ifNull(field("preferredName"), field("fullName")) ### ifNull(ifExpr, elseValue) {:#ifnull_c34e5ed} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if `ifExpr` is null, else return the result of the `ifExpr` argument evaluation. This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. @@ -9581,9 +8801,6 @@ ifNull(field("displayName"), "Anonymous") ### ifAbsent(ifFieldName, elseExpr) {:#ifabsent_e6dabea} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseExpr` argument if `ifFieldName` is absent, else return the value of the field. Signature: @@ -9617,9 +8834,6 @@ ifAbsent("optional_field", field("default_field")) ### ifAbsent(ifFieldName, elseValue) {:#ifabsent_d8f2823} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if `ifFieldName` is absent, else return the value of the field. Signature: @@ -9653,9 +8867,6 @@ ifAbsent("optional_field", "default_value") ### ifNull(ifFieldName, elseExpr) {:#ifnull_e6dabea} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseExpr` argument if `ifFieldName` field is null, else return the value of the field. This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. @@ -9690,9 +8901,6 @@ ifNull("preferredName", field("fullName")) ### ifNull(ifFieldName, elseValue) {:#ifnull_587c2f0} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `elseValue` argument if `ifFieldName` field is null, else return the value of the field. This function provides a fallback for both absent and explicit null values. In contrast, `ifAbsent()` only triggers for missing fields. @@ -9729,9 +8937,6 @@ ifNull("displayName", "Anonymous") ### substring(input, position, length) {:#substring_e6e0aa3} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a substring of a string or byte array. Signature: @@ -9754,9 +8959,6 @@ export declare function substring(input: Expression, position: number, length?: ### substring(input, position, length) {:#substring_ab56dc6} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a substring of a string or byte array. Signature: @@ -9781,9 +8983,6 @@ export declare function substring(input: Expression, position: Expression, lengt ### divide(left, right) {:#divide_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that divides two expressions. Signature: @@ -9816,9 +9015,6 @@ divide(field("total"), field("count")); ### equal(left, right) {:#equal_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if two expressions are equal. Signature: @@ -9851,9 +9047,6 @@ equal(field("age"), field("minAge").add(10)); ### greaterThan(left, right) {:#greaterthan_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the first expression is greater than the second expression. Signature: @@ -9886,9 +9079,6 @@ greaterThan(field("age"), constant(9).add(9)); ### greaterThanOrEqual(left, right) {:#greaterthanorequal_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the first expression is greater than or equal to the second expression. Signature: @@ -9921,9 +9111,6 @@ greaterThanOrEqual(field("quantity"), field("threshold")); ### lessThan(left, right) {:#lessthan_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the first expression is less than the second expression. Signature: @@ -9956,9 +9143,6 @@ lessThan(field("age"), field("limit")); ### lessThanOrEqual(left, right) {:#lessthanorequal_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if the first expression is less than or equal to the second expression. Signature: @@ -9991,9 +9175,6 @@ lessThan(field("quantity"), field("limit")); ### mod(left, right) {:#mod_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the modulo (remainder) of dividing two expressions. Signature: @@ -10026,9 +9207,6 @@ mod(field("field1"), field("field2")); ### notEqual(left, right) {:#notequal_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if two expressions are not equal. Signature: @@ -10061,9 +9239,6 @@ notEqual(field("status"), field("finalState")); ### pipelineResultEqual(left, right) {:#pipelineresultequal_707a755} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Test equality of two PipelineResults. Signature: @@ -10085,9 +9260,6 @@ boolean ### subtract(left, right) {:#subtract_b3c3382} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts two expressions. Signature: @@ -10122,9 +9294,6 @@ subtract(field("price"), field("discount")); ### mapRemove(mapExpr, key) {:#mapremove_23c7d51} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes a key from the map produced by evaluating an expression. Signature: @@ -10156,9 +9325,6 @@ mapRemove(map({foo: 'bar', baz: true}), 'baz'); ### mapRemove(mapExpr, keyExpr) {:#mapremove_9fbcaa3} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes a key from the map produced by evaluating an expression. Signature: @@ -10192,9 +9358,6 @@ mapRemove(map({foo: 'bar', baz: true}), constant('baz')); ### mapEntries(mapExpression) {:#mapentries_9cf124c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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" }, ...]`. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -10228,9 +9391,6 @@ mapEntries(map({"city": "San Francisco"})); ### mapGet(mapExpression, subField) {:#mapget_688c050} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Accesses a value from a map (object) expression using the provided key. Signature: @@ -10263,9 +9423,6 @@ mapGet(field("address"), "city"); ### mapKeys(mapExpression) {:#mapkeys_9cf124c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the keys of a map. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -10299,9 +9456,6 @@ mapKeys(map({"city": "San Francisco"})); ### mapSet(mapExpression, key, value, moreKeyValues) {:#mapset_45b48ff} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a new map with the specified entries added or updated. This 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`. @@ -10338,9 +9492,6 @@ mapSet(map({"state": "California"}), "city", "San Francisco"); ### mapValues(mapExpression) {:#mapvalues_9cf124c} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the values of a map. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -10376,9 +9527,6 @@ mapValues(map({"city": "San Francisco"})); ### mapEntries(mapField) {:#mapentries_83ad836} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - 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" }, ...]`. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -10412,9 +9560,6 @@ mapEntries("address"); ### mapKeys(mapField) {:#mapkeys_83ad836} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the keys of a map. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -10448,9 +9593,6 @@ mapKeys("address"); ### mapMerge(mapField, secondMap, otherMaps) {:#mapmerge_70a564b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that merges multiple map values. Signature: @@ -10483,9 +9625,6 @@ mapMerge('settings', { enabled: true }, conditional(field('isAdmin'), { admin: t ### mapRemove(mapField, key) {:#mapremove_bd5726e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes a key from the map at the specified field name. Signature: @@ -10516,9 +9655,6 @@ mapRemove('address', 'city'); ### mapRemove(mapField, keyExpr) {:#mapremove_8406d13} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes a key from the map at the specified field name. Signature: @@ -10549,9 +9685,6 @@ mapRemove('address', constant('city')); ### mapSet(mapField, key, value, moreKeyValues) {:#mapset_baadc2a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns a new map with the specified entries added or updated. This 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`. @@ -10588,9 +9721,6 @@ mapSet("address", "city", "San Francisco"); ### mapValues(mapField) {:#mapvalues_83ad836} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the values of a map. While the backend generally preserves insertion order, relying on the order of the output array is not guaranteed and should be avoided. @@ -10626,9 +9756,6 @@ mapValues("address"); ### field(name) {:#field_1eaaff4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). @@ -10667,9 +9794,6 @@ const authorFirstNameField = field("author.firstName"); ### execute(options) {:#execute_9e87e31} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Executes a pipeline and returns a Promise to represent the asynchronous operation. The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously. @@ -10712,9 +9836,6 @@ const results: PipelineResult[] = snapshot.results; ### field(path) {:#field_34ee07d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. Signature: @@ -10739,9 +9860,6 @@ A new [Field](./firestore_pipelines.field.md#field_class) instance representing ### execute(pipeline) {:#execute_01df620} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Executes a pipeline and returns a Promise to represent the asynchronous operation. The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously. @@ -10784,9 +9902,6 @@ const results: PipelineResult[] = snapshot.results; ### charLength(stringExpression) {:#charlength_c25a54a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the character length of a string expression in UTF-8. Signature: @@ -10818,9 +9933,6 @@ charLength(field("name")); ### endsWith(stringExpression, suffix) {:#endswith_0a0b889} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression ends with a given postfix. Signature: @@ -10853,9 +9965,6 @@ endsWith(field("fullName"), "Jr."); ### endsWith(stringExpression, suffix) {:#endswith_13aee0d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression ends with a given postfix. Signature: @@ -10888,9 +9997,6 @@ endsWith(field("fullName"), constant("Jr.")); ### like(stringExpression, pattern) {:#like_a84c581} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a case-sensitive wildcard string comparison. Signature: @@ -10923,9 +10029,6 @@ like(field("title"), "%guide%"); ### like(stringExpression, pattern) {:#like_b534848} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that performs a case-sensitive wildcard string comparison. Signature: @@ -10958,9 +10061,6 @@ like(field("title"), field("pattern")); ### regexContains(stringExpression, pattern) {:#regexcontains_a84c581} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression contains a specified regular expression as a substring. Signature: @@ -10993,9 +10093,6 @@ regexContains(field("description"), "(?i)example"); ### regexContains(stringExpression, pattern) {:#regexcontains_b534848} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression contains a specified regular expression as a substring. Signature: @@ -11028,9 +10125,6 @@ regexContains(field("description"), field("pattern")); ### regexFind(stringExpression, pattern) {:#regexfind_a84c581} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first substring of a string expression that matches a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -11065,9 +10159,6 @@ regexFind(field("email"), "@[A-Za-z0-9.-]+"); ### regexFind(stringExpression, pattern) {:#regexfind_b534848} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the first substring of a string expression that matches a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -11102,9 +10193,6 @@ regexFind(field("email"), field("pattern")); ### regexFindAll(stringExpression, pattern) {:#regexfindall_a84c581} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -11139,9 +10227,6 @@ regexFindAll(field("comment"), "@[A-Za-z0-9_]+"); ### regexFindAll(stringExpression, pattern) {:#regexfindall_b534848} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that evaluates to a list of all substrings in a string expression that match a specified regular expression. This expression uses the [RE2](https://github.com/google/re2/wiki/Syntax) regular expression syntax. @@ -11176,9 +10261,6 @@ regexFindAll(field("comment"), field("pattern")); ### regexMatch(stringExpression, pattern) {:#regexmatch_a84c581} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression matches a specified regular expression. Signature: @@ -11211,9 +10293,6 @@ regexMatch(field("email"), "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"); ### regexMatch(stringExpression, pattern) {:#regexmatch_b534848} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression matches a specified regular expression. Signature: @@ -11246,9 +10325,6 @@ regexMatch(field("email"), field("pattern")); ### reverse(stringExpression) {:#reverse_c25a54a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses a string. Signature: @@ -11280,9 +10356,6 @@ reverse(field("myString")); ### startsWith(stringExpression, prefix) {:#startswith_75c3dbb} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression starts with a given prefix. Signature: @@ -11315,9 +10388,6 @@ startsWith(field("fullName"), "Mr."); ### startsWith(stringExpression, prefix) {:#startswith_52f218a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression starts with a given prefix. Signature: @@ -11350,9 +10420,6 @@ startsWith(field("fullName"), field("prefix")); ### stringContains(stringExpression, substring) {:#stringcontains_3e9ff32} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression contains a specified substring. Signature: @@ -11385,9 +10452,6 @@ stringContains(field("description"), "example"); ### stringContains(stringExpression, substring) {:#stringcontains_cc6ee02} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a string expression contains a substring specified by another expression. Signature: @@ -11420,9 +10484,6 @@ stringContains(field("description"), field("keyword")); ### stringReverse(stringExpression) {:#stringreverse_c25a54a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that reverses a string. Signature: @@ -11454,9 +10515,6 @@ stringReverse(field("myString")); ### toLower(stringExpression) {:#tolower_c25a54a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a string expression to lowercase. Signature: @@ -11488,9 +10546,6 @@ toLower(field("name")); ### toUpper(stringExpression) {:#toupper_c25a54a} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that converts a string expression to uppercase. Signature: @@ -11522,9 +10577,6 @@ toUpper(field("title")); ### trim(stringExpression, valueToTrim) {:#trim_dd54322} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that removes leading and trailing characters from a string or byte array expression. Signature: @@ -11562,9 +10614,6 @@ trim(field("userInput"), '"'); ### timestampAdd(timestamp, unit, amount) {:#timestampadd_98418f9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds a specified amount of time to a timestamp. Signature: @@ -11598,9 +10647,6 @@ timestampAdd(field("timestamp"), field("unit"), field("amount")); ### timestampAdd(timestamp, unit, amount) {:#timestampadd_06ef927} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that adds a specified amount of time to a timestamp. Signature: @@ -11634,9 +10680,6 @@ timestampAdd(field("timestamp"), "day", 1); ### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_98418f9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a specified amount of time from a timestamp. Signature: @@ -11670,9 +10713,6 @@ timestampSubtract(field("timestamp"), field("unit"), field("amount")); ### timestampSubtract(timestamp, unit, amount) {:#timestampsubtract_06ef927} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that subtracts a specified amount of time from a timestamp. Signature: @@ -11708,9 +10748,6 @@ timestampSubtract(field("timestamp"), "day", 1); ### timestampExtract(timestampExpression, part, timezone) {:#timestampextract_b2f8f48} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that extracts a specified part from a timestamp. Signature: @@ -11744,9 +10781,6 @@ timestampExtract(field('createdAt'), 'year') ### timestampExtract(timestampExpression, part, timezone) {:#timestampextract_73e0311} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that extracts a specified part from a timestamp. Signature: @@ -11780,9 +10814,6 @@ timestampExtract(field('createdAt'), field('part')) ### timestampTruncate(timestampExpression, granularity, timezone) {:#timestamptruncate_ad5d843} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a timestamp to a specified granularity. Signature: @@ -11816,9 +10847,6 @@ timestampTruncate(field('createdAt'), 'day') ### timestampTruncate(timestampExpression, granularity, timezone) {:#timestamptruncate_d6ab2a4} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that truncates a timestamp to a specified granularity. Signature: @@ -11854,9 +10882,6 @@ timestampTruncate(field('createdAt'), field('granularity')) ### ifError(tryExpr, catchExpr) {:#iferror_a99a327} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. This overload is useful when a BooleanExpression is required. @@ -11892,9 +10917,6 @@ ifError(constant(50).divide(field('length')).greaterThan(1), constant(false)); ### ifError(tryExpr, catchExpr) {:#iferror_756c12e} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. Signature: @@ -11928,9 +10950,6 @@ ifError(field("title").arrayGet(0), field("title")); ### ifError(tryExpr, catchValue) {:#iferror_dc532f9} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns the `catch` argument if there is an error, else return the result of the `try` argument evaluation. Signature: @@ -11966,9 +10985,6 @@ ifError(field("title").arrayGet(0), "Default Title"); ### constant(value) {:#constant_0c00f91} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a number value. Signature: @@ -11991,9 +11007,6 @@ A new `Constant` instance. ### constant(value) {:#constant_6dac335} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a VectorValue value. Signature: @@ -12016,9 +11029,6 @@ A new `Constant` instance. ### constant(value) {:#constant_7c807cd} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a string value. Signature: @@ -12041,9 +11051,6 @@ A new `Constant` instance. ### constant(value) {:#constant_b2e4f8d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `BooleanExpression` instance for a boolean value. Signature: @@ -12066,9 +11073,6 @@ A new `Constant` instance. ### constant(value) {:#constant_73ebd84} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a null value. Signature: @@ -12091,9 +11095,6 @@ A new `Constant` instance. ### constant(value) {:#constant_72a76cb} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a GeoPoint value. Signature: @@ -12116,9 +11117,6 @@ A new `Constant` instance. ### constant(value) {:#constant_000477d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a Timestamp value. Signature: @@ -12141,9 +11139,6 @@ A new `Constant` instance. ### constant(value) {:#constant_5131bf7} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a Date value. Signature: @@ -12166,9 +11161,6 @@ A new `Constant` instance. ### constant(value) {:#constant_fdf565d} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a Bytes value. Signature: @@ -12191,9 +11183,6 @@ A new `Constant` instance. ### constant(value) {:#constant_bcd2b0b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates a `Constant` instance for a DocumentReference value. Signature: @@ -12216,9 +11205,6 @@ A new `Constant` instance. ### exists(value) {:#exists_f3daf14} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a field exists. Signature: @@ -12250,9 +11236,6 @@ exists(field("phoneNumber")); ### isAbsent(value) {:#isabsent_f3daf14} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that returns `true` if a value is absent. Otherwise, returns `false` even if the value is `null`. Signature: @@ -12284,9 +11267,6 @@ isAbsent(field("value")); ### isError(value) {:#iserror_f3daf14} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that checks if a given expression produces an error. Signature: @@ -12320,9 +11300,6 @@ isError(field("title").arrayContains(1)); ### cosineDistance(vectorExpression, vector) {:#cosinedistance_3a80317} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Cosine distance between a vector expression and a vector literal. Signature: @@ -12355,9 +11332,6 @@ cosineDistance(field("location"), [37.7749, -122.4194]); ### cosineDistance(vectorExpression, otherVectorExpression) {:#cosinedistance_17b5bcc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Cosine distance between two vector expressions. Signature: @@ -12390,9 +11364,6 @@ cosineDistance(field("userVector"), field("itemVector")); ### dotProduct(vectorExpression, vector) {:#dotproduct_3a80317} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the dot product between a vector expression and a double array. Signature: @@ -12425,9 +11396,6 @@ dotProduct(field("features"), [0.5, 0.8, 0.2]); ### dotProduct(vectorExpression, otherVectorExpression) {:#dotproduct_17b5bcc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the dot product between two vector expressions. Signature: @@ -12460,9 +11428,6 @@ dotProduct(field("docVector1"), field("docVector2")); ### euclideanDistance(vectorExpression, vector) {:#euclideandistance_3a80317} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Euclidean distance between a vector expression and a double array. Signature: @@ -12496,9 +11461,6 @@ euclideanDistance(field("location"), [37.7749, -122.4194]); ### euclideanDistance(vectorExpression, otherVectorExpression) {:#euclideandistance_17b5bcc} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Calculates the Euclidean distance between two vector expressions. Signature: @@ -12531,9 +11493,6 @@ euclideanDistance(field("pointA"), field("pointB")); ### vectorLength(vectorExpression) {:#vectorlength_58a039b} -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Creates an expression that calculates the length of a Firestore Vector. Signature: @@ -12565,9 +11524,6 @@ vectorLength(field("embedding")); ## AddFieldsStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how an AddFieldsStage is evaluated. See [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields). Signature: @@ -12580,9 +11536,6 @@ export declare type AddFieldsStageOptions = StageOptions & { ## AggregateStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how an AggregateStage is evaluated. See [Pipeline.aggregate()](./firestore_pipelines.pipeline.md#pipelineaggregate). Signature: @@ -12596,9 +11549,6 @@ export declare type AggregateStageOptions = StageOptions & { ## CollectionGroupStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution. See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. @@ -12614,9 +11564,6 @@ export declare type CollectionGroupStageOptions = StageOptions & { ## CollectionStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). Signature: @@ -12630,9 +11577,6 @@ export declare type CollectionStageOptions = StageOptions & { ## DatabaseStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). Signature: @@ -12643,9 +11587,6 @@ export declare type DatabaseStageOptions = StageOptions & {}; ## DistinctStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). Signature: @@ -12658,9 +11599,6 @@ export declare type DistinctStageOptions = StageOptions & { ## DocumentsStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a DocumentsStage is evaluated. See [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments). Signature: @@ -12673,9 +11611,6 @@ export declare type DocumentsStageOptions = StageOptions & { ## ExpressionType -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An enumeration of the different types of expressions. Signature: @@ -12686,9 +11621,6 @@ export declare type ExpressionType = 'Field' | 'Constant' | 'Function' | 'Aggreg ## FindNearestStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a FindNearestStage is evaluated. See [Pipeline.findNearest()](./firestore_pipelines.pipeline.md#pipelinefindnearest). Signature: @@ -12705,9 +11637,6 @@ export declare type FindNearestStageOptions = StageOptions & { ## LimitStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a LimitStage is evaluated. See [Pipeline.limit()](./firestore_pipelines.pipeline.md#pipelinelimit). Signature: @@ -12720,9 +11649,6 @@ export declare type LimitStageOptions = StageOptions & { ## OffsetStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how an OffsetStage is evaluated. See [Pipeline.offset()](./firestore_pipelines.pipeline.md#pipelineoffset). Signature: @@ -12735,9 +11661,6 @@ export declare type OffsetStageOptions = StageOptions & { ## OneOf -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Utility type to create an type that only allows one property of the Type param T to be set. Signature: @@ -12785,9 +11708,6 @@ export declare type Primitive = string | number | boolean | undefined | null; ## RemoveFieldsStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). Signature: @@ -12800,9 +11720,6 @@ export declare type RemoveFieldsStageOptions = StageOptions & { ## ReplaceWithStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). Signature: @@ -12815,9 +11732,6 @@ export declare type ReplaceWithStageOptions = StageOptions & { ## SampleStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied. See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. @@ -12833,9 +11747,6 @@ export declare type SampleStageOptions = StageOptions & OneOf<{ ## SelectStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). Signature: @@ -12862,9 +11773,6 @@ export declare type SetOptions = { ## SortStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). Signature: @@ -12877,9 +11785,6 @@ export declare type SortStageOptions = StageOptions & { ## TimeGranularity -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Specify time granularity for expressions. Signature: @@ -12890,9 +11795,6 @@ export declare type TimeGranularity = TimeUnit | 'week' | 'week(monday)' | 'week ## TimePart -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Specify time parts for `timestampExtract` expressions. Signature: @@ -12903,9 +11805,6 @@ export declare type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; ## TimeUnit -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Specify time units for expressions. Signature: @@ -12916,9 +11815,6 @@ export declare type TimeUnit = 'microsecond' | 'millisecond' | 'second' | 'minut ## Type -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An enumeration of the different types generated by the Firestore backend.
    • Numerics evaluate directly to backend representation (`int64` or `float64`), not JS `number`.
    • JavaScript `Date` and firestore `Timestamp` objects strictly evaluate to `'timestamp'`.
    • Advanced configurations parsing backend types (such as `decimal128`, `max_key` or `min_key` from BSON) are also incorporated in this union string type. Note that `decimal128` is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    @@ -12931,9 +11827,6 @@ export declare type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' ## UnionStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). Signature: @@ -12946,9 +11839,6 @@ export declare type UnionStageOptions = StageOptions & { ## UnnestStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents the specific options available for configuring an `UnnestStage` within a pipeline. Signature: @@ -12962,9 +11852,6 @@ export declare type UnnestStageOptions = StageOptions & { ## WhereStageOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). Signature: diff --git a/docs-devsite/firestore_pipelines.ordering.md b/docs-devsite/firestore_pipelines.ordering.md index 373f962aee..fad55e25a8 100644 --- a/docs-devsite/firestore_pipelines.ordering.md +++ b/docs-devsite/firestore_pipelines.ordering.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # Ordering class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents an ordering criterion for sorting documents in a Firestore pipeline. You create `Ordering` instances using the `ascending` and `descending` helper functions. @@ -27,20 +24,17 @@ export declare class Ordering | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(expr, direction, \_methodName)](./firestore_pipelines.ordering.md#orderingconstructor) | | (Public Preview) Constructs a new instance of the Ordering class | +| [(constructor)(expr, direction, \_methodName)](./firestore_pipelines.ordering.md#orderingconstructor) | | Constructs a new instance of the Ordering class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [direction](./firestore_pipelines.ordering.md#orderingdirection) | | 'ascending' \| 'descending' | (Public Preview) | -| [expr](./firestore_pipelines.ordering.md#orderingexpr) | | [Expression](./firestore_pipelines.expression.md#expression_class) | (Public Preview) | +| [direction](./firestore_pipelines.ordering.md#orderingdirection) | | 'ascending' \| 'descending' | | +| [expr](./firestore_pipelines.ordering.md#orderingexpr) | | [Expression](./firestore_pipelines.expression.md#expression_class) | | ## Ordering.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `Ordering` class Signature: @@ -59,9 +53,6 @@ constructor(expr: Expression, direction: 'ascending' | 'descending', _methodName ## Ordering.direction -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript @@ -70,9 +61,6 @@ readonly direction: 'ascending' | 'descending'; ## Ordering.expr -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/firestore_pipelines.pipeline.md b/docs-devsite/firestore_pipelines.pipeline.md index 4ba1ba716c..87c516b13c 100644 --- a/docs-devsite/firestore_pipelines.pipeline.md +++ b/docs-devsite/firestore_pipelines.pipeline.md @@ -10,10 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # Pipeline class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - - Signature: ```typescript @@ -24,40 +20,63 @@ export declare class Pipeline | Method | Modifiers | Description | | --- | --- | --- | -| [addFields(field, additionalFields)](./firestore_pipelines.pipeline.md#pipelineaddfields) | | (Public Preview) | -| [addFields(options)](./firestore_pipelines.pipeline.md#pipelineaddfields) | | (Public Preview) | -| [aggregate(accumulator, additionalAccumulators)](./firestore_pipelines.pipeline.md#pipelineaggregate) | | (Public Preview) | -| [aggregate(options)](./firestore_pipelines.pipeline.md#pipelineaggregate) | | (Public Preview) | -| [distinct(group, additionalGroups)](./firestore_pipelines.pipeline.md#pipelinedistinct) | | (Public Preview) | -| [distinct(options)](./firestore_pipelines.pipeline.md#pipelinedistinct) | | (Public Preview) | -| [findNearest(options)](./firestore_pipelines.pipeline.md#pipelinefindnearest) | | (Public Preview) | -| [limit(limit)](./firestore_pipelines.pipeline.md#pipelinelimit) | | (Public Preview) | -| [limit(options)](./firestore_pipelines.pipeline.md#pipelinelimit) | | (Public Preview) | -| [offset(offset)](./firestore_pipelines.pipeline.md#pipelineoffset) | | (Public Preview) | -| [offset(options)](./firestore_pipelines.pipeline.md#pipelineoffset) | | (Public Preview) | -| [rawStage(name, params, options)](./firestore_pipelines.pipeline.md#pipelinerawstage) | | (Public Preview) | -| [removeFields(fieldValue, additionalFields)](./firestore_pipelines.pipeline.md#pipelineremovefields) | | (Public Preview) | -| [removeFields(options)](./firestore_pipelines.pipeline.md#pipelineremovefields) | | (Public Preview) | -| [replaceWith(fieldName)](./firestore_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) | -| [replaceWith(expr)](./firestore_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) | -| [replaceWith(options)](./firestore_pipelines.pipeline.md#pipelinereplacewith) | | (Public Preview) | -| [sample(documents)](./firestore_pipelines.pipeline.md#pipelinesample) | | (Public Preview) | -| [sample(options)](./firestore_pipelines.pipeline.md#pipelinesample) | | (Public Preview) | -| [select(selection, additionalSelections)](./firestore_pipelines.pipeline.md#pipelineselect) | | (Public Preview) | -| [select(options)](./firestore_pipelines.pipeline.md#pipelineselect) | | (Public Preview) | -| [sort(ordering, additionalOrderings)](./firestore_pipelines.pipeline.md#pipelinesort) | | (Public Preview) | -| [sort(options)](./firestore_pipelines.pipeline.md#pipelinesort) | | (Public Preview) | -| [union(other)](./firestore_pipelines.pipeline.md#pipelineunion) | | (Public Preview) | -| [union(options)](./firestore_pipelines.pipeline.md#pipelineunion) | | (Public Preview) | -| [unnest(selectable, indexField)](./firestore_pipelines.pipeline.md#pipelineunnest) | | (Public Preview) | -| [unnest(options)](./firestore_pipelines.pipeline.md#pipelineunnest) | | (Public Preview) | -| [where(condition)](./firestore_pipelines.pipeline.md#pipelinewhere) | | (Public Preview) | -| [where(options)](./firestore_pipelines.pipeline.md#pipelinewhere) | | (Public Preview) | +| [addFields(field, additionalFields)](./firestore_pipelines.pipeline.md#pipelineaddfields) | | Adds new fields to outputs from previous stages.This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps).The added fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s, which can be:- [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [Expression](./firestore_pipelines.expression.md#expression_class): Either a literal value (see [constant()](./firestore_pipelines.md#constant_0c00f91)) or a computed value with an assigned alias using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | +| [addFields(options)](./firestore_pipelines.pipeline.md#pipelineaddfields) | | | +| [aggregate(accumulator, additionalAccumulators)](./firestore_pipelines.pipeline.md#pipelineaggregate) | | Performs aggregation operations on the documents from previous stages.

    This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions which are typically results of calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances.

    Example: | +| [aggregate(options)](./firestore_pipelines.pipeline.md#pipelineaggregate) | | Performs optionally grouped aggregation operations on the documents from previous stages.

    This stage allows you to calculate aggregate values over a set of documents, optionally grouped by one or more fields or functions. You can specify:

    • \*\*Grouping Fields or Functions:\*\* One or more fields or functions to group the documents by. For each distinct combination of values in these fields, a separate group is created. If no grouping fields are provided, a single group containing all documents is used. Not specifying groups is the same as putting the entire inputs into one group.
    • \*\*Accumulators:\*\* One or more accumulation operations to perform within each group. These are defined using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions, which are typically created by calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances. Each aggregation calculates a value (e.g., sum, average, count) based on the documents within its group.

    Example: | +| [distinct(group, additionalGroups)](./firestore_pipelines.pipeline.md#pipelinedistinct) | | Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc).The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings:- string: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | +| [distinct(options)](./firestore_pipelines.pipeline.md#pipelinedistinct) | | | +| [findNearest(options)](./firestore_pipelines.pipeline.md#pipelinefindnearest) | | Performs a vector proximity search on the documents from the previous stage, returning the K-nearest documents based on the specified query vectorValue and distanceMeasure. The returned documents will be sorted in order from nearest to furthest from the query vectorValue.

    Example: +```typescript +// Find the 10 most similar books based on the book description. +const bookDescription = "Lorem ipsum..."; +const queryVector: number[] = ...; // compute embedding of `bookDescription` + +firestore.pipeline().collection("books") +.findNearest({ +field: 'embedding', +vectorValue: queryVector, +distanceMeasure: 'euclidean', +limit: 10, // optional +distanceField: 'computedDistance' // optional +}); + +``` + | +| [limit(limit)](./firestore_pipelines.pipeline.md#pipelinelimit) | | Limits the maximum number of documents returned by previous stages to limit.

    This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for:

    • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
    • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.

    Example: | +| [limit(options)](./firestore_pipelines.pipeline.md#pipelinelimit) | | | +| [offset(offset)](./firestore_pipelines.pipeline.md#pipelineoffset) | | Skips the first offset number of documents from the results of previous stages.

    This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page.

    Example: | +| [offset(options)](./firestore_pipelines.pipeline.md#pipelineoffset) | | | +| [rawStage(name, params, options)](./firestore_pipelines.pipeline.md#pipelinerawstage) | | Adds a raw stage to the pipeline.

    This method provides a flexible way to extend the pipeline's functionality by adding custom stages. Each raw stage is defined by a unique name and a set of params that control its behavior.

    Example (Assuming there is no 'where' stage available in SDK): | +| [removeFields(fieldValue, additionalFields)](./firestore_pipelines.pipeline.md#pipelineremovefields) | | Remove fields from outputs of previous stages.Example: | +| [removeFields(options)](./firestore_pipelines.pipeline.md#pipelineremovefields) | | | +| [replaceWith(fieldName)](./firestore_pipelines.pipeline.md#pipelinereplacewith) | | Fully overwrites all fields in a document with those coming from a nested map.

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

    Example: | +| [replaceWith(expr)](./firestore_pipelines.pipeline.md#pipelinereplacewith) | | Fully overwrites all fields in a document with those coming from a map.

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

    Example: | +| [replaceWith(options)](./firestore_pipelines.pipeline.md#pipelinereplacewith) | | | +| [sample(documents)](./firestore_pipelines.pipeline.md#pipelinesample) | | Performs a pseudo-random sampling of the documents from the previous stage.

    This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned.

    Examples: | +| [sample(options)](./firestore_pipelines.pipeline.md#pipelinesample) | | Performs a pseudo-random sampling of the documents from the previous stage.

    This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) for more information. | +| [select(selection, additionalSelections)](./firestore_pipelines.pipeline.md#pipelineselect) | | Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

    • string : Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

    Example: | +| [select(options)](./firestore_pipelines.pipeline.md#pipelineselect) | | Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

    • string: Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

    Example: | +| [sort(ordering, additionalOrderings)](./firestore_pipelines.pipeline.md#pipelinesort) | | Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

    Example: | +| [sort(options)](./firestore_pipelines.pipeline.md#pipelinesort) | | | +| [union(other)](./firestore_pipelines.pipeline.md#pipelineunion) | | Performs union of all documents from two pipelines, including duplicates.

    This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined.

    Example: | +| [union(options)](./firestore_pipelines.pipeline.md#pipelineunion) | | | +| [unnest(selectable, indexField)](./firestore_pipelines.pipeline.md#pipelineunnest) | | Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: | +| [unnest(options)](./firestore_pipelines.pipeline.md#pipelineunnest) | | | +| [where(condition)](./firestore_pipelines.pipeline.md#pipelinewhere) | | Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class).

    This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to:

    • field comparators: [Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), [Expression.greaterThan()](./firestore_pipelines.expression.md#expressiongreaterthan), etc.
    • logical operators: , , , etc.
    • advanced functions: [Expression.regexMatch()](./firestore_pipelines.expression.md#expressionregexmatch), [Expression.arrayContains()](./firestore_pipelines.expression.md#expressionarraycontains), etc.

    Example: | +| [where(options)](./firestore_pipelines.pipeline.md#pipelinewhere) | | Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class).

    This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to:

    • field comparators: , (less than), [Expression.greaterThan()](./firestore_pipelines.expression.md#expressiongreaterthan), etc.
    • logical operators: , , , etc.
    • advanced functions: [Expression.regexMatch()](./firestore_pipelines.expression.md#expressionregexmatch), [Expression.arrayContains()](./firestore_pipelines.expression.md#expressionarraycontains), etc.

    Example: | ## Pipeline.addFields() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Adds new fields to outputs from previous stages. + +This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps). + +The added fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s, which can be: + +- [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [Expression](./firestore_pipelines.expression.md#expression_class): Either a literal value (see [constant()](./firestore_pipelines.md#constant_0c00f91)) or a computed value with an assigned alias using [Expression.as()](./firestore_pipelines.expression.md#expressionas). + +Example: Signature: @@ -69,17 +88,28 @@ addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| field | [Selectable](./firestore_pipelines.selectable.md#selectable_interface) | | -| additionalFields | [Selectable](./firestore_pipelines.selectable.md#selectable_interface)\[\] | | +| field | [Selectable](./firestore_pipelines.selectable.md#selectable_interface) | The first field to add to the documents, specified as a [Selectable](./firestore_pipelines.selectable.md#selectable_interface). | +| additionalFields | [Selectable](./firestore_pipelines.selectable.md#selectable_interface)\[\] | Optional additional fields to add to the documents, specified as [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) -## Pipeline.addFields() +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +firestore.pipeline().collection("books") +.addFields( +field("rating").as("bookRating"), // Rename 'rating' to 'bookRating' +add(field("quantity"), 5).as("totalCost") // Calculate 'totalCost' +); + +``` -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +## Pipeline.addFields() Signature: @@ -99,8 +129,11 @@ addFields(options: AddFieldsStageOptions): Pipeline; ## Pipeline.aggregate() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Performs aggregation operations on the documents from previous stages. + +

    This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions which are typically results of calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances. + +

    Example: Signature: @@ -112,17 +145,37 @@ aggregate(accumulator: AliasedAggregate, ...additionalAccumulators: AliasedAggre | Parameter | Type | Description | | --- | --- | --- | -| accumulator | [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) | | -| additionalAccumulators | [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class)\[\] | | +| accumulator | [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) | The first [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class), wrapping an [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) and providing a name for the accumulated results. | +| additionalAccumulators | [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class)\[\] | Optional additional [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class), each wrapping an [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) and providing a name for the accumulated results. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +// Calculate the average rating and the total number of books +firestore.pipeline().collection("books") +.aggregate( +field("rating").average().as("averageRating"), +countAll().as("totalBooks") +); + +``` + ## Pipeline.aggregate() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Performs optionally grouped aggregation operations on the documents from previous stages. + +

    This stage allows you to calculate aggregate values over a set of documents, optionally grouped by one or more fields or functions. You can specify: + +

    • \*\*Grouping Fields or Functions:\*\* One or more fields or functions to group the documents by. For each distinct combination of values in these fields, a separate group is created. If no grouping fields are provided, a single group containing all documents is used. Not specifying groups is the same as putting the entire inputs into one group.
    • \*\*Accumulators:\*\* One or more accumulation operations to perform within each group. These are defined using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions, which are typically created by calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances. Each aggregation calculates a value (e.g., sum, average, count) based on the documents within its group.
    + +

    Example: Signature: @@ -134,16 +187,38 @@ aggregate(options: AggregateStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [AggregateStageOptions](./firestore_pipelines.md#aggregatestageoptions) | | +| options | [AggregateStageOptions](./firestore_pipelines.md#aggregatestageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Calculate the average rating for each genre. +firestore.pipeline().collection("books") +.aggregate({ +accumulators: [average(field("rating")).as("avg_rating")], +groups: ["genre"] +}); + +``` + ## Pipeline.distinct() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Returns a set of distinct values from the inputs to this stage. + +This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc). + +The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings: + +- `string`: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas). + +Example: Signature: @@ -155,17 +230,27 @@ distinct(group: string | Selectable, ...additionalGroups: Array> | | +| group | string \| [Selectable](./firestore_pipelines.selectable.md#selectable_interface) | The [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expression or field name to consider when determining distinct value combinations. | +| additionalGroups | Array<string \| [Selectable](./firestore_pipelines.selectable.md#selectable_interface)> | Optional additional [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions to consider when determining distinct value combinations or strings representing field names. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) -## Pipeline.distinct() +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Get a list of unique author names in uppercase and genre combinations. +firestore.pipeline().collection("books") +.distinct(toUpper(field("author")).as("authorName"), field("genre"), "publishedAt") +.select("authorName"); -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +``` + +## Pipeline.distinct() Signature: @@ -185,8 +270,25 @@ distinct(options: DistinctStageOptions): Pipeline; ## Pipeline.findNearest() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Performs a vector proximity search on the documents from the previous stage, returning the K-nearest documents based on the specified query `vectorValue` and `distanceMeasure`. The returned documents will be sorted in order from nearest to furthest from the query `vectorValue`. + +

    Example: + +```typescript +// Find the 10 most similar books based on the book description. +const bookDescription = "Lorem ipsum..."; +const queryVector: number[] = ...; // compute embedding of `bookDescription` + +firestore.pipeline().collection("books") +.findNearest({ +field: 'embedding', +vectorValue: queryVector, +distanceMeasure: 'euclidean', +limit: 10, // optional +distanceField: 'computedDistance' // optional +}); + +``` Signature: @@ -198,16 +300,23 @@ findNearest(options: FindNearestStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [FindNearestStageOptions](./firestore_pipelines.md#findneareststageoptions) | | +| options | [FindNearestStageOptions](./firestore_pipelines.md#findneareststageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + ## Pipeline.limit() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Limits the maximum number of documents returned by previous stages to `limit`. + +

    This stage is particularly useful when you want to retrieve a controlled subset of data from a potentially large result set. It's often used for: + +

    • \*\*Pagination:\*\* In combination with to retrieve specific pages of results.
    • \*\*Limiting Data Retrieval:\*\* To prevent excessive data transfer and improve performance, especially when dealing with large collections.
    + +

    Example: Signature: @@ -219,16 +328,26 @@ limit(limit: number): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| limit | number | | +| limit | number | The maximum number of documents to return. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) -## Pipeline.limit() +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +// Limit the results to the top 10 highest-rated books +firestore.pipeline().collection('books') +.sort(field('rating').descending()) +.limit(10); + +``` -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +## Pipeline.limit() Signature: @@ -248,8 +367,11 @@ limit(options: LimitStageOptions): Pipeline; ## Pipeline.offset() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Skips the first `offset` number of documents from the results of previous stages. + +

    This stage is useful for implementing pagination in your pipelines, allowing you to retrieve results in chunks. It is typically used in conjunction with to control the size of each page. + +

    Example: Signature: @@ -261,16 +383,27 @@ offset(offset: number): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| offset | number | | +| offset | number | The number of documents to skip. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) -## Pipeline.offset() +A new Pipeline object with this stage appended to the stage list. -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +### Example + + +```typescript +// Retrieve the second page of 20 results +firestore.pipeline().collection('books') +.sort(field('published').descending()) +.offset(20) // Skip the first 20 results +.limit(20); // Take the next 20 results + +``` + +## Pipeline.offset() Signature: @@ -290,8 +423,11 @@ offset(options: OffsetStageOptions): Pipeline; ## Pipeline.rawStage() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Adds a raw stage to the pipeline. + +

    This method provides a flexible way to extend the pipeline's functionality by adding custom stages. Each raw stage is defined by a unique `name` and a set of `params` that control its behavior. + +

    Example (Assuming there is no 'where' stage available in SDK): Signature: @@ -303,18 +439,32 @@ rawStage(name: string, params: unknown[], options?: { [key: string]: Expression | Parameter | Type | Description | | --- | --- | --- | -| name | string | | -| params | unknown\[\] | | -| options | { \[key: string\]: [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown; } | | +| name | string | The unique name of the raw stage to add. | +| params | unknown\[\] | A list of parameters to configure the raw stage's behavior. | +| options | { \[key: string\]: [Expression](./firestore_pipelines.expression.md#expression_class) \| unknown; } | An object of key value pairs that specifies optional parameters for the stage. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Assume we don't have a built-in 'where' stage +firestore.pipeline().collection('books') +.rawStage('where', [field('published').lessThan(1900)]) // Custom 'where' stage +.select('title', 'author'); + +``` + ## Pipeline.removeFields() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Remove fields from outputs of previous stages. + +Example: Signature: @@ -326,17 +476,29 @@ removeFields(fieldValue: Field | string, ...additionalFields: ArrayReturns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) -## Pipeline.removeFields() +A new Pipeline object with this stage appended to the stage list. + +### Example -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> + +```typescript +firestore.pipeline().collection('books') +// removes field 'rating' and 'cost' from the previous stage outputs. +.removeFields( +field('rating'), +'cost' +); + +``` + +## Pipeline.removeFields() Signature: @@ -356,8 +518,11 @@ removeFields(options: RemoveFieldsStageOptions): Pipeline; ## Pipeline.replaceWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Fully overwrites all fields in a document with those coming from a nested map. + +

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value. + +

    Example: Signature: @@ -369,16 +534,43 @@ replaceWith(fieldName: string): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| fieldName | string | | +| fieldName | string | The [Field](./firestore_pipelines.field.md#field_class) field containing the nested map. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Input. +// { +// 'name': 'John Doe Jr.', +// 'parents': { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } +// } +// Emit parents as document. +firestore.pipeline().collection('people').replaceWith('parents'); +// Output +// { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } + +``` + ## Pipeline.replaceWith() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Fully overwrites all fields in a document with those coming from a map. + +

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value. + +

    Example: Signature: @@ -390,16 +582,42 @@ replaceWith(expr: Expression): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | | +| expr | [Expression](./firestore_pipelines.expression.md#expression_class) | An [Expression](./firestore_pipelines.expression.md#expression_class) that when returned evaluates to a map. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) -## Pipeline.replaceWith() +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> + +```typescript +// Input. +// { +// 'name': 'John Doe Jr.', +// 'parents': { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } +// } +// Emit parents as document. +firestore.pipeline().collection('people').replaceWith(map({ +foo: 'bar', +info: { +name: field('name') +} +})); +// Output +// { +// 'father': 'John Doe Sr.', +// 'mother': 'Jane Doe' +// } + +``` + +## Pipeline.replaceWith() Signature: @@ -419,8 +637,11 @@ replaceWith(options: ReplaceWithStageOptions): Pipeline; ## Pipeline.sample() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Performs a pseudo-random sampling of the documents from the previous stage. + +

    This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned. + +

    Examples: Signature: @@ -432,16 +653,29 @@ sample(documents: number): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| documents | number | | +| documents | number | The number of documents to sample. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Sample 25 books, if available. +firestore.pipeline().collection('books') +.sample(25); + +``` + ## Pipeline.sample() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Performs a pseudo-random sampling of the documents from the previous stage. + +

    This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) for more information. Signature: @@ -453,16 +687,38 @@ sample(options: SampleStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) | | +| options | [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + + +```typescript +// Sample 10 books, if available. +firestore.pipeline().collection("books") +.sample({ documents: 10 }); +// Sample 50% of books. +firestore.pipeline().collection("books") +.sample({ percentage: 0.5 }); + +``` + ## Pipeline.select() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Selects or creates a set of fields from the outputs of previous stages. + +

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be: + +

    • `string` : Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)
    + +

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired. + +

    Example: Signature: @@ -474,17 +730,39 @@ select(selection: Selectable | string, ...additionalSelections: Arraystring values representing field names. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +db.pipeline().collection("books") +.select( +"firstName", +field("lastName"), +field("address").toUpper().as("upperAddress"), +); + +``` + ## Pipeline.select() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Selects or creates a set of fields from the outputs of previous stages. + +

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be: + +

    • `string`: Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)
    + +

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired. + +

    Example: Signature: @@ -496,16 +774,34 @@ select(options: SelectStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [SelectStageOptions](./firestore_pipelines.md#selectstageoptions) | | +| options | [SelectStageOptions](./firestore_pipelines.md#selectstageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +db.pipeline().collection("books") +.select( +"firstName", +field("lastName"), +field("address").toUpper().as("upperAddress"), +); + +``` + ## Pipeline.sort() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria. + +

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified. + +

    Example: Signature: @@ -517,17 +813,30 @@ sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| ordering | [Ordering](./firestore_pipelines.ordering.md#ordering_class) | | -| additionalOrderings | [Ordering](./firestore_pipelines.ordering.md#ordering_class)\[\] | | +| ordering | [Ordering](./firestore_pipelines.ordering.md#ordering_class) | The first [Ordering](./firestore_pipelines.ordering.md#ordering_class) instance specifying the sorting criteria. | +| additionalOrderings | [Ordering](./firestore_pipelines.ordering.md#ordering_class)\[\] | Optional additional [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances specifying the additional sorting criteria. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) -## Pipeline.sort() +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> + +```typescript +// Sort books by rating in descending order, and then by title in ascending order for books +// with the same rating +firestore.pipeline().collection("books") +.sort( +field("rating").descending(), +field("title").ascending() +); + +``` + +## Pipeline.sort() Signature: @@ -547,8 +856,11 @@ sort(options: SortStageOptions): Pipeline; ## Pipeline.union() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Performs union of all documents from two pipelines, including duplicates. + +

    This stage will pass through documents from previous stage, and also pass through documents from previous stage of the `other` [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined. + +

    Example: Signature: @@ -560,16 +872,25 @@ union(other: Pipeline): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| other | [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | | +| other | [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | The other [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) that is part of union. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) -## Pipeline.union() +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> + +```typescript +// Emit documents from books collection and magazines collection. +firestore.pipeline().collection('books') +.union(firestore.pipeline().collection('magazines')); + +``` + +## Pipeline.union() Signature: @@ -589,8 +910,15 @@ union(options: UnionStageOptions): Pipeline; ## Pipeline.unnest() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Produces a document for each element in an input array. + +For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the `selectable` parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the `alias` field with the array element value. + +When `selectable` evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the `alias` field absent. + +No documents are emitted when `selectable` evaluates to an empty array. + +Example: Signature: @@ -602,17 +930,32 @@ unnest(selectable: Selectable, indexField?: string): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| selectable | [Selectable](./firestore_pipelines.selectable.md#selectable_interface) | | -| indexField | string | | +| selectable | [Selectable](./firestore_pipelines.selectable.md#selectable_interface) | A selectable expression defining the field to unnest and the alias to use for each un-nested element in the output documents. | +| indexField | string | An optional string value specifying the field path to write the offset (starting at zero) into the array the un-nested element is from | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) -## Pipeline.unnest() +A new [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) object with this stage appended to the stage list. + +### Example + -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +```typescript +// Input: +// { "title": "The Hitchhiker's Guide to the Galaxy", "tags": [ "comedy", "space", "adventure" ], ... } +// Emit a book document for each tag of the book. +firestore.pipeline().collection("books") +.unnest(field("tags").as('tag'), 'tagIndex'); +// Output: +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "comedy", "tagIndex": 0, ... } +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "space", "tagIndex": 1, ... } +// { "title": "The Hitchhiker's Guide to the Galaxy", "tag": "adventure", "tagIndex": 2, ... } + +``` + +## Pipeline.unnest() Signature: @@ -632,8 +975,13 @@ unnest(options: UnnestStageOptions): Pipeline; ## Pipeline.where() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class). + +

    This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to: + +

    • field comparators: [Expression.equal()](./firestore_pipelines.expression.md#expressionequal), [Expression.lessThan()](./firestore_pipelines.expression.md#expressionlessthan), [Expression.greaterThan()](./firestore_pipelines.expression.md#expressiongreaterthan), etc.
    • logical operators: , , , etc.
    • advanced functions: [Expression.regexMatch()](./firestore_pipelines.expression.md#expressionregexmatch), [Expression.arrayContains()](./firestore_pipelines.expression.md#expressionarraycontains), etc.
    + +

    Example: Signature: @@ -645,16 +993,37 @@ where(condition: BooleanExpression): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| condition | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | | +| condition | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) to apply. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +firestore.pipeline().collection("books") +.where( +and( +greaterThan(field("rating"), 4.0), // Filter for ratings greater than 4.0 +field("genre").equal("Science Fiction") // Equivalent to equal("genre", "Science Fiction") +) +); + +``` + ## Pipeline.where() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> +Filters the documents from previous stages to only include those matching the specified [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class). + +

    This stage allows you to apply conditions to the data, similar to a "WHERE" clause in SQL. You can filter documents based on their field values, using implementations of [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class), typically including but not limited to: + +

    • field comparators: , (less than), [Expression.greaterThan()](./firestore_pipelines.expression.md#expressiongreaterthan), etc.
    • logical operators: , , , etc.
    • advanced functions: [Expression.regexMatch()](./firestore_pipelines.expression.md#expressionregexmatch), [Expression.arrayContains()](./firestore_pipelines.expression.md#expressionarraycontains), etc.
    + +

    Example: Signature: @@ -666,9 +1035,25 @@ where(options: WhereStageOptions): Pipeline; | Parameter | Type | Description | | --- | --- | --- | -| options | [WhereStageOptions](./firestore_pipelines.md#wherestageoptions) | | +| options | [WhereStageOptions](./firestore_pipelines.md#wherestageoptions) | An object that specifies required and optional parameters for the stage. | Returns: [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +firestore.pipeline().collection("books") +.where( +and( +greaterThan(field("rating"), 4.0), // Filter for ratings greater than 4.0 +field("genre").equal("Science Fiction") // Equivalent to equal("genre", "Science Fiction") +) +); + +``` + diff --git a/docs-devsite/firestore_pipelines.pipelineexecuteoptions.md b/docs-devsite/firestore_pipelines.pipelineexecuteoptions.md index 68110fa74f..e34488307d 100644 --- a/docs-devsite/firestore_pipelines.pipelineexecuteoptions.md +++ b/docs-devsite/firestore_pipelines.pipelineexecuteoptions.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # PipelineExecuteOptions interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining Pipeline execution. Signature: @@ -25,15 +22,12 @@ export declare interface PipelineExecuteOptions | Property | Type | Description | | --- | --- | --- | -| [indexMode](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionsindexmode) | 'recommended' | (Public Preview) Specify the index mode. | -| [pipeline](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionspipeline) | [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | (Public Preview) Pipeline to be evaluated. | -| [rawOptions](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionsrawoptions) | { \[name: string\]: unknown; } | (Public Preview) An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Custom option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK. | +| [indexMode](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionsindexmode) | 'recommended' | Specify the index mode. | +| [pipeline](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionspipeline) | [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) | Pipeline to be evaluated. | +| [rawOptions](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptionsrawoptions) | { \[name: string\]: unknown; } | An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Custom option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK. | ## PipelineExecuteOptions.indexMode -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Specify the index mode. Signature: @@ -44,9 +38,6 @@ indexMode?: 'recommended'; ## PipelineExecuteOptions.pipeline -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Pipeline to be evaluated. Signature: @@ -57,9 +48,6 @@ pipeline: Pipeline; ## PipelineExecuteOptions.rawOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK. The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name). diff --git a/docs-devsite/firestore_pipelines.pipelineresult.md b/docs-devsite/firestore_pipelines.pipelineresult.md index 6a04334e14..cf9849d57f 100644 --- a/docs-devsite/firestore_pipelines.pipelineresult.md +++ b/docs-devsite/firestore_pipelines.pipelineresult.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # PipelineResult class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the [PipelineResult.data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) or [PipelineResult.get()](./firestore_pipelines.pipelineresult.md#pipelineresultget) methods.

    If the PipelineResult represents a non-document result, `ref` will return a undefined value. @@ -27,23 +24,20 @@ export declare class PipelineResult | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [createTime](./firestore_pipelines.pipelineresult.md#pipelineresultcreatetime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was created. Undefined if this result is not a document. | -| [id](./firestore_pipelines.pipelineresult.md#pipelineresultid) | | string \| undefined | (Public Preview) The ID of the document for which this PipelineResult contains data, if it is a document; otherwise undefined. | -| [ref](./firestore_pipelines.pipelineresult.md#pipelineresultref) | | [DocumentReference](./firestore_.documentreference.md#documentreference_class) \| undefined | (Public Preview) The reference of the document, if it is a document; otherwise undefined. | -| [updateTime](./firestore_pipelines.pipelineresult.md#pipelineresultupdatetime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) \| undefined | (Public Preview) The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. | +| [createTime](./firestore_pipelines.pipelineresult.md#pipelineresultcreatetime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) \| undefined | The time the document was created. Undefined if this result is not a document. | +| [id](./firestore_pipelines.pipelineresult.md#pipelineresultid) | | string \| undefined | The ID of the document for which this PipelineResult contains data, if it is a document; otherwise undefined. | +| [ref](./firestore_pipelines.pipelineresult.md#pipelineresultref) | | [DocumentReference](./firestore_.documentreference.md#documentreference_class) \| undefined | The reference of the document, if it is a document; otherwise undefined. | +| [updateTime](./firestore_pipelines.pipelineresult.md#pipelineresultupdatetime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) \| undefined | The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. | ## Methods | Method | Modifiers | Description | | --- | --- | --- | -| [data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) | | (Public Preview) Retrieves all fields in the result as an object. | -| [get(fieldPath)](./firestore_pipelines.pipelineresult.md#pipelineresultget) | | (Public Preview) Retrieves the field specified by field. | +| [data()](./firestore_pipelines.pipelineresult.md#pipelineresultdata) | | Retrieves all fields in the result as an object. | +| [get(fieldPath)](./firestore_pipelines.pipelineresult.md#pipelineresultget) | | Retrieves the field specified by field. | ## PipelineResult.createTime -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The time the document was created. Undefined if this result is not a document. Signature: @@ -54,9 +48,6 @@ get createTime(): Timestamp | undefined; ## PipelineResult.id -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The ID of the document for which this PipelineResult contains data, if it is a document; otherwise `undefined`. Signature: @@ -67,9 +58,6 @@ get id(): string | undefined; ## PipelineResult.ref -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The reference of the document, if it is a document; otherwise `undefined`. Signature: @@ -80,9 +68,6 @@ get ref(): DocumentReference | undefined; ## PipelineResult.updateTime -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The time the document was last updated (at the time the snapshot was generated). Undefined if this result is not a document. Signature: @@ -93,9 +78,6 @@ get updateTime(): Timestamp | undefined; ## PipelineResult.data() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Retrieves all fields in the result as an object. Signature: @@ -124,9 +106,6 @@ p.execute().then(results => { ## PipelineResult.get() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Retrieves the field specified by `field`. Signature: diff --git a/docs-devsite/firestore_pipelines.pipelinesnapshot.md b/docs-devsite/firestore_pipelines.pipelinesnapshot.md index 6aced9e047..86cd01e836 100644 --- a/docs-devsite/firestore_pipelines.pipelinesnapshot.md +++ b/docs-devsite/firestore_pipelines.pipelinesnapshot.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # PipelineSnapshot class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Represents the results of a Firestore pipeline execution. A `PipelineSnapshot` contains zero or more [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects representing the documents returned by a pipeline query. It provides methods to iterate over the documents and access metadata about the query results. @@ -27,20 +24,17 @@ export declare class PipelineSnapshot | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(pipeline, results, executionTime)](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshotconstructor) | | (Public Preview) Constructs a new instance of the PipelineSnapshot class | +| [(constructor)(pipeline, results, executionTime)](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshotconstructor) | | Constructs a new instance of the PipelineSnapshot class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [executionTime](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshotexecutiontime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) | (Public Preview) The time at which the pipeline producing this result is executed. | -| [results](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshotresults) | | [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class)\[\] | (Public Preview) An array of all the results in the PipelineSnapshot. | +| [executionTime](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshotexecutiontime) | | [Timestamp](./firestore_.timestamp.md#timestamp_class) | The time at which the pipeline producing this result is executed. | +| [results](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshotresults) | | [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class)\[\] | An array of all the results in the PipelineSnapshot. | ## PipelineSnapshot.(constructor) -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Constructs a new instance of the `PipelineSnapshot` class Signature: @@ -59,9 +53,6 @@ constructor(pipeline: Pipeline, results: PipelineResult[], executionTime?: Times ## PipelineSnapshot.executionTime -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - The time at which the pipeline producing this result is executed. Signature: @@ -72,9 +63,6 @@ get executionTime(): Timestamp; ## PipelineSnapshot.results -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An array of all the results in the `PipelineSnapshot`. Signature: diff --git a/docs-devsite/firestore_pipelines.pipelinesource.md b/docs-devsite/firestore_pipelines.pipelinesource.md index 31c5192dfd..1c573ef73f 100644 --- a/docs-devsite/firestore_pipelines.pipelinesource.md +++ b/docs-devsite/firestore_pipelines.pipelinesource.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # PipelineSource class -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Provides the entry point for defining the data source of a Firestore [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class). Use the methods of this class (e.g., [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection), [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup), [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase), or [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments)) to specify the initial data for your pipeline, such as a collection, a collection group, the entire database, or a set of specific documents. @@ -27,21 +24,18 @@ export declare class PipelineSource | Method | Modifiers | Description | | --- | --- | --- | -| [collection(collection)](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection) | | (Public Preview) Returns all documents from the entire collection. The collection can be nested. | -| [collection(options)](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection) | | (Public Preview) Returns all documents from the entire collection. The collection can be nested. | -| [collectionGroup(collectionId)](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) | | (Public Preview) Returns all documents from a collection ID regardless of the parent. | -| [collectionGroup(options)](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) | | (Public Preview) Returns all documents from a collection ID regardless of the parent. | -| [createFrom(query)](./firestore_pipelines.pipelinesource.md#pipelinesourcecreatefrom) | | (Public Preview) Convert the given Query into an equivalent Pipeline. | -| [database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase) | | (Public Preview) Returns all documents from the entire database. | -| [database(options)](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase) | | (Public Preview) Returns all documents from the entire database. | -| [documents(docs)](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments) | | (Public Preview) Set the pipeline's source to the documents specified by the given paths and DocumentReferences. | -| [documents(options)](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments) | | (Public Preview) Set the pipeline's source to the documents specified by the given paths and DocumentReferences. | +| [collection(collection)](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection) | | Returns all documents from the entire collection. The collection can be nested. | +| [collection(options)](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection) | | Returns all documents from the entire collection. The collection can be nested. | +| [collectionGroup(collectionId)](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) | | Returns all documents from a collection ID regardless of the parent. | +| [collectionGroup(options)](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) | | Returns all documents from a collection ID regardless of the parent. | +| [createFrom(query)](./firestore_pipelines.pipelinesource.md#pipelinesourcecreatefrom) | | Convert the given Query into an equivalent Pipeline. | +| [database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase) | | Returns all documents from the entire database. | +| [database(options)](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase) | | Returns all documents from the entire database. | +| [documents(docs)](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments) | | Set the pipeline's source to the documents specified by the given paths and DocumentReferences. | +| [documents(options)](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments) | | Set the pipeline's source to the documents specified by the given paths and DocumentReferences. | ## PipelineSource.collection() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all documents from the entire collection. The collection can be nested. Signature: @@ -62,9 +56,6 @@ PipelineType ## PipelineSource.collection() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all documents from the entire collection. The collection can be nested. Signature: @@ -85,9 +76,6 @@ PipelineType ## PipelineSource.collectionGroup() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all documents from a collection ID regardless of the parent. Signature: @@ -108,9 +96,6 @@ PipelineType ## PipelineSource.collectionGroup() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all documents from a collection ID regardless of the parent. Signature: @@ -131,9 +116,6 @@ PipelineType ## PipelineSource.createFrom() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Convert the given Query into an equivalent Pipeline. Signature: @@ -158,9 +140,6 @@ createFrom(query: Query): Pipeline; ## PipelineSource.database() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all documents from the entire database. Signature: @@ -174,9 +153,6 @@ PipelineType ## PipelineSource.database() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Returns all documents from the entire database. Signature: @@ -197,9 +173,6 @@ PipelineType ## PipelineSource.documents() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Set the pipeline's source to the documents specified by the given paths and DocumentReferences. Signature: @@ -224,9 +197,6 @@ PipelineType ## PipelineSource.documents() -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Set the pipeline's source to the documents specified by the given paths and DocumentReferences. Signature: diff --git a/docs-devsite/firestore_pipelines.selectable.md b/docs-devsite/firestore_pipelines.selectable.md index 53bde7320b..58081c7c65 100644 --- a/docs-devsite/firestore_pipelines.selectable.md +++ b/docs-devsite/firestore_pipelines.selectable.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # Selectable interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An interface that represents a selectable expression. Signature: @@ -25,13 +22,10 @@ export declare interface Selectable | Property | Type | Description | | --- | --- | --- | -| [selectable](./firestore_pipelines.selectable.md#selectableselectable) | true | (Public Preview) | +| [selectable](./firestore_pipelines.selectable.md#selectableselectable) | true | | ## Selectable.selectable -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Signature: ```typescript diff --git a/docs-devsite/firestore_pipelines.stageoptions.md b/docs-devsite/firestore_pipelines.stageoptions.md index e85f6809dd..f371f9ed91 100644 --- a/docs-devsite/firestore_pipelines.stageoptions.md +++ b/docs-devsite/firestore_pipelines.stageoptions.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # StageOptions interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Options defining how a Stage is evaluated. Signature: @@ -25,13 +22,10 @@ export declare interface StageOptions | Property | Type | Description | | --- | --- | --- | -| [rawOptions](./firestore_pipelines.stageoptions.md#stageoptionsrawoptions) | { \[name: string\]: unknown; } | (Public Preview) An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Raw option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK.rawOptions supports dot notation, if you want to override a nested option. | +| [rawOptions](./firestore_pipelines.stageoptions.md#stageoptionsrawoptions) | { \[name: string\]: unknown; } | An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Raw option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK.rawOptions supports dot notation, if you want to override a nested option. | ## StageOptions.rawOptions -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK. The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name). diff --git a/packages/firestore/src/api/pipeline.ts b/packages/firestore/src/api/pipeline.ts index 49f0c43c14..26146f4755 100644 --- a/packages/firestore/src/api/pipeline.ts +++ b/packages/firestore/src/api/pipeline.ts @@ -20,9 +20,6 @@ import { Stage } from '../lite-api/stage'; import { Firestore } from './database'; -/** - * @beta - */ export class Pipeline extends LitePipeline { /** * @internal diff --git a/packages/firestore/src/api/pipeline_impl.ts b/packages/firestore/src/api/pipeline_impl.ts index c92bd66057..831eedff23 100644 --- a/packages/firestore/src/api/pipeline_impl.ts +++ b/packages/firestore/src/api/pipeline_impl.ts @@ -38,7 +38,6 @@ import { ExpUserDataWriter } from './user_data_writer'; declare module './database' { /** - * @beta * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link @firebase/firestore/pipelines#Pipeline}. * * @example @@ -52,7 +51,6 @@ declare module './database' { } /** - * @beta * Executes a pipeline and returns a Promise to represent the asynchronous operation. * * The returned Promise can be used to track the progress of the pipeline execution @@ -87,7 +85,6 @@ declare module './database' { */ export function execute(pipeline: LitePipeline): Promise; /** - * @beta * Executes a pipeline and returns a Promise to represent the asynchronous operation. * * The returned Promise can be used to track the progress of the pipeline execution @@ -190,7 +187,6 @@ export function execute( } /** - * @beta * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link @firebase/firestore/pipelines#Pipeline}. * * @example diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index 38954a633c..de308152f1 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -43,7 +43,6 @@ import { fieldPathFromArgument, parseData, UserData } from './user_data_reader'; import { VectorValue } from './vector_value'; /** - * @beta * * An enumeration of the different types of expressions. */ @@ -56,7 +55,6 @@ export type ExpressionType = | 'AliasedExpression'; /** - * @beta * * An enumeration of the different types generated by the Firestore backend. * @@ -151,7 +149,6 @@ function fieldOrExpression(value: unknown): Expression { } /** - * @beta * * Represents an expression that can be evaluated to a value within the execution of a {@link * @firebase/firestore/pipelines#Pipeline}. @@ -206,7 +203,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Wraps the expression in a [BooleanExpression]. * * @returns A [BooleanExpression] representing the same expression. @@ -229,7 +225,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that subtracts another expression from this expression. * * @example @@ -244,7 +239,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { subtract(subtrahend: Expression): FunctionExpression; /** - * @beta * Creates an expression that subtracts a constant value from this expression. * * @example @@ -266,7 +260,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that multiplies this expression by another expression. * * @example @@ -288,7 +281,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that divides this expression by another expression. * * @example @@ -303,7 +295,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { divide(divisor: Expression): FunctionExpression; /** - * @beta * Creates an expression that divides this expression by a constant value. * * @example @@ -325,7 +316,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that calculates the modulo (remainder) of dividing this expression by another expression. * * @example @@ -340,7 +330,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { mod(expression: Expression): FunctionExpression; /** - * @beta * Creates an expression that calculates the modulo (remainder) of dividing this expression by a constant value. * * @example @@ -362,7 +351,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if this expression is equal to another expression. * * @example @@ -377,7 +365,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { equal(expression: Expression): BooleanExpression; /** - * @beta * Creates an expression that checks if this expression is equal to a constant value. * * @example @@ -399,7 +386,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if this expression is not equal to another expression. * * @example @@ -414,7 +400,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { notEqual(expression: Expression): BooleanExpression; /** - * @beta * Creates an expression that checks if this expression is not equal to a constant value. * * @example @@ -436,7 +421,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if this expression is less than another expression. * * @example @@ -451,7 +435,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { lessThan(experession: Expression): BooleanExpression; /** - * @beta * Creates an expression that checks if this expression is less than a constant value. * * @example @@ -473,7 +456,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if this expression is less than or equal to another * expression. * @@ -489,7 +471,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { lessThanOrEqual(expression: Expression): BooleanExpression; /** - * @beta * Creates an expression that checks if this expression is less than or equal to a constant value. * * @example @@ -511,7 +492,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if this expression is greater than another expression. * * @example @@ -526,7 +506,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { greaterThan(expression: Expression): BooleanExpression; /** - * @beta * Creates an expression that checks if this expression is greater than a constant value. * * @example @@ -548,7 +527,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if this expression is greater than or equal to another * expression. * @@ -564,7 +542,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { greaterThanOrEqual(expression: Expression): BooleanExpression; /** - * @beta * Creates an expression that checks if this expression is greater than or equal to a constant * value. * @@ -587,7 +564,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that concatenates an array expression with one or more other arrays. * * @example @@ -613,7 +589,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if an array contains a specific element. * * @example @@ -628,7 +603,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { arrayContains(expression: Expression): BooleanExpression; /** - * @beta * Creates an expression that checks if an array contains a specific value. * * @example @@ -650,7 +624,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if an array contains all the specified elements. * * @example @@ -665,7 +638,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { arrayContainsAll(values: Array): BooleanExpression; /** - * @beta * Creates an expression that checks if an array contains all the specified elements. * * @example @@ -690,7 +662,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if an array contains any of the specified elements. * * @example @@ -705,7 +676,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { arrayContainsAny(values: Array): BooleanExpression; /** - * @beta * Creates an expression that checks if an array contains any of the specified elements. * * @example @@ -733,7 +703,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that reverses an array. * * @example @@ -749,7 +718,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that calculates the length of an array. * * @example @@ -765,7 +733,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if this expression is equal to any of the provided values or * expressions. * @@ -781,7 +748,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { equalAny(values: Array): BooleanExpression; /** - * @beta * Creates an expression that checks if this expression is equal to any of the provided values or * expressions. * @@ -807,7 +773,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if this expression is not equal to any of the provided values or * expressions. * @@ -823,7 +788,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { notEqualAny(values: Array): BooleanExpression; /** - * @beta * Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. * * @example @@ -848,7 +812,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if a field exists in the document. * * @example @@ -864,7 +827,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that calculates the character length of a string in UTF-8. * * @example @@ -880,7 +842,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that performs a case-sensitive string comparison. * * @example @@ -895,7 +856,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { like(pattern: string): BooleanExpression; /** - * @beta * Creates an expression that performs a case-sensitive string comparison. * * @example @@ -917,7 +877,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if a string contains a specified regular expression as a * substring. * @@ -933,7 +892,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { regexContains(pattern: string): BooleanExpression; /** - * @beta * Creates an expression that checks if a string contains a specified regular expression as a * substring. * @@ -956,7 +914,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that returns the first substring of a string expression that matches * a specified regular expression. * @@ -974,7 +931,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { regexFind(pattern: string): FunctionExpression; /** - * @beta * Creates an expression that returns the first substring of a string expression that matches * a specified regular expression. * @@ -999,7 +955,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * * Creates an expression that evaluates to a list of all substrings in this string expression that * match a specified regular expression. @@ -1018,7 +973,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { regexFindAll(pattern: string): FunctionExpression; /** - * @beta * * Creates an expression that evaluates to a list of all substrings in this string expression that * match a specified regular expression. @@ -1044,7 +998,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if a string matches a specified regular expression. * * @example @@ -1059,7 +1012,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { regexMatch(pattern: string): BooleanExpression; /** - * @beta * Creates an expression that checks if a string matches a specified regular expression. * * @example @@ -1081,7 +1033,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if a string contains a specified substring. * * @example @@ -1096,7 +1047,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { stringContains(substring: string): BooleanExpression; /** - * @beta * Creates an expression that checks if a string contains the string represented by another expression. * * @example @@ -1118,7 +1068,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if a string starts with a given prefix. * * @example @@ -1133,7 +1082,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { startsWith(prefix: string): BooleanExpression; /** - * @beta * Creates an expression that checks if a string starts with a given prefix (represented as an * expression). * @@ -1156,7 +1104,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that checks if a string ends with a given postfix. * * @example @@ -1171,7 +1118,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { endsWith(suffix: string): BooleanExpression; /** - * @beta * Creates an expression that checks if a string ends with a given postfix (represented as an * expression). * @@ -1194,7 +1140,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that converts a string to lowercase. * * @example @@ -1210,7 +1155,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that converts a string to uppercase. * * @example @@ -1226,7 +1170,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that removes leading and trailing characters from a string or byte array. * * @example @@ -1250,7 +1193,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. * * @example @@ -1275,7 +1217,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. * * @example @@ -1300,7 +1241,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that returns the data type of this expression's result, as a string. * * @remarks @@ -1324,7 +1264,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @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. @@ -1347,7 +1286,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that concatenates string expressions together. * * @example @@ -1374,7 +1312,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that finds the index of the first occurrence of a substring or byte sequence. * * @example @@ -1395,7 +1332,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that repeats a string or byte array a specified number of times. * * @example @@ -1416,7 +1352,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. * * @example @@ -1441,7 +1376,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. * * @example @@ -1466,7 +1400,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that concatenates expression results together. * * @example @@ -1489,7 +1422,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that reverses this string expression. * * @example @@ -1505,7 +1437,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Returns the first element of the array. * * @example @@ -1521,7 +1452,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Returns the first `n` elements of the array. * * @example @@ -1536,7 +1466,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { arrayFirstN(n: number): FunctionExpression; /** - * @beta * Returns the first `n` elements of the array. * * @example @@ -1558,7 +1487,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Returns the last element of the array. * * @example @@ -1574,7 +1502,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Returns the last `n` elements of the array. * * @example @@ -1589,7 +1516,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { arrayLastN(n: number): FunctionExpression; /** - * @beta * Returns the last `n` elements of the array. * * @example @@ -1611,7 +1537,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Returns the maximum value in the array. * * @example @@ -1627,7 +1552,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Returns the largest `n` elements of the array. * * Note: Returns the n largest non-null elements in the array, in descending @@ -1646,7 +1570,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { arrayMaximumN(n: number): FunctionExpression; /** - * @beta * Returns the largest `n` elements of the array. * * Note: Returns the n largest non-null elements in the array, in descending @@ -1672,7 +1595,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Returns the minimum value in the array. * * @example @@ -1688,7 +1610,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Returns the smallest `n` elements of the array. * * Note: Returns the n smallest non-null elements in the array, in ascending @@ -1707,7 +1628,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { arrayMinimumN(n: number): FunctionExpression; /** - * @beta * Returns the smallest `n` elements of the array. * * Note: Returns the n smallest non-null elements in the array, in ascending @@ -1733,7 +1653,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Returns the first index of the search value in the array, or -1 if not found. * * @example @@ -1748,7 +1667,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { arrayIndexOf(search: unknown): FunctionExpression; /** - * @beta * Returns the first index of the search value in the array, or -1 if not found. * * @example @@ -1770,7 +1688,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Returns the last index of the search value in the array, or -1 if not found. * * @example @@ -1785,7 +1702,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { arrayLastIndexOf(search: unknown): FunctionExpression; /** - * @beta * Returns the last index of the search value in the array, or -1 if not found. * * @example @@ -1807,7 +1723,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Returns all indices of the search value in the array. * * @example @@ -1822,7 +1737,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { arrayIndexOfAll(search: unknown): FunctionExpression; /** - * @beta * Returns all indices of the search value in the array. * * @example @@ -1844,7 +1758,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that calculates the length of this string expression in bytes. * * @example @@ -1860,7 +1773,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that computes the ceiling of a numeric value. * * @example @@ -1876,7 +1788,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that computes the floor of a numeric value. * * @example @@ -1892,7 +1803,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that computes the absolute value of a numeric value. * * @example @@ -1908,7 +1818,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that computes e to the power of this expression. * * @example @@ -1924,7 +1833,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Accesses a value from a map (object) field using the provided key. * * @example @@ -1945,7 +1853,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that returns a new map with the specified entries added or updated. * * @remarks @@ -1978,7 +1885,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that returns the keys of a map. * * @remarks @@ -1998,7 +1904,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that returns the values of a map. * * @remarks @@ -2018,7 +1923,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @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" }, ...]`. @@ -2036,7 +1940,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an aggregation that counts the number of stage inputs with valid evaluations of the * expression or field. * @@ -2053,7 +1956,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs. * * @example @@ -2069,7 +1971,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an aggregation that calculates the average (mean) of a numeric field across multiple * stage inputs. * @@ -2086,7 +1987,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an aggregation that finds the minimum value of a field across multiple stage inputs. * * @example @@ -2102,7 +2002,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an aggregation that finds the maximum value of a field across multiple stage inputs. * * @example @@ -2118,7 +2017,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an aggregation that finds the first value of an expression across multiple stage inputs. * * @example @@ -2134,7 +2032,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an aggregation that finds the last value of an expression across multiple stage inputs. * * @example @@ -2150,7 +2047,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an aggregation that collects all values of an expression across multiple stage inputs * into an array. * @@ -2171,7 +2067,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an aggregation that collects all distinct values of an expression across multiple stage * inputs into an array. * @@ -2196,7 +2091,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an aggregation that counts the number of distinct values of the expression or field. * * @example @@ -2212,7 +2106,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering. * * @example @@ -2238,7 +2131,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering. * * @example @@ -2264,7 +2156,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression. * * @example @@ -2280,7 +2171,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Calculates the cosine distance between two vectors. * * @example @@ -2294,7 +2184,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { */ cosineDistance(vectorExpression: Expression): FunctionExpression; /** - * @beta * Calculates the Cosine distance between two vectors. * * @example @@ -2318,7 +2207,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Calculates the dot product between two vectors. * * @example @@ -2333,7 +2221,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { dotProduct(vectorExpression: Expression): FunctionExpression; /** - * @beta * Calculates the dot product between two vectors. * * @example @@ -2355,7 +2242,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Calculates the Euclidean distance between two vectors. * * @example @@ -2370,7 +2256,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { euclideanDistance(vectorExpression: Expression): FunctionExpression; /** - * @beta * Calculates the Euclidean distance between two vectors. * * @example @@ -2394,7 +2279,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @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. * @@ -2415,7 +2299,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @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 @@ -2435,7 +2318,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @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. * @@ -2456,7 +2338,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @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 @@ -2476,7 +2357,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @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. * @@ -2497,7 +2377,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @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 @@ -2517,7 +2396,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that adds a specified amount of time to this timestamp expression. * * @example @@ -2533,7 +2411,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { timestampAdd(unit: Expression, amount: Expression): FunctionExpression; /** - * @beta * Creates an expression that adds a specified amount of time to this timestamp expression. * * @example @@ -2559,7 +2436,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that subtracts a specified amount of time from this timestamp expression. * * @example @@ -2575,7 +2451,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { timestampSubtract(unit: Expression, amount: Expression): FunctionExpression; /** - * @beta * Creates an expression that subtracts a specified amount of time from this timestamp expression. * * @example @@ -2601,7 +2476,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that calculates the difference between this timestamp and another timestamp. * * @example @@ -2617,7 +2491,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { timestampDiff(start: Expression, unit: Expression): FunctionExpression; /** - * @beta * Creates an expression that calculates the difference between this timestamp and another timestamp. * * @example @@ -2643,7 +2516,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that extracts a specified part from this timestamp expression. * * @example @@ -2663,7 +2535,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { ): FunctionExpression; /** - * @beta * Creates an expression that extracts a specified part from this timestamp expression. * * @example @@ -2697,7 +2568,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * * Creates an expression that returns the document ID from a path. * @@ -2714,7 +2584,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * * Creates an expression that returns a substring of the results of this expression. * @@ -2725,7 +2594,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { substring(position: number, length?: number): FunctionExpression; /** - * @beta * * Creates an expression that returns a substring of the results of this expression. * @@ -2755,7 +2623,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that indexes into an array from the beginning or end * and returns the element. If the offset exceeds the array length, an error is * returned. A negative offset, starts from the end. @@ -2772,7 +2639,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { arrayGet(offset: number): FunctionExpression; /** - * @beta * Creates an expression that indexes into an array from the beginning or end * and returns the element. If the offset exceeds the array length, an error is * returned. A negative offset, starts from the end. @@ -2797,7 +2663,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * * Creates an expression that checks if a given expression produces an error. * @@ -2814,7 +2679,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * * Creates an expression that returns the result of the `catchExpr` argument * if there is an error, else return the result of this expression. @@ -2833,7 +2697,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { ifError(catchExpr: Expression): FunctionExpression; /** - * @beta * * Creates an expression that returns the `catch` argument if there is an * error, else return the result of this expression. @@ -2863,7 +2726,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * * Creates an expression that returns `true` if the result of this expression * is absent. Otherwise, returns `false` even if the value is `null`. @@ -2881,7 +2743,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * * Creates an expression that removes a key from the map produced by evaluating this expression. * @@ -2896,7 +2757,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { */ mapRemove(key: string): FunctionExpression; /** - * @beta * * Creates an expression that removes a key from the map produced by evaluating this expression. * @@ -2920,7 +2780,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * * Creates an expression that merges multiple map values. * @@ -2952,7 +2811,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that returns the value of this expression raised to the power of another expression. * * @example @@ -2967,7 +2825,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { pow(exponent: Expression): FunctionExpression; /** - * @beta * Creates an expression that returns the value of this expression raised to the power of a constant value. * * @example @@ -2985,7 +2842,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that truncates the numeric value to an integer. * * @example @@ -2999,7 +2855,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { trunc(): FunctionExpression; /** - * @beta * Creates an expression that truncates a numeric value to the specified number of decimal places. * * @example @@ -3014,7 +2869,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { trunc(decimalPlaces: number): FunctionExpression; /** - * @beta * Creates an expression that truncates a numeric value to the specified number of decimal places. * * @example @@ -3040,7 +2894,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that rounds a numeric value to the nearest whole number. * * @example @@ -3053,7 +2906,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { */ round(): FunctionExpression; /** - * @beta * Creates an expression that rounds a numeric value to the specified number of decimal places. * * @example @@ -3068,7 +2920,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { */ round(decimalPlaces: number): FunctionExpression; /** - * @beta * Creates an expression that rounds a numeric value to the specified number of decimal places. * * @example @@ -3095,7 +2946,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that returns the collection ID from a path. * * @example @@ -3111,7 +2961,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that calculates the length of a string, array, map, vector, or bytes. * * @example @@ -3130,7 +2979,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that computes the natural logarithm of a numeric value. * * @example @@ -3146,7 +2994,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that computes the square root of a numeric value. * * @example @@ -3162,7 +3009,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that reverses a string. * * @example @@ -3178,7 +3024,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else * return the result of this expression evaluation. * @@ -3195,7 +3040,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { ifAbsent(elseValue: unknown): Expression; /** - * @beta * Creates an expression that returns the `elseValue` argument if this expression results in an absent value, else * return the result of this expression evaluation. * @@ -3220,7 +3064,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that returns the `elseValue` argument if this expression evaluates to null, else * return the result of this expression evaluation. * @@ -3240,7 +3083,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { ifNull(elseExpression: Expression): FunctionExpression; /** - * @beta * Creates an expression that returns the `elseValue` argument if this expression evaluates to null, else * return the result of this expression evaluation. * @@ -3267,7 +3109,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that returns the first non-null, non-absent argument, without evaluating * the rest of the arguments. When all arguments are null or absent, returns the last argument. * @@ -3298,7 +3139,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that joins the elements of an array into a string. * * @example @@ -3313,7 +3153,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { join(delimiterExpression: Expression): Expression; /** - * @beta * Creates an expression that joins the elements of an array field into a string. * * @example @@ -3336,7 +3175,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that computes the base-10 logarithm of a numeric value. * * @example @@ -3352,7 +3190,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that computes the sum of the elements in an array. * * @example @@ -3368,7 +3205,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an expression that splits the result of this expression into an * array of substrings based on the provided delimiter. * @@ -3383,7 +3219,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { split(delimiter: string): FunctionExpression; /** - * @beta * Creates an expression that splits the result of this expression into an * array of substrings based on the provided delimiter. * @@ -3454,7 +3289,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { // 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 @@ -3471,7 +3305,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Creates an {@link @firebase/firestore/pipelines#Ordering} that sorts documents in descending order based on this expression. * * @example @@ -3488,7 +3321,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Assigns an alias to this expression. * * Aliases are useful for renaming fields in the output of a stage or for giving meaningful @@ -3511,7 +3343,6 @@ export abstract class Expression implements ProtoValueSerializable, UserData { } /** - * @beta * Specify time units for expressions. */ export type TimeUnit = @@ -3523,7 +3354,6 @@ export type TimeUnit = | 'day'; /** - * @beta * Specify time granularity for expressions. */ export type TimeGranularity = @@ -3543,13 +3373,11 @@ export type TimeGranularity = | 'isoyear'; /** - * @beta * Specify time parts for `timestampExtract` expressions. */ export type TimePart = TimeGranularity | 'dayofweek' | 'dayofyear'; /** - * @beta * * An interface that represents a selectable expression. */ @@ -3568,7 +3396,6 @@ export interface Selectable { } /** - * @beta * * A class that represents an aggregate function. */ @@ -3598,7 +3425,6 @@ export class AggregateFunction implements ProtoValueSerializable, UserData { } /** - * @beta * Assigns an alias to this AggregateFunction. The alias specifies the name that * the aggregated value will have in the output document. * @@ -3647,7 +3473,6 @@ export class AggregateFunction implements ProtoValueSerializable, UserData { } /** - * @beta * * An AggregateFunction with alias. */ @@ -3667,9 +3492,6 @@ export class AliasedAggregate implements UserData { } } -/** - * @beta - */ export class AliasedExpression implements Selectable, UserData { exprType: ExpressionType = 'AliasedExpression'; selectable = true as const; @@ -3724,7 +3546,6 @@ class ListOfExprs extends Expression implements UserData { } /** - * @beta * * Represents a reference to a field in a Firestore document, or outputs of a {@link @firebase/firestore/pipelines#Pipeline} stage. * @@ -3789,7 +3610,6 @@ export class Field extends Expression implements Selectable { } /** - * @beta * Creates a {@link @firebase/firestore/pipelines#Field} instance representing the field at the given path. * * The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field @@ -3810,7 +3630,6 @@ export class Field extends Expression implements Selectable { export function field(name: string): Field; /** - * @beta * Creates a {@link @firebase/firestore/pipelines#Field} instance representing the field at the given path. * * @param path - A FieldPath specifying the field. @@ -3909,7 +3728,6 @@ export class Constant extends Expression { } /** - * @beta * Creates a `Constant` instance for a number value. * * @param value - The number value. @@ -3918,7 +3736,6 @@ export class Constant extends Expression { export function constant(value: number): Expression; /** - * @beta * Creates a `Constant` instance for a string value. * * @param value - The string value. @@ -3927,7 +3744,6 @@ export function constant(value: number): Expression; export function constant(value: string): Expression; /** - * @beta * Creates a `BooleanExpression` instance for a boolean value. * * @param value - The boolean value. @@ -3936,7 +3752,6 @@ export function constant(value: string): Expression; export function constant(value: boolean): BooleanExpression; /** - * @beta * Creates a `Constant` instance for a null value. * * @param value - The null value. @@ -3945,7 +3760,6 @@ export function constant(value: boolean): BooleanExpression; export function constant(value: null): Expression; /** - * @beta * Creates a `Constant` instance for a GeoPoint value. * * @param value - The GeoPoint value. @@ -3954,7 +3768,6 @@ export function constant(value: null): Expression; export function constant(value: GeoPoint): Expression; /** - * @beta * Creates a `Constant` instance for a Timestamp value. * * @param value - The Timestamp value. @@ -3963,7 +3776,6 @@ export function constant(value: GeoPoint): Expression; export function constant(value: Timestamp): Expression; /** - * @beta * Creates a `Constant` instance for a Date value. * * @param value - The Date value. @@ -3972,7 +3784,6 @@ export function constant(value: Timestamp): Expression; export function constant(value: Date): Expression; /** - * @beta * Creates a `Constant` instance for a Bytes value. * * @param value - The Bytes value. @@ -3981,7 +3792,6 @@ export function constant(value: Date): Expression; export function constant(value: Bytes): Expression; /** - * @beta * Creates a `Constant` instance for a DocumentReference value. * * @param value - The DocumentReference value. @@ -4000,7 +3810,6 @@ export function constant(value: DocumentReference): Expression; export function constant(value: ProtoValue): Expression; /** - * @beta * Creates a `Constant` instance for a VectorValue value. * * @param value - The VectorValue value. @@ -4060,7 +3869,6 @@ export class MapValue extends Expression { } /** - * @beta * * This class defines the base class for Firestore {@link @firebase/firestore/pipelines#Pipeline} functions, which can be evaluated within pipeline * execution. @@ -4113,7 +3921,6 @@ export class FunctionExpression extends Expression { } /** - * @beta * * An interface that represents a filter condition. */ @@ -4125,7 +3932,6 @@ export abstract class BooleanExpression extends Expression { } /** - * @beta * Creates an aggregation that finds the count of input documents satisfying * this boolean expression. * @@ -4142,7 +3948,6 @@ export abstract class BooleanExpression extends Expression { } /** - * @beta * Creates an expression that negates this boolean expression. * * @example @@ -4158,7 +3963,6 @@ export abstract class BooleanExpression extends Expression { } /** - * @beta * Creates a conditional expression that evaluates to the 'then' expression * if `this` expression evaluates to `true`, * or evaluates to the 'else' expression if `this` expressions evaluates `false`. @@ -4182,7 +3986,6 @@ export abstract class BooleanExpression extends Expression { } /** - * @beta * * Creates an expression that returns the `catch` argument if there is an * error, else return the result of this expression. @@ -4201,7 +4004,6 @@ export abstract class BooleanExpression extends Expression { ifError(catchValue: BooleanExpression): BooleanExpression; /** - * @beta * * Creates an expression that returns the `catch` argument if there is an * error, else return the result of this expression. @@ -4220,7 +4022,6 @@ export abstract class BooleanExpression extends Expression { ifError(catchValue: boolean): BooleanExpression; /** - * @beta * * Creates an expression that returns the `catch` argument if there is an * error, else return the result of this expression. @@ -4238,7 +4039,6 @@ export abstract class BooleanExpression extends Expression { ifError(catchValue: Expression): FunctionExpression; /** - * @beta * * Creates an expression that returns the `catch` argument if there is an * error, else return the result of this expression. @@ -4306,7 +4106,6 @@ export class BooleanField extends BooleanExpression { } /** - * @beta * Creates an aggregation that counts the number of stage inputs where the provided * boolean expression evaluates to true. * @@ -4324,7 +4123,6 @@ export function countIf(booleanExpr: BooleanExpression): AggregateFunction { } /** - * @beta * Creates an expression that indexes into an array from the beginning or end * and return the element. If the offset exceeds the array length, an error is * returned. A negative offset, starts from the end. @@ -4345,7 +4143,6 @@ export function arrayGet( ): FunctionExpression; /** - * @beta * Creates an expression that indexes into an array from the beginning or end * and return the element. If the offset exceeds the array length, an error is * returned. A negative offset, starts from the end. @@ -4367,7 +4164,6 @@ export function arrayGet( ): FunctionExpression; /** - * @beta * Creates an expression that indexes into an array from the beginning or end * and return the element. If the offset exceeds the array length, an error is * returned. A negative offset, starts from the end. @@ -4388,7 +4184,6 @@ export function arrayGet( ): FunctionExpression; /** - * @beta * Creates an expression that indexes into an array from the beginning or end * and return the element. If the offset exceeds the array length, an error is * returned. A negative offset, starts from the end. @@ -4416,7 +4211,6 @@ export function arrayGet( } /** - * @beta * * Creates an expression that checks if a given expression produces an error. * @@ -4434,7 +4228,6 @@ export function isError(value: Expression): BooleanExpression { } /** - * @beta * * Creates an expression that returns the `catch` argument if there is an * error, else return the result of the `try` argument evaluation. @@ -4459,7 +4252,6 @@ export function ifError( ): BooleanExpression; /** - * @beta * * Creates an expression that returns the `catch` argument if there is an * error, else return the result of the `try` argument evaluation. @@ -4482,7 +4274,6 @@ export function ifError( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the `catch` argument if there is an * error, else return the result of the `try` argument evaluation. @@ -4519,7 +4310,6 @@ export function ifError( } /** - * @beta * * Creates an expression that returns `true` if a value is absent. Otherwise, * returns `false` even if the value is `null`. @@ -4536,7 +4326,6 @@ export function ifError( export function isAbsent(value: Expression): BooleanExpression; /** - * @beta * * Creates an expression that returns `true` if a field is absent. Otherwise, * returns `false` even if the field value is `null`. @@ -4556,7 +4345,6 @@ export function isAbsent(value: Expression | string): BooleanExpression { } /** - * @beta * * Creates an expression that removes a key from the map at the specified field name. * @@ -4571,7 +4359,6 @@ export function isAbsent(value: Expression | string): BooleanExpression { */ export function mapRemove(mapField: string, key: string): FunctionExpression; /** - * @beta * * Creates an expression that removes a key from the map produced by evaluating an expression. * @@ -4587,7 +4374,6 @@ export function mapRemove(mapField: string, key: string): FunctionExpression; */ export function mapRemove(mapExpr: Expression, key: string): FunctionExpression; /** - * @beta * * Creates an expression that removes a key from the map at the specified field name. * @@ -4605,7 +4391,6 @@ export function mapRemove( keyExpr: Expression ): FunctionExpression; /** - * @beta * * Creates an expression that removes a key from the map produced by evaluating an expression. * @@ -4632,7 +4417,6 @@ export function mapRemove( } /** - * @beta * * Creates an expression that merges multiple map values. * @@ -4656,7 +4440,6 @@ export function mapMerge( ): FunctionExpression; /** - * @beta * * Creates an expression that merges multiple map values. * @@ -4690,7 +4473,6 @@ export function mapMerge( } /** - * @beta * * Creates an expression that returns the document ID from a path. * @@ -4707,7 +4489,6 @@ export function documentId( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the document ID from a path. * @@ -4730,7 +4511,6 @@ export function documentId( } /** - * @beta * * Creates an expression that returns a substring of a string or byte array. * @@ -4745,7 +4525,6 @@ export function substring( ): FunctionExpression; /** - * @beta * * Creates an expression that returns a substring of a string or byte array. * @@ -4760,7 +4539,6 @@ export function substring( ): FunctionExpression; /** - * @beta * * Creates an expression that returns a substring of a string or byte array. * @@ -4775,7 +4553,6 @@ export function substring( ): FunctionExpression; /** - * @beta * * Creates an expression that returns a substring of a string or byte array. * @@ -4802,7 +4579,6 @@ export function substring( } /** - * @beta * * Creates an expression that adds two expressions together. * @@ -4823,7 +4599,6 @@ export function add( ): FunctionExpression; /** - * @beta * * Creates an expression that adds a field's value to an expression. * @@ -4851,7 +4626,6 @@ export function add( } /** - * @beta * * Creates an expression that subtracts two expressions. * @@ -4871,7 +4645,6 @@ export function subtract( ): FunctionExpression; /** - * @beta * * Creates an expression that subtracts a constant value from an expression. * @@ -4891,7 +4664,6 @@ export function subtract( ): FunctionExpression; /** - * @beta * * Creates an expression that subtracts an expression from a field's value. * @@ -4911,7 +4683,6 @@ export function subtract( ): FunctionExpression; /** - * @beta * * Creates an expression that subtracts a constant value from a field's value. * @@ -4936,7 +4707,6 @@ export function subtract( } /** - * @beta * * Creates an expression that multiplies two expressions together. * @@ -4957,7 +4727,6 @@ export function multiply( ): FunctionExpression; /** - * @beta * * Creates an expression that multiplies a field's value by an expression. * @@ -4985,7 +4754,6 @@ export function multiply( } /** - * @beta * * Creates an expression that divides two expressions. * @@ -5002,7 +4770,6 @@ export function multiply( export function divide(left: Expression, right: Expression): FunctionExpression; /** - * @beta * * Creates an expression that divides an expression by a constant value. * @@ -5022,7 +4789,6 @@ export function divide( ): FunctionExpression; /** - * @beta * * Creates an expression that divides a field's value by an expression. * @@ -5042,7 +4808,6 @@ export function divide( ): FunctionExpression; /** - * @beta * * Creates an expression that divides a field's value by a constant value. * @@ -5067,7 +4832,6 @@ export function divide( } /** - * @beta * * Creates an expression that calculates the modulo (remainder) of dividing two expressions. * @@ -5084,7 +4848,6 @@ export function divide( export function mod(left: Expression, right: Expression): FunctionExpression; /** - * @beta * * Creates an expression that calculates the modulo (remainder) of dividing an expression by a constant. * @@ -5101,7 +4864,6 @@ export function mod(left: Expression, right: Expression): FunctionExpression; export function mod(expression: Expression, value: unknown): FunctionExpression; /** - * @beta * * Creates an expression that calculates the modulo (remainder) of dividing a field's value by an expression. * @@ -5121,7 +4883,6 @@ export function mod( ): FunctionExpression; /** - * @beta * * Creates an expression that calculates the modulo (remainder) of dividing a field's value by a constant. * @@ -5146,7 +4907,6 @@ export function mod( } /** - * @beta * * Creates an expression that creates a Firestore map value from an input object. * @@ -5200,7 +4960,6 @@ export function _mapValue(plainObject: Record): MapValue { } /** - * @beta * * Creates an expression that creates a Firestore array value from an input array. * @@ -5228,7 +4987,6 @@ export function _array( } /** - * @beta * * Creates an expression that checks if two expressions are equal. * @@ -5245,7 +5003,6 @@ export function _array( export function equal(left: Expression, right: Expression): BooleanExpression; /** - * @beta * * Creates an expression that checks if an expression is equal to a constant value. * @@ -5265,7 +5022,6 @@ export function equal( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is equal to an expression. * @@ -5285,7 +5041,6 @@ export function equal( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is equal to a constant value. * @@ -5310,7 +5065,6 @@ export function equal( } /** - * @beta * * Creates an expression that checks if two expressions are not equal. * @@ -5330,7 +5084,6 @@ export function notEqual( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if an expression is not equal to a constant value. * @@ -5350,7 +5103,6 @@ export function notEqual( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is not equal to an expression. * @@ -5370,7 +5122,6 @@ export function notEqual( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is not equal to a constant value. * @@ -5395,7 +5146,6 @@ export function notEqual( } /** - * @beta * * Creates an expression that checks if the first expression is less than the second expression. * @@ -5415,7 +5165,6 @@ export function lessThan( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if an expression is less than a constant value. * @@ -5435,7 +5184,6 @@ export function lessThan( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is less than an expression. * @@ -5455,7 +5203,6 @@ export function lessThan( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is less than a constant value. * @@ -5480,7 +5227,6 @@ export function lessThan( } /** - * @beta * * Creates an expression that checks if the first expression is less than or equal to the second * expression. @@ -5501,7 +5247,6 @@ export function lessThanOrEqual( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if an expression is less than or equal to a constant value. * @@ -5521,7 +5266,6 @@ export function lessThanOrEqual( ): BooleanExpression; /** - * @beta * Creates an expression that checks if a field's value is less than or equal to an expression. * * @example @@ -5540,7 +5284,6 @@ export function lessThanOrEqual( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is less than or equal to a constant value. * @@ -5568,7 +5311,6 @@ export function lessThanOrEqual( } /** - * @beta * * Creates an expression that checks if the first expression is greater than the second * expression. @@ -5589,7 +5331,6 @@ export function greaterThan( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if an expression is greater than a constant value. * @@ -5609,7 +5350,6 @@ export function greaterThan( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is greater than an expression. * @@ -5629,7 +5369,6 @@ export function greaterThan( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is greater than a constant value. * @@ -5657,7 +5396,6 @@ export function greaterThan( } /** - * @beta * * Creates an expression that checks if the first expression is greater than or equal to the * second expression. @@ -5678,7 +5416,6 @@ export function greaterThanOrEqual( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if an expression is greater than or equal to a constant * value. @@ -5699,7 +5436,6 @@ export function greaterThanOrEqual( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is greater than or equal to an expression. * @@ -5719,7 +5455,6 @@ export function greaterThanOrEqual( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is greater than or equal to a constant * value. @@ -5748,7 +5483,6 @@ export function greaterThanOrEqual( } /** - * @beta * * Creates an expression that concatenates an array expression with other arrays. * @@ -5770,7 +5504,6 @@ export function arrayConcat( ): FunctionExpression; /** - * @beta * * Creates an expression that concatenates a field's array value with other arrays. * @@ -5804,7 +5537,6 @@ export function arrayConcat( } /** - * @beta * * Creates an expression that checks if an array expression contains a specific element. * @@ -5824,7 +5556,6 @@ export function arrayContains( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if an array expression contains a specific element. * @@ -5844,7 +5575,6 @@ export function arrayContains( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's array value contains a specific element. * @@ -5864,7 +5594,6 @@ export function arrayContains( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's array value contains a specific value. * @@ -5892,7 +5621,6 @@ export function arrayContains( } /** - * @beta * * Creates an expression that checks if an array expression contains any of the specified * elements. @@ -5913,7 +5641,6 @@ export function arrayContainsAny( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's array value contains any of the specified * elements. @@ -5935,7 +5662,6 @@ export function arrayContainsAny( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if an array expression contains any of the specified * elements. @@ -5956,7 +5682,6 @@ export function arrayContainsAny( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's array value contains any of the specified * elements. @@ -5985,7 +5710,6 @@ export function arrayContainsAny( } /** - * @beta * * Creates an expression that checks if an array expression contains all the specified elements. * @@ -6005,7 +5729,6 @@ export function arrayContainsAll( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's array value contains all the specified values or * expressions. @@ -6026,7 +5749,6 @@ export function arrayContainsAll( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if an array expression contains all the specified elements. * @@ -6046,7 +5768,6 @@ export function arrayContainsAll( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's array value contains all the specified values or * expressions. @@ -6074,7 +5795,6 @@ export function arrayContainsAll( } /** - * @beta * * Creates an expression that calculates the length of an array in a specified field. * @@ -6090,7 +5810,6 @@ export function arrayContainsAll( export function arrayLength(fieldName: string): FunctionExpression; /** - * @beta * * Creates an expression that calculates the length of an array expression. * @@ -6109,7 +5828,6 @@ export function arrayLength(array: Expression | string): FunctionExpression { } /** - * @beta * * Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or * expressions. @@ -6130,7 +5848,6 @@ export function equalAny( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if an expression is equal to any of the provided values. * @@ -6150,7 +5867,6 @@ export function equalAny( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is equal to any of the provided values or * expressions. @@ -6171,7 +5887,6 @@ export function equalAny( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is equal to any of the provided values or * expressions. @@ -6199,7 +5914,6 @@ export function equalAny( } /** - * @beta * * Creates an expression that checks if an expression is not equal to any of the provided values * or expressions. @@ -6220,7 +5934,6 @@ export function notEqualAny( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is not equal to any of the provided values * or expressions. @@ -6241,7 +5954,6 @@ export function notEqualAny( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if an expression is not equal to any of the provided values * or expressions. @@ -6262,7 +5974,6 @@ export function notEqualAny( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value is not equal to any of the values in the evaluated expression. * @@ -6290,7 +6001,6 @@ export function notEqualAny( } /** - * @beta * * Creates an expression that performs a logical 'XOR' (exclusive OR) operation on multiple BooleanExpressions. * @@ -6322,7 +6032,6 @@ export function xor( } /** - * @beta * * Creates a conditional expression that evaluates to a 'then' expression if a condition is true * and an 'else' expression if the condition is false. @@ -6352,7 +6061,6 @@ export function conditional( } /** - * @beta * * Creates an expression that negates a filter condition. * @@ -6370,7 +6078,6 @@ export function not(booleanExpr: BooleanExpression): BooleanExpression { } /** - * @beta * * Creates an expression that returns the largest value between multiple input * expressions or literal values. Based on Firestore's value type ordering. @@ -6394,7 +6101,6 @@ export function logicalMaximum( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the largest value between multiple input * expressions or literal values. Based on Firestore's value type ordering. @@ -6429,7 +6135,6 @@ export function logicalMaximum( } /** - * @beta * * Creates an expression that returns the smallest value between multiple input * expressions and literal values. Based on Firestore's value type ordering. @@ -6453,7 +6158,6 @@ export function logicalMinimum( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the smallest value between a field's value * and other input expressions or literal values. @@ -6489,7 +6193,6 @@ export function logicalMinimum( } /** - * @beta * * Creates an expression that checks if a field exists. * @@ -6505,7 +6208,6 @@ export function logicalMinimum( export function exists(value: Expression): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field exists. * @@ -6524,7 +6226,6 @@ export function exists(valueOrField: Expression | string): BooleanExpression { } /** - * @beta * * Creates an expression that reverses a string. * @@ -6540,7 +6241,6 @@ export function exists(valueOrField: Expression | string): BooleanExpression { export function reverse(stringExpression: Expression): FunctionExpression; /** - * @beta * * Creates an expression that reverses a string value in the specified field. * @@ -6559,7 +6259,6 @@ export function reverse(expr: Expression | string): FunctionExpression { } /** - * @beta * * Creates an expression that calculates the byte length of a string in UTF-8, or just the length of a Blob. * @@ -6575,7 +6274,6 @@ export function reverse(expr: Expression | string): FunctionExpression { export function byteLength(expr: Expression): FunctionExpression; /** - * @beta * * Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. * @@ -6595,7 +6293,6 @@ export function byteLength(expr: Expression | string): FunctionExpression { } /** - * @beta * Creates an expression that reverses an array. * * @example @@ -6610,7 +6307,6 @@ export function byteLength(expr: Expression | string): FunctionExpression { export function arrayReverse(fieldName: string): FunctionExpression; /** - * @beta * Creates an expression that reverses an array. * * @example @@ -6628,7 +6324,6 @@ export function arrayReverse(expr: Expression | string): FunctionExpression { } /** - * @beta * Creates an expression that computes e to the power of the expression's result. * * @example @@ -6642,7 +6337,6 @@ export function arrayReverse(expr: Expression | string): FunctionExpression { export function exp(expression: Expression): FunctionExpression; /** - * @beta * Creates an expression that computes e to the power of the expression's result. * * @example @@ -6662,7 +6356,6 @@ export function exp( } /** - * @beta * Creates an expression that computes the ceiling of a numeric value. * * @example @@ -6677,7 +6370,6 @@ export function exp( export function ceil(fieldName: string): FunctionExpression; /** - * @beta * Creates an expression that computes the ceiling of a numeric value. * * @example @@ -6695,7 +6387,6 @@ export function ceil(expr: Expression | string): FunctionExpression { } /** - * @beta * Creates an expression that computes the floor of a numeric value. * * @param expr - The expression to compute the floor of. @@ -6704,7 +6395,6 @@ export function ceil(expr: Expression | string): FunctionExpression { export function floor(expr: Expression): FunctionExpression; /** - * @beta * Creates an expression that computes the floor of a numeric value. * * @param fieldName - The name of the field to compute the floor of. @@ -6716,7 +6406,6 @@ export function floor(expr: Expression | string): FunctionExpression { } /** - * @beta * Creates an aggregation that counts the number of distinct values of a field. * * @param expr - The expression or field to count distinct values of. @@ -6727,7 +6416,6 @@ export function countDistinct(expr: Expression | string): AggregateFunction { } /** - * @beta * * Creates an expression that calculates the character length of a string field in UTF8. * @@ -6743,7 +6431,6 @@ export function countDistinct(expr: Expression | string): AggregateFunction { export function charLength(fieldName: string): FunctionExpression; /** - * @beta * * Creates an expression that calculates the character length of a string expression in UTF-8. * @@ -6763,7 +6450,6 @@ export function charLength(value: Expression | string): FunctionExpression { } /** - * @beta * * Creates an expression that performs a case-sensitive wildcard string comparison against a * field. @@ -6781,7 +6467,6 @@ export function charLength(value: Expression | string): FunctionExpression { export function like(fieldName: string, pattern: string): BooleanExpression; /** - * @beta * * Creates an expression that performs a case-sensitive wildcard string comparison against a * field. @@ -6799,7 +6484,6 @@ export function like(fieldName: string, pattern: string): BooleanExpression; export function like(fieldName: string, pattern: Expression): BooleanExpression; /** - * @beta * * Creates an expression that performs a case-sensitive wildcard string comparison. * @@ -6819,7 +6503,6 @@ export function like( ): BooleanExpression; /** - * @beta * * Creates an expression that performs a case-sensitive wildcard string comparison. * @@ -6847,7 +6530,6 @@ export function like( } /** - * @beta * * Creates an expression that checks if a string field contains a specified regular expression as * a substring. @@ -6868,7 +6550,6 @@ export function regexContains( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string field contains a specified regular expression as * a substring. @@ -6889,7 +6570,6 @@ export function regexContains( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string expression contains a specified regular * expression as a substring. @@ -6910,7 +6590,6 @@ export function regexContains( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string expression contains a specified regular * expression as a substring. @@ -6939,7 +6618,6 @@ export function regexContains( } /** - * @beta * * Creates an expression that returns the first element of an array. * @@ -6955,7 +6633,6 @@ export function regexContains( export function arrayFirst(fieldName: string): FunctionExpression; /** - * @beta * * Creates an expression that returns the first element of an array. * @@ -6974,7 +6651,6 @@ export function arrayFirst(array: Expression | string): FunctionExpression { } /** - * @beta * * Creates an expression that returns the first `n` elements of an array. * @@ -6991,7 +6667,6 @@ export function arrayFirst(array: Expression | string): FunctionExpression { export function arrayFirstN(fieldName: string, n: number): FunctionExpression; /** - * @beta * * Creates an expression that returns the first `n` elements of an array. * @@ -7011,7 +6686,6 @@ export function arrayFirstN( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the first `n` elements of an array. * @@ -7031,7 +6705,6 @@ export function arrayFirstN( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the first `n` elements of an array. * @@ -7057,7 +6730,6 @@ export function arrayFirstN( } /** - * @beta * * Creates an expression that returns the last element of an array. * @@ -7073,7 +6745,6 @@ export function arrayFirstN( export function arrayLast(fieldName: string): FunctionExpression; /** - * @beta * * Creates an expression that returns the last element of an array. * @@ -7092,7 +6763,6 @@ export function arrayLast(array: Expression | string): FunctionExpression { } /** - * @beta * * Creates an expression that returns the last `n` elements of an array. * @@ -7109,7 +6779,6 @@ export function arrayLast(array: Expression | string): FunctionExpression { export function arrayLastN(fieldName: string, n: number): FunctionExpression; /** - * @beta * * Creates an expression that returns the last `n` elements of an array. * @@ -7129,7 +6798,6 @@ export function arrayLastN( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the last `n` elements of an array. * @@ -7149,7 +6817,6 @@ export function arrayLastN( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the last `n` elements of an array. * @@ -7175,7 +6842,6 @@ export function arrayLastN( } /** - * @beta * * Creates an expression that returns the maximum value in an array. * @@ -7191,7 +6857,6 @@ export function arrayLastN( export function arrayMaximum(fieldName: string): FunctionExpression; /** - * @beta * * Creates an expression that returns the maximum value in an array. * @@ -7210,7 +6875,6 @@ export function arrayMaximum(array: Expression | string): FunctionExpression { } /** - * @beta * * Creates an expression that returns the largest `n` elements of an array. * @@ -7231,7 +6895,6 @@ export function arrayMaximum(array: Expression | string): FunctionExpression { export function arrayMaximumN(fieldName: string, n: number): FunctionExpression; /** - * @beta * * Creates an expression that returns the largest `n` elements of an array. * @@ -7255,7 +6918,6 @@ export function arrayMaximumN( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the largest `n` elements of an array. * @@ -7279,7 +6941,6 @@ export function arrayMaximumN( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the largest `n` elements of an array. * @@ -7309,7 +6970,6 @@ export function arrayMaximumN( } /** - * @beta * * Creates an expression that returns the minimum value in an array. * @@ -7325,7 +6985,6 @@ export function arrayMaximumN( export function arrayMinimum(fieldName: string): FunctionExpression; /** - * @beta * * Creates an expression that returns the minimum value in an array. * @@ -7344,7 +7003,6 @@ export function arrayMinimum(array: Expression | string): FunctionExpression { } /** - * @beta * * Creates an expression that returns the smallest `n` elements of an array. * @@ -7365,7 +7023,6 @@ export function arrayMinimum(array: Expression | string): FunctionExpression { export function arrayMinimumN(fieldName: string, n: number): FunctionExpression; /** - * @beta * * Creates an expression that returns the smallest `n` elements of an array. * @@ -7389,7 +7046,6 @@ export function arrayMinimumN( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the smallest `n` elements of an array. * @@ -7413,7 +7069,6 @@ export function arrayMinimumN( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the smallest `n` elements of an array. * @@ -7443,7 +7098,6 @@ export function arrayMinimumN( } /** - * @beta * * Creates an expression that returns the first index of the search value in an array. * Returns -1 if the value is not found. @@ -7464,7 +7118,6 @@ export function arrayIndexOf( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the first index of the search value in an array. * Returns -1 if the value is not found. @@ -7491,7 +7144,6 @@ export function arrayIndexOf( } /** - * @beta * * Creates an expression that returns the last index of the search value in an array. * Returns -1 if the value is not found. @@ -7512,7 +7164,6 @@ export function arrayLastIndexOf( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the last index of the search value in an array. * Returns -1 if the value is not found. @@ -7539,7 +7190,6 @@ export function arrayLastIndexOf( } /** - * @beta * * Creates an expression that returns all indices of the search value in an array. * @@ -7559,7 +7209,6 @@ export function arrayIndexOfAll( ): FunctionExpression; /** - * @beta * * Creates an expression that returns all indices of the search value in an array. * @@ -7585,7 +7234,6 @@ export function arrayIndexOfAll( } /** - * @beta * * Creates an expression that returns the first substring of a string field that matches a * specified regular expression. @@ -7608,7 +7256,6 @@ export function regexFind( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the first substring of a string field that matches a * specified regular expression. @@ -7631,7 +7278,6 @@ export function regexFind( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the first substring of a string expression that matches * a specified regular expression. @@ -7654,7 +7300,6 @@ export function regexFind( ): FunctionExpression; /** - * @beta * * Creates an expression that returns the first substring of a string expression that matches * a specified regular expression. @@ -7685,7 +7330,6 @@ export function regexFind( } /** - * @beta * * Creates an expression that evaluates to a list of all substrings in a string field that * match a specified regular expression. @@ -7708,7 +7352,6 @@ export function regexFindAll( ): FunctionExpression; /** - * @beta * * Creates an expression that evaluates to a list of all substrings in a string field that * match a specified regular expression. @@ -7731,7 +7374,6 @@ export function regexFindAll( ): FunctionExpression; /** - * @beta * * Creates an expression that evaluates to a list of all substrings in a string expression * that match a specified regular expression. @@ -7754,7 +7396,6 @@ export function regexFindAll( ): FunctionExpression; /** - * @beta * * Creates an expression that evaluates to a list of all substrings in a string expression * that match a specified regular expression. @@ -7785,7 +7426,6 @@ export function regexFindAll( } /** - * @beta * * Creates an expression that checks if a string field matches a specified regular expression. * @@ -7805,7 +7445,6 @@ export function regexMatch( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string field matches a specified regular expression. * @@ -7825,7 +7464,6 @@ export function regexMatch( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string expression matches a specified regular * expression. @@ -7846,7 +7484,6 @@ export function regexMatch( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string expression matches a specified regular * expression. @@ -7875,7 +7512,6 @@ export function regexMatch( } /** - * @beta * * Creates an expression that checks if a string field contains a specified substring. * @@ -7895,7 +7531,6 @@ export function stringContains( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string field contains a substring specified by an expression. * @@ -7915,7 +7550,6 @@ export function stringContains( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string expression contains a specified substring. * @@ -7935,7 +7569,6 @@ export function stringContains( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string expression contains a substring specified by another expression. * @@ -7963,7 +7596,6 @@ export function stringContains( } /** - * @beta * * Creates an expression that checks if a field's value starts with a given prefix. * @@ -7983,7 +7615,6 @@ export function startsWith( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value starts with a given prefix. * @@ -8003,7 +7634,6 @@ export function startsWith( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string expression starts with a given prefix. * @@ -8023,7 +7653,6 @@ export function startsWith( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string expression starts with a given prefix. * @@ -8049,7 +7678,6 @@ export function startsWith( } /** - * @beta * * Creates an expression that checks if a field's value ends with a given postfix. * @@ -8066,7 +7694,6 @@ export function startsWith( export function endsWith(fieldName: string, suffix: string): BooleanExpression; /** - * @beta * * Creates an expression that checks if a field's value ends with a given postfix. * @@ -8086,7 +7713,6 @@ export function endsWith( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string expression ends with a given postfix. * @@ -8106,7 +7732,6 @@ export function endsWith( ): BooleanExpression; /** - * @beta * * Creates an expression that checks if a string expression ends with a given postfix. * @@ -8132,7 +7757,6 @@ export function endsWith( } /** - * @beta * * Creates an expression that converts a string field to lowercase. * @@ -8148,7 +7772,6 @@ export function endsWith( export function toLower(fieldName: string): FunctionExpression; /** - * @beta * * Creates an expression that converts a string expression to lowercase. * @@ -8167,7 +7790,6 @@ export function toLower(expr: Expression | string): FunctionExpression { } /** - * @beta * * Creates an expression that converts a string field to uppercase. * @@ -8183,7 +7805,6 @@ export function toLower(expr: Expression | string): FunctionExpression { export function toUpper(fieldName: string): FunctionExpression; /** - * @beta * * Creates an expression that converts a string expression to uppercase. * @@ -8202,7 +7823,6 @@ export function toUpper(expr: Expression | string): FunctionExpression { } /** - * @beta * * Creates an expression that removes leading and trailing whitespace from a string or byte array. * @@ -8226,7 +7846,6 @@ export function trim( ): FunctionExpression; /** - * @beta * * Creates an expression that removes leading and trailing characters from a string or byte array expression. * @@ -8256,7 +7875,6 @@ export function trim( } /** - * @beta * Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. * * @example @@ -8279,7 +7897,6 @@ export function ltrim( ): FunctionExpression; /** - * @beta * Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array. * * @example @@ -8308,7 +7925,6 @@ export function ltrim( } /** - * @beta * Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. * * @example @@ -8331,7 +7947,6 @@ export function rtrim( ): FunctionExpression; /** - * @beta * Trims whitespace or a specified set of characters/bytes from the end of a string or byte array. * * @example @@ -8360,7 +7975,6 @@ export function rtrim( } /** - * @beta * Creates an expression that returns the data type of the data in the specified field. * * @remarks @@ -8377,7 +7991,6 @@ export function rtrim( */ export function type(fieldName: string): FunctionExpression; /** - * @beta * Creates an expression that returns the data type of an expression's result. * * @example @@ -8396,7 +8009,6 @@ export function type( } /** - * @beta * Creates an expression that checks if the value in the specified field is of the given type. * * @remarks Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. @@ -8414,7 +8026,6 @@ export function type( export function isType(fieldName: string, type: Type): BooleanExpression; /** - * @beta * Creates an expression that checks if the result of an expression is of the given type. * * @remarks Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. @@ -8438,7 +8049,6 @@ export function isType( } /** - * @beta * * Creates an expression that concatenates string functions, fields or constants together. * @@ -8460,7 +8070,6 @@ export function stringConcat( ): FunctionExpression; /** - * @beta * Creates an expression that concatenates string expressions together. * * @example @@ -8491,7 +8100,6 @@ export function stringConcat( } /** - * @beta * Creates an expression that finds the index of the first occurrence of a substring or byte sequence. * * @example @@ -8510,7 +8118,6 @@ export function stringIndexOf( ): FunctionExpression; /** - * @beta * Creates an expression that finds the index of the first occurrence of a substring or byte sequence. * * @example @@ -8535,7 +8142,6 @@ export function stringIndexOf( } /** - * @beta * Creates an expression that repeats a string or byte array a specified number of times. * * @example @@ -8554,7 +8160,6 @@ export function stringRepeat( ): FunctionExpression; /** - * @beta * Creates an expression that repeats a string or byte array a specified number of times. * * @example @@ -8579,7 +8184,6 @@ export function stringRepeat( } /** - * @beta * Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. * * @example @@ -8600,7 +8204,6 @@ export function stringReplaceAll( ): FunctionExpression; /** - * @beta * Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement. * * @example @@ -8628,7 +8231,6 @@ export function stringReplaceAll( } /** - * @beta * Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. * * @example @@ -8649,7 +8251,6 @@ export function stringReplaceOne( ): FunctionExpression; /** - * @beta * Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement. * * @example @@ -8677,7 +8278,6 @@ export function stringReplaceOne( } /** - * @beta * * Accesses a value from a map (object) field using the provided key. * @@ -8694,7 +8294,6 @@ export function stringReplaceOne( export function mapGet(fieldName: string, subField: string): FunctionExpression; /** - * @beta * * Accesses a value from a map (object) expression using the provided key. * @@ -8720,7 +8319,6 @@ export function mapGet( } /** - * @beta * Creates an expression that returns a new map with the specified entries added or updated. * * @remarks @@ -8747,7 +8345,6 @@ export function mapSet( ): FunctionExpression; /** - * @beta * Creates an expression that returns a new map with the specified entries added or updated. * * @remarks @@ -8782,7 +8379,6 @@ export function mapSet( } /** - * @beta * Creates an expression that returns the keys of a map. * * @remarks @@ -8801,7 +8397,6 @@ export function mapSet( export function mapKeys(mapField: string): FunctionExpression; /** - * @beta * Creates an expression that returns the keys of a map. * * @remarks @@ -8823,7 +8418,6 @@ export function mapKeys(fieldOrExpr: string | Expression): FunctionExpression { } /** - * @beta * Creates an expression that returns the values of a map. * * @remarks @@ -8842,7 +8436,6 @@ export function mapKeys(fieldOrExpr: string | Expression): FunctionExpression { export function mapValues(mapField: string): FunctionExpression; /** - * @beta * Creates an expression that returns the values of a map. * * @remarks @@ -8866,7 +8459,6 @@ export function 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" }, ...]`. @@ -8887,7 +8479,6 @@ export function mapValues( export function mapEntries(mapField: string): FunctionExpression; /** - * @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" }, ...]`. @@ -8913,7 +8504,6 @@ export function mapEntries( } /** - * @beta * * Creates an aggregation that counts the total number of stage inputs. * @@ -8930,7 +8520,6 @@ export function countAll(): AggregateFunction { } /** - * @beta * * Creates an aggregation that counts the number of stage inputs with valid evaluations of the * provided expression. @@ -8947,7 +8536,6 @@ export function countAll(): AggregateFunction { export function count(expression: Expression): AggregateFunction; /** - * @beta * Creates an aggregation that counts the number of stage inputs where the input field exists. * * @example @@ -8965,7 +8553,6 @@ export function count(value: Expression | string): AggregateFunction { } /** - * @beta * * Creates an aggregation that calculates the sum of values from an expression across multiple * stage inputs. @@ -8982,7 +8569,6 @@ export function count(value: Expression | string): AggregateFunction { export function sum(expression: Expression): AggregateFunction; /** - * @beta * * Creates an aggregation that calculates the sum of a field's values across multiple stage * inputs. @@ -9002,7 +8588,6 @@ export function sum(value: Expression | string): AggregateFunction { } /** - * @beta * * Creates an aggregation that calculates the average (mean) of values from an expression across * multiple stage inputs. @@ -9019,7 +8604,6 @@ export function sum(value: Expression | string): AggregateFunction { export function average(expression: Expression): AggregateFunction; /** - * @beta * * Creates an aggregation that calculates the average (mean) of a field's values across multiple * stage inputs. @@ -9039,7 +8623,6 @@ export function average(value: Expression | string): AggregateFunction { } /** - * @beta * * Creates an aggregation that finds the minimum value of an expression across multiple stage * inputs. @@ -9056,7 +8639,6 @@ export function average(value: Expression | string): AggregateFunction { export function minimum(expression: Expression): AggregateFunction; /** - * @beta * * Creates an aggregation that finds the minimum value of a field across multiple stage inputs. * @@ -9075,7 +8657,6 @@ export function minimum(value: Expression | string): AggregateFunction { } /** - * @beta * * Creates an aggregation that finds the maximum value of an expression across multiple stage * inputs. @@ -9092,7 +8673,6 @@ export function minimum(value: Expression | string): AggregateFunction { export function maximum(expression: Expression): AggregateFunction; /** - * @beta * * Creates an aggregation that finds the maximum value of a field across multiple stage inputs. * @@ -9111,7 +8691,6 @@ export function maximum(value: Expression | string): AggregateFunction { } /** - * @beta * Creates an aggregation that finds the first value of an expression across multiple stage * inputs. * @@ -9127,7 +8706,6 @@ export function maximum(value: Expression | string): AggregateFunction { export function first(expression: Expression): AggregateFunction; /** - * @beta * Creates an aggregation that finds the first value of a field across multiple stage inputs. * * @example @@ -9145,7 +8723,6 @@ export function first(value: Expression | string): AggregateFunction { } /** - * @beta * Creates an aggregation that finds the last value of an expression across multiple stage * inputs. * @@ -9161,7 +8738,6 @@ export function first(value: Expression | string): AggregateFunction { export function last(expression: Expression): AggregateFunction; /** - * @beta * Creates an aggregation that finds the last value of a field across multiple stage inputs. * * @example @@ -9179,7 +8755,6 @@ export function last(value: Expression | string): AggregateFunction { } /** - * @beta * Creates an aggregation that collects all values of an expression across multiple stage * inputs into an array. * @@ -9199,7 +8774,6 @@ export function last(value: Expression | string): AggregateFunction { export function arrayAgg(expression: Expression): AggregateFunction; /** - * @beta * Creates an aggregation that collects all values of a field across multiple stage inputs * into an array. * @@ -9222,7 +8796,6 @@ export function arrayAgg(value: Expression | string): AggregateFunction { } /** - * @beta * Creates an aggregation that collects all distinct values of an expression across multiple stage * inputs into an array. * @@ -9242,7 +8815,6 @@ export function arrayAgg(value: Expression | string): AggregateFunction { export function arrayAggDistinct(expression: Expression): AggregateFunction; /** - * @beta * Creates an aggregation that collects all distinct values of a field across multiple stage inputs * into an array. * @@ -9267,7 +8839,6 @@ export function arrayAggDistinct( } /** - * @beta * * Calculates the Cosine distance between a field's vector value and a literal vector value. * @@ -9287,7 +8858,6 @@ export function cosineDistance( ): FunctionExpression; /** - * @beta * * Calculates the Cosine distance between a field's vector value and a vector expression. * @@ -9307,7 +8877,6 @@ export function cosineDistance( ): FunctionExpression; /** - * @beta * * Calculates the Cosine distance between a vector expression and a vector literal. * @@ -9327,7 +8896,6 @@ export function cosineDistance( ): FunctionExpression; /** - * @beta * * Calculates the Cosine distance between two vector expressions. * @@ -9355,7 +8923,6 @@ export function cosineDistance( } /** - * @beta * * Calculates the dot product between a field's vector value and a double array. * @@ -9375,7 +8942,6 @@ export function dotProduct( ): FunctionExpression; /** - * @beta * * Calculates the dot product between a field's vector value and a vector expression. * @@ -9395,7 +8961,6 @@ export function dotProduct( ): FunctionExpression; /** - * @beta * * Calculates the dot product between a vector expression and a double array. * @@ -9415,7 +8980,6 @@ export function dotProduct( ): FunctionExpression; /** - * @beta * * Calculates the dot product between two vector expressions. * @@ -9443,7 +9007,6 @@ export function dotProduct( } /** - * @beta * * Calculates the Euclidean distance between a field's vector value and a double array. * @@ -9463,7 +9026,6 @@ export function euclideanDistance( ): FunctionExpression; /** - * @beta * * Calculates the Euclidean distance between a field's vector value and a vector expression. * @@ -9483,7 +9045,6 @@ export function euclideanDistance( ): FunctionExpression; /** - * @beta * * Calculates the Euclidean distance between a vector expression and a double array. * @@ -9504,7 +9065,6 @@ export function euclideanDistance( ): FunctionExpression; /** - * @beta * * Calculates the Euclidean distance between two vector expressions. * @@ -9532,7 +9092,6 @@ export function euclideanDistance( } /** - * @beta * * Creates an expression that calculates the length of a Firestore Vector. * @@ -9548,7 +9107,6 @@ export function euclideanDistance( export function vectorLength(vectorExpression: Expression): FunctionExpression; /** - * @beta * * Creates an expression that calculates the length of a Firestore Vector represented by a field. * @@ -9567,7 +9125,6 @@ export function vectorLength(expr: Expression | string): FunctionExpression { } /** - * @beta * * Creates an expression that interprets an expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) * and returns a timestamp. @@ -9584,7 +9141,6 @@ export function vectorLength(expr: Expression | string): FunctionExpression { export function unixMicrosToTimestamp(expr: Expression): FunctionExpression; /** - * @beta * * Creates an expression that interprets a field's value as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC) * and returns a timestamp. @@ -9606,7 +9162,6 @@ export function unixMicrosToTimestamp( } /** - * @beta * * Creates an expression that converts a timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). * @@ -9622,7 +9177,6 @@ export function unixMicrosToTimestamp( export function timestampToUnixMicros(expr: Expression): FunctionExpression; /** - * @beta * * Creates an expression that converts a timestamp field to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC). * @@ -9643,7 +9197,6 @@ export function timestampToUnixMicros( } /** - * @beta * * Creates an expression that interprets an expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) * and returns a timestamp. @@ -9660,7 +9213,6 @@ export function timestampToUnixMicros( export function unixMillisToTimestamp(expr: Expression): FunctionExpression; /** - * @beta * * Creates an expression that interprets a field's value as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC) * and returns a timestamp. @@ -9683,7 +9235,6 @@ export function unixMillisToTimestamp( } /** - * @beta * * Creates an expression that converts a timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). * @@ -9699,7 +9250,6 @@ export function unixMillisToTimestamp( export function timestampToUnixMillis(expr: Expression): FunctionExpression; /** - * @beta * * Creates an expression that converts a timestamp field to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC). * @@ -9721,7 +9271,6 @@ export function timestampToUnixMillis( } /** - * @beta * * Creates an expression that interprets an expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) * and returns a timestamp. @@ -9738,7 +9287,6 @@ export function timestampToUnixMillis( export function unixSecondsToTimestamp(expr: Expression): FunctionExpression; /** - * @beta * * Creates an expression that interprets a field's value as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC) * and returns a timestamp. @@ -9761,7 +9309,6 @@ export function unixSecondsToTimestamp( } /** - * @beta * * Creates an expression that converts a timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). * @@ -9777,7 +9324,6 @@ export function unixSecondsToTimestamp( export function timestampToUnixSeconds(expr: Expression): FunctionExpression; /** - * @beta * * Creates an expression that converts a timestamp field to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC). * @@ -9799,7 +9345,6 @@ export function timestampToUnixSeconds( } /** - * @beta * * Creates an expression that adds a specified amount of time to a timestamp. * @@ -9821,7 +9366,6 @@ export function timestampAdd( ): FunctionExpression; /** - * @beta * * Creates an expression that adds a specified amount of time to a timestamp. * @@ -9843,7 +9387,6 @@ export function timestampAdd( ): FunctionExpression; /** - * @beta * * Creates an expression that adds a specified amount of time to a timestamp represented by a field. * @@ -9875,7 +9418,6 @@ export function timestampAdd( } /** - * @beta * * Creates an expression that subtracts a specified amount of time from a timestamp. * @@ -9897,7 +9439,6 @@ export function timestampSubtract( ): FunctionExpression; /** - * @beta * * Creates an expression that subtracts a specified amount of time from a timestamp. * @@ -9919,7 +9460,6 @@ export function timestampSubtract( ): FunctionExpression; /** - * @beta * * Creates an expression that subtracts a specified amount of time from a timestamp represented by a field. * @@ -9954,7 +9494,6 @@ export function timestampSubtract( } /** - * @beta * * Creates an expression that evaluates to the current server timestamp. * @@ -9971,7 +9510,6 @@ export function currentTimestamp(): FunctionExpression { } /** - * @beta * * Creates an expression that performs a logical 'AND' operation on multiple filter conditions. * @@ -10000,7 +9538,6 @@ export function and( } /** - * @beta * * Creates an expression that performs a logical 'OR' operation on multiple filter conditions. * @@ -10029,7 +9566,6 @@ export function or( } /** - * @beta * * Creates an expression that performs a logical 'NOR' operation on multiple filter conditions. * @@ -10060,7 +9596,6 @@ export function nor( } /** - * @beta * Creates an expression that returns the value of the base expression raised to the power of the exponent expression. * * @example @@ -10076,7 +9611,6 @@ export function nor( export function pow(base: Expression, exponent: Expression): FunctionExpression; /** - * @beta * Creates an expression that returns the value of the base expression raised to the power of the exponent. * * @example @@ -10092,7 +9626,6 @@ export function pow(base: Expression, exponent: Expression): FunctionExpression; export function pow(base: Expression, exponent: number): FunctionExpression; /** - * @beta * Creates an expression that returns the value of the base field raised to the power of the exponent expression. * * @example @@ -10108,7 +9641,6 @@ export function pow(base: Expression, exponent: number): FunctionExpression; export function pow(base: string, exponent: Expression): FunctionExpression; /** - * @beta * Creates an expression that returns the value of the base field raised to the power of the exponent. * * @example @@ -10130,7 +9662,6 @@ export function pow( } /** - * @beta * * Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. * @@ -10147,7 +9678,6 @@ export function rand(): FunctionExpression { } /** - * @beta * Creates an expression that rounds a numeric value to the nearest whole number. * * @example @@ -10162,7 +9692,6 @@ export function rand(): FunctionExpression { export function round(fieldName: string): FunctionExpression; /** - * @beta * Creates an expression that rounds a numeric value to the nearest whole number. * * @example @@ -10177,7 +9706,6 @@ export function round(fieldName: string): FunctionExpression; export function round(expression: Expression): FunctionExpression; /** - * @beta * Creates an expression that rounds a numeric value to the specified number of decimal places. * * @example @@ -10196,7 +9724,6 @@ export function round( ): FunctionExpression; /** - * @beta * Creates an expression that rounds a numeric value to the specified number of decimal places. * * @example @@ -10225,7 +9752,6 @@ export function round( } /** - * @beta * Creates an expression that truncates the numeric value of a field to an integer. * * @example @@ -10240,7 +9766,6 @@ export function round( export function trunc(fieldName: string): FunctionExpression; /** - * @beta * Creates an expression that truncates the numeric value of an expression to an integer. * * @example @@ -10255,7 +9780,6 @@ export function trunc(fieldName: string): FunctionExpression; export function trunc(expression: Expression): FunctionExpression; /** - * @beta * Creates an expression that truncates a numeric expression to the specified number of decimal places. * * @example @@ -10274,7 +9798,6 @@ export function trunc( ): FunctionExpression; /** - * @beta * Creates an expression that truncates a numeric value to the specified number of decimal places. * * @example @@ -10303,7 +9826,6 @@ export function trunc( } /** - * @beta * Creates an expression that returns the collection ID from a path. * * @example @@ -10318,7 +9840,6 @@ export function trunc( export function collectionId(fieldName: string): FunctionExpression; /** - * @beta * Creates an expression that returns the collection ID from a path. * * @example @@ -10336,7 +9857,6 @@ export function collectionId(expr: Expression | string): FunctionExpression { } /** - * @beta * Creates an expression that calculates the length of a string, array, map, vector, or bytes. * * @example @@ -10354,7 +9874,6 @@ export function collectionId(expr: Expression | string): FunctionExpression { export function length(fieldName: string): FunctionExpression; /** - * @beta * Creates an expression that calculates the length of a string, array, map, vector, or bytes. * * @example @@ -10375,7 +9894,6 @@ export function length(expr: Expression | string): FunctionExpression { } /** - * @beta * Creates an expression that computes the natural logarithm of a numeric value. * * @example @@ -10390,7 +9908,6 @@ export function length(expr: Expression | string): FunctionExpression { export function ln(fieldName: string): FunctionExpression; /** - * @beta * Creates an expression that computes the natural logarithm of a numeric value. * * @example @@ -10408,7 +9925,6 @@ export function ln(expr: Expression | string): FunctionExpression { } /** - * @beta * Creates an expression that computes the logarithm of an expression to a given base. * * @example @@ -10423,7 +9939,6 @@ export function ln(expr: Expression | string): FunctionExpression { */ export function log(expression: Expression, base: number): FunctionExpression; /** - * @beta * Creates an expression that computes the logarithm of an expression to a given base. * * @example @@ -10441,7 +9956,6 @@ export function log( base: Expression ): FunctionExpression; /** - * @beta * Creates an expression that computes the logarithm of a field to a given base. * * @example @@ -10456,7 +9970,6 @@ export function log( */ export function log(fieldName: string, base: number): FunctionExpression; /** - * @beta * Creates an expression that computes the logarithm of a field to a given base. * * @example @@ -10481,7 +9994,6 @@ export function log( } /** - * @beta * Creates an expression that computes the square root of a numeric value. * * @example @@ -10495,7 +10007,6 @@ export function log( */ export function sqrt(expression: Expression): FunctionExpression; /** - * @beta * Creates an expression that computes the square root of a numeric value. * * @example @@ -10513,7 +10024,6 @@ export function sqrt(expr: Expression | string): FunctionExpression { } /** - * @beta * Creates an expression that reverses a string. * * @example @@ -10528,7 +10038,6 @@ export function sqrt(expr: Expression | string): FunctionExpression { export function stringReverse(stringExpression: Expression): FunctionExpression; /** - * @beta * Creates an expression that reverses a string value in the specified field. * * @example @@ -10546,7 +10055,6 @@ export function stringReverse(expr: Expression | string): FunctionExpression { } /** - * @beta * Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. * * @example @@ -10567,7 +10075,6 @@ export function concat( ): FunctionExpression; /** - * @beta * Creates an expression that concatenates strings, arrays, or blobs. Types cannot be mixed. * * @example @@ -10600,7 +10107,6 @@ export function concat( } /** - * @beta * Creates an expression that computes the absolute value of a numeric value. * * @param expr - The expression to compute the absolute value of. @@ -10609,7 +10115,6 @@ export function concat( export function abs(expr: Expression): FunctionExpression; /** - * @beta * Creates an expression that computes the absolute value of a numeric value. * * @param fieldName - The field to compute the absolute value of. @@ -10621,7 +10126,6 @@ export function abs(expr: Expression | string): FunctionExpression { } /** - * @beta * Creates an expression that returns the `elseExpr` argument if `ifExpr` is absent, else return * the result of the `ifExpr` argument evaluation. * @@ -10639,7 +10143,6 @@ export function abs(expr: Expression | string): FunctionExpression { export function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expression; /** - * @beta * Creates an expression that returns the `elseValue` argument if `ifExpr` is absent, else * return the result of the `ifExpr` argument evaluation. * @@ -10657,7 +10160,6 @@ export function ifAbsent(ifExpr: Expression, elseExpr: Expression): Expression; export function ifAbsent(ifExpr: Expression, elseValue: unknown): Expression; /** - * @beta * Creates an expression that returns the `elseExpr` argument if `ifFieldName` is absent, else * return the value of the field. * @@ -10676,7 +10178,6 @@ export function ifAbsent(ifExpr: Expression, elseValue: unknown): Expression; export function ifAbsent(ifFieldName: string, elseExpr: Expression): Expression; /** - * @beta * Creates an expression that returns the `elseValue` argument if `ifFieldName` is absent, else * return the value of the field. * @@ -10705,7 +10206,6 @@ export function ifAbsent( } /** - * @beta * Creates an expression that returns the `elseExpr` argument if `ifExpr` is null, else * return the result of the `ifExpr` argument evaluation. * @@ -10729,7 +10229,6 @@ export function ifNull( ): FunctionExpression; /** - * @beta * Creates an expression that returns the `elseValue` argument if `ifExpr` is null, else * return the result of the `ifExpr` argument evaluation. * @@ -10753,7 +10252,6 @@ export function ifNull( ): FunctionExpression; /** - * @beta * Creates an expression that returns the `elseExpr` argument if `ifFieldName` field is null, else * return the value of the field. * @@ -10777,7 +10275,6 @@ export function ifNull( ): FunctionExpression; /** - * @beta * Creates an expression that returns the `elseValue` argument if `ifFieldName` field is null, else * return the value of the field. * @@ -10807,7 +10304,6 @@ export function ifNull( } /** - * @beta * Creates an expression that returns the first non-null, non-absent argument, without evaluating * the rest of the arguments. When all arguments are null or absent, returns the last argument. * @@ -10830,7 +10326,6 @@ export function coalesce( ): FunctionExpression; /** - * @beta * Creates an expression that returns the first non-null, non-absent argument, without evaluating * the rest of the arguments. When all arguments are null or absent, returns the last argument. * @@ -10863,7 +10358,6 @@ export function coalesce( } /** - * @beta * Creates an expression that evaluates to the result corresponding to the first true condition. * * @remarks @@ -10905,7 +10399,6 @@ export function switchOn( } /** - * @beta * Creates an expression that joins the elements of an array into a string. * * @example @@ -10921,7 +10414,6 @@ export function switchOn( export function join(arrayFieldName: string, delimiter: string): Expression; /** - * @beta * Creates an expression that joins the elements of an array into a string. * * @example @@ -10940,7 +10432,6 @@ export function join( ): Expression; /** - * @beta * Creates an expression that joins the elements of an array into a string. * * @example @@ -10959,7 +10450,6 @@ export function join( ): Expression; /** - * @beta * Creates an expression that joins the elements of an array into a string. * * @example @@ -10986,7 +10476,6 @@ export function join( } /** - * @beta * Creates an expression that computes the base-10 logarithm of a numeric value. * * @example @@ -11001,7 +10490,6 @@ export function join( export function log10(fieldName: string): FunctionExpression; /** - * @beta * Creates an expression that computes the base-10 logarithm of a numeric value. * * @example @@ -11019,7 +10507,6 @@ export function log10(expr: Expression | string): FunctionExpression { } /** - * @beta * Creates an expression that computes the sum of the elements in an array. * * @example @@ -11034,7 +10521,6 @@ export function log10(expr: Expression | string): FunctionExpression { export function arraySum(fieldName: string): FunctionExpression; /** - * @beta * Creates an expression that computes the sum of the elements in an array. * * @example @@ -11052,7 +10538,6 @@ export function arraySum(expr: Expression | string): FunctionExpression { } /** - * @beta * Creates an expression that splits the value of a field on the provided delimiter. * * @example @@ -11069,7 +10554,6 @@ export function arraySum(expr: Expression | string): FunctionExpression { export function split(fieldName: string, delimiter: string): FunctionExpression; /** - * @beta * Creates an expression that splits the value of a field on the provided delimiter. * * @example @@ -11089,7 +10573,6 @@ export function split( ): FunctionExpression; /** - * @beta * Creates an expression that splits a string into an array of substrings based on the provided delimiter. * * @example @@ -11109,7 +10592,6 @@ export function split( ): FunctionExpression; /** - * @beta * Creates an expression that splits a string into an array of substrings based on the provided delimiter. * * @example @@ -11137,7 +10619,6 @@ export function split( } /** - * @beta * Creates an expression that truncates a timestamp to a specified granularity. * * @example @@ -11159,7 +10640,6 @@ export function timestampTruncate( ): FunctionExpression; /** - * @beta * Creates an expression that truncates a timestamp to a specified granularity. * * @example @@ -11181,7 +10661,6 @@ export function timestampTruncate( ): FunctionExpression; /** - * @beta * Creates an expression that truncates a timestamp to a specified granularity. * * @example @@ -11203,7 +10682,6 @@ export function timestampTruncate( ): FunctionExpression; /** - * @beta * Creates an expression that truncates a timestamp to a specified granularity. * * @example @@ -11238,7 +10716,6 @@ export function timestampTruncate( } /** - * @beta * Creates an expression that calculates the difference between two timestamps. * * @example @@ -11259,7 +10736,6 @@ export function timestampDiff( ): FunctionExpression; /** - * @beta * Creates an expression that calculates the difference between two timestamps. * * @example @@ -11280,7 +10756,6 @@ export function timestampDiff( ): FunctionExpression; /** - * @beta * Creates an expression that calculates the difference between two timestamps. * * @example @@ -11301,7 +10776,6 @@ export function timestampDiff( ): FunctionExpression; /** - * @beta * Creates an expression that calculates the difference between two timestamps. * * @example @@ -11332,7 +10806,6 @@ export function timestampDiff( } /** - * @beta * Creates an expression that extracts a specified part from a timestamp. * * @example @@ -11354,7 +10827,6 @@ export function timestampExtract( ): FunctionExpression; /** - * @beta * Creates an expression that extracts a specified part from a timestamp. * * @example @@ -11376,7 +10848,6 @@ export function timestampExtract( ): FunctionExpression; /** - * @beta * Creates an expression that extracts a specified part from a timestamp. * * @example @@ -11398,7 +10869,6 @@ export function timestampExtract( ): FunctionExpression; /** - * @beta * Creates an expression that extracts a specified part from a timestamp. * * @example @@ -11432,7 +10902,6 @@ export function timestampExtract( // TODO(new-expression): Add new top-level expression function definitions above this line /** - * @beta * * Creates an {@link @firebase/firestore/pipelines#Ordering} that sorts documents in ascending order based on an expression. * @@ -11449,7 +10918,6 @@ export function timestampExtract( export function ascending(expr: Expression): Ordering; /** - * @beta * * Creates an {@link @firebase/firestore/pipelines#Ordering} that sorts documents in ascending order based on a field. * @@ -11469,7 +10937,6 @@ export function ascending(field: Expression | string): Ordering { } /** - * @beta * * Creates an {@link @firebase/firestore/pipelines#Ordering} that sorts documents in descending order based on an expression. * @@ -11486,7 +10953,6 @@ export function ascending(field: Expression | string): Ordering { export function descending(expr: Expression): Ordering; /** - * @beta * * Creates an {@link @firebase/firestore/pipelines#Ordering} that sorts documents in descending order based on a field. * @@ -11506,7 +10972,6 @@ export function descending(field: Expression | string): Ordering { } /** - * @beta * * Represents an ordering criterion for sorting documents in a Firestore pipeline. * diff --git a/packages/firestore/src/lite-api/pipeline-result.ts b/packages/firestore/src/lite-api/pipeline-result.ts index 219d2abb8a..d3dc649d3b 100644 --- a/packages/firestore/src/lite-api/pipeline-result.ts +++ b/packages/firestore/src/lite-api/pipeline-result.ts @@ -28,7 +28,6 @@ import { fieldPathFromArgument } from './user_data_reader'; import { AbstractUserDataWriter } from './user_data_writer'; /** - * @beta * Represents the results of a Firestore pipeline execution. * * A `PipelineSnapshot` contains zero or more {@link @firebase/firestore/pipelines#PipelineResult} objects @@ -63,14 +62,13 @@ export class PipelineSnapshot { } /** - * @beta An array of all the results in the `PipelineSnapshot`. + * An array of all the results in the `PipelineSnapshot`. */ get results(): PipelineResult[] { return this._results; } /** - * @beta * The time at which the pipeline producing this result is executed. * * @readonly @@ -87,7 +85,6 @@ export class PipelineSnapshot { } /** - * @beta * * A PipelineResult contains data read from a Firestore Pipeline. The data can be extracted with the * {@link @firebase/firestore/pipelines#PipelineResult.data} or {@link @firebase/firestore/pipelines#PipelineResult.(get:1)} methods. @@ -139,7 +136,6 @@ export class PipelineResult { } /** - * @beta * The reference of the document, if it is a document; otherwise `undefined`. */ get ref(): DocumentReference | undefined { @@ -147,7 +143,6 @@ export class PipelineResult { } /** - * @beta * The ID of the document for which this PipelineResult contains data, if it is a document; otherwise `undefined`. * * @readonly @@ -158,7 +153,6 @@ export class PipelineResult { } /** - * @beta * The time the document was created. Undefined if this result is not a document. * * @readonly @@ -168,7 +162,6 @@ export class PipelineResult { } /** - * @beta * The time the document was last updated (at the time the snapshot was * generated). Undefined if this result is not a document. * @@ -179,7 +172,6 @@ export class PipelineResult { } /** - * @beta * Retrieves all fields in the result as an object. * * @returns An object containing all fields in the document or @@ -215,7 +207,6 @@ export class PipelineResult { } /** - * @beta * Retrieves the field specified by `field`. * * @param field - The field path @@ -254,7 +245,6 @@ export class PipelineResult { } /** - * @beta * Test equality of two PipelineResults. * @param left - First PipelineResult to compare. * @param right - Second PipelineResult to compare. diff --git a/packages/firestore/src/lite-api/pipeline-source.ts b/packages/firestore/src/lite-api/pipeline-source.ts index ee11b9661c..f1cc4151dd 100644 --- a/packages/firestore/src/lite-api/pipeline-source.ts +++ b/packages/firestore/src/lite-api/pipeline-source.ts @@ -42,7 +42,6 @@ import { } from './stage_options'; /** - * @beta * Provides the entry point for defining the data source of a Firestore {@link @firebase/firestore/pipelines#Pipeline}. * * Use the methods of this class (e.g., {@link @firebase/firestore/pipelines#PipelineSource.(collection:1)}, {@link @firebase/firestore/pipelines#PipelineSource.(collectionGroup:1)}, @@ -66,13 +65,11 @@ export class PipelineSource { ) {} /** - * @beta * Returns all documents from the entire collection. The collection can be nested. * @param collection - Name or reference to the collection that will be used as the Pipeline source. */ collection(collection: string | CollectionReference): PipelineType; /** - * @beta * Returns all documents from the entire collection. The collection can be nested. * @param options - Options defining how this CollectionStage is evaluated. */ @@ -110,13 +107,11 @@ export class PipelineSource { } /** - * @beta * Returns all documents from a collection ID regardless of the parent. * @param collectionId - ID of the collection group to use as the Pipeline source. */ collectionGroup(collectionId: string): PipelineType; /** - * @beta * Returns all documents from a collection ID regardless of the parent. * @param options - Options defining how this CollectionGroupStage is evaluated. */ @@ -142,12 +137,10 @@ export class PipelineSource { } /** - * @beta * Returns all documents from the entire database. */ database(): PipelineType; /** - * @beta * Returns all documents from the entire database. * @param options - Options defining how a DatabaseStage is evaluated. */ @@ -164,7 +157,6 @@ export class PipelineSource { } /** - * @beta * Set the pipeline's source to the documents specified by the given paths and DocumentReferences. * * @param docs - An array of paths and DocumentReferences specifying the individual documents that will be the source of this pipeline. @@ -175,7 +167,6 @@ export class PipelineSource { documents(docs: Array): PipelineType; /** - * @beta * Set the pipeline's source to the documents specified by the given paths and DocumentReferences. * * @param options - Options defining how this DocumentsStage is evaluated. @@ -214,7 +205,6 @@ export class PipelineSource { } /** - * @beta * Convert the given Query into an equivalent Pipeline. * * @param query - A Query to be converted into a Pipeline. diff --git a/packages/firestore/src/lite-api/pipeline.ts b/packages/firestore/src/lite-api/pipeline.ts index 5d961885e5..febfdf200f 100644 --- a/packages/firestore/src/lite-api/pipeline.ts +++ b/packages/firestore/src/lite-api/pipeline.ts @@ -89,7 +89,6 @@ import { import { UserData } from './user_data_reader'; /** - * @beta * * The Pipeline class provides a flexible and expressive framework for building complex data * transformation and query pipelines for Firestore. @@ -158,7 +157,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Adds new fields to outputs from previous stages. * * This stage allows you to compute values on-the-fly based on existing data from previous @@ -188,7 +186,6 @@ export class Pipeline implements ProtoSerializable, UserData { */ addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; /** - * @beta * Adds new fields to outputs from previous stages. * * This stage allows you to compute values on-the-fly based on existing data from previous @@ -241,7 +238,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Remove fields from outputs of previous stages. * * Example: @@ -265,7 +261,6 @@ export class Pipeline implements ProtoSerializable, UserData { ...additionalFields: Array ): Pipeline; /** - * @beta * Remove fields from outputs of previous stages. * * Example: @@ -311,7 +306,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Selects or creates a set of fields from the outputs of previous stages. * *

    The selected fields are defined using {@link @firebase/firestore/pipelines#Selectable} expressions, which can be: @@ -350,7 +344,6 @@ export class Pipeline implements ProtoSerializable, UserData { ...additionalSelections: Array ): Pipeline; /** - * @beta * Selects or creates a set of fields from the outputs of previous stages. * *

    The selected fields are defined using {@link @firebase/firestore/pipelines#Selectable} expressions, which can be: @@ -409,7 +402,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Filters the documents from previous stages to only include those matching the specified {@link * @firebase/firestore/pipelines#BooleanExpression}. * @@ -443,7 +435,6 @@ export class Pipeline implements ProtoSerializable, UserData { */ where(condition: BooleanExpression): Pipeline; /** - * @beta * Filters the documents from previous stages to only include those matching the specified {@link * @firebase/firestore/pipelines#BooleanExpression}. * @@ -491,7 +482,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Skips the first `offset` number of documents from the results of previous stages. * *

    This stage is useful for implementing pagination in your pipelines, allowing you to retrieve @@ -514,7 +504,6 @@ export class Pipeline implements ProtoSerializable, UserData { */ offset(offset: number): Pipeline; /** - * @beta * Skips the first `offset` number of documents from the results of previous stages. * *

    This stage is useful for implementing pagination in your pipelines, allowing you to retrieve @@ -556,7 +545,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Limits the maximum number of documents returned by previous stages to `limit`. * *

    This stage is particularly useful when you want to retrieve a controlled subset of data from @@ -584,7 +572,6 @@ export class Pipeline implements ProtoSerializable, UserData { */ limit(limit: number): Pipeline; /** - * @beta * Limits the maximum number of documents returned by previous stages to `limit`. * *

    This stage is particularly useful when you want to retrieve a controlled subset of data from @@ -626,7 +613,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Returns a set of distinct values from the inputs to this stage. * * This stage runs through the results from previous stages to include only results with @@ -660,7 +646,6 @@ export class Pipeline implements ProtoSerializable, UserData { ...additionalGroups: Array ): Pipeline; /** - * @beta * Returns a set of distinct values from the inputs to this stage. * * This stage runs through the results from previous stages to include only results with @@ -712,7 +697,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Performs aggregation operations on the documents from previous stages. * *

    This stage allows you to calculate aggregate values over a set of documents. You define the @@ -742,7 +726,6 @@ export class Pipeline implements ProtoSerializable, UserData { ...additionalAccumulators: AliasedAggregate[] ): Pipeline; /** - * @beta * Performs optionally grouped aggregation operations on the documents from previous stages. * *

    This stage allows you to calculate aggregate values over a set of documents, optionally @@ -808,7 +791,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Performs a vector proximity search on the documents from the previous stage, returning the * K-nearest documents based on the specified query `vectorValue` and `distanceMeasure`. The * returned documents will be sorted in order from nearest to furthest from the query `vectorValue`. @@ -859,7 +841,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Sorts the documents from previous stages based on one or more {@link @firebase/firestore/pipelines#Ordering} criteria. * *

    This stage allows you to order the results of your pipeline. You can specify multiple {@link @@ -887,7 +868,6 @@ export class Pipeline implements ProtoSerializable, UserData { */ sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; /** - * @beta * Sorts the documents from previous stages based on one or more {@link @firebase/firestore/pipelines#Ordering} criteria. * *

    This stage allows you to order the results of your pipeline. You can specify multiple {@link @@ -931,7 +911,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Fully overwrites all fields in a document with those coming from a nested map. * *

    This stage allows you to emit a map value as a document. Each key of the map becomes a field @@ -965,7 +944,6 @@ export class Pipeline implements ProtoSerializable, UserData { */ replaceWith(fieldName: string): Pipeline; /** - * @beta * Fully overwrites all fields in a document with those coming from a map. * *

    This stage allows you to emit a map value as a document. Each key of the map becomes a field @@ -1004,7 +982,6 @@ export class Pipeline implements ProtoSerializable, UserData { */ replaceWith(expr: Expression): Pipeline; /** - * @beta * Fully overwrites all fields in a document with those coming from a map. * *

    This stage allows you to emit a map value as a document. Each key of the map becomes a field @@ -1064,7 +1041,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Performs a pseudo-random sampling of the documents from the previous stage. * *

    This stage will filter documents pseudo-randomly. The parameter specifies how number of @@ -1085,7 +1061,6 @@ export class Pipeline implements ProtoSerializable, UserData { sample(documents: number): Pipeline; /** - * @beta * Performs a pseudo-random sampling of the documents from the previous stage. * *

    This stage will filter documents pseudo-randomly. The 'options' parameter specifies how @@ -1130,7 +1105,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Performs union of all documents from two pipelines, including duplicates. * *

    This stage will pass through documents from previous stage, and also pass through documents @@ -1151,7 +1125,6 @@ export class Pipeline implements ProtoSerializable, UserData { */ union(other: Pipeline): Pipeline; /** - * @beta * Performs union of all documents from two pipelines, including duplicates. * *

    This stage will pass through documents from previous stage, and also pass through documents @@ -1190,7 +1163,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Produces a document for each element in an input array. * * For each previous stage document, this stage will emit zero or more augmented documents. The @@ -1225,7 +1197,6 @@ export class Pipeline implements ProtoSerializable, UserData { */ unnest(selectable: Selectable, indexField?: string): Pipeline; /** - * @beta * Produces a document for each element in an input array. * * For each previous stage document, this stage will emit zero or more augmented documents. The @@ -1293,7 +1264,6 @@ export class Pipeline implements ProtoSerializable, UserData { } /** - * @beta * Adds a raw stage to the pipeline. * *

    This method provides a flexible way to extend the pipeline's functionality by adding custom diff --git a/packages/firestore/src/lite-api/pipeline_impl.ts b/packages/firestore/src/lite-api/pipeline_impl.ts index 8a1c4553da..0c375ca4c7 100644 --- a/packages/firestore/src/lite-api/pipeline_impl.ts +++ b/packages/firestore/src/lite-api/pipeline_impl.ts @@ -35,7 +35,6 @@ import { newUserDataReader, UserDataSource } from './user_data_reader'; declare module './database' { interface Firestore { /** - * @beta * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link @firebase/firestore/pipelines#Pipeline}. * * @example @@ -48,7 +47,6 @@ declare module './database' { } /** - * @beta * Executes this pipeline and returns a Promise to represent the asynchronous operation. * * The returned Promise can be used to track the progress of the pipeline execution @@ -131,7 +129,6 @@ export function execute(pipeline: Pipeline): Promise { } /** - * @beta * Creates and returns a new PipelineSource, which allows specifying the source stage of a {@link @firebase/firestore/pipelines#Pipeline}. * * @example diff --git a/packages/firestore/src/lite-api/pipeline_options.ts b/packages/firestore/src/lite-api/pipeline_options.ts index 8f8f9d6238..e9dd35b3ed 100644 --- a/packages/firestore/src/lite-api/pipeline_options.ts +++ b/packages/firestore/src/lite-api/pipeline_options.ts @@ -1,5 +1,4 @@ /** - * @beta * @license * Copyright 2025 Google LLC * @@ -19,24 +18,20 @@ import type { Pipeline } from './pipeline'; /** - * @beta * Options defining Pipeline execution. */ export interface PipelineExecuteOptions { /** - * @beta * Pipeline to be evaluated. */ pipeline: Pipeline; /** - * @beta * Specify the index mode. */ indexMode?: 'recommended'; /** - * @beta * An escape hatch to set options not known at SDK build time. These values * will be passed directly to the Firestore backend and not used by the SDK. * diff --git a/packages/firestore/src/lite-api/stage.ts b/packages/firestore/src/lite-api/stage.ts index 0d6a17f08d..9c1d4c4639 100644 --- a/packages/firestore/src/lite-api/stage.ts +++ b/packages/firestore/src/lite-api/stage.ts @@ -44,9 +44,6 @@ import { Pipeline } from './pipeline'; import { StageOptions } from './stage_options'; import { isUserData, UserData } from './user_data_reader'; -/** - * @beta - */ export abstract class Stage implements ProtoSerializable, UserData { /** * Store optionsProto parsed by _readUserData. @@ -83,9 +80,6 @@ export abstract class Stage implements ProtoSerializable, UserData { abstract get _name(): string; } -/** - * @beta - */ export class AddFields extends Stage { get _name(): string { return 'add_fields'; @@ -111,9 +105,6 @@ export class AddFields extends Stage { } } -/** - * @beta - */ export class RemoveFields extends Stage { get _name(): string { return 'remove_fields'; @@ -144,9 +135,6 @@ export class RemoveFields extends Stage { } } -/** - * @beta - */ export class Aggregate extends Stage { get _name(): string { return 'aggregate'; @@ -185,9 +173,6 @@ export class Aggregate extends Stage { } } -/** - * @beta - */ export class Distinct extends Stage { get _name(): string { return 'distinct'; @@ -218,9 +203,6 @@ export class Distinct extends Stage { } } -/** - * @beta - */ export class CollectionSource extends Stage { get _name(): string { return 'collection'; @@ -261,9 +243,6 @@ export class CollectionSource extends Stage { } } -/** - * @beta - */ export class CollectionGroupSource extends Stage { get _name(): string { return 'collection_group'; @@ -297,9 +276,6 @@ export class CollectionGroupSource extends Stage { } } -/** - * @beta - */ export class DatabaseSource extends Stage { get _name(): string { return 'database'; @@ -323,9 +299,6 @@ export class DatabaseSource extends Stage { } } -/** - * @beta - */ export class DocumentsSource extends Stage { get _name(): string { return 'documents'; @@ -362,9 +335,6 @@ export class DocumentsSource extends Stage { } } -/** - * @beta - */ export class Where extends Stage { get _name(): string { return 'where'; @@ -394,9 +364,6 @@ export class Where extends Stage { } } -/** - * @beta - */ export class FindNearest extends Stage { get _name(): string { return 'find_nearest'; @@ -444,9 +411,6 @@ export class FindNearest extends Stage { } } -/** - * @beta - */ export class Limit extends Stage { get _name(): string { return 'limit'; @@ -476,9 +440,6 @@ export class Limit extends Stage { } } -/** - * @beta - */ export class Offset extends Stage { get _name(): string { return 'offset'; @@ -503,9 +464,6 @@ export class Offset extends Stage { } } -/** - * @beta - */ export class Select extends Stage { get _name(): string { return 'select'; @@ -538,9 +496,6 @@ export class Select extends Stage { } } -/** - * @beta - */ export class Sort extends Stage { get _name(): string { return 'sort'; @@ -571,9 +526,6 @@ export class Sort extends Stage { } } -/** - * @beta - */ export class Sample extends Stage { get _name(): string { return 'sample'; @@ -602,9 +554,6 @@ export class Sample extends Stage { } } -/** - * @beta - */ export class Union extends Stage { get _name(): string { return 'union'; @@ -631,9 +580,6 @@ export class Union extends Stage { } } -/** - * @beta - */ export class Unnest extends Stage { get _name(): string { return 'unnest'; @@ -671,9 +617,6 @@ export class Unnest extends Stage { } } -/** - * @beta - */ export class Replace extends Stage { static readonly MODE = 'full_replace'; @@ -702,9 +645,6 @@ export class Replace extends Stage { } } -/** - * @beta - */ export class RawStage extends Stage { /** * @private diff --git a/packages/firestore/src/lite-api/stage_options.ts b/packages/firestore/src/lite-api/stage_options.ts index ba53580bd1..5f0cbca74d 100644 --- a/packages/firestore/src/lite-api/stage_options.ts +++ b/packages/firestore/src/lite-api/stage_options.ts @@ -1,5 +1,4 @@ /** - * @beta * @license * Copyright 2025 Google LLC * @@ -31,12 +30,10 @@ import { CollectionReference, DocumentReference } from './reference'; import { VectorValue } from './vector_value'; /** - * @beta * Options defining how a Stage is evaluated. */ export interface StageOptions { /** - * @beta * An escape hatch to set options not known at SDK build time. These values * will be passed directly to the Firestore backend and not used by the SDK. * @@ -58,18 +55,15 @@ export interface StageOptions { }; } /** - * @beta * Options defining how a CollectionStage is evaluated. See {@link @firebase/firestore/pipelines#PipelineSource.(collection:1)}. */ export type CollectionStageOptions = StageOptions & { /** - * @beta * Name or reference to the collection that will be used as the Pipeline source. */ collection: string | CollectionReference; /** - * @beta * Specifies the name of an index to be used for a query, overriding the query optimizer's default choice. * This can be useful for performance tuning in specific scenarios where the default index selection * does not yield optimal performance. @@ -80,7 +74,6 @@ export type CollectionStageOptions = StageOptions & { }; /** - * @beta * Defines the configuration options for a CollectionGroupStage within a pipeline. * This type extends {@link @firebase/firestore/pipelines#StageOptions} and provides specific settings for how a collection group * is identified and processed during pipeline execution. @@ -89,13 +82,11 @@ export type CollectionStageOptions = StageOptions & { */ export type CollectionGroupStageOptions = StageOptions & { /** - * @beta * ID of the collection group to use as the Pipeline source. */ collectionId: string; /** - * @beta * Specifies the name of an index to be used for a query, overriding the query optimizer's default choice. * This can be useful for performance tuning in specific scenarios where the default index selection * does not yield optimal performance. @@ -105,17 +96,14 @@ export type CollectionGroupStageOptions = StageOptions & { forceIndex?: string; }; /** - * @beta * Options defining how a DatabaseStage is evaluated. See {@link @firebase/firestore/pipelines#PipelineSource.(database:1)}. */ export type DatabaseStageOptions = StageOptions & {}; /** - * @beta * Options defining how a DocumentsStage is evaluated. See {@link @firebase/firestore/pipelines#PipelineSource.(documents:1)}. */ export type DocumentsStageOptions = StageOptions & { /** - * @beta * An array of paths and DocumentReferences specifying the individual documents that will be the source of this pipeline. * The converters for these DocumentReferences will be ignored and not have an effect on this pipeline. * There must be at least one document specified in the array. @@ -123,80 +111,66 @@ export type DocumentsStageOptions = StageOptions & { docs: Array; }; /** - * @beta * Options defining how an AddFieldsStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(addFields:1)}. */ export type AddFieldsStageOptions = StageOptions & { /** - * @beta * The fields to add to each document, specified as a {@link @firebase/firestore/pipelines#Selectable}. * At least one field is required. */ fields: Selectable[]; }; /** - * @beta * Options defining how a RemoveFieldsStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(removeFields:1)}. */ export type RemoveFieldsStageOptions = StageOptions & { /** - * @beta * The fields to remove from each document. */ fields: Array; }; /** - * @beta * Options defining how a SelectStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(select:1)}. */ export type SelectStageOptions = StageOptions & { /** - * @beta * The fields to include in the output documents, specified as {@link @firebase/firestore/pipelines#Selectable} expression * or as a string value indicating the field name. */ selections: Array; }; /** - * @beta * Options defining how a WhereStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(where:1)}. */ export type WhereStageOptions = StageOptions & { /** - * @beta * The {@link @firebase/firestore/pipelines#BooleanExpression} to apply as a filter for each input document to this stage. */ condition: BooleanExpression; }; /** - * @beta * Options defining how an OffsetStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(offset:1)}. */ export type OffsetStageOptions = StageOptions & { /** - * @beta * The number of documents to skip. */ offset: number; }; /** - * @beta * Options defining how a LimitStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(limit:1)}. */ export type LimitStageOptions = StageOptions & { /** - * @beta * The maximum number of documents to return. */ limit: number; }; /** - * @beta * Options defining how a DistinctStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(distinct:1)}. */ export type DistinctStageOptions = StageOptions & { /** - * @beta * The {@link @firebase/firestore/pipelines#Selectable} expressions or field names to consider when determining * distinct value combinations (groups). */ @@ -204,42 +178,35 @@ export type DistinctStageOptions = StageOptions & { }; /** - * @beta * Options defining how an AggregateStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(aggregate:1)}. */ export type AggregateStageOptions = StageOptions & { /** - * @beta * The {@link @firebase/firestore/pipelines#AliasedAggregate} values specifying aggregate operations to * perform on the input documents. */ accumulators: AliasedAggregate[]; /** - * @beta * The {@link @firebase/firestore/pipelines#Selectable} expressions or field names to consider when determining * distinct value combinations (groups), which will be aggregated over. */ groups?: Array; }; /** - * @beta * Options defining how a FindNearestStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(findNearest:1)}. */ export type FindNearestStageOptions = StageOptions & { /** - * @beta * Specifies the field to be used. This can be a string representing the field path * (e.g., 'fieldName', 'nested.fieldName') or an object of type {@link @firebase/firestore/pipelines#Field} * representing a more complex field expression. */ field: Field | string; /** - * @beta * Specifies the query vector value, to which the vector distance will be computed. */ vectorValue: VectorValue | number[]; /** - * @beta * Specifies the method used to compute the distance between vectors. * * Possible values are: @@ -249,12 +216,10 @@ export type FindNearestStageOptions = StageOptions & { */ distanceMeasure: 'euclidean' | 'cosine' | 'dot_product'; /** - * @beta * The maximum number of documents to return from the FindNearest stage. */ limit?: number; /** - * @beta * If set, specifies the field on the output documents that will contain * the computed vector distance for the document. If not set, the computed * vector distance will not be returned. @@ -262,19 +227,16 @@ export type FindNearestStageOptions = StageOptions & { distanceField?: string; }; /** - * @beta * Options defining how a ReplaceWithStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(replaceWith:1)}. */ export type ReplaceWithStageOptions = StageOptions & { /** - * @beta * The name of a field that contains a map or an {@link @firebase/firestore/pipelines#Expression} that * evaluates to a map. */ map: Expression | string; }; /** - * @beta * Defines the options for evaluating a sample stage within a pipeline. * This type combines common {@link @firebase/firestore/pipelines#StageOptions} with a specific configuration * where only one of the defined sampling methods can be applied. @@ -284,7 +246,6 @@ export type ReplaceWithStageOptions = StageOptions & { export type SampleStageOptions = StageOptions & OneOf<{ /** - * @beta * If set, specifies the sample rate as a percentage of the * input documents. * @@ -292,7 +253,6 @@ export type SampleStageOptions = StageOptions & */ percentage: number; /** - * @beta * If set, specifies the sample rate as a total number of * documents to sample from the input documents. * @@ -301,43 +261,35 @@ export type SampleStageOptions = StageOptions & documents: number; }>; /** - * @beta * Options defining how a UnionStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(union:1)}. */ export type UnionStageOptions = StageOptions & { /** - * @beta * Specifies the other Pipeline to union with. */ other: Pipeline; }; /** - * @beta * Represents the specific options available for configuring an `UnnestStage` within a pipeline. */ export type UnnestStageOptions = StageOptions & { /** - * @beta * A `Selectable` object that defines an array expression to be un-nested * and the alias for the un-nested field. */ selectable: Selectable; /** - * @beta * If set, specifies the field on the output documents that will contain the * offset (starting at zero) that the element is from the original array. */ indexField?: string; }; /** - * @beta - * @beta * Options defining how a SortStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(sort:1)}. */ export type SortStageOptions = StageOptions & { /** - * @beta * Orderings specify how the input documents are sorted. * One or more ordering are required. */ diff --git a/packages/firestore/src/util/types.ts b/packages/firestore/src/util/types.ts index b5dd09fbbc..bbfcf40f01 100644 --- a/packages/firestore/src/util/types.ts +++ b/packages/firestore/src/util/types.ts @@ -75,7 +75,6 @@ export interface DocumentLike { } /** - * @beta * Utility type to create an type that only allows one * property of the Type param T to be set. * From 715c0424d656b1be2d423c31f12e9ffbaeea2dd5 Mon Sep 17 00:00:00 2001 From: Bhav Beri <43399374+bhavberi@users.noreply.github.com> Date: Wed, 1 Apr 2026 23:21:11 +0530 Subject: [PATCH 120/174] patch(auth): Peer dependency conflict with @react-native-async-storage/async-storage v3.x and @firebase/auth (^2.2.0) (#9740) --- .changeset/funky-teeth-pick.md | 6 +++++ docs-devsite/auth.md | 26 +++++++++++++++++-- packages/auth/index.rn.ts | 14 +++++++++- packages/auth/package.json | 2 +- .../persistence/react_native.ts | 21 ++++++++++++++- 5 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 .changeset/funky-teeth-pick.md diff --git a/.changeset/funky-teeth-pick.md b/.changeset/funky-teeth-pick.md new file mode 100644 index 0000000000..89e43a08fd --- /dev/null +++ b/.changeset/funky-teeth-pick.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/auth': minor +--- + +Updated the peer dependency range for @react-native-async-storage/async-storage to support both v2 and v3 diff --git a/docs-devsite/auth.md b/docs-devsite/auth.md index 97c1205227..0325212915 100644 --- a/docs-devsite/auth.md +++ b/docs-devsite/auth.md @@ -20,7 +20,7 @@ Firebase Authentication | [getAuth(app)](./auth.md#getauth_cf608e1) | Returns the Auth instance associated with the provided [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface). If no instance exists, initializes an Auth instance with platform-specific default dependencies. | | [initializeAuth(app, deps)](./auth.md#initializeauth_ca77c9b) | Initializes an [Auth](./auth.auth.md#auth_interface) instance with fine-grained control over [Dependencies](./auth.dependencies.md#dependencies_interface). | | function(storage, ...) | -| [getReactNativePersistence(storage)](./auth.md#getreactnativepersistence_bab4ada) | Returns a persistence object that wraps AsyncStorage imported from react-native or @react-native-community/async-storage, and can be used in the persistence dependency field in [initializeAuth()](./auth.md#initializeauth_ca77c9b). | +| [getReactNativePersistence(storage)](./auth.md#getreactnativepersistence_bab4ada) | Returns a persistence object that wraps AsyncStorage imported from react-native or @react-native-async-storage/async-storage, and can be used in the persistence dependency field in [initializeAuth()](./auth.md#initializeauth_ca77c9b). | | function(auth, ...) | | [applyActionCode(auth, oobCode)](./auth.md#applyactioncode_d2ae15a) | Applies a verification code sent to the user by email or other out-of-band mechanism. | | [beforeAuthStateChanged(auth, callback, onAbort)](./auth.md#beforeauthstatechanged_22f2ab6) | Adds a blocking callback that runs before an auth state change sets a new user. | @@ -232,7 +232,7 @@ export declare function initializeAuth(app: FirebaseApp, deps?: Dependencies): A ### getReactNativePersistence(storage) {:#getreactnativepersistence_bab4ada} -Returns a persistence object that wraps `AsyncStorage` imported from `react-native` or `@react-native-community/async-storage`, and can be used in the persistence dependency field in [initializeAuth()](./auth.md#initializeauth_ca77c9b). +Returns a persistence object that wraps `AsyncStorage` imported from `react-native` or `@react-native-async-storage/async-storage`, and can be used in the persistence dependency field in [initializeAuth()](./auth.md#initializeauth_ca77c9b). Signature: @@ -250,6 +250,28 @@ export declare function getReactNativePersistence(storage: ReactNativeAsyncStora [Persistence](./auth.persistence.md#persistence_interface) +### Example + + +```javascript +import { initializeAuth, getReactNativePersistence } from 'firebase/auth'; + +// For @react-native-async-storage/async-storage v3: +import { createAsyncStorage } from '@react-native-async-storage/async-storage'; +const appStorage = createAsyncStorage('app'); +const persistence = getReactNativePersistence(appStorage); + +// For @react-native-async-storage/async-storage v2: +// import ReactNativeAsyncStorage from '@react-native-async-storage/async-storage'; +// const persistence = getReactNativePersistence(ReactNativeAsyncStorage); + +// Then, initialize auth: +const auth = initializeAuth(app, { + persistence +}); + +``` + ## function(auth, ...) ### applyActionCode(auth, oobCode) {:#applyactioncode_d2ae15a} diff --git a/packages/auth/index.rn.ts b/packages/auth/index.rn.ts index ecf04d8ac2..9f6e5938c3 100644 --- a/packages/auth/index.rn.ts +++ b/packages/auth/index.rn.ts @@ -62,9 +62,21 @@ persist between sessions. In order to persist auth state, install the package initializeAuth: import { initializeAuth, getReactNativePersistence } from 'firebase/auth'; + +// For @react-native-async-storage/async-storage v3: +import { createAsyncStorage } from '@react-native-async-storage/async-storage'; +const appStorage = createAsyncStorage("app"); +const persistence = getReactNativePersistence(appStorage); + +/* +// For @react-native-async-storage/async-storage v2: import ReactNativeAsyncStorage from '@react-native-async-storage/async-storage'; +const persistence = getReactNativePersistence(ReactNativeAsyncStorage); +*/ + +// Then, initialize auth: const auth = initializeAuth(app, { - persistence: getReactNativePersistence(ReactNativeAsyncStorage) + persistence }); `; diff --git a/packages/auth/package.json b/packages/auth/package.json index 3af41f4100..60b0e5fa7b 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -116,7 +116,7 @@ }, "peerDependencies": { "@firebase/app": "0.x", - "@react-native-async-storage/async-storage": "^2.2.0" + "@react-native-async-storage/async-storage": "^2.2.0 || ^3.0.0" }, "peerDependenciesMeta": { "@react-native-async-storage/async-storage": { diff --git a/packages/auth/src/platform_react_native/persistence/react_native.ts b/packages/auth/src/platform_react_native/persistence/react_native.ts index 31ce3f70d2..121c330ff1 100644 --- a/packages/auth/src/platform_react_native/persistence/react_native.ts +++ b/packages/auth/src/platform_react_native/persistence/react_native.ts @@ -27,9 +27,28 @@ import { /** * Returns a persistence object that wraps `AsyncStorage` imported from - * `react-native` or `@react-native-community/async-storage`, and can + * `react-native` or `@react-native-async-storage/async-storage`, and can * be used in the persistence dependency field in {@link initializeAuth}. * + * @example + * ```javascript + * import { initializeAuth, getReactNativePersistence } from 'firebase/auth'; + * + * // For @react-native-async-storage/async-storage v3: + * import { createAsyncStorage } from '@react-native-async-storage/async-storage'; + * const appStorage = createAsyncStorage('app'); + * const persistence = getReactNativePersistence(appStorage); + * + * // For @react-native-async-storage/async-storage v2: + * // import ReactNativeAsyncStorage from '@react-native-async-storage/async-storage'; + * // const persistence = getReactNativePersistence(ReactNativeAsyncStorage); + * + * // Then, initialize auth: + * const auth = initializeAuth(app, { + * persistence + * }); + * ``` + * * @public */ export function getReactNativePersistence( From 620c8cae4e80cc183eba0a6f00fb47ae462e1305 Mon Sep 17 00:00:00 2001 From: macastelaz <34776182+macastelaz@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:49:58 -0500 Subject: [PATCH 121/174] Re-enable coverage reporting for firebase-js-sdk (#9761) --- .github/workflows/test-all.yml | 62 ++++++++++- config/webpack.test.js | 26 +++++ package.json | 1 + yarn.lock | 182 ++++++++++++++++++++++++++++++++- 4 files changed, 267 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 02c3ab0326..4a7d81f685 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -14,7 +14,14 @@ name: Test All Packages -on: pull_request +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read env: # make chromedriver detect installed Chrome version and download the corresponding driver @@ -73,6 +80,7 @@ jobs: - name: install Chrome stable run: | npx @puppeteer/browsers install chrome@stable + - uses: actions/checkout@v4 - name: Download build archive uses: actions/download-artifact@v4 with: @@ -98,11 +106,27 @@ jobs: FIREBASE_TOKEN: ${{ secrets.FIREBASE_CLI_TOKEN }} - name: Generate coverage file run: yarn ci:coverage + - name: Merge and fix coverage files for test-the-rest + run: | + # Clear out any existing master file just in case + > ./lcov-all.info + + # Find all LCOV files across all packages + find ./packages -type f -name "lcov.info" | while read lcov_file; do + # lcov_file looks like: ./packages/analytics/coverage/lcov.info + # Extract the package name (the 3rd part of the path split by '/') + PKG_NAME=$(echo "$lcov_file" | cut -d'/' -f3) + + # Fix the path for this specific package and append it to the master file + sed "s|SF:src/|SF:packages/$PKG_NAME/src/|g" "$lcov_file" >> ./lcov-all.info + done - name: Run coverage uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} path-to-lcov: ./lcov-all.info + flag-name: test-the-rest-coverage + parallel: true continue-on-error: true test-auth: @@ -120,6 +144,7 @@ jobs: echo "::warning ::${CHROME_VERSION_MISMATCH_MESSAGE}" echo "::warning ::Previously validated version: ${CHROME_VALIDATED_VERSION} vs. Installed version: $chromeVersionString" fi + - uses: actions/checkout@v4 - name: Download build archive uses: actions/download-artifact@v4 with: @@ -144,11 +169,20 @@ jobs: FIREBASE_TOKEN: ${{ secrets.FIREBASE_CLI_TOKEN }} - name: Generate coverage file run: yarn ci:coverage + - name: Merge and fix coverage files for test-auth + run: | + # 1. Smash all Node and Browser coverage files into one giant file + find ./packages/auth/coverage -type f -name "lcov.info" -exec cat {} + > ./lcov-all-auth.info + + # 2. Fix standard Node paths + sed -i 's|SF:src/|SF:packages/auth/src/|g' ./lcov-all-auth.info - name: Run coverage uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ./lcov-all.info + path-to-lcov: ./lcov-all-auth.info + flag-name: test-auth-coverage + parallel: true continue-on-error: true test-firestore: @@ -160,6 +194,7 @@ jobs: - name: install Chrome stable run: | npx @puppeteer/browsers install chrome@stable + - uses: actions/checkout@v4 - name: Download build archive uses: actions/download-artifact@v4 with: @@ -184,11 +219,20 @@ jobs: EXPERIMENTAL_MODE: true - name: Generate coverage file run: yarn ci:coverage + - name: Merge and fix coverage files for test-firestore + run: | + # 1. Smash all Node and Browser coverage files into one giant file + find ./packages/firestore/coverage -type f -name "lcov.info" -exec cat {} + > ./lcov-all-firestore.info + + # 2. Fix standard Node paths + sed -i 's|SF:src/|SF:packages/firestore/src/|g' ./lcov-all-firestore.info - name: Run coverage uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ./lcov-all.info + path-to-lcov: ./lcov-all-firestore.info + flag-name: test-firestore-coverage + parallel: true continue-on-error: true test-firestore-integration: strategy: @@ -203,6 +247,7 @@ jobs: - name: install Chrome stable run: | npx @puppeteer/browsers install chrome@stable + - uses: actions/checkout@v4 - name: Download build archive uses: actions/download-artifact@v4 with: @@ -221,3 +266,14 @@ jobs: working-directory: integration/firestore env: FIREBASE_TOKEN: ${{ secrets.FIREBASE_CLI_TOKEN }} + + coveralls-finish: + name: Finalize Coveralls + needs: [test-the-rest-coverage, test-auth-coverage, test-firestore-coverage] + runs-on: ubuntu-latest + steps: + - name: Coveralls Finished + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + parallel-finished: true \ No newline at end of file diff --git a/config/webpack.test.js b/config/webpack.test.js index cc73931377..211880007d 100644 --- a/config/webpack.test.js +++ b/config/webpack.test.js @@ -112,3 +112,29 @@ module.exports = { }) ] }; + +// If we are in a CI environment or a developer has explicity asked for coverage (e.g. +// "COVERAGE=true yarn test:browser:unit"), add the babel-loader to instrument the code with +// istanbul +if ( + (process.env.CI && process.env.CI !== 'false') || + process.env.COVERAGE === 'true' +) { + module.exports.module.rules.push({ + test: /\.tsx?$/, + // 'post' ensures this runs AFTER ts-loader converts TS to ES2020 JS + enforce: 'post', + use: { + loader: 'babel-loader', + options: { + plugins: ['istanbul'] // Uses babel-plugin-istanbul to add coverage counters + } + }, + include: path.resolve(__dirname, '../packages'), + exclude: [ + /node_modules/, + /\.test\.tsx?$/, // Don't instrument the tests themselves + /test\// + ] + }); +} diff --git a/package.json b/package.json index 9d79c73560..958a90ff59 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,7 @@ "api-documenter-me": "0.1.1", "api-extractor-me": "0.1.2", "babel-loader": "8.4.1", + "babel-plugin-istanbul": "7.0.1", "chai": "4.5.0", "chai-as-promised": "7.1.2", "chalk": "4.1.2", diff --git a/yarn.lock b/yarn.lock index b990c9a35e..09f5a4389e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29,6 +29,15 @@ js-tokens "^4.0.0" picocolors "^1.0.0" +"@babel/code-frame@^7.28.6", "@babel/code-frame@^7.29.0": + version "7.29.0" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz#7cd7a59f15b3cc0dcd803038f7792712a7d0b15c" + integrity sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw== + dependencies: + "@babel/helper-validator-identifier" "^7.28.5" + js-tokens "^4.0.0" + picocolors "^1.1.1" + "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.5": version "7.26.5" resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz#df93ac37f4417854130e21d72c66ff3d4b897fc7" @@ -39,6 +48,11 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== +"@babel/compat-data@^7.28.6": + version "7.29.0" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz#00d03e8c0ac24dd9be942c5370990cbe1f17d88d" + integrity sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg== + "@babel/core@7.26.8": version "7.26.8" resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.8.tgz#7742f11c75acea6b08a8e24c5c0c8c89e89bf53e" @@ -82,6 +96,27 @@ json5 "^2.2.3" semver "^6.3.1" +"@babel/core@^7.23.9": + version "7.29.0" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz#5286ad785df7f79d656e88ce86e650d16ca5f322" + integrity sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA== + dependencies: + "@babel/code-frame" "^7.29.0" + "@babel/generator" "^7.29.0" + "@babel/helper-compilation-targets" "^7.28.6" + "@babel/helper-module-transforms" "^7.28.6" + "@babel/helpers" "^7.28.6" + "@babel/parser" "^7.29.0" + "@babel/template" "^7.28.6" + "@babel/traverse" "^7.29.0" + "@babel/types" "^7.29.0" + "@jridgewell/remapping" "^2.3.5" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/generator@^7.26.5", "@babel/generator@^7.7.2": version "7.26.5" resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz#e44d4ab3176bbcaf78a5725da5f1dc28802a9458" @@ -104,6 +139,17 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" +"@babel/generator@^7.29.0": + version "7.29.1" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz#d09876290111abbb00ef962a7b83a5307fba0d50" + integrity sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw== + dependencies: + "@babel/parser" "^7.29.0" + "@babel/types" "^7.29.0" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + "@babel/helper-annotate-as-pure@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" @@ -122,6 +168,17 @@ lru-cache "^5.1.1" semver "^6.3.1" +"@babel/helper-compilation-targets@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz#32c4a3f41f12ed1532179b108a4d746e105c2b25" + integrity sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA== + dependencies: + "@babel/compat-data" "^7.28.6" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + "@babel/helper-create-class-features-plugin@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz#7644147706bb90ff613297d49ed5266bde729f83" @@ -155,6 +212,11 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + "@babel/helper-member-expression-to-functions@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3" @@ -171,6 +233,14 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" +"@babel/helper-module-imports@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz#60632cbd6ffb70b22823187201116762a03e2d5c" + integrity sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw== + dependencies: + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" + "@babel/helper-module-transforms@^7.25.9", "@babel/helper-module-transforms@^7.26.0": version "7.26.0" resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" @@ -180,6 +250,15 @@ "@babel/helper-validator-identifier" "^7.25.9" "@babel/traverse" "^7.25.9" +"@babel/helper-module-transforms@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz#9312d9d9e56edc35aeb6e95c25d4106b50b9eb1e" + integrity sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA== + dependencies: + "@babel/helper-module-imports" "^7.28.6" + "@babel/helper-validator-identifier" "^7.28.5" + "@babel/traverse" "^7.28.6" + "@babel/helper-optimise-call-expression@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e" @@ -238,11 +317,21 @@ resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== +"@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + "@babel/helper-validator-option@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + "@babel/helper-wrap-function@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz#d99dfd595312e6c894bd7d237470025c85eea9d0" @@ -260,6 +349,14 @@ "@babel/template" "^7.25.9" "@babel/types" "^7.26.7" +"@babel/helpers@^7.28.6": + version "7.29.2" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz#9cfbccb02b8e229892c0b07038052cc1a8709c49" + integrity sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw== + dependencies: + "@babel/template" "^7.28.6" + "@babel/types" "^7.29.0" + "@babel/parser@^7.14.7", "@babel/parser@^7.25.9", "@babel/parser@^7.26.5", "@babel/parser@^7.26.7": version "7.26.7" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz#e114cd099e5f7d17b05368678da0fb9f69b3385c" @@ -274,6 +371,13 @@ dependencies: "@babel/types" "^7.28.4" +"@babel/parser@^7.23.9", "@babel/parser@^7.28.6", "@babel/parser@^7.29.0": + version "7.29.2" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz#58bd50b9a7951d134988a1ae177a35ef9a703ba1" + integrity sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA== + dependencies: + "@babel/types" "^7.29.0" + "@babel/parser@^7.26.8": version "7.26.8" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.26.8.tgz#deca2b4d99e5e1b1553843b99823f118da6107c2" @@ -988,6 +1092,15 @@ "@babel/parser" "^7.26.8" "@babel/types" "^7.26.8" +"@babel/template@^7.28.6": + version "7.28.6" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57" + integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.7": version "7.26.7" resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz#99a0a136f6a75e7fb8b0a1ace421e0b25994b8bb" @@ -1014,6 +1127,19 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.28.6", "@babel/traverse@^7.29.0": + version "7.29.0" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz#f323d05001440253eead3c9c858adbe00b90310a" + integrity sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA== + dependencies: + "@babel/code-frame" "^7.29.0" + "@babel/generator" "^7.29.0" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.29.0" + "@babel/template" "^7.28.6" + "@babel/types" "^7.29.0" + debug "^4.3.1" + "@babel/types@^7.25.9", "@babel/types@^7.26.5", "@babel/types@^7.26.7", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.26.7" resolved "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz#5e2b89c0768e874d4d061961f3a5a153d71dc17a" @@ -1038,6 +1164,14 @@ "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.27.1" +"@babel/types@^7.28.6", "@babel/types@^7.29.0": + version "7.29.0" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz#9f5b1e838c446e72cf3cd4b918152b8c605e37c7" + integrity sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" + "@bazel/runfiles@^6.3.1": version "6.3.1" resolved "https://registry.npmjs.org/@bazel/runfiles/-/runfiles-6.3.1.tgz#3f8824b2d82853377799d42354b4df78ab0ace0b" @@ -1481,7 +1615,7 @@ js-yaml "^3.13.1" resolve-from "^5.0.0" -"@istanbuljs/schema@^0.1.2": +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": version "0.1.3" resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== @@ -1555,6 +1689,14 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" +"@jridgewell/gen-mapping@^0.3.12": + version "0.3.13" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/gen-mapping@^0.3.5": version "0.3.8" resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" @@ -1564,6 +1706,14 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.24" +"@jridgewell/remapping@^2.3.5": + version "2.3.5" + resolved "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" @@ -1603,6 +1753,14 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@js-sdsl/ordered-map@^4.4.2": version "4.4.2" resolved "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz#9299f82874bab9e4c7f9c48d865becbfe8d6907c" @@ -4466,6 +4624,17 @@ babel-loader@8.4.1: make-dir "^3.1.0" schema-utils "^2.6.5" +babel-plugin-istanbul@7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz#d8b518c8ea199364cf84ccc82de89740236daf92" + integrity sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-instrument "^6.0.2" + test-exclude "^6.0.0" + babel-plugin-istanbul@^6.1.1: version "6.1.1" resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" @@ -9882,6 +10051,17 @@ istanbul-lib-instrument@^5.0.4: istanbul-lib-coverage "^3.2.0" semver "^6.3.0" +istanbul-lib-instrument@^6.0.2: + version "6.0.3" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + istanbul-lib-processinfo@^2.0.2: version "2.0.3" resolved "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz#366d454cd0dcb7eb6e0e419378e60072c8626169" From 31bddcdd6200642f836c1eca7c9068470ca840bd Mon Sep 17 00:00:00 2001 From: Mark Duckworth <1124037+MarkDuckworth@users.noreply.github.com> Date: Thu, 2 Apr 2026 08:42:13 -0600 Subject: [PATCH 122/174] feat(firestore): add public preview support for full-text search and geo search (#9734) --------- Co-authored-by: Daniel La Rocque --- .changeset/happy-bugs-attack.md | 6 + .../firestore-lite-pipelines.api.md | 25 +- common/api-review/firestore-pipelines.api.md | 27 +- docs-devsite/_toc.yaml | 4 - .../firestore_lite_pipelines.field.md | 31 + ...store_lite_pipelines.functionexpression.md | 19 - docs-devsite/firestore_lite_pipelines.md | 149 ++- .../firestore_lite_pipelines.pipeline.md | 59 ++ .../firestore_lite_pipelines.stageoptions.md | 45 - docs-devsite/firestore_pipelines.field.md | 31 + .../firestore_pipelines.functionexpression.md | 19 - docs-devsite/firestore_pipelines.md | 149 ++- docs-devsite/firestore_pipelines.pipeline.md | 19 + .../firestore_pipelines.stageoptions.md | 45 - .../firestore/lite/pipelines/pipelines.ts | 11 +- packages/firestore/src/api_pipelines.ts | 12 +- .../firestore/src/lite-api/expressions.ts | 487 ++++++++- packages/firestore/src/lite-api/pipeline.ts | 82 +- packages/firestore/src/lite-api/stage.ts | 108 +- .../firestore/src/lite-api/stage_options.ts | 116 ++- packages/firestore/src/util/pipeline_util.ts | 16 +- .../test/integration/api/pipeline.test.ts | 981 +++++++++++++++--- .../test/integration/util/settings.ts | 8 +- packages/firestore/test/lite/pipeline.test.ts | 760 +++++++++++++- .../test/unit/api/expressions.test.ts | 114 ++ .../test/unit/api/pipeline_impl.test.ts | 108 ++ .../firestore/test/util/mocha_extensions.ts | 10 +- 27 files changed, 3064 insertions(+), 377 deletions(-) create mode 100644 .changeset/happy-bugs-attack.md delete mode 100644 docs-devsite/firestore_lite_pipelines.stageoptions.md delete mode 100644 docs-devsite/firestore_pipelines.stageoptions.md create mode 100644 packages/firestore/test/unit/api/expressions.test.ts diff --git a/.changeset/happy-bugs-attack.md b/.changeset/happy-bugs-attack.md new file mode 100644 index 0000000000..82e6d18ae5 --- /dev/null +++ b/.changeset/happy-bugs-attack.md @@ -0,0 +1,6 @@ +--- +"firebase": minor +"@firebase/firestore": minor +--- + +Added public preview support for full-text and geo search in Pipelines. diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index c69b50d3d3..01645cf52b 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -399,6 +399,9 @@ export function documentId(documentPath: string | DocumentReference): FunctionEx // @public export function documentId(documentPathExpr: Expression): FunctionExpression; +// @beta +export function documentMatches(rquery: string | Expression): BooleanExpression; + // @public export type DocumentsStageOptions = StageOptions & { docs: Array; @@ -834,6 +837,8 @@ export class Field extends Expression implements Selectable { readonly expressionType: ExpressionType; // (undocumented) get fieldName(): string; + // @beta + geoDistance(location: GeoPoint | Expression): Expression; // (undocumented) selectable: true; } @@ -868,11 +873,13 @@ export function floor(fieldName: string): FunctionExpression; // @public export class FunctionExpression extends Expression { constructor(name: string, params: Expression[]); - constructor(name: string, params: Expression[], _methodName: string | undefined); // (undocumented) readonly expressionType: ExpressionType; } +// @beta +export function geoDistance(fieldName: string | Field, location: GeoPoint | Expression): Expression; + // @public export function greaterThan(left: Expression, right: Expression): BooleanExpression; @@ -1212,6 +1219,8 @@ export class Pipeline { replaceWith(options: ReplaceWithStageOptions): Pipeline; sample(documents: number): Pipeline; sample(options: SampleStageOptions): Pipeline; + // @beta + search(options: SearchStageOptions): Pipeline; select(selection: Selectable | string, ...additionalSelections: Array): Pipeline; select(options: SelectStageOptions): Pipeline; sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; @@ -1376,6 +1385,16 @@ export type SampleStageOptions = StageOptions & OneOf<{ documents: number; }>; +// @beta +export function score(): Expression; + +// @beta +export type SearchStageOptions = StageOptions & { + query: BooleanExpression | string; + sort?: Ordering | Ordering[]; + addFields?: Selectable[]; +}; + // @public export interface Selectable { // (undocumented) @@ -1411,11 +1430,11 @@ export function sqrt(expression: Expression): FunctionExpression; export function sqrt(fieldName: string): FunctionExpression; // @public -export interface StageOptions { +export type StageOptions = { rawOptions?: { [name: string]: unknown; }; -} +}; // @public export function startsWith(fieldName: string, prefix: string): BooleanExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 7b9cf6a147..f8d539540b 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -399,6 +399,9 @@ export function documentId(documentPath: string | DocumentReference): FunctionEx // @public export function documentId(documentPathExpr: Expression): FunctionExpression; +// @beta +export function documentMatches(rquery: string | Expression): BooleanExpression; + // @public export type DocumentsStageOptions = StageOptions & { docs: Array; @@ -837,6 +840,8 @@ export class Field extends Expression implements Selectable { readonly expressionType: ExpressionType; // (undocumented) get fieldName(): string; + // @beta + geoDistance(location: GeoPoint | Expression): Expression; // (undocumented) selectable: true; } @@ -871,11 +876,13 @@ export function floor(fieldName: string): FunctionExpression; // @public export class FunctionExpression extends Expression { constructor(name: string, params: Expression[]); - constructor(name: string, params: Expression[], _methodName: string | undefined); // (undocumented) readonly expressionType: ExpressionType; } +// @beta +export function geoDistance(fieldName: string | Field, location: GeoPoint | Expression): Expression; + // @public export function greaterThan(left: Expression, right: Expression): BooleanExpression; @@ -1219,6 +1226,10 @@ export class Pipeline { replaceWith(options: ReplaceWithStageOptions): Pipeline; sample(documents: number): Pipeline; sample(options: SampleStageOptions): Pipeline; + // Warning: (ae-incompatible-release-tags) The symbol "search" is marked as @public, but its signature references "SearchStageOptions" which is marked as @beta + // + // (undocumented) + search(options: SearchStageOptions): Pipeline; select(selection: Selectable | string, ...additionalSelections: Array): Pipeline; select(options: SelectStageOptions): Pipeline; sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; @@ -1398,6 +1409,16 @@ export type SampleStageOptions = StageOptions & OneOf<{ documents: number; }>; +// @beta +export function score(): Expression; + +// @beta +export type SearchStageOptions = StageOptions & { + query: BooleanExpression | string; + sort?: Ordering | Ordering[]; + addFields?: Selectable[]; +}; + // @public export interface Selectable { // (undocumented) @@ -1433,11 +1454,11 @@ export function sqrt(expression: Expression): FunctionExpression; export function sqrt(fieldName: string): FunctionExpression; // @public -export interface StageOptions { +export type StageOptions = { rawOptions?: { [name: string]: unknown; }; -} +}; // @public export function startsWith(fieldName: string, prefix: string): BooleanExpression; diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index 3523913cb9..cdad1d79cb 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -654,8 +654,6 @@ toc: path: /docs/reference/js/firestore_lite_pipelines.querydocumentsnapshot.md - title: Selectable path: /docs/reference/js/firestore_lite_pipelines.selectable.md - - title: StageOptions - path: /docs/reference/js/firestore_lite_pipelines.stageoptions.md - title: Timestamp path: /docs/reference/js/firestore_lite_pipelines.timestamp.md - title: VectorValue @@ -719,8 +717,6 @@ toc: path: /docs/reference/js/firestore_pipelines.snapshotmetadata.md - title: SnapshotOptions path: /docs/reference/js/firestore_pipelines.snapshotoptions.md - - title: StageOptions - path: /docs/reference/js/firestore_pipelines.stageoptions.md - title: Timestamp path: /docs/reference/js/firestore_pipelines.timestamp.md - title: VectorValue diff --git a/docs-devsite/firestore_lite_pipelines.field.md b/docs-devsite/firestore_lite_pipelines.field.md index 22e83878f1..614459d8a4 100644 --- a/docs-devsite/firestore_lite_pipelines.field.md +++ b/docs-devsite/firestore_lite_pipelines.field.md @@ -35,6 +35,12 @@ export declare class Field extends Expression implements Selectable | [fieldName](./firestore_lite_pipelines.field.md#fieldfieldname) | | string | | | [selectable](./firestore_lite_pipelines.field.md#fieldselectable) | | true | | +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [geoDistance(location)](./firestore_lite_pipelines.field.md#fieldgeodistance) | | (Public Preview) Evaluates to the distance in meters between the location specified by this field and the query location. | + ## Field.alias Signature: @@ -75,6 +81,31 @@ get fieldName(): string; selectable: true; ``` +## Field.geoDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Evaluates to the distance in meters between the location specified by this field and the query location. + +This Expression can only be used within a `Search` stage. + +Signature: + +```typescript +geoDistance(location: GeoPoint | Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| location | [GeoPoint](./firestore_lite.geopoint.md#geopoint_class) \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Compute distance to this GeoPoint. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + ### Example diff --git a/docs-devsite/firestore_lite_pipelines.functionexpression.md b/docs-devsite/firestore_lite_pipelines.functionexpression.md index a7897b6d4e..775088feec 100644 --- a/docs-devsite/firestore_lite_pipelines.functionexpression.md +++ b/docs-devsite/firestore_lite_pipelines.functionexpression.md @@ -26,7 +26,6 @@ export declare class FunctionExpression extends Expression | Constructor | Modifiers | Description | | --- | --- | --- | | [(constructor)(name, params)](./firestore_lite_pipelines.functionexpression.md#functionexpressionconstructor) | | Constructs a new instance of the FunctionExpression class | -| [(constructor)(name, params, \_methodName)](./firestore_lite_pipelines.functionexpression.md#functionexpressionconstructor) | | Constructs a new instance of the FunctionExpression class | ## Properties @@ -51,24 +50,6 @@ constructor(name: string, params: Expression[]); | name | string | | | params | [Expression](./firestore_lite_pipelines.expression.md#expression_class)\[\] | | -## FunctionExpression.(constructor) - -Constructs a new instance of the `FunctionExpression` class - -Signature: - -```typescript -constructor(name: string, params: Expression[], _methodName: string | undefined); -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| name | string | | -| params | [Expression](./firestore_lite_pipelines.expression.md#expression_class)\[\] | | -| \_methodName | string \| undefined | | - ## FunctionExpression.expressionType Signature: diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 2df2241972..9c5f7b5444 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -19,6 +19,7 @@ https://github.com/firebase/firebase-js-sdk | [countAll()](./firestore_lite_pipelines.md#countall) | Creates an aggregation that counts the total number of stage inputs. | | [currentTimestamp()](./firestore_lite_pipelines.md#currenttimestamp) | Creates an expression that evaluates to the current server timestamp. | | [rand()](./firestore_lite_pipelines.md#rand) | Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. | +| [score()](./firestore_lite_pipelines.md#score) | (Public Preview) Evaluates to the search score that reflects the topicality of the document to all of the text predicates (for example: documentMatches) in the search query. If SearchOptions.query is not set or does not contain any text predicates, then this topicality score will always be 0. | | function(array, ...) | | [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_a00ea48) | Creates an expression that checks if an array expression contains a specific element. | | [arrayContains(array, element)](./firestore_lite_pipelines.md#arraycontains_7328608) | Creates an expression that checks if an array expression contains a specific element. | @@ -201,6 +202,7 @@ https://github.com/firebase/firebase-js-sdk | [exp(fieldName)](./firestore_lite_pipelines.md#exp_e5b0480) | Creates an expression that computes e to the power of the expression's result. | | [first(fieldName)](./firestore_lite_pipelines.md#first_e5b0480) | Creates an aggregation that finds the first value of a field across multiple stage inputs. | | [floor(fieldName)](./firestore_lite_pipelines.md#floor_e5b0480) | Creates an expression that computes the floor of a numeric value. | +| [geoDistance(fieldName, location)](./firestore_lite_pipelines.md#geodistance_ea237a8) | (Public Preview) Evaluates to the distance in meters between the location in the specified field and the query location. | | [greaterThan(fieldName, expression)](./firestore_lite_pipelines.md#greaterthan_1e91657) | Creates an expression that checks if a field's value is greater than an expression. | | [greaterThan(fieldName, value)](./firestore_lite_pipelines.md#greaterthan_65e2f32) | Creates an expression that checks if a field's value is greater than a constant value. | | [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_2e16acb) | Creates an expression that checks if a field's value is greater than or equal to an expression. | @@ -340,6 +342,8 @@ https://github.com/firebase/firebase-js-sdk | [field(path)](./firestore_lite_pipelines.md#field_34ee07d) | Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. | | function(pipeline, ...) | | [execute(pipeline)](./firestore_lite_pipelines.md#execute_01df620) | Executes this pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:

    • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
    • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
    • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
    | +| function(rquery, ...) | +| [documentMatches(rquery)](./firestore_lite_pipelines.md#documentmatches_d7a12c2) | (Public Preview) Perform a full-text search on all indexed search fields in the document. | | function(stringExpression, ...) | | [charLength(stringExpression)](./firestore_lite_pipelines.md#charlength_c25a54a) | Creates an expression that calculates the character length of a string expression in UTF-8. | | [endsWith(stringExpression, suffix)](./firestore_lite_pipelines.md#endswith_0a0b889) | Creates an expression that checks if a string expression ends with a given postfix. | @@ -436,7 +440,6 @@ https://github.com/firebase/firebase-js-sdk | [DocumentData](./firestore_lite_pipelines.documentdata.md#documentdata_interface) | Document data (for use with [setDoc()](./firestore_lite.md#setdoc_ee215ad)) consists of fields mapped to values. | | [FirestoreDataConverter](./firestore_lite_pipelines.firestoredataconverter.md#firestoredataconverter_interface) | Converter used by withConverter() to transform user objects of type AppModelType into Firestore data of type DbModelType.Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore.In this context, an "AppModel" is a class that is used in an application to package together related information and functionality. Such a class could, for example, have properties with complex, nested data types, properties used for memoization, properties of types not supported by Firestore (such as symbol and bigint), and helper functions that perform compound operations. Such classes are not suitable and/or possible to store into a Firestore database. Instead, instances of such classes need to be converted to "plain old JavaScript objects" (POJOs) with exclusively primitive properties, potentially nested inside other POJOs or arrays of POJOs. In this context, this type is referred to as the "DbModel" and would be an object suitable for persisting into Firestore. For convenience, applications can implement FirestoreDataConverter and register the converter with Firestore objects, such as DocumentReference or Query, to automatically convert AppModel to DbModel when storing into Firestore, and convert DbModel to AppModel when retrieving from Firestore. | | [Selectable](./firestore_lite_pipelines.selectable.md#selectable_interface) | An interface that represents a selectable expression. | -| [StageOptions](./firestore_lite_pipelines.stageoptions.md#stageoptions_interface) | Options defining how a Stage is evaluated. | ## Type Aliases @@ -444,7 +447,7 @@ https://github.com/firebase/firebase-js-sdk | --- | --- | | [AddFieldsStageOptions](./firestore_lite_pipelines.md#addfieldsstageoptions) | Options defining how an AddFieldsStage is evaluated. See [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields). | | [AggregateStageOptions](./firestore_lite_pipelines.md#aggregatestageoptions) | Options defining how an AggregateStage is evaluated. See [Pipeline.aggregate()](./firestore_pipelines.pipeline.md#pipelineaggregate). | -| [CollectionGroupStageOptions](./firestore_lite_pipelines.md#collectiongroupstageoptions) | Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution.See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. | +| [CollectionGroupStageOptions](./firestore_lite_pipelines.md#collectiongroupstageoptions) | Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.md#stageoptions) and provides specific settings for how a collection group is identified and processed during pipeline execution.See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. | | [CollectionStageOptions](./firestore_lite_pipelines.md#collectionstageoptions) | Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). | | [DatabaseStageOptions](./firestore_lite_pipelines.md#databasestageoptions) | Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). | | [DistinctStageOptions](./firestore_lite_pipelines.md#distinctstageoptions) | Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). | @@ -458,10 +461,12 @@ https://github.com/firebase/firebase-js-sdk | [Primitive](./firestore_lite_pipelines.md#primitive) | Primitive types. | | [RemoveFieldsStageOptions](./firestore_lite_pipelines.md#removefieldsstageoptions) | Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). | | [ReplaceWithStageOptions](./firestore_lite_pipelines.md#replacewithstageoptions) | Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). | -| [SampleStageOptions](./firestore_lite_pipelines.md#samplestageoptions) | Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied.See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. | +| [SampleStageOptions](./firestore_lite_pipelines.md#samplestageoptions) | Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.md#stageoptions) with a specific configuration where only one of the defined sampling methods can be applied.See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. | +| [SearchStageOptions](./firestore_lite_pipelines.md#searchstageoptions) | (Public Preview) Options defining how a SearchStage is evaluated. See . | | [SelectStageOptions](./firestore_lite_pipelines.md#selectstageoptions) | Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). | | [SetOptions](./firestore_lite_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | | [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | +| [StageOptions](./firestore_lite_pipelines.md#stageoptions) | Options defining how a Stage is evaluated. | | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | Specify time granularity for expressions. | | [TimePart](./firestore_lite_pipelines.md#timepart) | Specify time parts for timestampExtract expressions. | | [TimeUnit](./firestore_lite_pipelines.md#timeunit) | Specify time units for expressions. | @@ -545,6 +550,35 @@ rand(); ``` +### score() {:#score} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Evaluates to the search score that reflects the topicality of the document to all of the text predicates (for example: `documentMatches`) in the search query. If `SearchOptions.query` is not set or does not contain any text predicates, then this topicality score will always be `0`. + +This Expression can only be used within a `Search` stage. + +Signature: + +```typescript +export declare function score(): Expression; +``` +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### Example + + +```typescript +db.pipeline().collection('restaurants').search({ + query: 'waffles', + sort: score().descending() +}) + +``` + ## function(array, ...) ### arrayContains(array, element) {:#arraycontains_a00ea48} @@ -5791,6 +5825,43 @@ export declare function floor(fieldName: string): FunctionExpression; A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the floor of the numeric value. +### geoDistance(fieldName, location) {:#geodistance_ea237a8} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Evaluates to the distance in meters between the location in the specified field and the query location. + +This Expression can only be used within a `Search` stage. + +Signature: + +```typescript +export declare function geoDistance(fieldName: string | Field, location: GeoPoint | Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string \| [Field](./firestore_lite_pipelines.field.md#field_class) | Specifies the field in the document which contains the first GeoPoint for distance computation. | +| location | [GeoPoint](./firestore_lite.geopoint.md#geopoint_class) \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Compute distance to this GeoPoint. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +### Example + + +```typescript +db.pipeline().collection('restaurants').search({ + query: 'waffles', + sort: geoDistance('location', new GeoPoint(37.0, -122.0)).ascending() +}) + +``` + ### greaterThan(fieldName, expression) {:#greaterthan_1e91657} Creates an expression that checks if a field's value is greater than an expression. @@ -9829,6 +9900,43 @@ const results: PipelineResults = snapshot.results; ``` +## function(rquery, ...) + +### documentMatches(rquery) {:#documentmatches_d7a12c2} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Perform a full-text search on all indexed search fields in the document. + +This Expression can only be used within a `Search` stage. + +Signature: + +```typescript +export declare function documentMatches(rquery: string | Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| rquery | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | Define the search query using the search domain-specific language (DSL). | + +Returns: + +[BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) + +### Example + + +```typescript +db.pipeline().collection('restaurants').search({ + query: documentMatches('waffles OR pancakes') +}) + +``` + ## function(stringExpression, ...) ### charLength(stringExpression) {:#charlength_c25a54a} @@ -11480,7 +11588,7 @@ export declare type AggregateStageOptions = StageOptions & { ## CollectionGroupStageOptions -Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution. +Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.md#stageoptions) and provides specific settings for how a collection group is identified and processed during pipeline execution. See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. @@ -11663,7 +11771,7 @@ export declare type ReplaceWithStageOptions = StageOptions & { ## SampleStageOptions -Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied. +Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.md#stageoptions) with a specific configuration where only one of the defined sampling methods can be applied. See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. @@ -11676,6 +11784,23 @@ export declare type SampleStageOptions = StageOptions & OneOf<{ }>; ``` +## SearchStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a SearchStage is evaluated. See . + +Signature: + +```typescript +export declare type SearchStageOptions = StageOptions & { + query: BooleanExpression | string; + sort?: Ordering | Ordering[]; + addFields?: Selectable[]; +}; +``` + ## SelectStageOptions Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). @@ -11714,6 +11839,20 @@ export declare type SortStageOptions = StageOptions & { }; ``` +## StageOptions + +Options defining how a Stage is evaluated. + +Signature: + +```typescript +export declare type StageOptions = { + rawOptions?: { + [name: string]: unknown; + }; +}; +``` + ## TimeGranularity Specify time granularity for expressions. diff --git a/docs-devsite/firestore_lite_pipelines.pipeline.md b/docs-devsite/firestore_lite_pipelines.pipeline.md index 85e7d8c15d..8a9040555d 100644 --- a/docs-devsite/firestore_lite_pipelines.pipeline.md +++ b/docs-devsite/firestore_lite_pipelines.pipeline.md @@ -65,6 +65,7 @@ firestore.pipeline().collection("books") | [replaceWith(options)](./firestore_lite_pipelines.pipeline.md#pipelinereplacewith) | | Fully overwrites all fields in a document with those coming from a map.

    This stage allows you to emit a map value as a document. Each key of the map becomes a field on the document that contains the corresponding value.

    Example: | | [sample(documents)](./firestore_lite_pipelines.pipeline.md#pipelinesample) | | Performs a pseudo-random sampling of the documents from the previous stage.

    This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned.

    Examples: | | [sample(options)](./firestore_lite_pipelines.pipeline.md#pipelinesample) | | Performs a pseudo-random sampling of the documents from the previous stage.

    This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) for more information. | +| [search(options)](./firestore_lite_pipelines.pipeline.md#pipelinesearch) | | (Public Preview) Add a search stage to the Pipeline. The search stage supports full-text search and geo search expressions. | | [select(selection, additionalSelections)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

    • string : Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

    Example: | | [select(options)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

    • string: Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

    Example: | | [sort(ordering, additionalOrderings)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

    Example: | @@ -869,6 +870,64 @@ firestore.pipeline().collection("books") ``` +## Pipeline.search() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Add a search stage to the Pipeline. The search stage supports full-text search and geo search expressions. + +A limited set of expressions are supported in the search stage. + +Signature: + +```typescript +search(options: SearchStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [SearchStageOptions](./firestore_lite_pipelines.md#searchstageoptions) | An object that specifies parameters for the stage. A new Pipeline object with this stage appended to the stage list. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +### Example 1 + + +```typescript +// Full-text search example +firestore.pipeline().collection("restaurants") +.search({ + query: documentMatches("waffles OR pancakes"), + sort: [ + score().descending(), + ], + addFields: [ + score().as("searchScore"), + ] +}) + +``` + +### Example 2 + + +```typescript +// Geo distance search example +const queryLocation = new GeoPoint(0, 0); +db.pipeline().collection('restaurants').search({ + query: field('location').geoDistance(queryLocation).lessThanOrEqual(1000), + sort: [ + score().descending(), + ], +}) + +``` + ## Pipeline.select() Selects or creates a set of fields from the outputs of previous stages. diff --git a/docs-devsite/firestore_lite_pipelines.stageoptions.md b/docs-devsite/firestore_lite_pipelines.stageoptions.md deleted file mode 100644 index 597d446a80..0000000000 --- a/docs-devsite/firestore_lite_pipelines.stageoptions.md +++ /dev/null @@ -1,45 +0,0 @@ -Project: /docs/reference/js/_project.yaml -Book: /docs/reference/_book.yaml -page_type: reference - -{% comment %} -DO NOT EDIT THIS FILE! -This is generated by the JS SDK team, and any local changes will be -overwritten. Changes should be made in the source code at -https://github.com/firebase/firebase-js-sdk -{% endcomment %} - -# StageOptions interface -Options defining how a Stage is evaluated. - -Signature: - -```typescript -export declare interface StageOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [rawOptions](./firestore_lite_pipelines.stageoptions.md#stageoptionsrawoptions) | { \[name: string\]: unknown; } | An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Raw option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK.rawOptions supports dot notation, if you want to override a nested option. | - -## StageOptions.rawOptions - -An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK. - -The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name). - -Raw option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected. - -Values specified in rawOptions will take precedence over any options with the same name set by the SDK. - -`rawOptions` supports dot notation, if you want to override a nested option. - -Signature: - -```typescript -rawOptions?: { - [name: string]: unknown; - }; -``` diff --git a/docs-devsite/firestore_pipelines.field.md b/docs-devsite/firestore_pipelines.field.md index 2a56e5ea4d..058117f032 100644 --- a/docs-devsite/firestore_pipelines.field.md +++ b/docs-devsite/firestore_pipelines.field.md @@ -35,6 +35,12 @@ export declare class Field extends Expression implements Selectable | [fieldName](./firestore_pipelines.field.md#fieldfieldname) | | string | | | [selectable](./firestore_pipelines.field.md#fieldselectable) | | true | | +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [geoDistance(location)](./firestore_pipelines.field.md#fieldgeodistance) | | (Public Preview) Evaluates to the distance in meters between the location specified by this field and the query location. | + ## Field.alias Signature: @@ -75,6 +81,31 @@ get fieldName(): string; selectable: true; ``` +## Field.geoDistance() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Evaluates to the distance in meters between the location specified by this field and the query location. + +This Expression can only be used within a `Search` stage. + +Signature: + +```typescript +geoDistance(location: GeoPoint | Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| location | [GeoPoint](./firestore_.geopoint.md#geopoint_class) \| [Expression](./firestore_pipelines.expression.md#expression_class) | Compute distance to this GeoPoint. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + ### Example diff --git a/docs-devsite/firestore_pipelines.functionexpression.md b/docs-devsite/firestore_pipelines.functionexpression.md index 3715f684b7..339642a997 100644 --- a/docs-devsite/firestore_pipelines.functionexpression.md +++ b/docs-devsite/firestore_pipelines.functionexpression.md @@ -26,7 +26,6 @@ export declare class FunctionExpression extends Expression | Constructor | Modifiers | Description | | --- | --- | --- | | [(constructor)(name, params)](./firestore_pipelines.functionexpression.md#functionexpressionconstructor) | | Constructs a new instance of the FunctionExpression class | -| [(constructor)(name, params, \_methodName)](./firestore_pipelines.functionexpression.md#functionexpressionconstructor) | | Constructs a new instance of the FunctionExpression class | ## Properties @@ -51,24 +50,6 @@ constructor(name: string, params: Expression[]); | name | string | | | params | [Expression](./firestore_pipelines.expression.md#expression_class)\[\] | | -## FunctionExpression.(constructor) - -Constructs a new instance of the `FunctionExpression` class - -Signature: - -```typescript -constructor(name: string, params: Expression[], _methodName: string | undefined); -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| name | string | | -| params | [Expression](./firestore_pipelines.expression.md#expression_class)\[\] | | -| \_methodName | string \| undefined | | - ## FunctionExpression.expressionType Signature: diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index dc6dc893c6..485c0038af 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -19,6 +19,7 @@ https://github.com/firebase/firebase-js-sdk | [countAll()](./firestore_pipelines.md#countall) | Creates an aggregation that counts the total number of stage inputs. | | [currentTimestamp()](./firestore_pipelines.md#currenttimestamp) | Creates an expression that evaluates to the current server timestamp. | | [rand()](./firestore_pipelines.md#rand) | Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. | +| [score()](./firestore_pipelines.md#score) | (Public Preview) Evaluates to the search score that reflects the topicality of the document to all of the text predicates (for example: documentMatches) in the search query. If SearchOptions.query is not set or does not contain any text predicates, then this topicality score will always be 0. | | function(array, ...) | | [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_a00ea48) | Creates an expression that checks if an array expression contains a specific element. | | [arrayContains(array, element)](./firestore_pipelines.md#arraycontains_7328608) | Creates an expression that checks if an array expression contains a specific element. | @@ -201,6 +202,7 @@ https://github.com/firebase/firebase-js-sdk | [exp(fieldName)](./firestore_pipelines.md#exp_e5b0480) | Creates an expression that computes e to the power of the expression's result. | | [first(fieldName)](./firestore_pipelines.md#first_e5b0480) | Creates an aggregation that finds the first value of a field across multiple stage inputs. | | [floor(fieldName)](./firestore_pipelines.md#floor_e5b0480) | Creates an expression that computes the floor of a numeric value. | +| [geoDistance(fieldName, location)](./firestore_pipelines.md#geodistance_ea237a8) | (Public Preview) Evaluates to the distance in meters between the location in the specified field and the query location. | | [greaterThan(fieldName, expression)](./firestore_pipelines.md#greaterthan_1e91657) | Creates an expression that checks if a field's value is greater than an expression. | | [greaterThan(fieldName, value)](./firestore_pipelines.md#greaterthan_65e2f32) | Creates an expression that checks if a field's value is greater than a constant value. | | [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_2e16acb) | Creates an expression that checks if a field's value is greater than or equal to an expression. | @@ -343,6 +345,8 @@ https://github.com/firebase/firebase-js-sdk | [field(path)](./firestore_pipelines.md#field_34ee07d) | Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. | | function(pipeline, ...) | | [execute(pipeline)](./firestore_pipelines.md#execute_01df620) | Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:

    • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
    • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
    • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
    | +| function(rquery, ...) | +| [documentMatches(rquery)](./firestore_pipelines.md#documentmatches_d7a12c2) | (Public Preview) Perform a full-text search on all indexed search fields in the document. | | function(stringExpression, ...) | | [charLength(stringExpression)](./firestore_pipelines.md#charlength_c25a54a) | Creates an expression that calculates the character length of a string expression in UTF-8. | | [endsWith(stringExpression, suffix)](./firestore_pipelines.md#endswith_0a0b889) | Creates an expression that checks if a string expression ends with a given postfix. | @@ -442,7 +446,6 @@ https://github.com/firebase/firebase-js-sdk | [PipelineExecuteOptions](./firestore_pipelines.pipelineexecuteoptions.md#pipelineexecuteoptions_interface) | Options defining Pipeline execution. | | [Selectable](./firestore_pipelines.selectable.md#selectable_interface) | An interface that represents a selectable expression. | | [SnapshotOptions](./firestore_pipelines.snapshotoptions.md#snapshotoptions_interface) | Options that configure how data is retrieved from a DocumentSnapshot (for example the desired behavior for server timestamps that have not yet been set to their final value). | -| [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) | Options defining how a Stage is evaluated. | ## Type Aliases @@ -450,7 +453,7 @@ https://github.com/firebase/firebase-js-sdk | --- | --- | | [AddFieldsStageOptions](./firestore_pipelines.md#addfieldsstageoptions) | Options defining how an AddFieldsStage is evaluated. See [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields). | | [AggregateStageOptions](./firestore_pipelines.md#aggregatestageoptions) | Options defining how an AggregateStage is evaluated. See [Pipeline.aggregate()](./firestore_pipelines.pipeline.md#pipelineaggregate). | -| [CollectionGroupStageOptions](./firestore_pipelines.md#collectiongroupstageoptions) | Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution.See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. | +| [CollectionGroupStageOptions](./firestore_pipelines.md#collectiongroupstageoptions) | Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.md#stageoptions) and provides specific settings for how a collection group is identified and processed during pipeline execution.See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. | | [CollectionStageOptions](./firestore_pipelines.md#collectionstageoptions) | Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). | | [DatabaseStageOptions](./firestore_pipelines.md#databasestageoptions) | Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). | | [DistinctStageOptions](./firestore_pipelines.md#distinctstageoptions) | Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). | @@ -464,10 +467,12 @@ https://github.com/firebase/firebase-js-sdk | [Primitive](./firestore_pipelines.md#primitive) | Primitive types. | | [RemoveFieldsStageOptions](./firestore_pipelines.md#removefieldsstageoptions) | Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). | | [ReplaceWithStageOptions](./firestore_pipelines.md#replacewithstageoptions) | Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). | -| [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) | Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied.See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. | +| [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) | Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.md#stageoptions) with a specific configuration where only one of the defined sampling methods can be applied.See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. | +| [SearchStageOptions](./firestore_pipelines.md#searchstageoptions) | (Public Preview) Options defining how a SearchStage is evaluated. See . | | [SelectStageOptions](./firestore_pipelines.md#selectstageoptions) | Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). | | [SetOptions](./firestore_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | | [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | +| [StageOptions](./firestore_pipelines.md#stageoptions) | Options defining how a Stage is evaluated. | | [TimeGranularity](./firestore_pipelines.md#timegranularity) | Specify time granularity for expressions. | | [TimePart](./firestore_pipelines.md#timepart) | Specify time parts for timestampExtract expressions. | | [TimeUnit](./firestore_pipelines.md#timeunit) | Specify time units for expressions. | @@ -551,6 +556,35 @@ rand(); ``` +### score() {:#score} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Evaluates to the search score that reflects the topicality of the document to all of the text predicates (for example: `documentMatches`) in the search query. If `SearchOptions.query` is not set or does not contain any text predicates, then this topicality score will always be `0`. + +This Expression can only be used within a `Search` stage. + +Signature: + +```typescript +export declare function score(): Expression; +``` +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### Example + + +```typescript +db.pipeline().collection('restaurants').search({ + query: 'waffles', + sort: score().descending() +}) + +``` + ## function(array, ...) ### arrayContains(array, element) {:#arraycontains_a00ea48} @@ -5797,6 +5831,43 @@ export declare function floor(fieldName: string): FunctionExpression; A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the floor of the numeric value. +### geoDistance(fieldName, location) {:#geodistance_ea237a8} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Evaluates to the distance in meters between the location in the specified field and the query location. + +This Expression can only be used within a `Search` stage. + +Signature: + +```typescript +export declare function geoDistance(fieldName: string | Field, location: GeoPoint | Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string \| [Field](./firestore_pipelines.field.md#field_class) | Specifies the field in the document which contains the first GeoPoint for distance computation. | +| location | [GeoPoint](./firestore_.geopoint.md#geopoint_class) \| [Expression](./firestore_pipelines.expression.md#expression_class) | Compute distance to this GeoPoint. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +### Example + + +```typescript +db.pipeline().collection('restaurants').search({ + query: 'waffles', + sort: geoDistance('location', new GeoPoint(37.0, -122.0)).ascending() +}) + +``` + ### greaterThan(fieldName, expression) {:#greaterthan_1e91657} Creates an expression that checks if a field's value is greater than an expression. @@ -9898,6 +9969,43 @@ const results: PipelineResult[] = snapshot.results; ``` +## function(rquery, ...) + +### documentMatches(rquery) {:#documentmatches_d7a12c2} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Perform a full-text search on all indexed search fields in the document. + +This Expression can only be used within a `Search` stage. + +Signature: + +```typescript +export declare function documentMatches(rquery: string | Expression): BooleanExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| rquery | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | Define the search query using the search domain-specific language (DSL). | + +Returns: + +[BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) + +### Example + + +```typescript +db.pipeline().collection('restaurants').search({ + query: documentMatches('waffles OR pancakes') +}) + +``` + ## function(stringExpression, ...) ### charLength(stringExpression) {:#charlength_c25a54a} @@ -11549,7 +11657,7 @@ export declare type AggregateStageOptions = StageOptions & { ## CollectionGroupStageOptions -Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) and provides specific settings for how a collection group is identified and processed during pipeline execution. +Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.md#stageoptions) and provides specific settings for how a collection group is identified and processed during pipeline execution. See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. @@ -11732,7 +11840,7 @@ export declare type ReplaceWithStageOptions = StageOptions & { ## SampleStageOptions -Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.stageoptions.md#stageoptions_interface) with a specific configuration where only one of the defined sampling methods can be applied. +Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.md#stageoptions) with a specific configuration where only one of the defined sampling methods can be applied. See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. @@ -11745,6 +11853,23 @@ export declare type SampleStageOptions = StageOptions & OneOf<{ }>; ``` +## SearchStageOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Options defining how a SearchStage is evaluated. See . + +Signature: + +```typescript +export declare type SearchStageOptions = StageOptions & { + query: BooleanExpression | string; + sort?: Ordering | Ordering[]; + addFields?: Selectable[]; +}; +``` + ## SelectStageOptions Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). @@ -11783,6 +11908,20 @@ export declare type SortStageOptions = StageOptions & { }; ``` +## StageOptions + +Options defining how a Stage is evaluated. + +Signature: + +```typescript +export declare type StageOptions = { + rawOptions?: { + [name: string]: unknown; + }; +}; +``` + ## TimeGranularity Specify time granularity for expressions. diff --git a/docs-devsite/firestore_pipelines.pipeline.md b/docs-devsite/firestore_pipelines.pipeline.md index 87c516b13c..b897f796a4 100644 --- a/docs-devsite/firestore_pipelines.pipeline.md +++ b/docs-devsite/firestore_pipelines.pipeline.md @@ -55,6 +55,7 @@ distanceField: 'computedDistance' // optional | [replaceWith(options)](./firestore_pipelines.pipeline.md#pipelinereplacewith) | | | | [sample(documents)](./firestore_pipelines.pipeline.md#pipelinesample) | | Performs a pseudo-random sampling of the documents from the previous stage.

    This stage will filter documents pseudo-randomly. The parameter specifies how number of documents to be returned.

    Examples: | | [sample(options)](./firestore_pipelines.pipeline.md#pipelinesample) | | Performs a pseudo-random sampling of the documents from the previous stage.

    This stage will filter documents pseudo-randomly. The 'options' parameter specifies how sampling will be performed. See [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) for more information. | +| [search(options)](./firestore_pipelines.pipeline.md#pipelinesearch) | | | | [select(selection, additionalSelections)](./firestore_pipelines.pipeline.md#pipelineselect) | | Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

    • string : Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

    Example: | | [select(options)](./firestore_pipelines.pipeline.md#pipelineselect) | | Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

    • string: Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

    Example: | | [sort(ordering, additionalOrderings)](./firestore_pipelines.pipeline.md#pipelinesort) | | Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

    Example: | @@ -708,6 +709,24 @@ firestore.pipeline().collection("books") ``` +## Pipeline.search() + +Signature: + +```typescript +search(options: SearchStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [SearchStageOptions](./firestore_pipelines.md#searchstageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + ## Pipeline.select() Selects or creates a set of fields from the outputs of previous stages. diff --git a/docs-devsite/firestore_pipelines.stageoptions.md b/docs-devsite/firestore_pipelines.stageoptions.md deleted file mode 100644 index f371f9ed91..0000000000 --- a/docs-devsite/firestore_pipelines.stageoptions.md +++ /dev/null @@ -1,45 +0,0 @@ -Project: /docs/reference/js/_project.yaml -Book: /docs/reference/_book.yaml -page_type: reference - -{% comment %} -DO NOT EDIT THIS FILE! -This is generated by the JS SDK team, and any local changes will be -overwritten. Changes should be made in the source code at -https://github.com/firebase/firebase-js-sdk -{% endcomment %} - -# StageOptions interface -Options defining how a Stage is evaluated. - -Signature: - -```typescript -export declare interface StageOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [rawOptions](./firestore_pipelines.stageoptions.md#stageoptionsrawoptions) | { \[name: string\]: unknown; } | An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK.The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name).Raw option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected.Values specified in rawOptions will take precedence over any options with the same name set by the SDK.rawOptions supports dot notation, if you want to override a nested option. | - -## StageOptions.rawOptions - -An escape hatch to set options not known at SDK build time. These values will be passed directly to the Firestore backend and not used by the SDK. - -The option name will be used as provided. And must match the name format used by the backend (hint: use a snake\_case\_name). - -Raw option values can be any type supported by Firestore (for example: string, boolean, number, map, …). Value types not known to the SDK will be rejected. - -Values specified in rawOptions will take precedence over any options with the same name set by the SDK. - -`rawOptions` supports dot notation, if you want to override a nested option. - -Signature: - -```typescript -rawOptions?: { - [name: string]: unknown; - }; -``` diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index 898e24add8..9cdb0302a1 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -80,7 +80,10 @@ export { SampleStageOptions, UnionStageOptions, UnnestStageOptions, - SortStageOptions + SortStageOptions, + SearchStageOptions + // TODO(search) export with backend support + // QueryEnhancement } from '../../src/lite-api/stage_options'; export { @@ -216,6 +219,12 @@ export { split, timestampTruncate, timestampExtract, + // snippet, + // SnippetOptions, + score, + // matches, + documentMatches, + geoDistance, AliasedExpression, Field, Constant, diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index deb9eb4408..eb4ff33c6d 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -50,7 +50,10 @@ export { SampleStageOptions, UnionStageOptions, UnnestStageOptions, - SortStageOptions + SortStageOptions, + SearchStageOptions + // TODO(search) export with backend support + // QueryEnhancement } from './lite-api/stage_options'; export { @@ -185,6 +188,13 @@ export { timestampTruncate, timestampExtract, split, + score, + documentMatches, + geoDistance, + // TODO(search) add with backend support + // snippet, + // SnippetOptions, + // matches, Expression, AliasedExpression, Field, diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index de308152f1..361a3bdc04 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -17,11 +17,16 @@ import { FirestoreError } from '../api'; import { ParseContext } from '../api/parse_context'; +import { OptionsUtil } from '../core/options_util'; import { DOCUMENT_KEY_NAME, FieldPath as InternalFieldPath } from '../model/path'; -import { Value as ProtoValue } from '../protos/firestore_proto_api'; +import { + ApiClientObjectMap, + firestoreV1ApiClientInterfaces, + Value as ProtoValue +} from '../protos/firestore_proto_api'; import { JsonProtoSerializer, ProtoValueSerializable, @@ -147,7 +152,6 @@ function fieldOrExpression(value: unknown): Expression { return valueToDefaultExpr(value); } } - /** * * Represents an expression that can be evaluated to a value within the execution of a {@link @@ -3286,6 +3290,85 @@ export abstract class Expression implements ProtoValueSerializable, UserData { return new FunctionExpression('timestamp_trunc', args); } + // TODO(search) enable with backend support + // /** + // * Evaluates if the result of this `expression` is between + // * the `lowerBound` (inclusive) and `upperBound` (inclusive). + // * + // * @example + // * ``` + // * // Evaluate if the 'tireWidth' is between 2.2 and 2.4 + // * field('tireWidth').between(constant(2.2), constant(2.4)) + // * + // * // This is functionally equivalent to + // * and(field('tireWidth').greaterThanOrEqual(contant(2.2)), field('tireWidth').lessThanOrEqual(constant(2.4))) + // * ``` + // * + // * @param lowerBound - Lower bound (inclusive) of the range. + // * @param upperBound - Upper bound (inclusive) of the range. + // */ + // between(lowerBound: Expression, upperBound: Expression): BooleanExpression; + // + // /** + // * Evaluates if the result of this `expression` is between + // * the `lowerBound` (inclusive) and `upperBound` (inclusive). + // * + // * @example + // * ``` + // * // Evaluate if the 'tireWidth' is between 2.2 and 2.4 + // * field('tireWidth').between(2.2, 2.4) + // * + // * // This is functionally equivalent to + // * and(field('tireWidth').greaterThanOrEqual(2.2), field('tireWidth').lessThanOrEqual(2.4)) + // * ``` + // * + // * @param lowerBound - Lower bound (inclusive) of the range. + // * @param upperBound - Upper bound (inclusive) of the range. + // */ + // between(lowerBound: unknown, upperBound: unknown): BooleanExpression; + // + // between(lowerBound: unknown, upperBound: unknown): BooleanExpression { + // return new FunctionExpression('between', [ + // this, + // valueToDefaultExpr(lowerBound), + // valueToDefaultExpr(upperBound) + // ]).asBoolean(); + // } + + // TODO(search) enable with backend support + // /** + // * Evaluates to an HTML-formatted text snippet that renders terms matching + // * the search query in `bold`. + // * + // * @remarks This Expression can only be used within a `Search` stage. + // * + // * @param rquery Define the search query using the search domain-specific language (DSL). + // */ + // snippet(rquery: string): Expression; + // + // /** + // * Evaluates to an HTML-formatted text snippet that renders terms matching + // * the search query in `bold`. + // * + // * @remarks This Expression can only be used within a `Search` stage. + // * + // * @param options Define how snippeting behaves. + // */ + // snippet(options: SnippetOptions): Expression; + // + // snippet(queryOrOptions: string | SnippetOptions): Expression { + // const options: SnippetOptions = isString(queryOrOptions) + // ? { rquery: queryOrOptions } + // : queryOrOptions; + // const rquery = options.rquery; + // const internalOptions = { + // maxSnippetWidth: options.maxSnippetWidth, + // maxSnippets: options.maxSnippets, + // separator: options.separator + // }; + // return new SnippetExpression([this, constant(rquery)], internalOptions); + // } + // TODO(new-expression): Add new expression method definitions above this line /** @@ -3592,6 +3675,39 @@ export class Field extends Expression implements Selectable { return this; } + // TODO(search) enable with backend support + // /** + // * Perform a full-text search on this field. + // * + // * @remarks This Expression can only be used within a `Search` stage. + // * + // * @param rquery Define the search query using the search domain-specific language (DSL). + // */ + // matches(rquery: string | Expression): BooleanExpression { + // return new FunctionExpression( + // 'matches', + // [this, valueToDefaultExpr(rquery)], + // 'matches' + // ).asBoolean(); + // } + + /** + * @beta + * Evaluates to the distance in meters between the location specified + * by this field and the query location. + * + * @remarks This Expression can only be used within a `Search` stage. + * + * @param location - Compute distance to this GeoPoint. + */ + geoDistance(location: GeoPoint | Expression): Expression { + return new FunctionExpression( + 'geo_distance', + [this, valueToDefaultExpr(location)], + 'geoDistance' + ); + } + /** * @private * @internal @@ -3880,30 +3996,81 @@ export class FunctionExpression extends Expression { readonly expressionType: ExpressionType = 'Function'; constructor(name: string, params: Expression[]); + + /** + * @hideconstructor + */ constructor( name: string, params: Expression[], - _methodName: string | undefined + _methodName?: string, + options?: {} ); + + /** + * @hideconstructor + */ constructor( private name: string, private params: Expression[], - readonly _methodName?: string + methodName?: string, + options?: {} ) { super(); + + if (methodName !== undefined) { + this._methodName = methodName; + } + if (options !== undefined) { + this._options = options; + } } + /** + * @private + * @internal + */ + _methodName: string | undefined; + + /** + * @private + * @internal + */ + private _options: {} | undefined; + + /** + * @private + * @internal + */ + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + /** + * @private + * @internal + */ + _optionsProto: + | ApiClientObjectMap + | undefined = undefined; + /** * @private * @internal */ _toProto(serializer: JsonProtoSerializer): ProtoValue { - return { + const returnValue: ProtoValue = { functionValue: { name: this.name, args: this.params.map(p => p._toProto(serializer)) } }; + + if (this._optionsProto) { + returnValue.functionValue!.options = this._optionsProto; + } + + return returnValue; } /** @@ -3917,6 +4084,12 @@ export class FunctionExpression extends Expression { this.params.forEach(expr => { return expr._readUserData(context); }); + if (this._options) { + this._optionsProto = this._optionsUtil.getOptionsProto( + context, + this._options + ); + } } } @@ -4105,6 +4278,37 @@ export class BooleanField extends BooleanExpression { } } +/** + * SnippetExpression extends from FunctionExpression because it + * supports options and requires the options util. + */ +export class SnippetExpression extends FunctionExpression { + /** + * @private + * @internal + */ + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({ + maxSnippetWidth: { + serverName: 'max_snippet_width' + }, + maxSnippets: { + serverName: 'max_snippets' + }, + separator: { + serverName: 'separator' + } + }); + } + + /** + * @hideconstructor + */ + constructor(params: Expression[], options?: {}) { + super('snippet', params, 'snippet', options); + } +} + /** * Creates an aggregation that counts the number of stage inputs where the provided * boolean expression evaluates to true. @@ -10899,6 +11103,275 @@ export function timestampExtract( ); } +// TODO(search) enable with backend support +// /** +// * Perform a full-text search on the specified field. +// * +// * @remarks This Expression can only be used within a `Search` stage. +// * +// * @example +// * ```typescript +// * db.pipeline().collection('restaurants').search({ +// * query: matches('menu', 'waffles') +// * }) +// * ``` +// * +// * @param searchField Search the specified field. +// * @param rquery Define the search query using the search domain-specific language (DSL). +// */ +// export function matches( +// searchField: string | Field, +// rquery: string | Expression +// ): BooleanExpression { +// return toField(searchField).matches(rquery); +// } + +/** + * @beta + * Perform a full-text search on all indexed search fields in the document. + * + * @remarks This Expression can only be used within a `Search` stage. + * + * @example + * ```typescript + * db.pipeline().collection('restaurants').search({ + * query: documentMatches('waffles OR pancakes') + * }) + * ``` + * + * @param rquery Define the search query using the search domain-specific language (DSL). + */ +export function documentMatches( + rquery: string | Expression +): BooleanExpression { + return new FunctionExpression( + 'document_matches', + [valueToDefaultExpr(rquery)], + 'documentMatches' + ).asBoolean(); +} + +/** + * @beta + * + * Evaluates to the search score that reflects the topicality of the document + * to all of the text predicates (for example: `documentMatches`) + * in the search query. If `SearchOptions.query` is not set or does not contain + * any text predicates, then this topicality score will always be `0`. + * + * @example + * ```typescript + * db.pipeline().collection('restaurants').search({ + * query: 'waffles', + * sort: score().descending() + * }) + * ``` + * + * @remarks This Expression can only be used within a `Search` stage. + */ +export function score(): Expression { + return new FunctionExpression('score', [], 'score'); +} + +// TODO(search) enable with backend support +// /** +// * Options defining how a snippet expression is evaluated. +// */ +// export interface SnippetOptions { +// /** +// * Define the search query using the search domain-specific language (DSL). +// */ +// rquery: string; +// +// /** +// * The maximum width of the string estimated for a variable width font. The +// * unit is tenths of ems. The default is `160`. +// */ +// maxSnippetWidth?: number; +// +// /** +// * The maximum number of non-contiguous pieces of text in the returned snippet. +// * The default is `1`. +// */ +// maxSnippets?: number; +// +// /** +// * The string to join the pieces. The default value is '\n' +// */ +// separator?: string; +// } +// +// /** +// * Evaluates to an HTML-formatted text snippet that highlights terms matching +// * the search query in `bold`. +// * +// * @remarks This Expression can only be used within a `Search` stage. +// * +// * @example +// * ```typescript +// * db.pipeline().collection('restaurants').search({ +// * query: 'waffles', +// * addFields: { snippet: snippet('menu', 'waffles') } +// * }) +// * ``` +// * +// * @param searchField Search the specified field for matching terms. +// * @param rquery Define the search query using the search domain-specific language (DSL). +// */ +// export function snippet( +// searchField: string | Field, +// rquery: string +// ): Expression; +// +// /** +// * Evaluates to an HTML-formatted text snippet that highlights terms matching +// * the search query in `bold`. +// * +// * @remarks This Expression can only be used within a `Search` stage. +// * +// * @param searchField Search the specified field for matching terms. +// * @param options Define the search query using the search domain-specific language (DSL). +// */ +// export function snippet( +// searchField: string | Field, +// options: SnippetOptions +// ): Expression; +// export function snippet( +// field: string | Field, +// queryOrOptions: string | SnippetOptions +// ): Expression { +// return toField(field).snippet( +// isString(queryOrOptions) ? { rquery: queryOrOptions } : queryOrOptions +// ); +// } + +/** + * @beta + * Evaluates to the distance in meters between the location in the specified + * field and the query location. + * + * @remarks This Expression can only be used within a `Search` stage. + * + * @example + * ```typescript + * db.pipeline().collection('restaurants').search({ + * query: 'waffles', + * sort: geoDistance('location', new GeoPoint(37.0, -122.0)).ascending() + * }) + * ``` + * + * @param fieldName - Specifies the field in the document which contains + * the first GeoPoint for distance computation. + * @param location - Compute distance to this GeoPoint. + */ +export function geoDistance( + fieldName: string | Field, + location: GeoPoint | Expression +): Expression { + return toField(fieldName).geoDistance(location); +} + +// TODO(search) enable with backend support +// /** +// * Evaluates if the value in the field specified by `fieldName` is between +// * the evaluated values for `lowerBound` (inclusive) and `upperBound` (inclusive). +// * +// * @example +// * ``` +// * // Evaluate if the 'tireWidth' is between 2.2 and 2.4 +// * between('tireWidth', constant(2.2), constant(2.4)) +// * +// * // This is functionally equivalent to +// * and(greaterThanOrEqual('tireWidth', constant(2.2)), lessThanOrEqual('tireWidth', constant(2.4))) +// * ``` +// * +// * @param fieldName - Evaluate if the value stored in this field is between the lower and upper bounds. +// * @param lowerBound - Lower bound (inclusive) of the range. +// * @param upperBound - Upper bound (inclusive) of the range. +// */ +// export function between( +// fieldName: string, +// lowerBound: Expression, +// upperBound: Expression +// ): BooleanExpression; +// +// /** +// * Evaluates if the value in the field specified by `fieldName` is between +// * the values for `lowerBound` (inclusive) and `upperBound` (inclusive). +// * +// * @example +// * ``` +// * // Evaluate if the 'tireWidth' is between 2.2 and 2.4 +// * between('tireWidth', 2.2, 2.4) +// * +// * // This is functionally equivalent to +// * and(greaterThanOrEqual('tireWidth', 2.2), lessThanOrEqual('tireWidth', 2.4)) +// * ``` +// * +// * @param fieldName - Evaluate if the value stored in this field is between the lower and upper bounds. +// * @param lowerBound - Lower bound (inclusive) of the range. +// * @param upperBound - Upper bound (inclusive) of the range. +// */ +// export function between( +// fieldName: string, +// lowerBound: unknown, +// upperBound: unknown +// ): BooleanExpression; +// +// /** +// * Evaluates if the result of the specified `expression` is between +// * the results of `lowerBound` (inclusive) and `upperBound` (inclusive). +// * +// * @example +// * ``` +// * // Evaluate if the 'tireWidth' is between 2.2 and 2.4 +// * between(field('tireWidth'), constant(2.2), constant(2.4)) +// * +// * // This is functionally equivalent to +// * and(greaterThanOrEqual(field('tireWidth'), constant(2.2)), lessThanOrEqual(field('tireWidth'), constant(2.4))) +// * ``` +// * +// * @param expression - Evaluate if the result of this expression is between the lower and upper bounds. +// * @param lowerBound - Lower bound (inclusive) of the range. +// * @param upperBound - Upper bound (inclusive) of the range. +// */ +// export function between( +// expression: Expression, +// lowerBound: Expression, +// upperBound: Expression +// ): BooleanExpression; +// +// /** +// * Evaluates if the result of the specified `expression` is between +// * the `lowerBound` (inclusive) and `upperBound` (inclusive). +// * +// * @example +// * ``` +// * // Evaluate if the 'tireWidth' is between 2.2 and 2.4 +// * between(field('tireWidth'), 2.2, 2.4) +// * +// * // This is functionally equivalent to +// * and(greaterThanOrEqual(field('tireWidth'), 2.2), lessThanOrEqual(field('tireWidth'), 2.4)) +// * ``` +// * +// * @param expression - Evaluate if the result of this expression is between the lower and upper bounds. +// * @param lowerBound - Lower bound (inclusive) of the range. +// * @param upperBound - Upper bound (inclusive) of the range. +// */ +// export function between( +// expression: Expression, +// lowerBound: unknown, +// upperBound: unknown +// ): BooleanExpression; +// +// export function between( +// expression: Expression | string, +// lowerBound: unknown, +// upperBound: unknown +// ): BooleanExpression { +// return fieldOrExpression(expression).between(lowerBound, upperBound); +// } + // TODO(new-expression): Add new top-level expression function definitions above this line /** @@ -11018,8 +11491,10 @@ export function isSelectable(val: unknown): val is Selectable { } export function isOrdering(val: unknown): val is Ordering { - const candidate = val as Ordering; + const candidate = val as Ordering | undefined; return ( + candidate !== undefined && + candidate !== null && isExpr(candidate.expr) && (candidate.direction === 'ascending' || candidate.direction === 'descending') diff --git a/packages/firestore/src/lite-api/pipeline.ts b/packages/firestore/src/lite-api/pipeline.ts index febfdf200f..f73220418a 100644 --- a/packages/firestore/src/lite-api/pipeline.ts +++ b/packages/firestore/src/lite-api/pipeline.ts @@ -26,6 +26,7 @@ import { aliasedAggregateToMap, fieldOrExpression, selectablesToMap, + selectablesToObject, vectorToExpr } from '../util/pipeline_util'; import { isNumber, isString } from '../util/types'; @@ -49,7 +50,8 @@ import { isAliasedAggregate, toField, isOrdering, - isExpr + isExpr, + documentMatches } from './expressions'; import { AddFields, @@ -67,7 +69,8 @@ import { Stage, Union, Unnest, - Where + Where, + Search } from './stage'; import { AddFieldsStageOptions, @@ -79,6 +82,7 @@ import { RemoveFieldsStageOptions, ReplaceWithStageOptions, SampleStageOptions, + SearchStageOptions, SelectStageOptions, SortStageOptions, StageOptions, @@ -840,6 +844,80 @@ export class Pipeline implements ProtoSerializable, UserData { return this._addStage(stage); } + // TODO(search) link to external documentation citing list of supported + // expressions, when that documentation is created. List is not maintained + // in the SDK because the list will change as the backend enables support. + /** + * @beta + * Add a search stage to the Pipeline. The search stage supports + * full-text search and geo search expressions. + * + * @remarks This must be the first stage of the pipeline. + * @remarks A limited set of expressions are supported in the search stage. + * + * @example + * ```typescript + * // Full-text search example + * firestore.pipeline().collection("restaurants") + * .search({ + * query: documentMatches("waffles OR pancakes"), + * sort: [ + * score().descending(), + * ], + * addFields: [ + * score().as("searchScore"), + * ] + * }) + * ``` + * + * @example + * ```typescript + * // Geo distance search example + * const queryLocation = new GeoPoint(0, 0); + * db.pipeline().collection('restaurants').search({ + * query: field('location').geoDistance(queryLocation).lessThanOrEqual(1000), + * sort: [ + * score().descending(), + * ], + * }) + * ``` + * + * @param options - An object that specifies parameters for the stage. + * @return A new `Pipeline` object with this stage appended to the stage list. + */ + search(options: SearchStageOptions): Pipeline { + // Convert user land convenience types to internal types + const addFields: Record | undefined = options.addFields + ? selectablesToObject(options.addFields) + : undefined; + const query: BooleanExpression = isExpr(options.query) + ? options.query + : documentMatches(options.query); + const sort: Ordering[] | undefined = isOrdering(options.sort) + ? [options.sort] + : options.sort; + + const select: Record | undefined = undefined; + // TODO(search) enable with backend support + // select = options.select + // ? selectablesToObject(options.select) + // : undefined; + + const internalOptions = { + ...options, + addFields, + select, + query, + sort + }; + + // Create stage object + const stage = new Search(internalOptions); + + // Add stage to the pipeline + return this._addStage(stage); + } + /** * Sorts the documents from previous stages based on one or more {@link @firebase/firestore/pipelines#Ordering} criteria. * diff --git a/packages/firestore/src/lite-api/stage.ts b/packages/firestore/src/lite-api/stage.ts index 9c1d4c4639..f6fc5dc453 100644 --- a/packages/firestore/src/lite-api/stage.ts +++ b/packages/firestore/src/lite-api/stage.ts @@ -41,12 +41,12 @@ import { Ordering } from './expressions'; import { Pipeline } from './pipeline'; -import { StageOptions } from './stage_options'; +import { QueryEnhancement, StageOptions } from './stage_options'; import { isUserData, UserData } from './user_data_reader'; export abstract class Stage implements ProtoSerializable, UserData { /** - * Store optionsProto parsed by _readUserData. + * Store _optionsProto parsed by _readUserData. * @private * @internal * @protected @@ -57,7 +57,7 @@ export abstract class Stage implements ProtoSerializable, UserData { protected knownOptions: Record; protected rawOptions?: Record; - constructor(options: StageOptions) { + constructor(options: Record & StageOptions) { ({ rawOptions: this.rawOptions, ...this.knownOptions } = options); } @@ -645,6 +645,96 @@ export class Replace extends Stage { } } +// eslint-disable-next-line -- eslint should not convert this type to an interface +type InternalSearchOptions = { + // These are constrained from the public type + query: BooleanExpression; + sort?: Ordering[]; + select?: Record; + addFields?: Record; + + // These are the same as the public type + languageCode?: string; + retrievalDepth?: number; + offset?: number; + limit?: number; + queryEnhancement?: QueryEnhancement; +}; + +/** + * @beta + */ +export class Search extends Stage { + constructor(private _searchOptions: InternalSearchOptions) { + super(_searchOptions); + } + + get _name(): string { + return 'search'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({ + query: { + serverName: 'query' + }, + limit: { + serverName: 'limit' + }, + retrievalDepth: { + serverName: 'retrieval_depth' + }, + sort: { + serverName: 'sort' + }, + addFields: { + serverName: 'add_fields' + }, + select: { + serverName: 'select' + }, + offset: { + serverName: 'offset' + }, + queryEnhancement: { + serverName: 'query_enhancement' + }, + languageCode: { + serverName: 'language_code' + } + }); + } + + /** + * @private + * @internal + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [] + }; + } + + _readUserData(context: ParseContext): void { + readUserDataHelper(this._searchOptions.query, context); + if (this._searchOptions.addFields) { + readUserDataHelper(this._searchOptions.addFields, context); + } + if (this._searchOptions.select) { + readUserDataHelper(this._searchOptions.select, context); + } + if (this._searchOptions.sort) { + readUserDataHelper(this._searchOptions.sort, context); + } + + super._readUserData(context); + } +} + +/** + * @beta + */ export class RawStage extends Stage { /** * @private @@ -692,14 +782,22 @@ export class RawStage extends Stage { * @private */ function readUserDataHelper< - T extends Map | UserData[] | UserData + T extends + | Map + | Record + | UserData[] + | UserData >(expressionMap: T, context: ParseContext): T { if (isUserData(expressionMap)) { expressionMap._readUserData(context); } else if (Array.isArray(expressionMap)) { expressionMap.forEach(readableData => readableData._readUserData(context)); - } else { + } else if (expressionMap instanceof Map) { expressionMap.forEach(expr => expr._readUserData(context)); + } else { + Object.values(expressionMap).forEach(expression => + expression._readUserData(context) + ); } return expressionMap; } diff --git a/packages/firestore/src/lite-api/stage_options.ts b/packages/firestore/src/lite-api/stage_options.ts index 5f0cbca74d..7c78aac169 100644 --- a/packages/firestore/src/lite-api/stage_options.ts +++ b/packages/firestore/src/lite-api/stage_options.ts @@ -32,7 +32,8 @@ import { VectorValue } from './vector_value'; /** * Options defining how a Stage is evaluated. */ -export interface StageOptions { +// eslint-disable-next-line -- eslint should not convert this type to an interface +export type StageOptions = { /** * An escape hatch to set options not known at SDK build time. These values * will be passed directly to the Firestore backend and not used by the SDK. @@ -53,7 +54,7 @@ export interface StageOptions { rawOptions?: { [name: string]: unknown; }; -} +}; /** * Options defining how a CollectionStage is evaluated. See {@link @firebase/firestore/pipelines#PipelineSource.(collection:1)}. */ @@ -226,6 +227,117 @@ export type FindNearestStageOptions = StageOptions & { */ distanceField?: string; }; + +/** + * @beta + * + * Specifies if the `matches` and `snippet` expressions will enhance the user + * provided query to perform matching of synonyms, misspellings, lemmatization, + * stemming. + * + * required - search will fail if the query enhancement times out or if the query + * enhancement is not supported by the project's DRZ compliance + * requirements. + * preferred - search will fall back to the un-enhanced, user provided query, if + * the query enhancement fails. + */ +export type QueryEnhancement = 'disabled' | 'required' | 'preferred'; + +/** + * @beta + * Options defining how a SearchStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(search)}. + */ +export type SearchStageOptions = StageOptions & { + /** + * Specifies the search query that will be used to query and score documents + * by the search stage. + * + * The query can be expressed as an `Expression`, which will be used to score + * and filter the results. Not all expressions supported by Pipelines + * are supported in the Search query. + * + * @example + * ```typescript + * db.pipeline().collection('restaurants').search({ + * query: or( + * documentMatches("breakfast"), + * field('menu').matches('waffle AND coffee') + * ) + * }) + * ``` + * + * The query can also be expressed as a string in the Search domain-specific language (DSL): + * + * @example + * ```typescript + * db.pipeline().collection('restaurants').search({ + * query: 'menu:(waffle and coffee) OR breakfast' + * }) + * ``` + * + * The query can also represent a geoDistance query: + * + * @example + * ```typescript + * db.pipeline().collection('restaurants').search({ + * query: field('location').geoDistance(new GeoPoint(0, 0)).lessThanOrEqual(1000) + * }) + * ``` + */ + query: BooleanExpression | string; + + // TODO(search) enable with backend support + // /** + // * The BCP-47 language code of text in the search query, such as, “en-US” or “sr-Latn” + // */ + // languageCode?: string; + + // TODO(search) add indexPartition after languageCode + + // TODO(search) enable with backend support + // /** + // * The maximum number of documents to retrieve. Documents will be retrieved in the + // * pre-sort order specified by the search index. + // */ + // retrievalDepth?: number; + + /** + * Orderings specify how the returned documents are sorted. + * One or more ordering are required. + */ + sort?: Ordering | Ordering[]; + + // TODO(search) enable with backend support + // /** + // * The number of documents to skip from the beginning of the search result set. + // */ + // offset?: number; + + // TODO(search) enable with backend support + // /** + // * The maximum number of documents to return from the Search stage. + // */ + // limit?: number; + + // TODO(search) enable with backend support + // /** + // * The fields to keep or add to each document, + // * specified as an array of {@link @firebase/firestore/pipelines#Selectable}. + // */ + // select?: Array; + + /** + * The fields to add to each document, specified as a {@link @firebase/firestore/pipelines#Selectable}. + */ + addFields?: Selectable[]; + + // TODO(search) enable with backend support + // /** + // * Define the query expansion behavior used by full-text search expressions + // * in this search stage. + // */ + // queryEnhancement?: QueryEnhancement; +}; /** * Options defining how a ReplaceWithStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(replaceWith:1)}. */ diff --git a/packages/firestore/src/util/pipeline_util.ts b/packages/firestore/src/util/pipeline_util.ts index d191e08e10..9f91ca8240 100644 --- a/packages/firestore/src/util/pipeline_util.ts +++ b/packages/firestore/src/util/pipeline_util.ts @@ -36,10 +36,20 @@ import { isPlainObject } from './input_validation'; import { isFirestoreValue } from './proto'; import { isString } from './types'; +/** + * @deprecated use selectablesToObject instead + * @param selectables + */ export function selectablesToMap( selectables: Array ): Map { - const result = new Map(); + return new Map(Object.entries(selectablesToObject(selectables))); +} + +export function selectablesToObject( + selectables: Array +): Record { + const result: Record = {}; for (const selectable of selectables) { let alias: string; let expression: Expression; @@ -56,14 +66,14 @@ export function selectablesToMap( fail(0x5319, '`selectable` has an unsupported type', { selectable }); } - if (result.get(alias) !== undefined) { + if (result[alias] !== undefined) { throw new FirestoreError( 'invalid-argument', `Duplicate alias or field '${alias}'` ); } - result.set(alias, expression); + result[alias] = expression; } return result; } diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 03195a3401..0707a8ebb4 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -15,6 +15,11 @@ * limitations under the License. */ +// TODO(search) remove this eslint directive when we migrate the search tests +// to the IndexTestHelper. For now, we want to keep the test data identical between +// search tests. +/* eslint-disable camelcase -- use consistent field names for the search tests */ + import { FirebaseError } from '@firebase/util'; import { expect, use } from 'chai'; import chaiAsPromised from 'chai-as-promised'; @@ -38,9 +43,10 @@ import { writeBatch, addDoc, DocumentReference, - deleteDoc + deleteDoc, + getDocs } from '../util/firebase_export'; -import { apiDescribe, withTestCollection } from '../util/helpers'; +import { apiDescribe, withTestCollection, withTestDbs } from '../util/helpers'; import { array, mod, @@ -176,172 +182,182 @@ import { type, isType, coalesce, - ifNull + ifNull, + score, + documentMatches } from '../util/pipeline_export'; +import { + getRunEnterpriseTests, + getTargetBackend, + TargetBackend +} from '../util/settings'; use(chaiAsPromised); const timestampDeltaMS = 10000; +let beginDocCreation: number = 0; +let endDocCreation: number = 0; + +async function testCollectionWithDocs( + collection: CollectionReference, + docs: { [id: string]: DocumentData } +): Promise> { + beginDocCreation = new Date().valueOf(); + for (const id in docs) { + if (docs.hasOwnProperty(id)) { + const ref = doc(collection, id); + await setDoc(ref, docs[id]); + } + } + endDocCreation = new Date().valueOf(); + return collection; +} + +function expectResults(snapshot: PipelineSnapshot, ...docs: string[]): void; +function expectResults( + snapshot: PipelineSnapshot, + ...data: DocumentData[] +): void; + +function expectResults( + snapshot: PipelineSnapshot, + ...data: DocumentData[] | string[] +): void { + const docs = snapshot.results; + + expect(docs.length).to.equal(data.length); + + if (data.length > 0) { + if (typeof data[0] === 'string') { + const actualIds = docs.map(doc => doc.id); + expect(actualIds).to.deep.equal(data); + } else { + docs.forEach(r => { + expect(r.data()).to.deep.equal(data.shift()); + }); + } + } +} + apiDescribe.skipClassic('Pipelines', persistence => { addEqualityMatcher(); let firestore: Firestore; let randomCol: CollectionReference; - let beginDocCreation: number = 0; - let endDocCreation: number = 0; - - async function testCollectionWithDocs(docs: { - [id: string]: DocumentData; - }): Promise> { - beginDocCreation = new Date().valueOf(); - for (const id in docs) { - if (docs.hasOwnProperty(id)) { - const ref = doc(randomCol, id); - await setDoc(ref, docs[id]); - } - } - endDocCreation = new Date().valueOf(); - return randomCol; - } - function expectResults(snapshot: PipelineSnapshot, ...docs: string[]): void; - function expectResults( - snapshot: PipelineSnapshot, - ...data: DocumentData[] - ): void; - - function expectResults( - snapshot: PipelineSnapshot, - ...data: DocumentData[] | string[] - ): void { - const docs = snapshot.results; - - expect(docs.length).to.equal(data.length); - - if (data.length > 0) { - if (typeof data[0] === 'string') { - const actualIds = docs.map(doc => doc.id); - expect(actualIds).to.deep.equal(data); - } else { - docs.forEach(r => { - expect(r.data()).to.deep.equal(data.shift()); - }); - } + const bookDocs: { [id: string]: DocumentData } = { + book1: { + title: "The Hitchhiker's Guide to the Galaxy", + author: 'Douglas Adams', + genre: 'Science Fiction', + published: 1979, + rating: 4.2, + tags: ['comedy', 'space', 'adventure'], + awards: { + hugo: true, + nebula: false, + others: { unknown: { year: 1980 } } + }, + nestedField: { 'level.1': { 'level.2': true } }, + embedding: vector([10, 1, 1, 1, 1, 1, 1, 1, 1, 1]) + }, + book2: { + title: 'Pride and Prejudice', + author: 'Jane Austen', + genre: 'Romance', + published: 1813, + rating: 4.5, + tags: ['classic', 'social commentary', 'love'], + awards: { none: true }, + embedding: vector([1, 10, 1, 1, 1, 1, 1, 1, 1, 1]) + }, + book3: { + title: 'One Hundred Years of Solitude', + author: 'Gabriel García Márquez', + genre: 'Magical Realism', + published: 1967, + rating: 4.3, + tags: ['family', 'history', 'fantasy'], + awards: { nobel: true, nebula: false }, + embedding: vector([1, 1, 10, 1, 1, 1, 1, 1, 1, 1]) + }, + book4: { + title: 'The Lord of the Rings', + author: 'J.R.R. Tolkien', + genre: 'Fantasy', + published: 1954, + rating: 4.7, + tags: ['adventure', 'magic', 'epic'], + awards: { hugo: false, nebula: false }, + remarks: null, + cost: NaN, + embedding: vector([1, 1, 1, 10, 1, 1, 1, 1, 1, 1]) + }, + book5: { + title: "The Handmaid's Tale", + author: 'Margaret Atwood', + genre: 'Dystopian', + published: 1985, + rating: 4.1, + tags: ['feminism', 'totalitarianism', 'resistance'], + awards: { 'arthur c. clarke': true, 'booker prize': false }, + embedding: vector([1, 1, 1, 1, 10, 1, 1, 1, 1, 1]) + }, + book6: { + title: 'Crime and Punishment', + author: 'Fyodor Dostoevsky', + genre: 'Psychological Thriller', + published: 1866, + rating: 4.3, + tags: ['philosophy', 'crime', 'redemption'], + awards: { none: true }, + embedding: vector([1, 1, 1, 1, 1, 10, 1, 1, 1, 1]) + }, + book7: { + title: 'To Kill a Mockingbird', + author: 'Harper Lee', + genre: 'Southern Gothic', + published: 1960, + rating: 4.2, + tags: ['racism', 'injustice', 'coming-of-age'], + awards: { pulitzer: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 10, 1, 1, 1]) + }, + book8: { + title: '1984', + author: 'George Orwell', + genre: 'Dystopian', + published: 1949, + rating: 4.2, + tags: ['surveillance', 'totalitarianism', 'propaganda'], + awards: { prometheus: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 1, 10, 1, 1]) + }, + book9: { + title: 'The Great Gatsby', + author: 'F. Scott Fitzgerald', + genre: 'Modernist', + published: 1925, + rating: 4.0, + tags: ['wealth', 'american dream', 'love'], + awards: { none: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 1, 1, 10, 1]) + }, + book10: { + title: 'Dune', + author: 'Frank Herbert', + genre: 'Science Fiction', + published: 1965, + rating: 4.6, + tags: ['politics', 'desert', 'ecology'], + awards: { hugo: true, nebula: true }, + embedding: vector([1, 1, 1, 1, 1, 1, 1, 1, 1, 10]) } - } + }; - async function setupBookDocs(): Promise> { - const bookDocs: { [id: string]: DocumentData } = { - book1: { - title: "The Hitchhiker's Guide to the Galaxy", - author: 'Douglas Adams', - genre: 'Science Fiction', - published: 1979, - rating: 4.2, - tags: ['comedy', 'space', 'adventure'], - awards: { - hugo: true, - nebula: false, - others: { unknown: { year: 1980 } } - }, - nestedField: { 'level.1': { 'level.2': true } }, - embedding: vector([10, 1, 1, 1, 1, 1, 1, 1, 1, 1]) - }, - book2: { - title: 'Pride and Prejudice', - author: 'Jane Austen', - genre: 'Romance', - published: 1813, - rating: 4.5, - tags: ['classic', 'social commentary', 'love'], - awards: { none: true }, - embedding: vector([1, 10, 1, 1, 1, 1, 1, 1, 1, 1]) - }, - book3: { - title: 'One Hundred Years of Solitude', - author: 'Gabriel García Márquez', - genre: 'Magical Realism', - published: 1967, - rating: 4.3, - tags: ['family', 'history', 'fantasy'], - awards: { nobel: true, nebula: false }, - embedding: vector([1, 1, 10, 1, 1, 1, 1, 1, 1, 1]) - }, - book4: { - title: 'The Lord of the Rings', - author: 'J.R.R. Tolkien', - genre: 'Fantasy', - published: 1954, - rating: 4.7, - tags: ['adventure', 'magic', 'epic'], - awards: { hugo: false, nebula: false }, - remarks: null, - cost: NaN, - embedding: vector([1, 1, 1, 10, 1, 1, 1, 1, 1, 1]) - }, - book5: { - title: "The Handmaid's Tale", - author: 'Margaret Atwood', - genre: 'Dystopian', - published: 1985, - rating: 4.1, - tags: ['feminism', 'totalitarianism', 'resistance'], - awards: { 'arthur c. clarke': true, 'booker prize': false }, - embedding: vector([1, 1, 1, 1, 10, 1, 1, 1, 1, 1]) - }, - book6: { - title: 'Crime and Punishment', - author: 'Fyodor Dostoevsky', - genre: 'Psychological Thriller', - published: 1866, - rating: 4.3, - tags: ['philosophy', 'crime', 'redemption'], - awards: { none: true }, - embedding: vector([1, 1, 1, 1, 1, 10, 1, 1, 1, 1]) - }, - book7: { - title: 'To Kill a Mockingbird', - author: 'Harper Lee', - genre: 'Southern Gothic', - published: 1960, - rating: 4.2, - tags: ['racism', 'injustice', 'coming-of-age'], - awards: { pulitzer: true }, - embedding: vector([1, 1, 1, 1, 1, 1, 10, 1, 1, 1]) - }, - book8: { - title: '1984', - author: 'George Orwell', - genre: 'Dystopian', - published: 1949, - rating: 4.2, - tags: ['surveillance', 'totalitarianism', 'propaganda'], - awards: { prometheus: true }, - embedding: vector([1, 1, 1, 1, 1, 1, 1, 10, 1, 1]) - }, - book9: { - title: 'The Great Gatsby', - author: 'F. Scott Fitzgerald', - genre: 'Modernist', - published: 1925, - rating: 4.0, - tags: ['wealth', 'american dream', 'love'], - awards: { none: true }, - embedding: vector([1, 1, 1, 1, 1, 1, 1, 1, 10, 1]) - }, - book10: { - title: 'Dune', - author: 'Frank Herbert', - genre: 'Science Fiction', - published: 1965, - rating: 4.6, - tags: ['politics', 'desert', 'ecology'], - awards: { hugo: true, nebula: true }, - embedding: vector([1, 1, 1, 1, 1, 1, 1, 1, 1, 10]) - } - }; - return testCollectionWithDocs(bookDocs); + async function setupTestDocs(): Promise { + return testCollectionWithDocs(randomCol, bookDocs); } let testDeferred: Deferred | undefined; @@ -356,7 +372,7 @@ apiDescribe.skipClassic('Pipelines', persistence => { async (collectionRef, firestoreInstance) => { randomCol = collectionRef; firestore = firestoreInstance; - await setupBookDocs(); + await setupTestDocs(); setupDeferred.resolve(); return testDeferred?.promise; @@ -5807,3 +5823,658 @@ apiDescribe.skipClassic('Pipelines', persistence => { }); }); }); + +(getRunEnterpriseTests() && getTargetBackend() === TargetBackend.NIGHTLY + ? apiDescribe + : apiDescribe.skip)('Pipeline search', persistence => { + addEqualityMatcher(); + let firestore: Firestore; + let restaurantsCollection: CollectionReference; + + const COLLECTION_NAME = 'TextSearchIntegrationTests'; + + async function setupRestaurantDocs( + collection: CollectionReference + ): Promise> { + const restaurantDocs: { [id: string]: DocumentData } = { + sunnySideUp: { + name: 'The Sunny Side Up', + description: + 'A cozy neighborhood diner serving classic breakfast favorites all day long, from fluffy pancakes to savory omelets.', + location: new GeoPoint(39.7541, -105.0002), + menu: '

    Breakfast Classics

    • Denver Omelet - $12
    • Buttermilk Pancakes - $10
    • Steak and Eggs - $16

    Sides

    • Hash Browns - $4
    • Thick-cut Bacon - $5
    • Drip Coffee - $2
    ', + average_price_per_person: 15 + }, + goldenWaffle: { + name: 'The Golden Waffle', + description: + 'Specializing exclusively in Belgian-style waffles. Open daily from 6:00 AM to 11:00 AM.', + location: new GeoPoint(39.7183, -104.9621), + menu: '

    Signature Waffles

    • Strawberry Delight - $11
    • Chicken and Waffles - $14
    • Chocolate Chip Crunch - $10

    Drinks

    • Fresh OJ - $4
    • Artisan Coffee - $3
    ', + average_price_per_person: 13 + }, + lotusBlossomThai: { + name: 'Lotus Blossom Thai', + description: + 'Authentic Thai cuisine featuring hand-crushed spices and traditional family recipes from the Chiang Mai region.', + location: new GeoPoint(39.7315, -104.9847), + menu: '

    Appetizers

    • Spring Rolls - $7
    • Chicken Satay - $9

    Main Course

    • Pad Thai - $15
    • Green Curry - $16
    • Drunken Noodles - $15
    ', + average_price_per_person: 22 + }, + mileHighCatch: { + name: 'Mile High Catch', + description: + 'Freshly sourced seafood offering a wide variety of Pacific fish and Atlantic shellfish in an upscale atmosphere.', + location: new GeoPoint(39.7401, -104.9903), + menu: '

    From the Raw Bar

    • Oysters (Half Dozen) - $18
    • Lobster Cocktail - $22

    Entrees

    • Pan-Seared Salmon - $28
    • King Crab Legs - $45
    • Fish and Chips - $19
    ', + average_price_per_person: 45 + }, + peakBurgers: { + name: 'Peak Burgers', + description: + 'Casual burger joint focused on locally sourced Colorado beef and hand-cut fries.', + location: new GeoPoint(39.7622, -105.0125), + menu: '

    Burgers

    • The Peak Double - $12
    • Bison Burger - $15
    • Veggie Stack - $11

    Sides

    • Truffle Fries - $6
    • Onion Rings - $5
    ', + average_price_per_person: 18 + }, + solTacos: { + name: 'El Sol Tacos', + description: + 'A vibrant street-side taco stand serving up quick, delicious, and traditional Mexican street food.', + location: new GeoPoint(39.6952, -105.0274), + menu: '

    Tacos ($3.50 each)

    • Al Pastor
    • Carne Asada
    • Pollo Asado
    • Nopales (Cactus)

    Beverages

    • Horchata - $4
    • Mexican Coke - $3
    ', + average_price_per_person: 12 + }, + eastsideTacos: { + name: 'Eastside Cantina', + description: + 'Authentic street tacos and hand-shaken margaritas on the vibrant east side of the city.', + location: new GeoPoint(39.735, -104.885), + menu: '

    Tacos

    • Carnitas Tacos - $4
    • Barbacoa Tacos - $4.50
    • Shrimp Tacos - $5

    Drinks

    • House Margarita - $9
    • Jarritos - $3
    ', + average_price_per_person: 18 + }, + eastsideChicken: { + name: 'Eastside Chicken', + description: 'Fried chicken to go - next to Eastside Cantina.', + location: new GeoPoint(39.735, -104.885), + menu: '

    Fried Chicken

    • Drumstick - $4
    • Wings - $1
    • Sandwich - $9

    Drinks

    • House Margarita - $9
    • Jarritos - $3
    ', + average_price_per_person: 12 + } + }; + + // TODO(search) - Migrate this over to IndexTestHelper when search supports the equal filter. + // Remove any restaurant docs not in the expected set - perhaps these were + // set by another dev or test suite. This has potential to cause flakes in another concurrent + // run of these tests, if they have added new test docs. + const collectionSnapshot = await getDocs(collection); + const expectedDocIds = Object.keys(restaurantDocs); + const deletes = collectionSnapshot.docs + .filter(ds => expectedDocIds.indexOf(ds.id) < 0) + .map(ds => deleteDoc(ds.ref)); + await Promise.all(deletes); + + // Add/overwrite all restaurant docs + return testCollectionWithDocs(collection, restaurantDocs); + } + + // Resolves in `after` indicating the test suite has finished. + // The function passed to withTestDbsPromise will await this promise, + // meaning the firestore instance created by withTestDbsSettings will + // not be disposed until this is resolved (after the test suite finished). + let testSuiteDeferred: Deferred | undefined; + + // Resolves when withTestDbsPromise resolves, indicating that the + // resources this method created have been disposed and the next test suite + // can begin. + let withTestDbsPromise: Promise | undefined; + + // Search tests will use restaurant docs + before(async () => { + // TODO(search) - Migrate this over to IndexTestHelper when search supports the equal filter. + // Note: using a static collection of documents for every search test has an inherent risk + // of flakiness. Search requires an index on the collection, which is the reason we use a pre-defined + // collection. We cannot use the IndexTestHelper because that relies on an equality match to the testID + // field. Search currently does not support the equal expression. + + const setupDeferred = new Deferred(); + testSuiteDeferred = new Deferred(); + withTestDbsPromise = withTestDbs( + persistence, + 1, + async firestoreInstance => { + firestore = firestoreInstance[0]; + restaurantsCollection = collection(firestore, 'SearchIntegrationTests'); + await setupRestaurantDocs(restaurantsCollection); + setupDeferred.resolve(); + + return testSuiteDeferred?.promise; + } + ); + + await setupDeferred.promise; + }); + + after(async () => { + testSuiteDeferred?.resolve(); + await withTestDbsPromise; + }); + + describe('search stage', () => { + describe('DISABLE query expansion', () => { + describe('query', () => { + // TODO(search) enable with backend support + // it('all search features', async () => { + // const queryLocation = new GeoPoint(0, 0); + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: and( + // documentMatches('waffles'), + // field('description').matches('breakfast'), + // field('location').geoDistance(queryLocation).lessThan(1000), + // field('avgPrice').between(10, 20) + // ), + // select: [ + // field('title'), + // field('menu'), + // field('description'), + // field('location').geoDistance(queryLocation).as('distance') + // ], + // addFields: [score().as('searchScore')], + // offset: 0, + // retrievalDepth: 1000, + // limit: 50, + // sort: [field('location').geoDistance(queryLocation).ascending()], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'goldenWaffle'); + // }); + + it('search full document', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: documentMatches('waffles') + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults(snapshot, 'goldenWaffle'); + }); + + // TODO(search) enable with backend support + // it('search a specific field', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches('waffles'), + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'goldenWaffle'); + // }); + + it('geo near query', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: field('location') + .geoDistance(new GeoPoint(39.6985, -105.024)) + .lessThanOrEqual(1000 /* m */) + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults(snapshot, 'solTacos'); + }); + + // TODO(search) enable with backend support + // it('conjunction of text search predicates', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: and( + // field('menu').matches('waffles'), + // field('description').matches('diner') + // ), + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'goldenWaffle', 'sunnySideUp'); + // }); + + // TODO(search) enable with backend support + // it('conjunction of text search and geo near', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: and( + // field('menu').matches('tacos'), + // field('location') + // .geoDistance(new GeoPoint(39.6985, -105.024)) + // .lessThan(10_000 /* meters */) + // ), + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'solTacos'); + // }); + + it('negate match', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: documentMatches('coffee -waffles') + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults(snapshot, 'sunnySideUp'); + }); + + // TODO(search) enable with backend support + // it('rquery search the document with conjunction and disjunction', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: documentMatches('(waffles OR pancakes) AND coffee'), + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'goldenWaffle', 'sunnySideUp'); + // }); + + it('rquery as query param', async () => { + const ppl = firestore.pipeline().collection(COLLECTION_NAME).search({ + query: 'chicken wings' + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults(snapshot, 'eastsideChicken'); + }); + + // TODO(search) enable with backend support + // it('rquery supports field paths', async () => { + // const ppl = firestore.pipeline().collection(COLLECTION_NAME).search({ + // query: + // 'menu:(waffles OR pancakes) AND description:"breakfast all day"', + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'sunnySideUp'); + // }); + + // TODO(search) enable with backend support + // it('conjunction of rquery and expression', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: and( + // documentMatches('tacos'), + // field('average_price_per_person').between(8, 15) + // ), + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'solTacos'); + // }); + }); + + describe('addFields', () => { + it('supports score', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: documentMatches('waffles'), + addFields: [score().as('searchScore')] + // queryEnhancement: 'disabled' + }) + .select('name', 'searchScore'); + + const snapshot = await execute(ppl); + expect(snapshot.results.length).to.equal(1); + expect(snapshot.results[0].get('name')).to.equal('The Golden Waffle'); + expect(snapshot.results[0].get('searchScore')).to.be.greaterThan(0); + }); + + // TODO(search) enable with backend support + // it('supports multiple fields', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: documentMatches('waffles'), + // addFields: [ + // score().as('searchScore'), + // field('menu').snippet('waffles').as('snippet') + // ], + // queryEnhancement: 'disabled' + // }) + // .select('name', 'searchScore', 'snippet'); + // + // const snapshot = await execute(ppl); + // expect(snapshot.results.length).to.equal(1); + // expect(snapshot.results[0].get('name')).to.equal('The Golden Waffle'); + // expect(snapshot.results[0].get('searchScore')).to.be.greaterThan(0); + // expect(snapshot.results[0].get('snippet')?.length).to.be.greaterThan( + // 0 + // ); + // }); + }); + + // TODO(search) enable with backend support + // describe('select', () => { + // it('topicality score and snippet', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches('waffles'), + // select: [ + // field('name'), + // 'location', + // score().as('searchScore'), + // field('menu').snippet('waffles').as('snippet') + // ], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expect(snapshot.results.length).to.equal(1); + // expect(snapshot.results[0].get('name')).to.equal('The Golden Waffle'); + // expect(snapshot.results[0].get('location')).to.equal( + // new GeoPoint(39.7183, -104.9621) + // ); + // expect(snapshot.results[0].get('searchScore')).to.be.greaterThan(0); + // expect(snapshot.results[0].get('snippet')?.length).to.be.greaterThan( + // 0 + // ); + // expect(Object.keys(snapshot.results[0].data()).sort()).to.deep.equal([ + // 'location', + // 'name', + // 'searchScore', + // 'snippet' + // ]); + // }); + // }); + + describe('sort', () => { + it('by score', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: documentMatches('tacos'), + sort: score().descending() + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults(snapshot, 'eastsideTacos', 'solTacos'); + }); + + it('by distance', async () => { + const queryLocation = new GeoPoint(39.6985, -105.024); + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: field('location') + .geoDistance(queryLocation) + .lessThanOrEqual(5600), + sort: field('location').geoDistance(queryLocation).ascending() + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults( + snapshot, + 'solTacos', + 'lotusBlossomThai', + 'mileHighCatch' + ); + }); + + // TODO(search) enable with backend support + // it('by multiple orderings', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches('tacos OR chicken'), + // sort: [ + // field('location') + // .geoDistance(new GeoPoint(39.6985, -105.024)) + // .ascending(), + // score().descending() + // ], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults( + // snapshot, + // 'solTacos', + // 'eastsideTacos', + // 'eastsideChicken' + // ); + // }); + }); + + // TODO(search) enable with backend support + // describe('limit', () => { + // it('limits the number of documents returned', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: constant(true), + // sort: field('location') + // .geoDistance(new GeoPoint(39.6985, -105.024)) + // .ascending(), + // limit: 5, + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults( + // snapshot, + // 'solTacos', + // 'lotusBlossomThai', + // 'goldenWaffle' + // ); + // }); + // + // it('limits the number of documents scored', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches( + // 'chicken OR tacos OR fish OR waffles' + // ), + // retrievalDepth: 6, + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults( + // snapshot, + // 'eastsideChicken', + // 'eastsideTacos', + // 'solTacos', + // 'mileHighCatch' + // ); + // }); + // }); + + // TODO(search) enable with backend support + // describe('offset', () => { + // it('skips N documents', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: constant(true), + // limit: 2, + // offset: 2, + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'eastsideChicken', 'eastsideTacos'); + // }); + // }); + }); + + // TODO(search) enable with backend support + // describe('REQUIRE query expansion', () => { + // it('search full document', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: documentMatches('waffles'), + // queryEnhancement: 'required' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'goldenWaffle', 'sunnySideUp'); + // }); + // + // it('search a specific field', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches('waffles'), + // queryEnhancement: 'required' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'goldenWaffle', 'sunnySideUp'); + // }); + // }); + }); + + // TODO(search) enable with backend support + // describe('snippet', () => { + // it('snippet options', async () => { + // const ppl1 = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches('waffles'), + // addFields: [ + // field('menu') + // .snippet({ + // rquery: 'waffles', + // maxSnippetWidth: 10 + // }) + // .as('snippet') + // ], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot1 = await execute(ppl1); + // expect(snapshot1.results.length).to.equal(1); + // expect(snapshot1.results[0].get('name')).to.equal('The Golden Waffle'); + // expect(snapshot1.results[0].get('snippet')?.length).to.be.greaterThan(0); + // + // const ppl2 = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches('waffles'), + // addFields: [ + // field('menu') + // .snippet({ + // rquery: 'waffles', + // maxSnippetWidth: 1000 + // }) + // .as('snippet') + // ], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot2 = await execute(ppl2); + // expect(snapshot2.results.length).to.equal(1); + // expect(snapshot2.results[0].get('name')).to.equal('The Golden Waffle'); + // expect(snapshot2.results[0].get('snippet')?.length).to.be.greaterThan(0); + // + // expect(snapshot2.results[0].get('snippet')?.length).to.be.greaterThan( + // snapshot2.results[0].get('snippet')?.length + // ); + // }); + // + // it('snippet on multiple fields', async () => { + // // Get snippet from 1 field + // const ppl1 = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: documentMatches('waffle'), + // addFields: [ + // field('menu') + // .snippet({ + // rquery: 'waffles', + // maxSnippetWidth: 2000 + // }) + // .as('snippet') + // ], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot1 = await execute(ppl1); + // expect(snapshot1.results.length).to.equal(1); + // expect(snapshot1.results[0].get('name')).to.equal('The Golden Waffle'); + // expect(snapshot1.results[0].get('snippet')?.length).to.be.greaterThan(0); + // + // // Get snippet from 2 fields + // const ppl2 = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: documentMatches('waffle'), + // addFields: [ + // concat(field('menu'), field('description')) + // .snippet({ + // rquery: 'waffles', + // maxSnippetWidth: 2000 + // }) + // .as('snippet') + // ], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot2 = await execute(ppl2); + // expect(snapshot2.results.length).to.equal(1); + // expect(snapshot2.results[0].get('name')).to.equal('The Golden Waffle'); + // expect(snapshot2.results[0].get('snippet')?.length).to.be.greaterThan(0); + // + // // Expect snippet from 2 fields to be longer than snippet from one field + // expect(snapshot2.results[0].get('snippet')?.length).to.be.greaterThan( + // snapshot2.results[0].get('snippet')?.length + // ); + // }); + // }); +}); diff --git a/packages/firestore/test/integration/util/settings.ts b/packages/firestore/test/integration/util/settings.ts index b47232730a..7e4cee939c 100644 --- a/packages/firestore/test/integration/util/settings.ts +++ b/packages/firestore/test/integration/util/settings.ts @@ -25,7 +25,7 @@ import { PrivateSettings } from './firebase_export'; // eslint-disable-next-line @typescript-eslint/no-explicit-any declare const __karma__: any; -enum TargetBackend { +export enum TargetBackend { EMULATOR = 'emulator', QA = 'qa', NIGHTLY = 'nightly', @@ -37,8 +37,6 @@ const PROJECT_CONFIG = require('../../../../../config/project.json'); export const TARGET_DB_ID: string | '(default)' = getTargetDbId(); -export const RUN_ENTERPRISE_TESTS: boolean = getRunEnterpriseTests(); - const TARGET_BACKEND: TargetBackend = getTargetBackend(); export const USE_EMULATOR: boolean = TARGET_BACKEND === TargetBackend.EMULATOR; @@ -64,7 +62,7 @@ function getTargetDbId(): string | '(default)' { return '(default)'; } -function getRunEnterpriseTests(): boolean { +export function getRunEnterpriseTests(): boolean { const karma = typeof __karma__ !== 'undefined' ? __karma__ : undefined; if (karma && karma.config.firestoreEdition === 'enterprise') { return true; @@ -89,7 +87,7 @@ function parseTargetBackend(targetBackend: string): TargetBackend { } } -function getTargetBackend(): TargetBackend { +export function getTargetBackend(): TargetBackend { const karma = typeof __karma__ !== 'undefined' ? __karma__ : undefined; if (karma && karma.config.targetBackend) { return parseTargetBackend(karma.config.targetBackend); diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index f5e2047607..24a548ff2a 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -15,6 +15,8 @@ * limitations under the License. */ +/* eslint-disable camelcase -- use consistent field names for the search tests */ + // eslint-disable-next-line import/no-extraneous-dependencies import { FirebaseError } from '@firebase/util'; import { expect, use } from 'chai'; @@ -41,15 +43,25 @@ import { doc, DocumentReference } from '../../src/lite-api/reference'; -import { addDoc, setDoc, deleteDoc } from '../../src/lite-api/reference_impl'; +import { + addDoc, + setDoc, + deleteDoc, + getDocs +} from '../../src/lite-api/reference_impl'; import { FindNearestStageOptions } from '../../src/lite-api/stage_options'; import { Timestamp } from '../../src/lite-api/timestamp'; import { writeBatch } from '../../src/lite-api/write_batch'; +import { + getRunEnterpriseTests, + getTargetBackend, + TargetBackend +} from '../integration/util/settings'; import { addEqualityMatcher } from '../util/equality_matcher'; import { describe } from '../util/mocha_extensions'; import { Deferred } from '../util/promise'; -import { withTestCollection } from './helpers'; +import { withTestCollection, withTestDb } from './helpers'; import { field, and, @@ -180,60 +192,64 @@ import { arrayIndexOf, arrayIndexOfAll, arrayLastIndexOf, - ifNull + ifNull, + documentMatches, + score } from './pipeline_export'; use(chaiAsPromised); const timestampDeltaMS = 10000; +let beginDocCreation: number = 0; +let endDocCreation: number = 0; + +async function testCollectionWithDocs( + collection: CollectionReference, + docs: { [id: string]: DocumentData } +): Promise> { + beginDocCreation = new Date().valueOf(); + for (const id in docs) { + if (docs.hasOwnProperty(id)) { + const ref = doc(collection, id); + await setDoc(ref, docs[id]); + } + } + endDocCreation = new Date().valueOf(); + return collection; +} + +function expectResults(snapshot: PipelineSnapshot, ...docs: string[]): void; +function expectResults( + snapshot: PipelineSnapshot, + ...data: DocumentData[] +): void; + +function expectResults( + snapshot: PipelineSnapshot, + ...data: DocumentData[] | string[] +): void { + const docs = snapshot.results; + + expect(docs.length).to.equal(data.length); + + if (data.length > 0) { + if (typeof data[0] === 'string') { + const actualIds = docs.map(doc => doc.id); + expect(actualIds).to.deep.equal(data); + } else { + docs.forEach(r => { + expect(r.data()).to.deep.equal(data.shift()); + }); + } + } +} + describe.skipClassic('Firestore Pipelines', () => { addEqualityMatcher(); let firestore: Firestore; let randomCol: CollectionReference; - let beginDocCreation: number = 0; - let endDocCreation: number = 0; - - async function testCollectionWithDocs(docs: { - [id: string]: DocumentData; - }): Promise> { - beginDocCreation = new Date().valueOf(); - for (const id in docs) { - if (docs.hasOwnProperty(id)) { - const ref = doc(randomCol, id); - await setDoc(ref, docs[id]); - } - } - endDocCreation = new Date().valueOf(); - return randomCol; - } - - function expectResults(snapshot: PipelineSnapshot, ...docs: string[]): void; - function expectResults( - snapshot: PipelineSnapshot, - ...data: DocumentData[] - ): void; - - function expectResults( - snapshot: PipelineSnapshot, - ...data: DocumentData[] | string[] - ): void { - const docs = snapshot.results; - - expect(docs.length).to.equal(data.length); - - if (data.length > 0) { - if (typeof data[0] === 'string') { - const actualIds = docs.map(doc => doc.id); - expect(actualIds).to.deep.equal(data); - } else { - docs.forEach(r => { - expect(r.data()).to.deep.equal(data.shift()); - }); - } - } - } async function setupBookDocs(): Promise> { const bookDocs: { [id: string]: DocumentData } = { @@ -345,7 +361,7 @@ describe.skipClassic('Firestore Pipelines', () => { embedding: vector([1, 1, 1, 1, 1, 1, 1, 1, 1, 10]) } }; - return testCollectionWithDocs(bookDocs); + return testCollectionWithDocs(randomCol, bookDocs); } let testDeferred: Deferred | undefined; @@ -5679,3 +5695,655 @@ describe.skipClassic('Firestore Pipelines', () => { }); }); }); + +(getRunEnterpriseTests() && getTargetBackend() === TargetBackend.NIGHTLY + ? describe + : /* eslint-disable-next-line -- okay to skip tests */ + describe.skip)('Pipeline search', () => { + addEqualityMatcher(); + let firestore: Firestore; + let restaurantsCollection: CollectionReference; + + const COLLECTION_NAME = 'TextSearchIntegrationTests'; + + async function setupRestaurantDocs( + collection: CollectionReference + ): Promise> { + const restaurantDocs: { [id: string]: DocumentData } = { + sunnySideUp: { + name: 'The Sunny Side Up', + description: + 'A cozy neighborhood diner serving classic breakfast favorites all day long, from fluffy pancakes to savory omelets.', + location: new GeoPoint(39.7541, -105.0002), + menu: '

    Breakfast Classics

    • Denver Omelet - $12
    • Buttermilk Pancakes - $10
    • Steak and Eggs - $16

    Sides

    • Hash Browns - $4
    • Thick-cut Bacon - $5
    • Drip Coffee - $2
    ', + average_price_per_person: 15 + }, + goldenWaffle: { + name: 'The Golden Waffle', + description: + 'Specializing exclusively in Belgian-style waffles. Open daily from 6:00 AM to 11:00 AM.', + location: new GeoPoint(39.7183, -104.9621), + menu: '

    Signature Waffles

    • Strawberry Delight - $11
    • Chicken and Waffles - $14
    • Chocolate Chip Crunch - $10

    Drinks

    • Fresh OJ - $4
    • Artisan Coffee - $3
    ', + average_price_per_person: 13 + }, + lotusBlossomThai: { + name: 'Lotus Blossom Thai', + description: + 'Authentic Thai cuisine featuring hand-crushed spices and traditional family recipes from the Chiang Mai region.', + location: new GeoPoint(39.7315, -104.9847), + menu: '

    Appetizers

    • Spring Rolls - $7
    • Chicken Satay - $9

    Main Course

    • Pad Thai - $15
    • Green Curry - $16
    • Drunken Noodles - $15
    ', + average_price_per_person: 22 + }, + mileHighCatch: { + name: 'Mile High Catch', + description: + 'Freshly sourced seafood offering a wide variety of Pacific fish and Atlantic shellfish in an upscale atmosphere.', + location: new GeoPoint(39.7401, -104.9903), + menu: '

    From the Raw Bar

    • Oysters (Half Dozen) - $18
    • Lobster Cocktail - $22

    Entrees

    • Pan-Seared Salmon - $28
    • King Crab Legs - $45
    • Fish and Chips - $19
    ', + average_price_per_person: 45 + }, + peakBurgers: { + name: 'Peak Burgers', + description: + 'Casual burger joint focused on locally sourced Colorado beef and hand-cut fries.', + location: new GeoPoint(39.7622, -105.0125), + menu: '

    Burgers

    • The Peak Double - $12
    • Bison Burger - $15
    • Veggie Stack - $11

    Sides

    • Truffle Fries - $6
    • Onion Rings - $5
    ', + average_price_per_person: 18 + }, + solTacos: { + name: 'El Sol Tacos', + description: + 'A vibrant street-side taco stand serving up quick, delicious, and traditional Mexican street food.', + location: new GeoPoint(39.6952, -105.0274), + menu: '

    Tacos ($3.50 each)

    • Al Pastor
    • Carne Asada
    • Pollo Asado
    • Nopales (Cactus)

    Beverages

    • Horchata - $4
    • Mexican Coke - $3
    ', + average_price_per_person: 12 + }, + eastsideTacos: { + name: 'Eastside Cantina', + description: + 'Authentic street tacos and hand-shaken margaritas on the vibrant east side of the city.', + location: new GeoPoint(39.735, -104.885), + menu: '

    Tacos

    • Carnitas Tacos - $4
    • Barbacoa Tacos - $4.50
    • Shrimp Tacos - $5

    Drinks

    • House Margarita - $9
    • Jarritos - $3
    ', + average_price_per_person: 18 + }, + eastsideChicken: { + name: 'Eastside Chicken', + description: 'Fried chicken to go - next to Eastside Cantina.', + location: new GeoPoint(39.735, -104.885), + menu: '

    Fried Chicken

    • Drumstick - $4
    • Wings - $1
    • Sandwich - $9

    Drinks

    • House Margarita - $9
    • Jarritos - $3
    ', + average_price_per_person: 12 + } + }; + + // TODO(search) - Migrate this over to IndexTestHelper when search supports the equal filter. + // Remove any restaurant docs not in the expected set - perhaps these were + // set by another dev or test suite. This has potential to cause flakes in another concurrent + // run of these tests, if they have added new test docs. + const collectionSnapshot = await getDocs(collection); + const expectedDocIds = Object.keys(restaurantDocs); + const deletes = collectionSnapshot.docs + .filter(ds => expectedDocIds.indexOf(ds.id) < 0) + .map(ds => deleteDoc(ds.ref)); + await Promise.all(deletes); + + // Add/overwrite all restaurant docs + return testCollectionWithDocs(collection, restaurantDocs); + } + + // Resolves in `after` indicating the test suite has finished. + // The function passed to withTestDbsPromise will await this promise, + // meaning the firestore instance created by withTestDbsSettings will + // not be disposed until this is resolved (after the test suite finished). + let testSuiteDeferred: Deferred | undefined; + + // Resolves when withTestDbsPromise resolves, indicating that the + // resources this method created have been disposed and the next test suite + // can begin. + let withTestDbsPromise: Promise | undefined; + + // Search tests will use restaurant docs + before(async () => { + // TODO(search) - Migrate this over to IndexTestHelper when search supports the equal filter. + // Note: using a static collection of documents for every search test has an inherent risk + // of flakiness. Search requires an index on the collection, which is the reason we use a pre-defined + // collection. We cannot use the IndexTestHelper because that relies on an equality match to the testID + // field. Search currently does not support the equal expression. + + const setupDeferred = new Deferred(); + testSuiteDeferred = new Deferred(); + withTestDbsPromise = withTestDb(async firestoreInstance => { + firestore = firestoreInstance; + restaurantsCollection = collection(firestore, 'SearchIntegrationTests'); + await setupRestaurantDocs(restaurantsCollection); + setupDeferred.resolve(); + + return testSuiteDeferred?.promise; + }); + + await setupDeferred.promise; + }); + + after(async () => { + testSuiteDeferred?.resolve(); + await withTestDbsPromise; + }); + + describe('search stage', () => { + describe('DISABLE query expansion', () => { + describe('query', () => { + // TODO(search) enable with backend support + // it('all search features', async () => { + // const queryLocation = new GeoPoint(0, 0); + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: and( + // documentMatches('waffles'), + // field('description').matches('breakfast'), + // field('location').geoDistance(queryLocation).lessThan(1000), + // field('avgPrice').between(10, 20) + // ), + // select: [ + // field('title'), + // field('menu'), + // field('description'), + // field('location').geoDistance(queryLocation).as('distance') + // ], + // addFields: [score().as('searchScore')], + // offset: 0, + // retrievalDepth: 1000, + // limit: 50, + // sort: [field('location').geoDistance(queryLocation).ascending()], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'goldenWaffle'); + // }); + + it('search full document', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: documentMatches('waffles') + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults(snapshot, 'goldenWaffle'); + }); + + // TODO(search) enable with backend support + // it('search a specific field', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches('waffles'), + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'goldenWaffle'); + // }); + + it('geo near query', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: field('location') + .geoDistance(new GeoPoint(39.6985, -105.024)) + .lessThanOrEqual(1000 /* m */) + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults(snapshot, 'solTacos'); + }); + + // TODO(search) enable with backend support + // it('conjunction of text search predicates', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: and( + // field('menu').matches('waffles'), + // field('description').matches('diner') + // ), + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'goldenWaffle', 'sunnySideUp'); + // }); + + // TODO(search) enable with backend support + // it('conjunction of text search and geo near', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: and( + // field('menu').matches('tacos'), + // field('location') + // .geoDistance(new GeoPoint(39.6985, -105.024)) + // .lessThan(10_000 /* meters */) + // ), + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'solTacos'); + // }); + + it('negate match', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: documentMatches('coffee -waffles') + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults(snapshot, 'sunnySideUp'); + }); + + // TODO(search) enable with backend support + // it('rquery search the document with conjunction and disjunction', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: documentMatches('(waffles OR pancakes) AND coffee'), + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'goldenWaffle', 'sunnySideUp'); + // }); + + it('rquery as query param', async () => { + const ppl = firestore.pipeline().collection(COLLECTION_NAME).search({ + query: 'chicken wings' + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults(snapshot, 'eastsideChicken'); + }); + + // TODO(search) enable with backend support + // it('rquery supports field paths', async () => { + // const ppl = firestore.pipeline().collection(COLLECTION_NAME).search({ + // query: + // 'menu:(waffles OR pancakes) AND description:"breakfast all day"', + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'sunnySideUp'); + // }); + + // TODO(search) enable with backend support + // it('conjunction of rquery and expression', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: and( + // documentMatches('tacos'), + // field('average_price_per_person').between(8, 15) + // ), + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'solTacos'); + // }); + }); + + describe('addFields', () => { + it('supports score', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: documentMatches('waffles'), + addFields: [score().as('searchScore')] + // queryEnhancement: 'disabled' + }) + .select('name', 'searchScore'); + + const snapshot = await execute(ppl); + expect(snapshot.results.length).to.equal(1); + expect(snapshot.results[0].get('name')).to.equal('The Golden Waffle'); + expect(snapshot.results[0].get('searchScore')).to.be.greaterThan(0); + }); + + // TODO(search) enable with backend support + // it('supports multiple fields', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: documentMatches('waffles'), + // addFields: [ + // score().as('searchScore'), + // field('menu').snippet('waffles').as('snippet') + // ], + // queryEnhancement: 'disabled' + // }) + // .select('name', 'searchScore', 'snippet'); + // + // const snapshot = await execute(ppl); + // expect(snapshot.results.length).to.equal(1); + // expect(snapshot.results[0].get('name')).to.equal('The Golden Waffle'); + // expect(snapshot.results[0].get('searchScore')).to.be.greaterThan(0); + // expect(snapshot.results[0].get('snippet')?.length).to.be.greaterThan( + // 0 + // ); + // }); + }); + + // TODO(search) enable with backend support + // describe('select', () => { + // it('topicality score and snippet', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches('waffles'), + // select: [ + // field('name'), + // 'location', + // score().as('searchScore'), + // field('menu').snippet('waffles').as('snippet') + // ], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expect(snapshot.results.length).to.equal(1); + // expect(snapshot.results[0].get('name')).to.equal('The Golden Waffle'); + // expect(snapshot.results[0].get('location')).to.equal( + // new GeoPoint(39.7183, -104.9621) + // ); + // expect(snapshot.results[0].get('searchScore')).to.be.greaterThan(0); + // expect(snapshot.results[0].get('snippet')?.length).to.be.greaterThan( + // 0 + // ); + // expect(Object.keys(snapshot.results[0].data()).sort()).to.deep.equal([ + // 'location', + // 'name', + // 'searchScore', + // 'snippet' + // ]); + // }); + // }); + + describe('sort', () => { + it('by score', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: documentMatches('tacos'), + sort: score().descending() + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults(snapshot, 'eastsideTacos', 'solTacos'); + }); + + it('by distance', async () => { + const queryLocation = new GeoPoint(39.6985, -105.024); + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: field('location') + .geoDistance(queryLocation) + .lessThanOrEqual(5600), + sort: field('location').geoDistance(queryLocation).ascending() + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults( + snapshot, + 'solTacos', + 'lotusBlossomThai', + 'mileHighCatch' + ); + }); + + // TODO(search) enable with backend support + // it('by multiple orderings', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches('tacos OR chicken'), + // sort: [ + // field('location') + // .geoDistance(new GeoPoint(39.6985, -105.024)) + // .ascending(), + // score().descending() + // ], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults( + // snapshot, + // 'solTacos', + // 'eastsideTacos', + // 'eastsideChicken' + // ); + // }); + }); + + // TODO(search) enable with backend support + // describe('limit', () => { + // it('limits the number of documents returned', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: constant(true), + // sort: field('location') + // .geoDistance(new GeoPoint(39.6985, -105.024)) + // .ascending(), + // limit: 5, + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults( + // snapshot, + // 'solTacos', + // 'lotusBlossomThai', + // 'goldenWaffle' + // ); + // }); + // + // it('limits the number of documents scored', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches( + // 'chicken OR tacos OR fish OR waffles' + // ), + // retrievalDepth: 6, + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults( + // snapshot, + // 'eastsideChicken', + // 'eastsideTacos', + // 'solTacos', + // 'mileHighCatch' + // ); + // }); + // }); + + // TODO(search) enable with backend support + // describe('offset', () => { + // it('skips N documents', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: constant(true), + // limit: 2, + // offset: 2, + // queryEnhancement: 'disabled' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'eastsideChicken', 'eastsideTacos'); + // }); + // }); + }); + + // TODO(search) enable with backend support + // describe('REQUIRE query expansion', () => { + // it('search full document', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: documentMatches('waffles'), + // queryEnhancement: 'required' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'goldenWaffle', 'sunnySideUp'); + // }); + // + // it('search a specific field', async () => { + // const ppl = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches('waffles'), + // queryEnhancement: 'required' + // }); + // + // const snapshot = await execute(ppl); + // expectResults(snapshot, 'goldenWaffle', 'sunnySideUp'); + // }); + // }); + }); + + // TODO(search) enable with backend support + // describe('snippet', () => { + // it('snippet options', async () => { + // const ppl1 = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches('waffles'), + // addFields: [ + // field('menu') + // .snippet({ + // rquery: 'waffles', + // maxSnippetWidth: 10 + // }) + // .as('snippet') + // ], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot1 = await execute(ppl1); + // expect(snapshot1.results.length).to.equal(1); + // expect(snapshot1.results[0].get('name')).to.equal('The Golden Waffle'); + // expect(snapshot1.results[0].get('snippet')?.length).to.be.greaterThan(0); + // + // const ppl2 = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: field('menu').matches('waffles'), + // addFields: [ + // field('menu') + // .snippet({ + // rquery: 'waffles', + // maxSnippetWidth: 1000 + // }) + // .as('snippet') + // ], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot2 = await execute(ppl2); + // expect(snapshot2.results.length).to.equal(1); + // expect(snapshot2.results[0].get('name')).to.equal('The Golden Waffle'); + // expect(snapshot2.results[0].get('snippet')?.length).to.be.greaterThan(0); + // + // expect(snapshot2.results[0].get('snippet')?.length).to.be.greaterThan( + // snapshot2.results[0].get('snippet')?.length + // ); + // }); + // + // it('snippet on multiple fields', async () => { + // // Get snippet from 1 field + // const ppl1 = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: documentMatches('waffle'), + // addFields: [ + // field('menu') + // .snippet({ + // rquery: 'waffles', + // maxSnippetWidth: 2000 + // }) + // .as('snippet') + // ], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot1 = await execute(ppl1); + // expect(snapshot1.results.length).to.equal(1); + // expect(snapshot1.results[0].get('name')).to.equal('The Golden Waffle'); + // expect(snapshot1.results[0].get('snippet')?.length).to.be.greaterThan(0); + // + // // Get snippet from 2 fields + // const ppl2 = firestore + // .pipeline() + // .collection(COLLECTION_NAME) + // .search({ + // query: documentMatches('waffle'), + // addFields: [ + // concat(field('menu'), field('description')) + // .snippet({ + // rquery: 'waffles', + // maxSnippetWidth: 2000 + // }) + // .as('snippet') + // ], + // queryEnhancement: 'disabled' + // }); + // + // const snapshot2 = await execute(ppl2); + // expect(snapshot2.results.length).to.equal(1); + // expect(snapshot2.results[0].get('name')).to.equal('The Golden Waffle'); + // expect(snapshot2.results[0].get('snippet')?.length).to.be.greaterThan(0); + // + // // Expect snippet from 2 fields to be longer than snippet from one field + // expect(snapshot2.results[0].get('snippet')?.length).to.be.greaterThan( + // snapshot2.results[0].get('snippet')?.length + // ); + // }); + // }); +}); diff --git a/packages/firestore/test/unit/api/expressions.test.ts b/packages/firestore/test/unit/api/expressions.test.ts new file mode 100644 index 0000000000..800135b0ea --- /dev/null +++ b/packages/firestore/test/unit/api/expressions.test.ts @@ -0,0 +1,114 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai'; + +import { ParseContext } from '../../../src/api/parse_context'; +import { UserDataSource } from '../../../src/lite-api/user_data_reader'; +import { constant, FunctionExpression } from '../../lite/pipeline_export'; +import { testUserDataReader } from '../../util/helpers'; + +describe('expressions', () => { + describe('serialization', () => { + let context: ParseContext | undefined; + beforeEach(async () => { + context = testUserDataReader(false).createContext( + UserDataSource.Argument, + 'beforeEach' + ); + }); + + // TODO(search) enable with backend support + // it('serializes snippet expression without options', async () => { + // const snippetExpression = field('foo').snippet('bar'); + // snippetExpression._readUserData(context!); + // + // const proto = snippetExpression._toProto(context!.serializer); + // + // expect(proto).to.deep.equal({ + // functionValue: { + // name: 'snippet', + // args: [ + // { + // 'fieldReferenceValue': 'foo' + // }, + // { + // stringValue: 'bar' + // } + // ], + // options: {} + // } + // }); + // }); + + // TODO(search) enable with backend support + // it('serializes snippet expression with options', async () => { + // const snippetExpression = field('foo').snippet({ + // rquery: 'bar', + // maxSnippetWidth: 123, + // maxSnippets: 321, + // separator: '...' + // }); + // snippetExpression._readUserData(context!); + // + // const proto = snippetExpression._toProto(context!.serializer); + // + // expect(proto).to.deep.equal({ + // functionValue: { + // name: 'snippet', + // args: [ + // { + // 'fieldReferenceValue': 'foo' + // }, + // { + // stringValue: 'bar' + // } + // ], + // options: { + // 'max_snippet_width': { + // integerValue: '123' + // }, + // 'max_snippets': { + // integerValue: '321' + // }, + // separator: { + // stringValue: '...' + // } + // } + // } + // }); + // }); + + it('serializes generic FunctionExpression without options', async () => { + const snippetExpression = new FunctionExpression('name', [constant(1)]); + snippetExpression._readUserData(context!); + + const proto = snippetExpression._toProto(context!.serializer); + + expect(proto).to.deep.equal({ + functionValue: { + name: 'name', + args: [ + { + integerValue: '1' + } + ] + } + }); + }); + }); +}); diff --git a/packages/firestore/test/unit/api/pipeline_impl.test.ts b/packages/firestore/test/unit/api/pipeline_impl.test.ts index f11db5a427..21d0962453 100644 --- a/packages/firestore/test/unit/api/pipeline_impl.test.ts +++ b/packages/firestore/test/unit/api/pipeline_impl.test.ts @@ -29,7 +29,9 @@ import { ExecutePipelineRequest as ProtoExecutePipelineRequest, ExecutePipelineResponse as ProtoExecutePipelineResponse } from '../../../src/protos/firestore_proto_api'; +import { constant, field } from '../../lite/pipeline_export'; import { newTestFirestore } from '../../util/api_helpers'; +import { describe } from '../../util/mocha_extensions'; const FIRST_CALL = 0; const EXECUTE_PIPELINE_REQUEST = 3; @@ -200,3 +202,109 @@ describe('execute(Pipeline|PipelineOptions)', () => { ); }); }); + +describe('stage serialization', () => { + describe('search stage', () => { + it('serializes the pipeline', async () => { + const firestore = newTestFirestore(); + const spy = fakePipelineResponse(firestore); + + await execute({ + pipeline: firestore + .pipeline() + .collection('foo') + .search({ + query: 'foo', + // limit: 1, + // retrievalDepth: 2, + // offset: 3, + // queryEnhancement: 'required', + // languageCode: 'en-US', + sort: [field('foo').ascending()], + addFields: [constant(true).as('bar')] + // select: [field('id')] + }) + }); + + const executePipelineRequest: ProtoExecutePipelineRequest = { + database: 'projects/new-project/databases/(default)', + structuredPipeline: { + 'options': {}, + 'pipeline': { + 'stages': [ + { + 'args': [ + { + 'referenceValue': '/foo' + } + ], + 'name': 'collection', + 'options': {} + }, + { + 'args': [], + 'name': 'search', + 'options': { + 'query': { + 'functionValue': { + 'args': [ + { + 'stringValue': 'foo' + } + ], + 'name': 'document_matches' + } + }, + // 'limit': { integerValue: '1' }, + // 'retrieval_depth': { integerValue: '2' }, + // 'offset': { integerValue: '3' }, + // 'query_enhancement': { stringValue: 'required' }, + // 'language_code': { stringValue: 'en-US' }, + // 'select': { + // 'mapValue': { + // 'fields': { + // 'id': { + // 'fieldReferenceValue': 'id' + // } + // } + // } + // }, + 'sort': { + 'arrayValue': { + 'values': [ + { + 'mapValue': { + 'fields': { + 'direction': { + 'stringValue': 'ascending' + }, + 'expression': { + 'fieldReferenceValue': 'foo' + } + } + } + } + ] + } + }, + 'add_fields': { + 'mapValue': { + 'fields': { + 'bar': { + 'booleanValue': true + } + } + } + } + } + } + ] + } + } + }; + expect(spy.args[FIRST_CALL][EXECUTE_PIPELINE_REQUEST]).to.deep.equal( + executePipelineRequest + ); + }); + }); +}); diff --git a/packages/firestore/test/util/mocha_extensions.ts b/packages/firestore/test/util/mocha_extensions.ts index 30df4ddee2..79ba786c1b 100644 --- a/packages/firestore/test/util/mocha_extensions.ts +++ b/packages/firestore/test/util/mocha_extensions.ts @@ -19,7 +19,7 @@ import { USE_EMULATOR, - RUN_ENTERPRISE_TESTS + getRunEnterpriseTests } from '../integration/util/settings'; // Helper to make a type itselt (T) and optionally union that with (T['skip']) @@ -44,6 +44,10 @@ declare module 'mocha' { // Define helpers export function mixinSkipImplementations(obj: unknown): void { + if (Object.getOwnPropertyDescriptor(obj, 'skipEmulator')) { + return; + } + Object.defineProperty(obj, 'skipEmulator', { get(): unknown { if (this === it.skip) { @@ -67,7 +71,7 @@ export function mixinSkipImplementations(obj: unknown): void { if (this === describe.skip) { return this; } - if (RUN_ENTERPRISE_TESTS) { + if (getRunEnterpriseTests()) { return this.skip; } return this; @@ -82,7 +86,7 @@ export function mixinSkipImplementations(obj: unknown): void { if (this === describe.skip) { return this; } - if (!RUN_ENTERPRISE_TESTS) { + if (!getRunEnterpriseTests()) { return this.skip; } return this; From cecd028de503302319a389a3331c5b94452daf95 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Thu, 2 Apr 2026 11:46:25 -0400 Subject: [PATCH 123/174] feat(firestore): Add support for pipeline subqueries (#9720) --- .changeset/ten-pugs-tie.md | 6 + .../firestore-lite-pipelines.api.md | 32 +- common/api-review/firestore-pipelines.api.md | 36 +- .../firestore_lite_pipelines.expression.md | 32 + docs-devsite/firestore_lite_pipelines.md | 159 +++- .../firestore_lite_pipelines.pipeline.md | 231 +++++ .../firestore_pipelines.expression.md | 32 + docs-devsite/firestore_pipelines.md | 156 +++- docs-devsite/firestore_pipelines.pipeline.md | 63 ++ .../firestore/lite/pipelines/pipelines.ts | 9 +- packages/firestore/src/api/pipeline.ts | 2 +- packages/firestore/src/api/pipeline_impl.ts | 10 + packages/firestore/src/api_pipelines.ts | 6 +- .../firestore/src/lite-api/expressions.ts | 206 ++++- .../firestore/src/lite-api/pipeline-source.ts | 43 +- packages/firestore/src/lite-api/pipeline.ts | 222 ++++- .../firestore/src/lite-api/pipeline_impl.ts | 11 +- packages/firestore/src/lite-api/stage.ts | 65 ++ .../firestore/src/lite-api/stage_options.ts | 25 + .../src/protos/firestore_proto_api.ts | 1 + .../protos/google/firestore/v1/document.proto | 7 + packages/firestore/src/protos/protos.json | 67 +- .../src/remote/internal_serializer.ts | 8 + packages/firestore/src/remote/serializer.ts | 4 +- packages/firestore/src/util/pipeline_util.ts | 19 +- .../test/integration/api/pipeline.test.ts | 867 +++++++++++++++++ packages/firestore/test/lite/pipeline.test.ts | 868 ++++++++++++++++++ 27 files changed, 3110 insertions(+), 77 deletions(-) create mode 100644 .changeset/ten-pugs-tie.md diff --git a/.changeset/ten-pugs-tie.md b/.changeset/ten-pugs-tie.md new file mode 100644 index 0000000000..9eefb840c7 --- /dev/null +++ b/.changeset/ten-pugs-tie.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/firestore': minor +--- + +Add subquery support to Pipelines. diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index 01645cf52b..fff56b2587 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -364,12 +364,20 @@ export function countDistinct(expr: Expression | string): AggregateFunction; // @public export function countIf(booleanExpr: BooleanExpression): AggregateFunction; +// @public +export function currentDocument(): Expression; + // @public export function currentTimestamp(): FunctionExpression; // @public export type DatabaseStageOptions = StageOptions & {}; +// @public +export type DefineStageOptions = StageOptions & { + variables: AliasedExpression[]; +}; + // @public export function descending(expr: Expression): Ordering; @@ -619,6 +627,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ floor(): FunctionExpression; /* Excluded from this release type: _readUserData */ + getField(key: string | Expression): Expression; + /* Excluded from this release type: _readUserData */ greaterThan(expression: Expression): BooleanExpression; /* Excluded from this release type: _readUserData */ greaterThan(value: unknown): BooleanExpression; @@ -825,7 +835,7 @@ export abstract class Expression { } // @public -export type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression'; +export type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression' | 'Variable' | 'PipelineValue'; // @public export class Field extends Expression implements Selectable { @@ -1202,6 +1212,8 @@ export class Pipeline { addFields(options: AddFieldsStageOptions): Pipeline; aggregate(accumulator: AliasedAggregate, ...additionalAccumulators: AliasedAggregate[]): Pipeline; aggregate(options: AggregateStageOptions): Pipeline; + define(aliasedExpression: AliasedExpression, ...additionalExpressions: AliasedExpression[]): Pipeline; + define(options: DefineStageOptions): Pipeline; distinct(group: string | Selectable, ...additionalGroups: Array): Pipeline; distinct(options: DistinctStageOptions): Pipeline; findNearest(options: FindNearestStageOptions): Pipeline; @@ -1225,6 +1237,8 @@ export class Pipeline { select(options: SelectStageOptions): Pipeline; sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; sort(options: SortStageOptions): Pipeline; + toArrayExpression(): Expression; + toScalarExpression(): Expression; union(other: Pipeline): Pipeline; union(options: UnionStageOptions): Pipeline; unnest(selectable: Selectable, indexField?: string): Pipeline; @@ -1496,6 +1510,17 @@ export function stringReverse(stringExpression: Expression): FunctionExpression; // @public export function stringReverse(field: string): FunctionExpression; +// @public +export function subcollection(path: string): Pipeline; + +// @public +export function subcollection(options: SubcollectionStageOptions): Pipeline; + +// @public +export type SubcollectionStageOptions = StageOptions & { + path: string; +}; + // @public export function substring(field: string, position: number, length?: number): FunctionExpression; @@ -1544,7 +1569,7 @@ export function timestampAdd(timestamp: Expression, unit: TimeUnit, amount: numb // @public export function timestampAdd(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; -// @public +// @public (undocumented) export function timestampDiff(endFieldName: string, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; // @public @@ -1678,6 +1703,9 @@ export type UnnestStageOptions = StageOptions & { indexField?: string; }; +// @public +export function variable(name: string): Expression; + // @public export function vectorLength(vectorExpression: Expression): FunctionExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index f8d539540b..07096bbe8e 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -364,12 +364,20 @@ export function countDistinct(expr: Expression | string): AggregateFunction; // @public export function countIf(booleanExpr: BooleanExpression): AggregateFunction; +// @public +export function currentDocument(): Expression; + // @public export function currentTimestamp(): FunctionExpression; // @public export type DatabaseStageOptions = StageOptions & {}; +// @public +export type DefineStageOptions = StageOptions & { + variables: AliasedExpression[]; +}; + // @public export function descending(expr: Expression): Ordering; @@ -622,6 +630,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ floor(): FunctionExpression; /* Excluded from this release type: _readUserData */ + getField(key: string | Expression): Expression; + /* Excluded from this release type: _readUserData */ greaterThan(expression: Expression): BooleanExpression; /* Excluded from this release type: _readUserData */ greaterThan(value: unknown): BooleanExpression; @@ -828,7 +838,7 @@ export abstract class Expression { } // @public -export type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression'; +export type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression' | 'Variable' | 'PipelineValue'; // @public export class Field extends Expression implements Selectable { @@ -1206,6 +1216,10 @@ export class Pipeline { addFields(options: AddFieldsStageOptions): Pipeline; aggregate(accumulator: AliasedAggregate, ...additionalAccumulators: AliasedAggregate[]): Pipeline; aggregate(options: AggregateStageOptions): Pipeline; + // (undocumented) + define(aliasedExpression: AliasedExpression, ...additionalExpressions: AliasedExpression[]): Pipeline; + // (undocumented) + define(options: DefineStageOptions): Pipeline; distinct(group: string | Selectable, ...additionalGroups: Array): Pipeline; // (undocumented) distinct(options: DistinctStageOptions): Pipeline; @@ -1235,6 +1249,10 @@ export class Pipeline { sort(ordering: Ordering, ...additionalOrderings: Ordering[]): Pipeline; // (undocumented) sort(options: SortStageOptions): Pipeline; + // (undocumented) + toArrayExpression(): Expression; + // (undocumented) + toScalarExpression(): Expression; union(other: Pipeline): Pipeline; // (undocumented) union(options: UnionStageOptions): Pipeline; @@ -1520,6 +1538,17 @@ export function stringReverse(stringExpression: Expression): FunctionExpression; // @public export function stringReverse(field: string): FunctionExpression; +// @public +export function subcollection(path: string): Pipeline; + +// @public +export function subcollection(options: SubcollectionStageOptions): Pipeline; + +// @public +export type SubcollectionStageOptions = StageOptions & { + path: string; +}; + // @public export function substring(field: string, position: number, length?: number): FunctionExpression; @@ -1568,7 +1597,7 @@ export function timestampAdd(timestamp: Expression, unit: TimeUnit, amount: numb // @public export function timestampAdd(fieldName: string, unit: TimeUnit, amount: number): FunctionExpression; -// @public +// @public (undocumented) export function timestampDiff(endFieldName: string, startFieldName: string, unit: TimeUnit | Expression): FunctionExpression; // @public @@ -1702,6 +1731,9 @@ export type UnnestStageOptions = StageOptions & { indexField?: string; }; +// @public +export function variable(name: string): Expression; + // @public export function vectorLength(vectorExpression: Expression): FunctionExpression; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index 98f04f933e..b63c7bbdd2 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -100,6 +100,7 @@ export declare abstract class Expression | [exp()](./firestore_lite_pipelines.expression.md#expressionexp) | | Creates an expression that computes e to the power of this expression. | | [first()](./firestore_lite_pipelines.expression.md#expressionfirst) | | Creates an aggregation that finds the first value of an expression across multiple stage inputs. | | [floor()](./firestore_lite_pipelines.expression.md#expressionfloor) | | Creates an expression that computes the floor of a numeric value. | +| [getField(key)](./firestore_lite_pipelines.expression.md#expressiongetfield) | | Creates an expression that returns the value of a field from the document that results from the evaluation of this expression. | | [greaterThan(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | Creates an expression that checks if this expression is greater than another expression. | | [greaterThan(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | Creates an expression that checks if this expression is greater than a constant value. | | [greaterThanOrEqual(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthanorequal) | | Creates an expression that checks if this expression is greater than or equal to another expression. | @@ -2096,6 +2097,37 @@ field("price").floor(); ``` +## Expression.getField() + +Creates an expression that returns the value of a field from the document that results from the evaluation of this expression. + +Signature: + +```typescript +getField(key: string | Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| key | string \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The field to access in the document. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +A new `Expression` representing the value of the field in the document. + +### Example + + +```typescript +// Get the value of the "city" field in the "address" document. +field("address").getField("city") + +``` + ## Expression.greaterThan() Creates an expression that checks if this expression is greater than another expression. diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 9c5f7b5444..ac33350f9c 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -17,6 +17,7 @@ https://github.com/firebase/firebase-js-sdk | --- | --- | | function() | | [countAll()](./firestore_lite_pipelines.md#countall) | Creates an aggregation that counts the total number of stage inputs. | +| [currentDocument()](./firestore_lite_pipelines.md#currentdocument) | Creates an expression that represents the current document being processed. | | [currentTimestamp()](./firestore_lite_pipelines.md#currenttimestamp) | Creates an expression that evaluates to the current server timestamp. | | [rand()](./firestore_lite_pipelines.md#rand) | Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. | | [score()](./firestore_lite_pipelines.md#score) | (Public Preview) Evaluates to the search score that reflects the topicality of the document to all of the text predicates (for example: documentMatches) in the search query. If SearchOptions.query is not set or does not contain any text predicates, then this topicality score will always be 0. | @@ -79,7 +80,7 @@ https://github.com/firebase/firebase-js-sdk | [timestampDiff(endExpression, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_4370feb) | Creates an expression that calculates the difference between two timestamps. | | [timestampDiff(endExpression, startExpression, unit)](./firestore_lite_pipelines.md#timestampdiff_bc0830f) | Creates an expression that calculates the difference between two timestamps. | | function(endFieldName, ...) | -| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_f60102c) | Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_lite_pipelines.md#timestampdiff_f60102c) | | | [timestampDiff(endFieldName, startExpression, unit)](./firestore_lite_pipelines.md#timestampdiff_6e54d92) | Creates an expression that calculates the difference between two timestamps. | | function(expr, ...) | | [abs(expr)](./firestore_lite_pipelines.md#abs_005f3d4) | Creates an expression that computes the absolute value of a numeric value. | @@ -338,8 +339,12 @@ https://github.com/firebase/firebase-js-sdk | [mapValues(mapField)](./firestore_lite_pipelines.md#mapvalues_83ad836) | Creates an expression that returns the values of a map. | | function(name, ...) | | [field(name)](./firestore_lite_pipelines.md#field_1eaaff4) | Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). | +| [variable(name)](./firestore_lite_pipelines.md#variable_1eaaff4) | Creates an expression that retrieves the value of a variable bound via define(). | +| function(options, ...) | +| [subcollection(options)](./firestore_lite_pipelines.md#subcollection_104dbc5) | Creates a new Pipeline targeted at a subcollection relative to the current document context. This creates a pipeline without a database instance, suitable for embedding as a subquery. If executed directly, this pipeline will fail. | | function(path, ...) | | [field(path)](./firestore_lite_pipelines.md#field_34ee07d) | Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. | +| [subcollection(path)](./firestore_lite_pipelines.md#subcollection_fe1f8e4) | Creates a new Pipeline targeted at a subcollection relative to the current document context. This creates a pipeline without a database instance, suitable for embedding as a subquery. If executed directly, this pipeline will fail. | | function(pipeline, ...) | | [execute(pipeline)](./firestore_lite_pipelines.md#execute_01df620) | Executes this pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:
    • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
    • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
    • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
    | | function(rquery, ...) | @@ -450,6 +455,7 @@ https://github.com/firebase/firebase-js-sdk | [CollectionGroupStageOptions](./firestore_lite_pipelines.md#collectiongroupstageoptions) | Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.md#stageoptions) and provides specific settings for how a collection group is identified and processed during pipeline execution.See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. | | [CollectionStageOptions](./firestore_lite_pipelines.md#collectionstageoptions) | Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). | | [DatabaseStageOptions](./firestore_lite_pipelines.md#databasestageoptions) | Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). | +| [DefineStageOptions](./firestore_lite_pipelines.md#definestageoptions) | Options defining how a DefineStage is evaluated. See [Pipeline.define()](./firestore_pipelines.pipeline.md#pipelinedefine). | | [DistinctStageOptions](./firestore_lite_pipelines.md#distinctstageoptions) | Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). | | [DocumentsStageOptions](./firestore_lite_pipelines.md#documentsstageoptions) | Options defining how a DocumentsStage is evaluated. See [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments). | | [ExpressionType](./firestore_lite_pipelines.md#expressiontype) | An enumeration of the different types of expressions. | @@ -467,6 +473,7 @@ https://github.com/firebase/firebase-js-sdk | [SetOptions](./firestore_lite_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | | [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | | [StageOptions](./firestore_lite_pipelines.md#stageoptions) | Options defining how a Stage is evaluated. | +| [SubcollectionStageOptions](./firestore_lite_pipelines.md#subcollectionstageoptions) | Options defining how a SubcollectionStage is evaluated. | | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | Specify time granularity for expressions. | | [TimePart](./firestore_lite_pipelines.md#timepart) | Specify time parts for timestampExtract expressions. | | [TimeUnit](./firestore_lite_pipelines.md#timeunit) | Specify time units for expressions. | @@ -502,6 +509,33 @@ countAll().as("totalDocument"); ``` +### currentDocument() {:#currentdocument} + +Creates an expression that represents the current document being processed. + +Signature: + +```typescript +export declare function currentDocument(): Expression; +``` +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +An [Expression](./firestore_pipelines.expression.md#expression_class) representing the current document. + +### Example + + +```typescript +// Define the current document as a variable "doc" +firestore.pipeline().collection("books") + .define(currentDocument().as("doc")) + // Access a field from the defined document variable + .select(variable("doc").mapGet("title")); + +``` + ### currentTimestamp() {:#currenttimestamp} Creates an expression that evaluates to the current server timestamp. @@ -2090,8 +2124,6 @@ timestampDiff(field('endTime'), field('startTime'), 'day') ### timestampDiff(endFieldName, startFieldName, unit) {:#timestampdiff_f60102c} -Creates an expression that calculates the difference between two timestamps. - Signature: ```typescript @@ -2102,25 +2134,14 @@ export declare function timestampDiff(endFieldName: string, startFieldName: stri | Parameter | Type | Description | | --- | --- | --- | -| endFieldName | string | The name of the field representing the ending timestamp. | -| startFieldName | string | The name of the field representing the starting timestamp. | -| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | +| endFieldName | string | | +| startFieldName | string | | +| unit | [TimeUnit](./firestore_lite_pipelines.md#timeunit) \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | | Returns: [FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the difference as an integer. - -### Example - - -```typescript -// Calculate the difference in days between 'endTime' and 'startTime' fields. -timestampDiff('endTime', 'startTime', 'day') - -``` - ### timestampDiff(endFieldName, startExpression, unit) {:#timestampdiff_6e54d92} Creates an expression that calculates the difference between two timestamps. @@ -9834,6 +9855,64 @@ const authorFirstNameField = field("author.firstName"); ``` +### variable(name) {:#variable_1eaaff4} + +Creates an expression that retrieves the value of a variable bound via `define()`. + +Signature: + +```typescript +export declare function variable(name: string): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | The name of the variable to retrieve. | + +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +An [Expression](./firestore_pipelines.expression.md#expression_class) representing the variable's value. + +### Example + + +```typescript +db.pipeline().collection("products") + .define( + field("price").multiply(0.9).as("discountedPrice"), + field("stock").add(10).as("newStock") + ) + .where(variable("discountedPrice").lessThan(100)) + .select(field("name"), variable("newStock")); + +``` + +## function(options, ...) + +### subcollection(options) {:#subcollection_104dbc5} + +Creates a new Pipeline targeted at a subcollection relative to the current document context. This creates a pipeline without a database instance, suitable for embedding as a subquery. If executed directly, this pipeline will fail. + +Signature: + +```typescript +export declare function subcollection(options: SubcollectionStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [SubcollectionStageOptions](./firestore_lite_pipelines.md#subcollectionstageoptions) | Options defining how this SubcollectionStage is evaluated. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + ## function(path, ...) ### field(path) {:#field_34ee07d} @@ -9858,6 +9937,26 @@ export declare function field(path: FieldPath): Field; A new [Field](./firestore_pipelines.field.md#field_class) instance representing the specified field. +### subcollection(path) {:#subcollection_fe1f8e4} + +Creates a new Pipeline targeted at a subcollection relative to the current document context. This creates a pipeline without a database instance, suitable for embedding as a subquery. If executed directly, this pipeline will fail. + +Signature: + +```typescript +export declare function subcollection(path: string): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| path | string | The relative path to the subcollection. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + ## function(pipeline, ...) ### execute(pipeline) {:#execute_01df620} @@ -11624,6 +11723,18 @@ Options defining how a DatabaseStage is evaluated. See [PipelineSource.database( export declare type DatabaseStageOptions = StageOptions & {}; ``` +## DefineStageOptions + +Options defining how a DefineStage is evaluated. See [Pipeline.define()](./firestore_pipelines.pipeline.md#pipelinedefine). + +Signature: + +```typescript +export declare type DefineStageOptions = StageOptions & { + variables: AliasedExpression[]; +}; +``` + ## DistinctStageOptions Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). @@ -11655,7 +11766,7 @@ An enumeration of the different types of expressions. Signature: ```typescript -export declare type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression'; +export declare type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression' | 'Variable' | 'PipelineValue'; ``` ## FindNearestStageOptions @@ -11853,6 +11964,18 @@ export declare type StageOptions = { }; ``` +## SubcollectionStageOptions + +Options defining how a `SubcollectionStage` is evaluated. + +Signature: + +```typescript +export declare type SubcollectionStageOptions = StageOptions & { + path: string; +}; +``` + ## TimeGranularity Specify time granularity for expressions. diff --git a/docs-devsite/firestore_lite_pipelines.pipeline.md b/docs-devsite/firestore_lite_pipelines.pipeline.md index 8a9040555d..7407009136 100644 --- a/docs-devsite/firestore_lite_pipelines.pipeline.md +++ b/docs-devsite/firestore_lite_pipelines.pipeline.md @@ -34,6 +34,8 @@ export declare class Pipeline | [addFields(options)](./firestore_lite_pipelines.pipeline.md#pipelineaddfields) | | Adds new fields to outputs from previous stages.This stage allows you to compute values on-the-fly based on existing data from previous stages or constants. You can use this to create new fields or overwrite existing ones (if there is name overlaps).The added fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface)s, which can be:- [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [Expression](./firestore_pipelines.expression.md#expression_class): Either a literal value (see [constant()](./firestore_pipelines.md#constant_0c00f91)) or a computed value with an assigned alias using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | | [aggregate(accumulator, additionalAccumulators)](./firestore_lite_pipelines.pipeline.md#pipelineaggregate) | | Performs aggregation operations on the documents from previous stages.

    This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions which are typically results of calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances.

    Example: | | [aggregate(options)](./firestore_lite_pipelines.pipeline.md#pipelineaggregate) | | Performs optionally grouped aggregation operations on the documents from previous stages.

    This stage allows you to calculate aggregate values over a set of documents, optionally grouped by one or more fields or functions. You can specify:

    • \*\*Grouping Fields or Functions:\*\* One or more fields or functions to group the documents by. For each distinct combination of values in these fields, a separate group is created. If no grouping fields are provided, a single group containing all documents is used. Not specifying groups is the same as putting the entire inputs into one group.
    • \*\*Accumulators:\*\* One or more accumulation operations to perform within each group. These are defined using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions, which are typically created by calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances. Each aggregation calculates a value (e.g., sum, average, count) based on the documents within its group.

    Example: | +| [define(aliasedExpression, additionalExpressions)](./firestore_lite_pipelines.pipeline.md#pipelinedefine) | | Defines one or more variables in the pipeline's scope. define is used to bind a value to a variable for internal reuse within the pipeline body (accessed via the variable() function).This stage is useful for declaring reusable values or intermediate calculations that can be referenced multiple times in later parts of the pipeline, improving readability and maintainability.Each variable is defined using an [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), which pairs an expression with a name (alias). The expression can be a simple constant, a field reference, or a complex computation. | +| [define(options)](./firestore_lite_pipelines.pipeline.md#pipelinedefine) | | Defines one or more variables in the pipeline's scope. define is used to bind a value to a variable for internal reuse within the pipeline body (accessed via the variable() function).This stage is useful for declaring reusable values or intermediate calculations that can be referenced multiple times in later parts of the pipeline, improving readability and maintainability.Each variable is defined using an [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), which pairs an expression with a name (alias). The expression can be a simple constant, a field reference, or a complex computation. | | [distinct(group, additionalGroups)](./firestore_lite_pipelines.pipeline.md#pipelinedistinct) | | Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc).The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings:- string: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | | [distinct(options)](./firestore_lite_pipelines.pipeline.md#pipelinedistinct) | | Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc).The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings:- string: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | | [findNearest(options)](./firestore_lite_pipelines.pipeline.md#pipelinefindnearest) | | Performs a vector proximity search on the documents from the previous stage, returning the K-nearest documents based on the specified query vectorValue and distanceMeasure. The returned documents will be sorted in order from nearest to furthest from the query vectorValue.

    Example: @@ -70,6 +72,8 @@ firestore.pipeline().collection("books") | [select(options)](./firestore_lite_pipelines.pipeline.md#pipelineselect) | | Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

    • string: Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

    Example: | | [sort(ordering, additionalOrderings)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

    Example: | | [sort(options)](./firestore_lite_pipelines.pipeline.md#pipelinesort) | | Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

    Example: | +| [toArrayExpression()](./firestore_lite_pipelines.pipeline.md#pipelinetoarrayexpression) | | Converts this Pipeline into an expression that evaluates to an array of results.

    Result Unwrapping:

    • If the items have a single field, their values are unwrapped and returned directly in the array.
    • If the items have multiple fields, they are returned as objects in the array
    | +| [toScalarExpression()](./firestore_lite_pipelines.pipeline.md#pipelinetoscalarexpression) | | Converts this Pipeline into an expression that evaluates to a single scalar result.

    Runtime Validation: The runtime validates that the result set contains zero or one item. If zero items, it evaluates to null.

    Result Unwrapping:

    • If the item has a single field, its value is unwrapped and returned directly.
    • f the item has multiple fields, they are returned as an object.
    | | [union(other)](./firestore_lite_pipelines.pipeline.md#pipelineunion) | | Performs union of all documents from two pipelines, including duplicates.

    This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined.

    Example: | | [union(options)](./firestore_lite_pipelines.pipeline.md#pipelineunion) | | Performs union of all documents from two pipelines, including duplicates.

    This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined.

    Example: | | [unnest(selectable, indexField)](./firestore_lite_pipelines.pipeline.md#pipelineunnest) | | Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: | @@ -243,6 +247,87 @@ firestore.pipeline().collection("books") ``` +## Pipeline.define() + +Defines one or more variables in the pipeline's scope. `define` is used to bind a value to a variable for internal reuse within the pipeline body (accessed via the `variable()` function). + +This stage is useful for declaring reusable values or intermediate calculations that can be referenced multiple times in later parts of the pipeline, improving readability and maintainability. + +Each variable is defined using an [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), which pairs an expression with a name (alias). The expression can be a simple constant, a field reference, or a complex computation. + +Signature: + +```typescript +define(aliasedExpression: AliasedExpression, ...additionalExpressions: AliasedExpression[]): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| aliasedExpression | [AliasedExpression](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpression_class) | The first expression to bind to a variable. | +| additionalExpressions | [AliasedExpression](./firestore_lite_pipelines.aliasedexpression.md#aliasedexpression_class)\[\] | Optional additional expression to bind to a variable. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +db.pipeline().collection("products") + .define( + field("price").multiply(0.9).as("discountedPrice"), + field("stock").add(10).as("newStock") + ) + .where(variable("discountedPrice").lessThan(100)) + .select(field("name"), variable("newStock")); + +``` + +## Pipeline.define() + +Defines one or more variables in the pipeline's scope. `define` is used to bind a value to a variable for internal reuse within the pipeline body (accessed via the `variable()` function). + +This stage is useful for declaring reusable values or intermediate calculations that can be referenced multiple times in later parts of the pipeline, improving readability and maintainability. + +Each variable is defined using an [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), which pairs an expression with a name (alias). The expression can be a simple constant, a field reference, or a complex computation. + +Signature: + +```typescript +define(options: DefineStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [DefineStageOptions](./firestore_lite_pipelines.md#definestageoptions) | An object that specifies required and optional parameters for the stage. | + +Returns: + +[Pipeline](./firestore_lite_pipelines.pipeline.md#pipeline_class) + +A new Pipeline object with this stage appended to the stage list. + +### Example + + +```typescript +db.pipeline().collection("products") + .define( + field("price").multiply(0.9).as("discountedPrice"), + field("stock").add(10).as("newStock") + ) + .where(variable("discountedPrice").lessThan(100)) + .select(field("name"), variable("newStock")); + +``` + ## Pipeline.distinct() Returns a set of distinct values from the inputs to this stage. @@ -1096,6 +1181,152 @@ firestore.pipeline().collection("books") ``` +## Pipeline.toArrayExpression() + +Converts this Pipeline into an expression that evaluates to an array of results. + +

    Result Unwrapping:

    • If the items have a single field, their values are unwrapped and returned directly in the array.
    • If the items have multiple fields, they are returned as objects in the array
    + +Signature: + +```typescript +toArrayExpression(): Expression; +``` +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +An `Expression` representing the execution of this pipeline. + +### Example + + +```typescript +// Get a list of reviewers for each book +db.pipeline().collection("books") + .define(field("id").as("book_id")) + .addFields( + db.pipeline().collection("reviews") + .where(field("book_id").equal(variable("book_id"))) + .select(field("reviewer")) + .toArrayExpression() + .as("reviewers") + ) + +``` +Output: + +```json +[ + { + "id": "1", + "title": "1984", + "reviewers": ["Alice", "Bob"] + } +] + +``` +Multiple Fields: + +```typescript +// Get a list of reviews (reviewer and rating) for each book +db.pipeline().collection("books") + .define(field("id").as("book_id")) + .addFields( + db.pipeline().collection("reviews") + .where(field("book_id").equal(variable("book_id"))) + .select(field("reviewer"), field("rating")) + .toArrayExpression() + .as("reviews")) + +``` +Output: + +```json +[ + { + "id": "1", + "title": "1984", + "reviews": [ + { "reviewer": "Alice", "rating": 5 }, + { "reviewer": "Bob", "rating": 4 } + ] + } +] + +``` + +## Pipeline.toScalarExpression() + +Converts this Pipeline into an expression that evaluates to a single scalar result. + +

    Runtime Validation: The runtime validates that the result set contains zero or one item. If zero items, it evaluates to `null`.

    + +

    Result Unwrapping:

    • If the item has a single field, its value is unwrapped and returned directly.
    • f the item has multiple fields, they are returned as an object.
    + +Signature: + +```typescript +toScalarExpression(): Expression; +``` +Returns: + +[Expression](./firestore_lite_pipelines.expression.md#expression_class) + +An `Expression` representing the execution of this pipeline. + +### Example + + +```typescript +// Calculate average rating for a restaurant +db.pipeline().collection("restaurants").addFields( + db.pipeline().collection("reviews") + .where(field("restaurant_id").equal(variable("rid"))) + .aggregate(average("rating").as("avg")) + // Unwraps the single "avg" field to a scalar double + .toScalarExpression().as("average_rating") +) + +``` +Output: + +```json +{ + "name": "The Burger Joint", + "average_rating": 4.5 +} + +``` +Multiple Fields: + +```typescript +// Calculate average rating AND count for a restaurant +db.pipeline().collection("restaurants").addFields( + db.pipeline().collection("reviews") + .where(field("restaurant_id").equal(variable("rid"))) + .aggregate( + average("rating").as("avg"), + count().as("count") + ) + // Returns an object with "avg" and "count" fields + .toScalarExpression().as("stats") +) + +``` +Output: + +```json +{ + "name": "The Burger Joint", + "stats": { + "avg": 4.5, + "count": 100 + } +} + +``` + ## Pipeline.union() Performs union of all documents from two pipelines, including duplicates. diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 07fca7c58d..942b76d5ee 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -100,6 +100,7 @@ export declare abstract class Expression | [exp()](./firestore_pipelines.expression.md#expressionexp) | | Creates an expression that computes e to the power of this expression. | | [first()](./firestore_pipelines.expression.md#expressionfirst) | | Creates an aggregation that finds the first value of an expression across multiple stage inputs. | | [floor()](./firestore_pipelines.expression.md#expressionfloor) | | Creates an expression that computes the floor of a numeric value. | +| [getField(key)](./firestore_pipelines.expression.md#expressiongetfield) | | Creates an expression that returns the value of a field from the document that results from the evaluation of this expression. | | [greaterThan(expression)](./firestore_pipelines.expression.md#expressiongreaterthan) | | Creates an expression that checks if this expression is greater than another expression. | | [greaterThan(value)](./firestore_pipelines.expression.md#expressiongreaterthan) | | Creates an expression that checks if this expression is greater than a constant value. | | [greaterThanOrEqual(expression)](./firestore_pipelines.expression.md#expressiongreaterthanorequal) | | Creates an expression that checks if this expression is greater than or equal to another expression. | @@ -2096,6 +2097,37 @@ field("price").floor(); ``` +## Expression.getField() + +Creates an expression that returns the value of a field from the document that results from the evaluation of this expression. + +Signature: + +```typescript +getField(key: string | Expression): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| key | string \| [Expression](./firestore_pipelines.expression.md#expression_class) | The field to access in the document. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +A new `Expression` representing the value of the field in the document. + +### Example + + +```typescript +// Get the value of the "city" field in the "address" document. +field("address").getField("city") + +``` + ## Expression.greaterThan() Creates an expression that checks if this expression is greater than another expression. diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 485c0038af..1fef6a7820 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -17,6 +17,7 @@ https://github.com/firebase/firebase-js-sdk | --- | --- | | function() | | [countAll()](./firestore_pipelines.md#countall) | Creates an aggregation that counts the total number of stage inputs. | +| [currentDocument()](./firestore_pipelines.md#currentdocument) | Creates an expression that represents the current document being processed. | | [currentTimestamp()](./firestore_pipelines.md#currenttimestamp) | Creates an expression that evaluates to the current server timestamp. | | [rand()](./firestore_pipelines.md#rand) | Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. | | [score()](./firestore_pipelines.md#score) | (Public Preview) Evaluates to the search score that reflects the topicality of the document to all of the text predicates (for example: documentMatches) in the search query. If SearchOptions.query is not set or does not contain any text predicates, then this topicality score will always be 0. | @@ -79,7 +80,7 @@ https://github.com/firebase/firebase-js-sdk | [timestampDiff(endExpression, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_4370feb) | Creates an expression that calculates the difference between two timestamps. | | [timestampDiff(endExpression, startExpression, unit)](./firestore_pipelines.md#timestampdiff_bc0830f) | Creates an expression that calculates the difference between two timestamps. | | function(endFieldName, ...) | -| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_f60102c) | Creates an expression that calculates the difference between two timestamps. | +| [timestampDiff(endFieldName, startFieldName, unit)](./firestore_pipelines.md#timestampdiff_f60102c) | | | [timestampDiff(endFieldName, startExpression, unit)](./firestore_pipelines.md#timestampdiff_6e54d92) | Creates an expression that calculates the difference between two timestamps. | | function(expr, ...) | | [abs(expr)](./firestore_pipelines.md#abs_005f3d4) | Creates an expression that computes the absolute value of a numeric value. | @@ -339,10 +340,13 @@ https://github.com/firebase/firebase-js-sdk | [mapValues(mapField)](./firestore_pipelines.md#mapvalues_83ad836) | Creates an expression that returns the values of a map. | | function(name, ...) | | [field(name)](./firestore_pipelines.md#field_1eaaff4) | Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path.The path can be a simple field name (e.g., "name") or a dot-separated path to a nested field (e.g., "address.city"). | +| [variable(name)](./firestore_pipelines.md#variable_1eaaff4) | Creates an expression that retrieves the value of a variable bound via define(). | | function(options, ...) | | [execute(options)](./firestore_pipelines.md#execute_9e87e31) | Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:
    • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
    • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
    • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
    | +| [subcollection(options)](./firestore_pipelines.md#subcollection_104dbc5) | Creates a new Pipeline targeted at a subcollection relative to the current document context. This creates a pipeline without a database instance, suitable for embedding as a subquery. If executed directly, this pipeline will fail. | | function(path, ...) | | [field(path)](./firestore_pipelines.md#field_34ee07d) | Creates a [Field](./firestore_pipelines.field.md#field_class) instance representing the field at the given path. | +| [subcollection(path)](./firestore_pipelines.md#subcollection_fe1f8e4) | Creates a new Pipeline targeted at a subcollection relative to the current document context. This creates a pipeline without a database instance, suitable for embedding as a subquery. If executed directly, this pipeline will fail. | | function(pipeline, ...) | | [execute(pipeline)](./firestore_pipelines.md#execute_01df620) | Executes a pipeline and returns a Promise to represent the asynchronous operation.The returned Promise can be used to track the progress of the pipeline execution and retrieve the results (or handle any errors) asynchronously.The pipeline results are returned as a [PipelineSnapshot](./firestore_pipelines.pipelinesnapshot.md#pipelinesnapshot_class) that contains a list of [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) objects. Each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) typically represents a single key/value map that has passed through all the stages of the pipeline, however this might differ depending on the stages involved in the pipeline. For example:
    • If there are no stages or only transformation stages, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a single document.
    • If there is an aggregation, only a single [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) is returned, representing the aggregated results over the entire dataset .
    • If there is an aggregation stage with grouping, each [PipelineResult](./firestore_pipelines.pipelineresult.md#pipelineresult_class) represents a distinct group and its associated aggregated values.
    | | function(rquery, ...) | @@ -456,6 +460,7 @@ https://github.com/firebase/firebase-js-sdk | [CollectionGroupStageOptions](./firestore_pipelines.md#collectiongroupstageoptions) | Defines the configuration options for a CollectionGroupStage within a pipeline. This type extends [StageOptions](./firestore_pipelines.md#stageoptions) and provides specific settings for how a collection group is identified and processed during pipeline execution.See [PipelineSource.collectionGroup()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollectiongroup) to create a collection group stage. | | [CollectionStageOptions](./firestore_pipelines.md#collectionstageoptions) | Options defining how a CollectionStage is evaluated. See [PipelineSource.collection()](./firestore_pipelines.pipelinesource.md#pipelinesourcecollection). | | [DatabaseStageOptions](./firestore_pipelines.md#databasestageoptions) | Options defining how a DatabaseStage is evaluated. See [PipelineSource.database()](./firestore_pipelines.pipelinesource.md#pipelinesourcedatabase). | +| [DefineStageOptions](./firestore_pipelines.md#definestageoptions) | Options defining how a DefineStage is evaluated. See [Pipeline.define()](./firestore_pipelines.pipeline.md#pipelinedefine). | | [DistinctStageOptions](./firestore_pipelines.md#distinctstageoptions) | Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). | | [DocumentsStageOptions](./firestore_pipelines.md#documentsstageoptions) | Options defining how a DocumentsStage is evaluated. See [PipelineSource.documents()](./firestore_pipelines.pipelinesource.md#pipelinesourcedocuments). | | [ExpressionType](./firestore_pipelines.md#expressiontype) | An enumeration of the different types of expressions. | @@ -473,6 +478,7 @@ https://github.com/firebase/firebase-js-sdk | [SetOptions](./firestore_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | | [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | | [StageOptions](./firestore_pipelines.md#stageoptions) | Options defining how a Stage is evaluated. | +| [SubcollectionStageOptions](./firestore_pipelines.md#subcollectionstageoptions) | Options defining how a SubcollectionStage is evaluated. | | [TimeGranularity](./firestore_pipelines.md#timegranularity) | Specify time granularity for expressions. | | [TimePart](./firestore_pipelines.md#timepart) | Specify time parts for timestampExtract expressions. | | [TimeUnit](./firestore_pipelines.md#timeunit) | Specify time units for expressions. | @@ -508,6 +514,33 @@ countAll().as("totalDocument"); ``` +### currentDocument() {:#currentdocument} + +Creates an expression that represents the current document being processed. + +Signature: + +```typescript +export declare function currentDocument(): Expression; +``` +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +An [Expression](./firestore_pipelines.expression.md#expression_class) representing the current document. + +### Example + + +```typescript +// Define the current document as a variable "doc" +firestore.pipeline().collection("books") + .define(currentDocument().as("doc")) + // Access a field from the defined document variable + .select(variable("doc").mapGet("title")); + +``` + ### currentTimestamp() {:#currenttimestamp} Creates an expression that evaluates to the current server timestamp. @@ -2096,8 +2129,6 @@ timestampDiff(field('endTime'), field('startTime'), 'day') ### timestampDiff(endFieldName, startFieldName, unit) {:#timestampdiff_f60102c} -Creates an expression that calculates the difference between two timestamps. - Signature: ```typescript @@ -2108,25 +2139,14 @@ export declare function timestampDiff(endFieldName: string, startFieldName: stri | Parameter | Type | Description | | --- | --- | --- | -| endFieldName | string | The name of the field representing the ending timestamp. | -| startFieldName | string | The name of the field representing the starting timestamp. | -| unit | [TimeUnit](./firestore_pipelines.md#timeunit) \| [Expression](./firestore_pipelines.expression.md#expression_class) | The unit of time for the difference (e.g., "day", "hour"). | +| endFieldName | string | | +| startFieldName | string | | +| unit | [TimeUnit](./firestore_pipelines.md#timeunit) \| [Expression](./firestore_pipelines.expression.md#expression_class) | | Returns: [FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) -A new `Expression` representing the difference as an integer. - -### Example - - -```typescript -// Calculate the difference in days between 'endTime' and 'startTime' fields. -timestampDiff('endTime', 'startTime', 'day') - -``` - ### timestampDiff(endFieldName, startExpression, unit) {:#timestampdiff_6e54d92} Creates an expression that calculates the difference between two timestamps. @@ -9861,6 +9881,42 @@ const authorFirstNameField = field("author.firstName"); ``` +### variable(name) {:#variable_1eaaff4} + +Creates an expression that retrieves the value of a variable bound via `define()`. + +Signature: + +```typescript +export declare function variable(name: string): Expression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | The name of the variable to retrieve. | + +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +An [Expression](./firestore_pipelines.expression.md#expression_class) representing the variable's value. + +### Example + + +```typescript +db.pipeline().collection("products") + .define( + field("price").multiply(0.9).as("discountedPrice"), + field("stock").add(10).as("newStock") + ) + .where(variable("discountedPrice").lessThan(100)) + .select(field("name"), variable("newStock")); + +``` + ## function(options, ...) ### execute(options) {:#execute_9e87e31} @@ -9903,6 +9959,26 @@ const results: PipelineResult[] = snapshot.results; ``` +### subcollection(options) {:#subcollection_104dbc5} + +Creates a new Pipeline targeted at a subcollection relative to the current document context. This creates a pipeline without a database instance, suitable for embedding as a subquery. If executed directly, this pipeline will fail. + +Signature: + +```typescript +export declare function subcollection(options: SubcollectionStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [SubcollectionStageOptions](./firestore_pipelines.md#subcollectionstageoptions) | Options defining how this SubcollectionStage is evaluated. | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + ## function(path, ...) ### field(path) {:#field_34ee07d} @@ -9927,6 +10003,26 @@ export declare function field(path: FieldPath): Field; A new [Field](./firestore_pipelines.field.md#field_class) instance representing the specified field. +### subcollection(path) {:#subcollection_fe1f8e4} + +Creates a new Pipeline targeted at a subcollection relative to the current document context. This creates a pipeline without a database instance, suitable for embedding as a subquery. If executed directly, this pipeline will fail. + +Signature: + +```typescript +export declare function subcollection(path: string): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| path | string | The relative path to the subcollection. | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + ## function(pipeline, ...) ### execute(pipeline) {:#execute_01df620} @@ -11693,6 +11789,18 @@ Options defining how a DatabaseStage is evaluated. See [PipelineSource.database( export declare type DatabaseStageOptions = StageOptions & {}; ``` +## DefineStageOptions + +Options defining how a DefineStage is evaluated. See [Pipeline.define()](./firestore_pipelines.pipeline.md#pipelinedefine). + +Signature: + +```typescript +export declare type DefineStageOptions = StageOptions & { + variables: AliasedExpression[]; +}; +``` + ## DistinctStageOptions Options defining how a DistinctStage is evaluated. See [Pipeline.distinct()](./firestore_pipelines.pipeline.md#pipelinedistinct). @@ -11724,7 +11832,7 @@ An enumeration of the different types of expressions. Signature: ```typescript -export declare type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression'; +export declare type ExpressionType = 'Field' | 'Constant' | 'Function' | 'AggregateFunction' | 'ListOfExpressions' | 'AliasedExpression' | 'Variable' | 'PipelineValue'; ``` ## FindNearestStageOptions @@ -11922,6 +12030,18 @@ export declare type StageOptions = { }; ``` +## SubcollectionStageOptions + +Options defining how a `SubcollectionStage` is evaluated. + +Signature: + +```typescript +export declare type SubcollectionStageOptions = StageOptions & { + path: string; +}; +``` + ## TimeGranularity Specify time granularity for expressions. diff --git a/docs-devsite/firestore_pipelines.pipeline.md b/docs-devsite/firestore_pipelines.pipeline.md index b897f796a4..3f3f0dc8a5 100644 --- a/docs-devsite/firestore_pipelines.pipeline.md +++ b/docs-devsite/firestore_pipelines.pipeline.md @@ -24,6 +24,8 @@ export declare class Pipeline | [addFields(options)](./firestore_pipelines.pipeline.md#pipelineaddfields) | | | | [aggregate(accumulator, additionalAccumulators)](./firestore_pipelines.pipeline.md#pipelineaggregate) | | Performs aggregation operations on the documents from previous stages.

    This stage allows you to calculate aggregate values over a set of documents. You define the aggregations to perform using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions which are typically results of calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances.

    Example: | | [aggregate(options)](./firestore_pipelines.pipeline.md#pipelineaggregate) | | Performs optionally grouped aggregation operations on the documents from previous stages.

    This stage allows you to calculate aggregate values over a set of documents, optionally grouped by one or more fields or functions. You can specify:

    • \*\*Grouping Fields or Functions:\*\* One or more fields or functions to group the documents by. For each distinct combination of values in these fields, a separate group is created. If no grouping fields are provided, a single group containing all documents is used. Not specifying groups is the same as putting the entire inputs into one group.
    • \*\*Accumulators:\*\* One or more accumulation operations to perform within each group. These are defined using [AliasedAggregate](./firestore_pipelines.aliasedaggregate.md#aliasedaggregate_class) expressions, which are typically created by calling [Expression.as()](./firestore_pipelines.expression.md#expressionas) on [AggregateFunction](./firestore_pipelines.aggregatefunction.md#aggregatefunction_class) instances. Each aggregation calculates a value (e.g., sum, average, count) based on the documents within its group.

    Example: | +| [define(aliasedExpression, additionalExpressions)](./firestore_pipelines.pipeline.md#pipelinedefine) | | | +| [define(options)](./firestore_pipelines.pipeline.md#pipelinedefine) | | | | [distinct(group, additionalGroups)](./firestore_pipelines.pipeline.md#pipelinedistinct) | | Returns a set of distinct values from the inputs to this stage.This stage runs through the results from previous stages to include only results with unique combinations of [Expression](./firestore_pipelines.expression.md#expression_class) values ([Field](./firestore_pipelines.field.md#field_class), [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class), etc).The parameters to this stage are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions or strings:- string: Name of an existing field - [Field](./firestore_pipelines.field.md#field_class): References an existing document field. - [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas).Example: | | [distinct(options)](./firestore_pipelines.pipeline.md#pipelinedistinct) | | | | [findNearest(options)](./firestore_pipelines.pipeline.md#pipelinefindnearest) | | Performs a vector proximity search on the documents from the previous stage, returning the K-nearest documents based on the specified query vectorValue and distanceMeasure. The returned documents will be sorted in order from nearest to furthest from the query vectorValue.

    Example: @@ -60,6 +62,8 @@ distanceField: 'computedDistance' // optional | [select(options)](./firestore_pipelines.pipeline.md#pipelineselect) | | Selects or creates a set of fields from the outputs of previous stages.

    The selected fields are defined using [Selectable](./firestore_pipelines.selectable.md#selectable_interface) expressions, which can be:

    • string: Name of an existing field
    • [Field](./firestore_pipelines.field.md#field_class): References an existing field.
    • [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class): Represents the result of a function with an assigned alias name using [Expression.as()](./firestore_pipelines.expression.md#expressionas)

    If no selections are provided, the output of this stage is empty. Use [Pipeline.addFields()](./firestore_pipelines.pipeline.md#pipelineaddfields) instead if only additions are desired.

    Example: | | [sort(ordering, additionalOrderings)](./firestore_pipelines.pipeline.md#pipelinesort) | | Sorts the documents from previous stages based on one or more [Ordering](./firestore_pipelines.ordering.md#ordering_class) criteria.

    This stage allows you to order the results of your pipeline. You can specify multiple [Ordering](./firestore_pipelines.ordering.md#ordering_class) instances to sort by multiple fields in ascending or descending order. If documents have the same value for a field used for sorting, the next specified ordering will be used. If all orderings result in equal comparison, the documents are considered equal and the order is unspecified.

    Example: | | [sort(options)](./firestore_pipelines.pipeline.md#pipelinesort) | | | +| [toArrayExpression()](./firestore_pipelines.pipeline.md#pipelinetoarrayexpression) | | | +| [toScalarExpression()](./firestore_pipelines.pipeline.md#pipelinetoscalarexpression) | | | | [union(other)](./firestore_pipelines.pipeline.md#pipelineunion) | | Performs union of all documents from two pipelines, including duplicates.

    This stage will pass through documents from previous stage, and also pass through documents from previous stage of the other [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) given in parameter. The order of documents emitted from this stage is undefined.

    Example: | | [union(options)](./firestore_pipelines.pipeline.md#pipelineunion) | | | | [unnest(selectable, indexField)](./firestore_pipelines.pipeline.md#pipelineunnest) | | Produces a document for each element in an input array.For each previous stage document, this stage will emit zero or more augmented documents. The input array specified by the selectable parameter, will emit an augmented document for each input array element. The input array element will augment the previous stage document by setting the alias field with the array element value.When selectable evaluates to a non-array value (ex: number, null, absent), then the stage becomes a no-op for the current input document, returning it as is with the alias field absent.No documents are emitted when selectable evaluates to an empty array.Example: | @@ -209,6 +213,43 @@ groups: ["genre"] ``` +## Pipeline.define() + +Signature: + +```typescript +define(aliasedExpression: AliasedExpression, ...additionalExpressions: AliasedExpression[]): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| aliasedExpression | [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class) | | +| additionalExpressions | [AliasedExpression](./firestore_pipelines.aliasedexpression.md#aliasedexpression_class)\[\] | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + +## Pipeline.define() + +Signature: + +```typescript +define(options: DefineStageOptions): Pipeline; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [DefineStageOptions](./firestore_pipelines.md#definestageoptions) | | + +Returns: + +[Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) + ## Pipeline.distinct() Returns a set of distinct values from the inputs to this stage. @@ -873,6 +914,28 @@ sort(options: SortStageOptions): Pipeline; [Pipeline](./firestore_pipelines.pipeline.md#pipeline_class) +## Pipeline.toArrayExpression() + +Signature: + +```typescript +toArrayExpression(): Expression; +``` +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + +## Pipeline.toScalarExpression() + +Signature: + +```typescript +toScalarExpression(): Expression; +``` +Returns: + +[Expression](./firestore_pipelines.expression.md#expression_class) + ## Pipeline.union() Performs union of all documents from two pipelines, including duplicates. diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index 9cdb0302a1..66a236f284 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -48,7 +48,10 @@ export type { Bytes } from '../index'; -export { PipelineSource } from '../../src/lite-api/pipeline-source'; +export { + PipelineSource, + subcollection +} from '../../src/lite-api/pipeline-source'; export { OneOf } from '../../src/util/types'; @@ -65,10 +68,12 @@ export { StageOptions, CollectionStageOptions, CollectionGroupStageOptions, + SubcollectionStageOptions, DatabaseStageOptions, DocumentsStageOptions, AddFieldsStageOptions, RemoveFieldsStageOptions, + DefineStageOptions, SelectStageOptions, WhereStageOptions, OffsetStageOptions, @@ -218,6 +223,8 @@ export { arraySum, split, timestampTruncate, + variable, + currentDocument, timestampExtract, // snippet, // SnippetOptions, diff --git a/packages/firestore/src/api/pipeline.ts b/packages/firestore/src/api/pipeline.ts index 26146f4755..105a1f098f 100644 --- a/packages/firestore/src/api/pipeline.ts +++ b/packages/firestore/src/api/pipeline.ts @@ -29,7 +29,7 @@ export class Pipeline extends LitePipeline { * @param stages * @protected */ - protected newPipeline(db: Firestore, stages: Stage[]): Pipeline { + protected newPipeline(db: Firestore | undefined, stages: Stage[]): Pipeline { return new Pipeline(db, stages); } } diff --git a/packages/firestore/src/api/pipeline_impl.ts b/packages/firestore/src/api/pipeline_impl.ts index 831eedff23..49a307d0a9 100644 --- a/packages/firestore/src/api/pipeline_impl.ts +++ b/packages/firestore/src/api/pipeline_impl.ts @@ -30,6 +30,7 @@ import { newUserDataReader, UserDataSource } from '../lite-api/user_data_reader'; +import { Code, FirestoreError } from '../util/error'; import { cast } from '../util/input_validation'; import { ensureFirestoreConfigured, Firestore } from './database'; @@ -133,6 +134,15 @@ export function execute( const { pipeline, rawOptions, ...rest } = options; + if (!pipeline._db) { + return Promise.reject( + new FirestoreError( + Code.FAILED_PRECONDITION, + 'This pipeline was created without a database (e.g., as a subcollection pipeline) and cannot be executed directly. It can only be used as part of another pipeline.' + ) + ); + } + const firestore = cast(pipeline._db, Firestore); const client = ensureFirestoreConfigured(firestore); diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index eb4ff33c6d..74ee09741d 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -export { PipelineSource } from './lite-api/pipeline-source'; +export { PipelineSource, subcollection } from './lite-api/pipeline-source'; export { OneOf } from './util/types'; @@ -35,10 +35,12 @@ export { StageOptions, CollectionStageOptions, CollectionGroupStageOptions, + SubcollectionStageOptions, DatabaseStageOptions, DocumentsStageOptions, AddFieldsStageOptions, RemoveFieldsStageOptions, + DefineStageOptions, SelectStageOptions, WhereStageOptions, OffsetStageOptions, @@ -188,6 +190,8 @@ export { timestampTruncate, timestampExtract, split, + variable, + currentDocument, score, documentMatches, geoDistance, diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index 361a3bdc04..32dba9e343 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -31,6 +31,7 @@ import { JsonProtoSerializer, ProtoValueSerializable, toMapValue, + toPipelineValue, toStringValue } from '../remote/serializer'; import { hardAssert } from '../util/assert'; @@ -42,6 +43,7 @@ import { Bytes } from './bytes'; import { documentId as documentIdFieldPath, FieldPath } from './field_path'; import { vector } from './field_value_impl'; import { GeoPoint } from './geo_point'; +import type { Pipeline } from './pipeline'; import { DocumentReference } from './reference'; import { Timestamp } from './timestamp'; import { fieldPathFromArgument, parseData, UserData } from './user_data_reader'; @@ -57,7 +59,9 @@ export type ExpressionType = | 'Function' | 'AggregateFunction' | 'ListOfExpressions' - | 'AliasedExpression'; + | 'AliasedExpression' + | 'Variable' + | 'PipelineValue'; /** * @@ -1943,6 +1947,27 @@ export abstract class Expression implements ProtoValueSerializable, UserData { return new FunctionExpression('map_entries', [this], 'mapEntries'); } + /** + * @public + * Creates an expression that returns the value of a field from the document that results from the evaluation of this expression. + * + * @example + * ```typescript + * // Get the value of the "city" field in the "address" document. + * field("address").getField("city") + * ``` + * + * @param key The field to access in the document. + * @returns A new `Expression` representing the value of the field in the document. + */ + getField(key: string | Expression): Expression { + return new FunctionExpression( + 'get_field', + [this, valueToDefaultExpr(key)], + 'get_field' + ); + } + /** * Creates an aggregation that counts the number of stage inputs with valid evaluations of the * expression or field. @@ -8708,7 +8733,72 @@ export function mapEntries( } /** + * @public + * Creates an expression that returns the value of a field from a document that results from the evaluation of the expression. + * + * @example + * ```typescript + * // Get the value of the "city" field in the "address" document. + * getField(field("address"), "city") + * ``` + * + * @param key The field to access in the document. + * @returns A new `Expression` representing the value of the field in the document. + */ +export function getField(expression: Expression, key: string): Expression; +/** + * @public + * Creates an expression that returns the value of a field from a document that results from the evaluation of the expression. + * + * @example + * ```typescript + * // Get the value of the key resulting from the "addressField" variable in the "address" document. + * getField(field("address", variable("addressField")), + * ``` + * + * @param key The expression representing the key to access in the document. + * @returns A new `Expression` representing the value of the field in the document. + */ +export function getField( + expression: Expression, + keyExpr: Expression +): Expression; +/** + * @public + * Creates an expression that returns the value of a field from the document with the given field name. + * + * @example + * ```typescript + * // Get the value of the "city" field in the "address" document. + * getField("address", "city") + * ``` + * + * @param key The field to access in the document. + * @returns A new `Expression` representing the value of the field in the document. + */ +export function getField(fieldName: string, key: string): Expression; +/** + * @public + * Creates an expression that returns the value of a field from the document with the given field name. * + * @example + * ```typescript + * // Get the value of the "city" field in the "address" document. + * getField("address", variable("addressField")) + * ``` + * + * @param key The field to access in the document. + * @returns A new `Expression` representing the value of the field in the document. + */ +export function getField(fieldName: string, keyExpr: Expression): Expression; +export function getField( + fieldOrExpr: string | Expression, + keyOrExpr: string | Expression +): Expression { + return fieldOrExpression(fieldOrExpr).getField(keyOrExpr); +} + +/** * Creates an aggregation that counts the total number of stage inputs. * * @example @@ -10920,6 +11010,116 @@ export function timestampTruncate( } /** + * @public + * Creates an expression that retrieves the value of a variable bound via `define()`. + * + * @example + * ```typescript + * db.pipeline().collection("products") + * .define( + * field("price").multiply(0.9).as("discountedPrice"), + * field("stock").add(10).as("newStock") + * ) + * .where(variable("discountedPrice").lessThan(100)) + * .select(field("name"), variable("newStock")); + * ``` + * + * @param name - The name of the variable to retrieve. + * @returns An {@link @firebase/firestore/pipelines#Expression} representing the variable's value. + */ +export function variable(name: string): Expression { + return new VariableExpression(name); +} + +/** + * @internal + * + * Expression representing a variable reference. This evaluates to the value of a variable + * defined in a pipeline. + */ +export class VariableExpression extends Expression { + readonly _methodName?: string | undefined; + + /** + * @hideconstructor + */ + constructor(private readonly name: string) { + super(); + } + + expressionType: ExpressionType = 'Variable'; + + /** + * @internal + */ + _toProto(_: JsonProtoSerializer): ProtoValue { + return { + variableReferenceValue: this.name + }; + } + + /** + * @internal + */ + _readUserData(_: ParseContext): void {} +} + +/** + * @public + * Creates an expression that represents the current document being processed. + * + * @example + * ```typescript + * // Define the current document as a variable "doc" + * firestore.pipeline().collection("books") + * .define(currentDocument().as("doc")) + * // Access a field from the defined document variable + * .select(variable("doc").mapGet("title")); + * ``` + * + * @returns An {@link @firebase/firestore/pipelines#Expression} representing the current document. + */ +export function currentDocument(): Expression { + return new FunctionExpression('current_document', []); +} + +/** + * @internal + */ +export function pipelineValue(pipeline: Pipeline): PipelineValueExpression { + return new PipelineValueExpression(pipeline); +} + +/** + * @internal + */ +class PipelineValueExpression extends Expression { + readonly _methodName?: string | undefined; + expressionType: ExpressionType = 'PipelineValue'; + + /** + * @hideconstructor + */ + constructor(private readonly pipeline: Pipeline) { + super(); + } + + /** + * @internal + */ + _toProto(jsonProtoSerializer: JsonProtoSerializer): ProtoValue { + return toPipelineValue(this.pipeline._toProto(jsonProtoSerializer)); + } + + /** + * @internal + */ + _readUserData(context: ParseContext): void { + this.pipeline._readUserData(context); + } +} + +/* * Creates an expression that calculates the difference between two timestamps. * * @example @@ -11517,6 +11717,10 @@ export function isBooleanExpr(val: unknown): val is BooleanExpression { return val instanceof BooleanExpression; } +export function isAliasedExpr(val: unknown): val is AliasedExpression { + return val instanceof AliasedExpression; +} + export function isField(val: unknown): val is Field { return val instanceof Field; } diff --git a/packages/firestore/src/lite-api/pipeline-source.ts b/packages/firestore/src/lite-api/pipeline-source.ts index f1cc4151dd..5620524204 100644 --- a/packages/firestore/src/lite-api/pipeline-source.ts +++ b/packages/firestore/src/lite-api/pipeline-source.ts @@ -32,13 +32,15 @@ import { CollectionSource, DatabaseSource, DocumentsSource, - Stage + Stage, + SubcollectionSource } from './stage'; import { CollectionGroupStageOptions, CollectionStageOptions, DatabaseStageOptions, - DocumentsStageOptions + DocumentsStageOptions, + SubcollectionStageOptions } from './stage_options'; /** @@ -231,3 +233,40 @@ export class PipelineSource { } } } + +/** + * @public + * Creates a new Pipeline targeted at a subcollection relative to the current document context. + * This creates a pipeline without a database instance, suitable for embedding as a subquery. + * If executed directly, this pipeline will fail. + * + * @param path - The relative path to the subcollection. + */ +export function subcollection(path: string): Pipeline; +/** + * @public + * Creates a new Pipeline targeted at a subcollection relative to the current document context. + * This creates a pipeline without a database instance, suitable for embedding as a subquery. + * If executed directly, this pipeline will fail. + * + * @param options - Options defining how this SubcollectionStage is evaluated. + */ +export function subcollection(options: SubcollectionStageOptions): Pipeline; +export function subcollection( + pathOrOptions: string | SubcollectionStageOptions +): Pipeline { + // Process argument union(s) from method overloads + let path: string; + let options: {}; + if (isString(pathOrOptions)) { + path = pathOrOptions; + options = {}; + } else { + ({ path, ...options } = pathOrOptions); + } + + // Create stage object + const stage = new SubcollectionSource(path, options); + + return new Pipeline(undefined, [stage]); +} diff --git a/packages/firestore/src/lite-api/pipeline.ts b/packages/firestore/src/lite-api/pipeline.ts index f73220418a..b31ccee330 100644 --- a/packages/firestore/src/lite-api/pipeline.ts +++ b/packages/firestore/src/lite-api/pipeline.ts @@ -51,6 +51,9 @@ import { toField, isOrdering, isExpr, + AliasedExpression, + FunctionExpression, + isAliasedExpr, documentMatches } from './expressions'; import { @@ -70,11 +73,13 @@ import { Union, Unnest, Where, + Define, Search } from './stage'; import { AddFieldsStageOptions, AggregateStageOptions, + DefineStageOptions, DistinctStageOptions, FindNearestStageOptions, LimitStageOptions, @@ -143,7 +148,7 @@ export class Pipeline implements ProtoSerializable, UserData { * @internal * @private */ - public _db: Firestore, + public _db: Firestore | undefined, /** * @internal * @private @@ -309,6 +314,219 @@ export class Pipeline implements ProtoSerializable, UserData { return this._addStage(stage); } + /** + * @public + * Defines one or more variables in the pipeline's scope. `define` is used to bind a value to a + * variable for internal reuse within the pipeline body (accessed via the `variable()` function). + * + * This stage is useful for declaring reusable values or intermediate calculations that can be + * referenced multiple times in later parts of the pipeline, improving readability and + * maintainability. + * + * Each variable is defined using an {@link @firebase/firestore/pipelines#AliasedExpression}, which pairs an expression with a name + * (alias). The expression can be a simple constant, a field reference, or a complex computation. + * + * @example + * ```typescript + * db.pipeline().collection("products") + * .define( + * field("price").multiply(0.9).as("discountedPrice"), + * field("stock").add(10).as("newStock") + * ) + * .where(variable("discountedPrice").lessThan(100)) + * .select(field("name"), variable("newStock")); + * ``` + * + * @param aliasedExpression - The first expression to bind to a variable. + * @param additionalExpressions - Optional additional expression to bind to a variable. + * @returns A new Pipeline object with this stage appended to the stage list. + */ + define( + aliasedExpression: AliasedExpression, + ...additionalExpressions: AliasedExpression[] + ): Pipeline; + /** + * @public + * Defines one or more variables in the pipeline's scope. `define` is used to bind a value to a + * variable for internal reuse within the pipeline body (accessed via the `variable()` function). + * + * This stage is useful for declaring reusable values or intermediate calculations that can be + * referenced multiple times in later parts of the pipeline, improving readability and + * maintainability. + * + * Each variable is defined using an {@link @firebase/firestore/pipelines#AliasedExpression}, which pairs an expression with a name + * (alias). The expression can be a simple constant, a field reference, or a complex computation. + * + * @example + * ```typescript + * db.pipeline().collection("products") + * .define( + * field("price").multiply(0.9).as("discountedPrice"), + * field("stock").add(10).as("newStock") + * ) + * .where(variable("discountedPrice").lessThan(100)) + * .select(field("name"), variable("newStock")); + * ``` + * + * @param options - An object that specifies required and optional parameters for the stage. + * @returns A new Pipeline object with this stage appended to the stage list. + */ + define(options: DefineStageOptions): Pipeline; + define( + aliasedExpressionOrOptions: AliasedExpression | DefineStageOptions, + ...additionalExpressions: AliasedExpression[] + ): Pipeline { + // Process argument union(s) from method overloads + const options = isAliasedExpr(aliasedExpressionOrOptions) + ? {} + : aliasedExpressionOrOptions; + const aliasedExpressions: AliasedExpression[] = isAliasedExpr( + aliasedExpressionOrOptions + ) + ? [aliasedExpressionOrOptions, ...additionalExpressions] + : aliasedExpressionOrOptions.variables; + + const convertedExpressions: Map = + selectablesToMap(aliasedExpressions); + + const stage = new Define(convertedExpressions, options); + + return this._addStage(stage); + } + + /** + * @public + * Converts this Pipeline into an expression that evaluates to an array of results. + * + *

    Result Unwrapping:

    + *
      + *
    • If the items have a single field, their values are unwrapped and returned directly in the array.
    • + *
    • If the items have multiple fields, they are returned as objects in the array
    • + *
    + * + * @example + * ```typescript + * // Get a list of reviewers for each book + * db.pipeline().collection("books") + * .define(field("id").as("book_id")) + * .addFields( + * db.pipeline().collection("reviews") + * .where(field("book_id").equal(variable("book_id"))) + * .select(field("reviewer")) + * .toArrayExpression() + * .as("reviewers") + * ) + * ``` + * + * Output: + * ```json + * [ + * { + * "id": "1", + * "title": "1984", + * "reviewers": ["Alice", "Bob"] + * } + * ] + * ``` + * + * Multiple Fields: + * ```typescript + * // Get a list of reviews (reviewer and rating) for each book + * db.pipeline().collection("books") + * .define(field("id").as("book_id")) + * .addFields( + * db.pipeline().collection("reviews") + * .where(field("book_id").equal(variable("book_id"))) + * .select(field("reviewer"), field("rating")) + * .toArrayExpression() + * .as("reviews")) + * ``` + * + * Output: + * ```json + * [ + * { + * "id": "1", + * "title": "1984", + * "reviews": [ + * { "reviewer": "Alice", "rating": 5 }, + * { "reviewer": "Bob", "rating": 4 } + * ] + * } + * ] + * ``` + * + * @returns An `Expression` representing the execution of this pipeline. + */ + toArrayExpression(): Expression { + return new FunctionExpression('array', [fieldOrExpression(this)]); + } + + /** + * @public + * Converts this Pipeline into an expression that evaluates to a single scalar result. + * + *

    Runtime Validation: The runtime validates that the result set contains zero or one item. If + * zero items, it evaluates to `null`.

    + * + *

    Result Unwrapping:

    + *
      + *
    • If the item has a single field, its value is unwrapped and returned directly.
    • + *
    • f the item has multiple fields, they are returned as an object.
    • + *
    + * + * @example + * ```typescript + * // Calculate average rating for a restaurant + * db.pipeline().collection("restaurants").addFields( + * db.pipeline().collection("reviews") + * .where(field("restaurant_id").equal(variable("rid"))) + * .aggregate(average("rating").as("avg")) + * // Unwraps the single "avg" field to a scalar double + * .toScalarExpression().as("average_rating") + * ) + * ``` + * + * Output: + * ```json + * { + * "name": "The Burger Joint", + * "average_rating": 4.5 + * } + * ``` + * + * Multiple Fields: + * ```typescript + * // Calculate average rating AND count for a restaurant + * db.pipeline().collection("restaurants").addFields( + * db.pipeline().collection("reviews") + * .where(field("restaurant_id").equal(variable("rid"))) + * .aggregate( + * average("rating").as("avg"), + * count().as("count") + * ) + * // Returns an object with "avg" and "count" fields + * .toScalarExpression().as("stats") + * ) + * ``` + * + * Output: + * ```json + * { + * "name": "The Burger Joint", + * "stats": { + * "avg": 4.5, + * "count": 100 + * } + * } + * ``` + * + * @returns An `Expression` representing the execution of this pipeline. + */ + toScalarExpression(): Expression { + return new FunctionExpression('scalar', [fieldOrExpression(this)]); + } + /** * Selects or creates a set of fields from the outputs of previous stages. * @@ -1414,7 +1632,7 @@ export class Pipeline implements ProtoSerializable, UserData { * @param stages * @protected */ - protected newPipeline(db: Firestore, stages: Stage[]): Pipeline { + protected newPipeline(db: Firestore | undefined, stages: Stage[]): Pipeline { return new Pipeline(db, stages); } } diff --git a/packages/firestore/src/lite-api/pipeline_impl.ts b/packages/firestore/src/lite-api/pipeline_impl.ts index 0c375ca4c7..bed3a5c43e 100644 --- a/packages/firestore/src/lite-api/pipeline_impl.ts +++ b/packages/firestore/src/lite-api/pipeline_impl.ts @@ -20,6 +20,7 @@ import { StructuredPipelineOptions } from '../core/structured_pipeline'; import { invokeExecutePipeline } from '../remote/datastore'; +import { Code, FirestoreError } from '../util/error'; import { cast } from '../util/input_validation'; import { getDatastore } from './components'; @@ -80,6 +81,14 @@ declare module './database' { * @returns A Promise representing the asynchronous pipeline execution. */ export function execute(pipeline: Pipeline): Promise { + if (!pipeline._db) { + return Promise.reject( + new FirestoreError( + Code.FAILED_PRECONDITION, + 'This pipeline was created without a database (e.g., as a subcollection pipeline) and cannot be executed directly. It can only be used as part of another pipeline.' + ) + ); + } const datastore = getDatastore(pipeline._db); const firestore = cast(pipeline._db, Firestore); @@ -117,7 +126,7 @@ export function execute(pipeline: Pipeline): Promise { userDataWriter, element.fields!, element.key?.path - ? new DocumentReference(pipeline._db, null, element.key) + ? new DocumentReference(firestore, null, element.key) : undefined, element.createTime?.toTimestamp(), element.updateTime?.toTimestamp() diff --git a/packages/firestore/src/lite-api/stage.ts b/packages/firestore/src/lite-api/stage.ts index f6fc5dc453..de6ee53adb 100644 --- a/packages/firestore/src/lite-api/stage.ts +++ b/packages/firestore/src/lite-api/stage.ts @@ -135,6 +135,42 @@ export class RemoveFields extends Stage { } } +/** + * @public + */ +export class Define extends Stage { + get _name(): string { + return 'let'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor( + private aliasedExpressions: Map, + options: StageOptions + ) { + super(options); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [toMapValue(serializer, this.aliasedExpressions)] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + readUserDataHelper(this.aliasedExpressions, context); + } +} + export class Aggregate extends Stage { get _name(): string { return 'aggregate'; @@ -276,6 +312,35 @@ export class CollectionGroupSource extends Stage { } } +export class SubcollectionSource extends Stage { + get _name(): string { + return 'subcollection'; + } + + get _optionsUtil(): OptionsUtil { + return new OptionsUtil({}); + } + + constructor(private path: string, options: StageOptions) { + super(options); + } + + /** + * @internal + * @private + */ + _toProto(serializer: JsonProtoSerializer): ProtoStage { + return { + ...super._toProto(serializer), + args: [{ stringValue: this.path }] + }; + } + + _readUserData(context: ParseContext): void { + super._readUserData(context); + } +} + export class DatabaseSource extends Stage { get _name(): string { return 'database'; diff --git a/packages/firestore/src/lite-api/stage_options.ts b/packages/firestore/src/lite-api/stage_options.ts index 7c78aac169..692a3004d5 100644 --- a/packages/firestore/src/lite-api/stage_options.ts +++ b/packages/firestore/src/lite-api/stage_options.ts @@ -19,6 +19,7 @@ import { OneOf } from '../util/types'; import { AliasedAggregate, + AliasedExpression, BooleanExpression, Expression, Field, @@ -96,6 +97,19 @@ export type CollectionGroupStageOptions = StageOptions & { */ forceIndex?: string; }; + +/** + * @public + * Options defining how a `SubcollectionStage` is evaluated. + */ +export type SubcollectionStageOptions = StageOptions & { + /** + * @public + * The relative path to the subcollection. + */ + path: string; +}; + /** * Options defining how a DatabaseStage is evaluated. See {@link @firebase/firestore/pipelines#PipelineSource.(database:1)}. */ @@ -130,6 +144,17 @@ export type RemoveFieldsStageOptions = StageOptions & { */ fields: Array; }; +/** + * @public + * Options defining how a DefineStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(define:1)}. + */ +export type DefineStageOptions = StageOptions & { + /** + * @public + * The variables to define. + */ + variables: AliasedExpression[]; +}; /** * Options defining how a SelectStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(select:1)}. */ diff --git a/packages/firestore/src/protos/firestore_proto_api.ts b/packages/firestore/src/protos/firestore_proto_api.ts index cc1c57259f..265cd3054d 100644 --- a/packages/firestore/src/protos/firestore_proto_api.ts +++ b/packages/firestore/src/protos/firestore_proto_api.ts @@ -458,6 +458,7 @@ export declare namespace firestoreV1ApiClientInterfaces { arrayValue?: ArrayValue; mapValue?: MapValue; fieldReferenceValue?: string; + variableReferenceValue?: string; // NOTE: This was added manually. // eslint-disable-next-line @typescript-eslint/ban-types functionValue?: Function; pipelineValue?: Pipeline; diff --git a/packages/firestore/src/protos/google/firestore/v1/document.proto b/packages/firestore/src/protos/google/firestore/v1/document.proto index f760575050..e186dd96d7 100644 --- a/packages/firestore/src/protos/google/firestore/v1/document.proto +++ b/packages/firestore/src/protos/google/firestore/v1/document.proto @@ -144,6 +144,13 @@ message Value { // allowed to be used on the write path. --) string field_reference_value = 19; + // Pointer to a variable defined elsewhere in a pipeline. + // + // Unlike `field_reference_value` which references a field within a + // document, this refers to a variable, defined in a separate namespace than + // the fields of a document. + string variable_reference_value = 22; + // A value that represents an unevaluated expression. // // **Requires:** diff --git a/packages/firestore/src/protos/protos.json b/packages/firestore/src/protos/protos.json index 5b73c4647f..ab3ddc50e8 100644 --- a/packages/firestore/src/protos/protos.json +++ b/packages/firestore/src/protos/protos.json @@ -89,6 +89,7 @@ } }, "FileDescriptorSet": { + "edition": "proto2", "fields": { "file": { "rule": "repeated", @@ -98,6 +99,7 @@ } }, "FileDescriptorProto": { + "edition": "proto2", "fields": { "name": { "type": "string", @@ -115,18 +117,12 @@ "publicDependency": { "rule": "repeated", "type": "int32", - "id": 10, - "options": { - "packed": false - } + "id": 10 }, "weakDependency": { "rule": "repeated", "type": "int32", - "id": 11, - "options": { - "packed": false - } + "id": 11 }, "messageType": { "rule": "repeated", @@ -163,6 +159,7 @@ } }, "DescriptorProto": { + "edition": "proto2", "fields": { "name": { "type": "string", @@ -245,6 +242,7 @@ } }, "ExtensionRangeOptions": { + "edition": "proto2", "fields": { "uninterpretedOption": { "rule": "repeated", @@ -260,6 +258,7 @@ ] }, "FieldDescriptorProto": { + "edition": "proto2", "fields": { "name": { "type": "string", @@ -335,6 +334,7 @@ } }, "OneofDescriptorProto": { + "edition": "proto2", "fields": { "name": { "type": "string", @@ -347,6 +347,7 @@ } }, "EnumDescriptorProto": { + "edition": "proto2", "fields": { "name": { "type": "string", @@ -388,6 +389,7 @@ } }, "EnumValueDescriptorProto": { + "edition": "proto2", "fields": { "name": { "type": "string", @@ -404,6 +406,7 @@ } }, "ServiceDescriptorProto": { + "edition": "proto2", "fields": { "name": { "type": "string", @@ -421,6 +424,7 @@ } }, "MethodDescriptorProto": { + "edition": "proto2", "fields": { "name": { "type": "string", @@ -455,6 +459,7 @@ } }, "FileOptions": { + "edition": "proto2", "fields": { "javaPackage": { "type": "string", @@ -595,6 +600,7 @@ } }, "MessageOptions": { + "edition": "proto2", "fields": { "messageSetWireFormat": { "type": "bool", @@ -645,6 +651,7 @@ ] }, "FieldOptions": { + "edition": "proto2", "fields": { "ctype": { "type": "CType", @@ -721,6 +728,7 @@ } }, "OneofOptions": { + "edition": "proto2", "fields": { "uninterpretedOption": { "rule": "repeated", @@ -736,6 +744,7 @@ ] }, "EnumOptions": { + "edition": "proto2", "fields": { "allowAlias": { "type": "bool", @@ -768,6 +777,7 @@ ] }, "EnumValueOptions": { + "edition": "proto2", "fields": { "deprecated": { "type": "bool", @@ -790,6 +800,7 @@ ] }, "ServiceOptions": { + "edition": "proto2", "fields": { "deprecated": { "type": "bool", @@ -812,6 +823,7 @@ ] }, "MethodOptions": { + "edition": "proto2", "fields": { "deprecated": { "type": "bool", @@ -850,6 +862,7 @@ } }, "UninterpretedOption": { + "edition": "proto2", "fields": { "name": { "rule": "repeated", @@ -899,6 +912,7 @@ } }, "SourceCodeInfo": { + "edition": "proto2", "fields": { "location": { "rule": "repeated", @@ -912,12 +926,18 @@ "path": { "rule": "repeated", "type": "int32", - "id": 1 + "id": 1, + "options": { + "packed": true + } }, "span": { "rule": "repeated", "type": "int32", - "id": 2 + "id": 2, + "options": { + "packed": true + } }, "leadingComments": { "type": "string", @@ -937,6 +957,7 @@ } }, "GeneratedCodeInfo": { + "edition": "proto2", "fields": { "annotation": { "rule": "repeated", @@ -950,7 +971,10 @@ "path": { "rule": "repeated", "type": "int32", - "id": 1 + "id": 1, + "options": { + "packed": true + } }, "sourceFile": { "type": "string", @@ -1129,6 +1153,7 @@ "arrayValue", "mapValue", "fieldReferenceValue", + "variableReferenceValue", "functionValue", "pipelineValue" ] @@ -1183,6 +1208,10 @@ "type": "string", "id": 19 }, + "variableReferenceValue": { + "type": "string", + "id": 22 + }, "functionValue": { "type": "Function", "id": 20 @@ -3091,9 +3120,9 @@ }, "api": { "options": { - "go_package": "google.golang.org/genproto/googleapis/api;api", + "go_package": "google.golang.org/genproto/googleapis/api/annotations;annotations", "java_multiple_files": true, - "java_outer_classname": "LaunchStageProto", + "java_outer_classname": "FieldBehaviorProto", "java_package": "com.google.api", "objc_class_prefix": "GAPI", "cc_enable_arenas": true @@ -3219,18 +3248,6 @@ "UNORDERED_LIST": 6, "NON_EMPTY_DEFAULT": 7 } - }, - "LaunchStage": { - "values": { - "LAUNCH_STAGE_UNSPECIFIED": 0, - "UNIMPLEMENTED": 6, - "PRELAUNCH": 7, - "EARLY_ACCESS": 1, - "ALPHA": 2, - "BETA": 3, - "GA": 4, - "DEPRECATED": 5 - } } } }, diff --git a/packages/firestore/src/remote/internal_serializer.ts b/packages/firestore/src/remote/internal_serializer.ts index d282bff1e5..eaf1251e1a 100644 --- a/packages/firestore/src/remote/internal_serializer.ts +++ b/packages/firestore/src/remote/internal_serializer.ts @@ -31,6 +31,7 @@ import { UserDataSource } from '../lite-api/user_data_reader'; import { ExecutePipelineRequest as ProtoExecutePipelineRequest } from '../protos/firestore_proto_api'; +import { Code, FirestoreError } from '../util/error'; import { cast } from '../util/input_validation'; import { mapToArray } from '../util/obj'; @@ -119,6 +120,13 @@ export function _internalPipelineToExecutePipelineRequestProto( pipeline: Pipeline // eslint-disable-next-line @typescript-eslint/no-explicit-any ): any { + if (!pipeline._db) { + throw new FirestoreError( + Code.FAILED_PRECONDITION, + 'This pipeline was created without a database and cannot be serialized for execution.' + ); + } + const firestore = cast(pipeline._db, Firestore); const userDataReader = newUserDataReader(firestore); diff --git a/packages/firestore/src/remote/serializer.ts b/packages/firestore/src/remote/serializer.ts index f11781ac33..b8283fad97 100644 --- a/packages/firestore/src/remote/serializer.ts +++ b/packages/firestore/src/remote/serializer.ts @@ -94,7 +94,7 @@ import { Value as ProtoValue, MapValue as ProtoMapValue, ExecutePipelineResponse as ProtoExecutePipelineResponse, - Pipeline + Pipeline as ProtoPipeline } from '../protos/firestore_proto_api'; import { debugAssert, fail, hardAssert } from '../util/assert'; import { ByteString } from '../util/byte_string'; @@ -1502,7 +1502,7 @@ export function toStringValue(value: string): ProtoValue { return { stringValue: value }; } -export function toPipelineValue(value: Pipeline): ProtoValue { +export function toPipelineValue(value: ProtoPipeline): ProtoValue { return { pipelineValue: value }; } diff --git a/packages/firestore/src/util/pipeline_util.ts b/packages/firestore/src/util/pipeline_util.ts index 9f91ca8240..38ce3fecb1 100644 --- a/packages/firestore/src/util/pipeline_util.ts +++ b/packages/firestore/src/util/pipeline_util.ts @@ -27,8 +27,10 @@ import { field, Field, map, - Selectable + Selectable, + pipelineValue } from '../lite-api/expressions'; +import type { Pipeline } from '../lite-api/pipeline'; import { VectorValue } from '../lite-api/vector_value'; import { fail } from './assert'; @@ -158,9 +160,24 @@ export function valueToDefaultExpr(value: unknown): Expression { result = map(value as Record); } else if (value instanceof Array) { result = array(value); + } else if (isPipeline(value)) { + result = pipelineValue(value); } else { result = _constant(value, undefined); } return result; } + +/** + * Checks if a value is a Pipeline object. + * + * We use duck typing here to avoid a circular dependency between pipeline.ts and pipeline_util.ts. + */ +function isPipeline(value: unknown): value is Pipeline { + return ( + typeof value === 'object' && + value !== null && + typeof (value as Pipeline).toArrayExpression === 'function' + ); +} diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 0707a8ebb4..af3cfeb6ef 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -24,6 +24,7 @@ import { FirebaseError } from '@firebase/util'; import { expect, use } from 'chai'; import chaiAsPromised from 'chai-as-promised'; +import { logWarn } from '../../../src/util/log'; import { addEqualityMatcher } from '../../util/equality_matcher'; import { Deferred } from '../../util/promise'; import { @@ -44,6 +45,7 @@ import { addDoc, DocumentReference, deleteDoc, + FirestoreError, getDocs } from '../util/firebase_export'; import { apiDescribe, withTestCollection, withTestDbs } from '../util/helpers'; @@ -181,6 +183,9 @@ import { split, type, isType, + currentDocument, + variable, + subcollection, coalesce, ifNull, score, @@ -5822,6 +5827,868 @@ apiDescribe.skipClassic('Pipelines', persistence => { }); }); }); + + describe('subquery', () => { + async function withSubqueryData( + data: { [path: string]: DocumentData }, + fn: () => Promise + ): Promise { + const refs: DocumentReference[] = []; + try { + await Promise.all( + Object.entries(data).map(async ([path, docData]) => { + const ref = doc(firestore, path); + await setDoc(ref, docData); + refs.push(ref); + }) + ); + return await fn(); + } finally { + await Promise.all(refs.map(r => deleteDoc(r))); + } + } + + it('zero result scalar returns null', async () => { + const testDocs = { + [`${randomCol.path}/book1`]: { title: 'A Book Title' } + }; + + await withSubqueryData(testDocs, async () => { + const emptyScalar = firestore + .pipeline() + .collection(`${randomCol.path}/book1/reviews`) + .where(equal('reviewer', 'Alice')) + .select(currentDocument().as('data')); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(emptyScalar.toScalarExpression().as('firstReviewData')) + .limit(1) + ); + + expectResults(results, { firstReviewData: null }); + }); + }); + + it('array subquery join and empty result', async () => { + const reviewsCollName = `book_reviews_${Date.now()}`; + const reviewsDocs = { + [`${reviewsCollName}/r1`]: { + bookTitle: "The Hitchhiker's Guide to the Galaxy", + reviewer: 'Alice' + }, + [`${reviewsCollName}/r2`]: { + bookTitle: "The Hitchhiker's Guide to the Galaxy", + reviewer: 'Bob' + } + }; + + await withSubqueryData(reviewsDocs, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .select(field('reviewer').as('reviewer')) + .sort(field('reviewer').ascending()); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + or( + equal('title', "The Hitchhiker's Guide to the Galaxy"), + equal('title', 'Pride and Prejudice') + ) + ) + .define(field('title').as('bookTitle')) + .addFields(reviewsSub.toArrayExpression().as('reviewsData')) + .select('title', 'reviewsData') + .sort(field('title').descending()) + ); + + expectResults( + results, + { + title: "The Hitchhiker's Guide to the Galaxy", + reviewsData: ['Alice', 'Bob'] + }, + { title: 'Pride and Prejudice', reviewsData: [] } + ); + }); + }); + + it('multiple array subqueries', async () => { + const reviewsCollectionName = `reviews_multi_${Date.now()}`; + const authorsCollectionName = `authors_multi_${Date.now()}`; + + const data = { + [`${reviewsCollectionName}/r1`]: { + bookTitle: '1984', + rating: 5 + }, + [`${authorsCollectionName}/a1`]: { + authorName: 'George Orwell', + nationality: 'British' + } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollectionName) + .where(equal('bookTitle', variable('bookTitle'))) + .select(field('rating').as('rating')); + + const authorsSub = firestore + .pipeline() + .collection(authorsCollectionName) + .where(equal('authorName', variable('authorName'))) + .select(field('nationality').as('nationality')); + + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define( + field('title').as('bookTitle'), + field('author').as('authorName') + ) + .addFields( + reviewsSub.toArrayExpression().as('reviewsData'), + authorsSub.toArrayExpression().as('authorsData') + ) + .select('title', 'reviewsData', 'authorsData') + ); + + expectResults(snapshot, { + title: '1984', + reviewsData: [5], + authorsData: ['British'] + }); + }); + }); + + it('array subquery join multiple fields preserves map', async () => { + const reviewsCollName = `reviews_map_${Date.now()}`; + + const data = { + [`${reviewsCollName}/r1`]: { + bookTitle: '1984', + reviewer: 'Alice', + rating: 5 + }, + [`${reviewsCollName}/r2`]: { + bookTitle: '1984', + reviewer: 'Bob', + rating: 4 + } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .select( + field('reviewer').as('reviewer'), + field('rating').as('rating') + ) + .sort(field('reviewer').ascending()); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define(field('title').as('bookTitle')) + .addFields(reviewsSub.toArrayExpression().as('reviewsData')) + .select('title', 'reviewsData') + ); + + expectResults(results, { + title: '1984', + reviewsData: [ + { reviewer: 'Alice', rating: 5 }, + { reviewer: 'Bob', rating: 4 } + ] + }); + }); + }); + + it('array subquery in where stage on books', async () => { + const reviewsCollName = `reviews_where_${Date.now()}`; + + const data = { + [`${reviewsCollName}/r1`]: { + bookTitle: 'Dune', + reviewer: 'Paul' + }, + [`${reviewsCollName}/r2`]: { + bookTitle: 'Foundation', + reviewer: 'Hari' + } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .select(field('reviewer').as('reviewer')); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + or(equal('title', 'Dune'), equal('title', 'The Great Gatsby')) + ) + .define(field('title').as('bookTitle')) + .where(reviewsSub.toArrayExpression().arrayContains('Paul')) + .select('title') + ); + + expectResults(results, { title: 'Dune' }); + }); + }); + + it('scalar subquery single aggregation unwrapping', async () => { + const reviewsCollName = `reviews_agg_single_${Date.now()}`; + + const data = { + [`${reviewsCollName}/r1`]: { bookTitle: '1984', rating: 4 }, + [`${reviewsCollName}/r2`]: { bookTitle: '1984', rating: 5 } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .aggregate(average('rating').as('val')); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define(field('title').as('bookTitle')) + .addFields(reviewsSub.toScalarExpression().as('averageRating')) + .select('title', 'averageRating') + ); + + expectResults(results, { title: '1984', averageRating: 4.5 }); + }); + }); + + it('scalar subquery multiple aggregations map wrapping', async () => { + const reviewsCollName = `reviews_agg_multi_${Date.now()}`; + + const data = { + [`${reviewsCollName}/r1`]: { bookTitle: '1984', rating: 4 }, + [`${reviewsCollName}/r2`]: { bookTitle: '1984', rating: 5 } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .aggregate(average('rating').as('avg'), countAll().as('count')); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define(field('title').as('bookTitle')) + .addFields(reviewsSub.toScalarExpression().as('stats')) + .select('title', 'stats') + ); + + expectResults(results, { + title: '1984', + stats: { avg: 4.5, count: 2 } + }); + }); + }); + + it('scalar subquery zero results', async () => { + const reviewsCollName = `reviews_zero_${Date.now()}`; + + // No reviews for "1984" + + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .aggregate(average('rating').as('avg')); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define(field('title').as('bookTitle')) + .addFields(reviewsSub.toScalarExpression().as('averageRating')) + .select('title', 'averageRating') + ); + + expectResults(results, { title: '1984', averageRating: null }); + }); + + it('scalar subquery multiple results runtime error', async () => { + const reviewsCollName = `reviews_multiple_${Date.now()}`; + + const data = { + [`${reviewsCollName}/r1`]: { bookTitle: '1984', rating: 4 }, + [`${reviewsCollName}/r2`]: { bookTitle: '1984', rating: 5 } + }; + + await withSubqueryData(data, async () => { + // This subquery will return 2 documents, which is invalid for toScalarExpression() + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))); + + await expect( + execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define(field('title').as('bookTitle')) + .addFields(reviewsSub.toScalarExpression().as('reviewData')) + ) + ).to.be.rejectedWith(/Subpipeline returned multiple results/); + }); + }); + + it('mixed scalar and array subqueries', async () => { + const reviewsCollName = `reviews_mixed_${Date.now()}`; + + const data = { + [`${reviewsCollName}/r1`]: { + bookTitle: '1984', + reviewer: 'Alice', + rating: 4 + }, + [`${reviewsCollName}/r2`]: { + bookTitle: '1984', + reviewer: 'Bob', + rating: 5 + } + }; + + await withSubqueryData(data, async () => { + const arraySub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .select(field('reviewer').as('reviewer')) + .sort(field('reviewer').ascending()); + + const scalarSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .aggregate(average('rating').as('val')); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define(field('title').as('bookTitle')) + .addFields( + arraySub.toArrayExpression().as('allReviewers'), + scalarSub.toScalarExpression().as('averageRating') + ) + .select('title', 'allReviewers', 'averageRating') + ); + + expectResults(results, { + title: '1984', + allReviewers: ['Alice', 'Bob'], + averageRating: 4.5 + }); + }); + }); + + it('single scope variable usage', async () => { + const collName = `single_scope_${Date.now()}`; + + await withSubqueryData( + { [`${collName}/doc1`]: { price: 100 } }, + async () => { + let results = await execute( + firestore + .pipeline() + .collection(collName) + .define(field('price').multiply(0.8).as('discount')) + .where(variable('discount').lessThan(50.0)) + .select('price') + ); + + expect(results.results).to.be.empty; + + const doc2Ref = doc(firestore, `${collName}/doc2`); + await setDoc(doc2Ref, { price: 50 }); + + try { + results = await execute( + firestore + .pipeline() + .collection(collName) + .define(field('price').multiply(0.8).as('discount')) + .where(variable('discount').lessThan(50.0)) + .select('price') + ); + + expectResults(results, { price: 50 }); + } finally { + await deleteDoc(doc2Ref); + } + } + ); + }); + + it('explicit field binding scope bridging', async () => { + const outerCollName = `outer_scope_${Date.now()}`; + const reviewsCollName = `reviews_scope_${Date.now()}`; + + const data = { + [`${outerCollName}/doc1`]: { title: '1984', id: '1' }, + [`${reviewsCollName}/r1`]: { bookId: '1', reviewer: 'Alice' } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookId', variable('rid'))) + .select(field('reviewer').as('reviewer')); + + const results = await execute( + firestore + .pipeline() + .collection(outerCollName) + .where(equal('title', '1984')) + .define(field('id').as('rid')) + .addFields(reviewsSub.toArrayExpression().as('reviews')) + .select('title', 'reviews') + ); + + expectResults(results, { title: '1984', reviews: ['Alice'] }); + }); + }); + + it('multiple variable bindings', async () => { + const outerCollName = `outer_multi_${Date.now()}`; // distinct from earlier test + const reviewsCollName = `reviews_multi_${Date.now()}`; + + const data = { + [`${outerCollName}/doc1`]: { + title: '1984', + id: '1', + category: 'sci-fi' + }, + [`${reviewsCollName}/r1`]: { + bookId: '1', + category: 'sci-fi', + reviewer: 'Alice' + } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where( + and( + equal('bookId', variable('rid')), + equal('category', variable('rcat')) + ) + ) + .select(field('reviewer').as('reviewer')); + + const results = await execute( + firestore + .pipeline() + .collection(outerCollName) + .where(equal('title', '1984')) + .define(field('id').as('rid'), field('category').as('rcat')) + .addFields(reviewsSub.toArrayExpression().as('reviews')) + .select('title', 'reviews') + ); + + expectResults(results, { title: '1984', reviews: ['Alice'] }); + }); + }); + + it('current document binding', async () => { + const outerCollName = `outer_currentdoc_${Date.now()}`; + const reviewsCollName = `reviews_currentdoc_${Date.now()}`; + + const data = { + [`${outerCollName}/doc1`]: { title: '1984', author: 'George Orwell' }, + [`${reviewsCollName}/r1`]: { + authorName: 'George Orwell', + reviewer: 'Alice' + } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('authorName', variable('doc').getField('author'))) + .select(field('reviewer').as('reviewer')); + + const ppl = firestore + .pipeline() + .collection(outerCollName) + .where(equal('title', '1984')) + .define(currentDocument().as('doc')) + .addFields(reviewsSub.toArrayExpression().as('reviews')) + .select('title', 'reviews'); + + // TODO(dlarocque): Remove these target backend conditionals once the 'get_field' rename has rolled out to prod. + const host = firestore._getSettings().host; + const isProd = host === 'firestore.googleapis.com'; + const isNightly = host === 'test-firestore.sandbox.googleapis.com'; + + if (isProd) { + // The execution of this pipeline is expected to result in a network error + // from the backend until the breaking change to rename the 'field' expression to + // 'get_field' has rolled out to prod. + try { + const results = await execute(ppl); + + // If this is reached, the execution of the pipeline didn't throw an error, so the + // breaking change must have rolled out to prod. We can assert the newly expected behaviour. + logWarn( + "The 'get_field' expression rename has rolled out to the prod backend. Remove the target backend conditionals in this test." + ); + expectResults(results, { title: '1984', reviews: ['Alice'] }); + } catch (err: unknown) { + const error: Error = err as Error; + expect(error.message).to.equals( + "The function 'get_field' does not exist, did you mean 'field'?" + ); + } + } else if (isNightly) { + const results = await execute(ppl); + expectResults(results, { title: '1984', reviews: ['Alice'] }); + } else { + expect(false).to.equal( + true, + `This test is only expected to run against firestore.googleapis.com or test-firestore.sandbox.googleapis.com, but it instead ran against ${host}` + ); + } + }); + }); + + it('unbound variable corner case', async () => { + const outerCollName = `outer_unbound_${Date.now()}`; + + try { + await execute( + firestore + .pipeline() + .collection(outerCollName) + .where(equal('title', variable('unknownVar'))) + ); + expect.fail('Should have thrown an error'); + } catch (e: unknown) { + expect(e).to.be.an.instanceOf(FirebaseError); + const err = e as FirestoreError; + expect(err.code).to.equal('invalid-argument'); + expect(err.message).to.match(/unknown variable/i); + } + }); + it('variable shadowing collision', async () => { + const outerCollName = `outer_shadow_${Date.now()}`; + const innerCollName = `inner_shadow_${Date.now()}`; + + const data = { + [`${outerCollName}/doc1`]: { title: '1984' }, + [`${innerCollName}/i1`]: { id: 'test' } + }; + + await withSubqueryData(data, async () => { + // Inner subquery re-defines variable "x" to be "inner_val" + const sub = firestore + .pipeline() + .collection(innerCollName) + .define(constant('inner_val').as('x')) + .select(variable('x').as('val')); + + // Outer pipeline defines variable "x" to be "outer_val" + const results = await execute( + firestore + .pipeline() + .collection(outerCollName) + .where(equal('title', '1984')) + .limit(1) + .define(constant('outer_val').as('x')) + .addFields(sub.toArrayExpression().as('shadowed')) + .select('shadowed') + ); + + // Due to innermost scope winning, the result should use "inner_val" + expectResults(results, { shadowed: ['inner_val'] }); + }); + }); + + it('missing field on current document', async () => { + const outerCollName = `outer_missing_${Date.now()}`; + const reviewsCollName = `reviews_missing_${Date.now()}`; + + const data = { + [`${outerCollName}/doc1`]: { title: '1984' }, + [`${reviewsCollName}/r1`]: { bookId: '1', reviewer: 'Alice' } + }; + + await withSubqueryData(data, async () => { + // This references a non-existent field 'doesNotExist' on the current document 'doc' + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + // using mapGet explicitly or just field path if supported on maps + .where(equal('bookId', variable('doc').getField('doesNotExist'))) + .select(field('reviewer').as('reviewer')); + + const ppl = firestore + .pipeline() + .collection(outerCollName) + .where(equal('title', '1984')) + .define(currentDocument().as('doc')) + .addFields(reviewsSub.toArrayExpression().as('reviews')) + .select('title', 'reviews'); + + // TODO(dlarocque): Remove these target backend conditionals once the 'get_field' rename has rolled out to prod. + const host = firestore._getSettings().host; + const isProd = host === 'firestore.googleapis.com'; + const isNightly = host === 'test-firestore.sandbox.googleapis.com'; + + if (isProd) { + // The execution of this pipeline is expected to result in a network error + // from the backend until the breaking change to rename the 'field' expression to + // 'get_field' has rolled out to prod. + try { + const results = await execute(ppl); + + // If this is reached, the execution of the pipeline didn't throw an error, so the + // breaking change must have rolled out to prod. We can assert the newly expected behaviour. + logWarn( + "The 'get_field' expression rename has rolled out to the prod backend. Remove the target backend conditionals in this test." + ); + expectResults(results, { title: '1984', reviews: [] }); + } catch (err: unknown) { + const error: Error = err as Error; + expect(error.message).to.equals( + "The function 'get_field' does not exist, did you mean 'field'?" + ); + } + } else if (isNightly) { + const results = await execute(ppl); + expectResults(results, { title: '1984', reviews: [] }); + } else { + expect(false).to.equal( + true, + `This test is only expected to run against firestore.googleapis.com or test-firestore.sandbox.googleapis.com, but it instead ran against ${host}` + ); + } + }); + }); + + it('3 level deep join', async () => { + const publishersCollName = `publishers_${Date.now()}`; + const booksCollName = `books_${Date.now()}`; + const reviewsCollName = `reviews_${Date.now()}`; + + const data = { + [`${publishersCollName}/p1`]: { publisherId: 'pub1', name: 'Penguin' }, + [`${booksCollName}/b1`]: { + bookId: 'book1', + publisherId: 'pub1', + title: '1984' + }, + [`${reviewsCollName}/r1`]: { bookId: 'book1', reviewer: 'Alice' } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where( + and( + equal('bookId', variable('bookId')), + equal(variable('pubName'), 'Penguin') + ) + ) + .select(field('reviewer').as('reviewer')); + + const booksSub = firestore + .pipeline() + .collection(booksCollName) + .where(equal('publisherId', variable('pubId'))) + .define(field('bookId').as('bookId')) + .addFields(reviewsSub.toArrayExpression().as('reviews')) + .select('title', 'reviews'); + + const results = await execute( + firestore + .pipeline() + .collection(publishersCollName) + .where(equal('publisherId', 'pub1')) + .define( + field('publisherId').as('pubId'), + field('name').as('pubName') + ) + .addFields(booksSub.toArrayExpression().as('books')) + .select('name', 'books') + ); + + expectResults(results, { + name: 'Penguin', + books: [{ title: '1984', reviews: ['Alice'] }] + }); + }); + }); + + it('deep aggregation', async () => { + const outerColl = `outer_agg_${Date.now()}`; + const innerColl = `inner_agg_${Date.now()}`; + + const data = { + [`${outerColl}/doc1`]: { id: '1' }, + [`${outerColl}/doc2`]: { id: '2' }, + [`${innerColl}/i1`]: { outerId: '1', score: 10 }, + [`${innerColl}/i2`]: { outerId: '2', score: 20 }, + [`${innerColl}/i3`]: { outerId: '1', score: 30 } + }; + + await withSubqueryData(data, async () => { + const innerSub = firestore + .pipeline() + .collection(innerColl) + .where(equal('outerId', variable('oid'))) + .aggregate(average('score').as('s')); + + const results = await execute( + firestore + .pipeline() + .collection(outerColl) + .define(field('id').as('oid')) + .addFields(innerSub.toScalarExpression().as('docScore')) + // Aggregate over calculated subquery results + .aggregate(sum('docScore').as('totalScore')) + ); + + expectResults(results, { totalScore: 40.0 }); + }); + }); + + // NOTE: We aren't able to created nested pipelines deeper than 9 layer + // because JSON is more verbose than gRPC format used on other platforms. + it('pipeline stage support 9 layers', async () => { + const collName = `depth_${Date.now()}`; + + await withSubqueryData( + { [`${collName}/doc1`]: { val: 'hello' } }, + async () => { + // Create a nested pipeline of depth 9 + let currentSubquery = firestore + .pipeline() + .collection(collName) + .limit(1) + .select(field('val').as('val')); + + for (let i = 0; i < 8; i++) { + currentSubquery = firestore + .pipeline() + .collection(collName) + .limit(1) + .addFields(currentSubquery.toArrayExpression().as(`nested_${i}`)) + .select(`nested_${i}`); + } + + const results = await execute(currentSubquery); + expect(results.results.length).to.be.greaterThan(0); + } + ); + }); + + it('standard subcollection query', async () => { + const collName = `subcoll_test_${Date.now()}`; + + const doc1Ref = doc(firestore, `${collName}/doc1`); + await setDoc(doc1Ref, { title: '1984' }); + + const r1Ref = doc(firestore, `${collName}/doc1/reviews/r1`); + await setDoc(r1Ref, { reviewer: 'Alice' }); + + // Assuming Pipeline.subcollection API exists or similar + const reviewsSub = subcollection('reviews').select( + field('reviewer').as('reviewer') + ); + + const results = await execute( + firestore + .pipeline() + .collection(collName) + .where(equal('title', '1984')) + .addFields(reviewsSub.toArrayExpression().as('reviews')) + .select('title', 'reviews') + ); + + expectResults(results, { + title: '1984', + reviews: ['Alice'] + }); + + await Promise.all([deleteDoc(doc1Ref), deleteDoc(r1Ref)]); + }); + + it('missing subcollection', async () => { + const collName = `subcoll_missing_${Date.now()}`; + const doc1Ref = doc(firestore, `${collName}/doc1`); + + await setDoc(doc1Ref, { id: 'no_subcollection_here' }); + + const missingSub = subcollection('doesNotExist').select( + variable('p').as('subP') + ); + + const results = await execute( + firestore + .pipeline() + .collection(collName) + .define(currentDocument().as('p')) + .select(missingSub.toArrayExpression().as('missingData')) + .limit(1) + ); + + expectResults(results, { missingData: [] }); + + await deleteDoc(doc1Ref); + }); + + it('direct execution of subcollection pipeline', async () => { + const sub = subcollection('reviews'); + + await expect(execute(sub)).to.be.rejectedWith( + /This pipeline was created without a database/ + ); + }); + }); }); (getRunEnterpriseTests() && getTargetBackend() === TargetBackend.NIGHTLY diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 24a548ff2a..0a86dcd3ed 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -52,6 +52,8 @@ import { import { FindNearestStageOptions } from '../../src/lite-api/stage_options'; import { Timestamp } from '../../src/lite-api/timestamp'; import { writeBatch } from '../../src/lite-api/write_batch'; +import { Code, FirestoreError } from '../../src/util/error'; +import { logWarn } from '../../src/util/log'; import { getRunEnterpriseTests, getTargetBackend, @@ -180,6 +182,8 @@ import { ifAbsent, coalesce, join, + variable, + currentDocument, arraySum, arrayFirst, arrayFirstN, @@ -192,6 +196,7 @@ import { arrayIndexOf, arrayIndexOfAll, arrayLastIndexOf, + subcollection, ifNull, documentMatches, score @@ -5694,6 +5699,869 @@ describe.skipClassic('Firestore Pipelines', () => { }); }); }); + + describe('subquery', () => { + async function withSubqueryData( + data: { [path: string]: DocumentData }, + fn: () => Promise + ): Promise { + const refs: DocumentReference[] = []; + try { + await Promise.all( + Object.entries(data).map(async ([path, docData]) => { + const ref = doc(firestore, path); + await setDoc(ref, docData); + refs.push(ref); + }) + ); + return await fn(); + } finally { + await Promise.all(refs.map(r => deleteDoc(r))); + } + } + + it('zero result scalar returns null', async () => { + const testDocs = { + [`${randomCol.path}/book1`]: { title: 'A Book Title' } + }; + + await withSubqueryData(testDocs, async () => { + const emptyScalar = firestore + .pipeline() + .collection(`${randomCol.path}/book1/reviews`) + .where(equal('reviewer', 'Alice')) + .select(currentDocument().as('data')); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .select(emptyScalar.toScalarExpression().as('firstReviewData')) + .limit(1) + ); + + expectResults(results, { firstReviewData: null }); + }); + }); + + it('array subquery join and empty result', async () => { + const reviewsCollName = `book_reviews_${Date.now()}`; + const reviewsDocs = { + [`${reviewsCollName}/r1`]: { + bookTitle: "The Hitchhiker's Guide to the Galaxy", + reviewer: 'Alice' + }, + [`${reviewsCollName}/r2`]: { + bookTitle: "The Hitchhiker's Guide to the Galaxy", + reviewer: 'Bob' + } + }; + + await withSubqueryData(reviewsDocs, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .select(field('reviewer').as('reviewer')) + .sort(field('reviewer').ascending()); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + or( + equal('title', "The Hitchhiker's Guide to the Galaxy"), + equal('title', 'Pride and Prejudice') + ) + ) + .define(field('title').as('bookTitle')) + .addFields(reviewsSub.toArrayExpression().as('reviewsData')) + .select('title', 'reviewsData') + .sort(field('title').descending()) + ); + + expectResults( + results, + { + title: "The Hitchhiker's Guide to the Galaxy", + reviewsData: ['Alice', 'Bob'] + }, + { title: 'Pride and Prejudice', reviewsData: [] } + ); + }); + }); + + it('multiple array subqueries', async () => { + const reviewsCollectionName = `reviews_multi_${Date.now()}`; + const authorsCollectionName = `authors_multi_${Date.now()}`; + + const data = { + [`${reviewsCollectionName}/r1`]: { + bookTitle: '1984', + rating: 5 + }, + [`${authorsCollectionName}/a1`]: { + authorName: 'George Orwell', + nationality: 'British' + } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollectionName) + .where(equal('bookTitle', variable('bookTitle'))) + .select(field('rating').as('rating')); + + const authorsSub = firestore + .pipeline() + .collection(authorsCollectionName) + .where(equal('authorName', variable('authorName'))) + .select(field('nationality').as('nationality')); + + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define( + field('title').as('bookTitle'), + field('author').as('authorName') + ) + .addFields( + reviewsSub.toArrayExpression().as('reviewsData'), + authorsSub.toArrayExpression().as('authorsData') + ) + .select('title', 'reviewsData', 'authorsData') + ); + + expectResults(snapshot, { + title: '1984', + reviewsData: [5], + authorsData: ['British'] + }); + }); + }); + + it('array subquery join multiple fields preserves map', async () => { + const reviewsCollName = `reviews_map_${Date.now()}`; + + const data = { + [`${reviewsCollName}/r1`]: { + bookTitle: '1984', + reviewer: 'Alice', + rating: 5 + }, + [`${reviewsCollName}/r2`]: { + bookTitle: '1984', + reviewer: 'Bob', + rating: 4 + } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .select( + field('reviewer').as('reviewer'), + field('rating').as('rating') + ) + .sort(field('reviewer').ascending()); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define(field('title').as('bookTitle')) + .addFields(reviewsSub.toArrayExpression().as('reviewsData')) + .select('title', 'reviewsData') + ); + + expectResults(results, { + title: '1984', + reviewsData: [ + { reviewer: 'Alice', rating: 5 }, + { reviewer: 'Bob', rating: 4 } + ] + }); + }); + }); + + it('array subquery in where stage on books', async () => { + const reviewsCollName = `reviews_where_${Date.now()}`; + + const data = { + [`${reviewsCollName}/r1`]: { + bookTitle: 'Dune', + reviewer: 'Paul' + }, + [`${reviewsCollName}/r2`]: { + bookTitle: 'Foundation', + reviewer: 'Hari' + } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .select(field('reviewer').as('reviewer')); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where( + or(equal('title', 'Dune'), equal('title', 'The Great Gatsby')) + ) + .define(field('title').as('bookTitle')) + .where(reviewsSub.toArrayExpression().arrayContains('Paul')) + .select('title') + ); + + expectResults(results, { title: 'Dune' }); + }); + }); + + it('scalar subquery single aggregation unwrapping', async () => { + const reviewsCollName = `reviews_agg_single_${Date.now()}`; + + const data = { + [`${reviewsCollName}/r1`]: { bookTitle: '1984', rating: 4 }, + [`${reviewsCollName}/r2`]: { bookTitle: '1984', rating: 5 } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .aggregate(average('rating').as('val')); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define(field('title').as('bookTitle')) + .addFields(reviewsSub.toScalarExpression().as('averageRating')) + .select('title', 'averageRating') + ); + + expectResults(results, { title: '1984', averageRating: 4.5 }); + }); + }); + + it('scalar subquery multiple aggregations map wrapping', async () => { + const reviewsCollName = `reviews_agg_multi_${Date.now()}`; + + const data = { + [`${reviewsCollName}/r1`]: { bookTitle: '1984', rating: 4 }, + [`${reviewsCollName}/r2`]: { bookTitle: '1984', rating: 5 } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .aggregate(average('rating').as('avg'), countAll().as('count')); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define(field('title').as('bookTitle')) + .addFields(reviewsSub.toScalarExpression().as('stats')) + .select('title', 'stats') + ); + + expectResults(results, { + title: '1984', + stats: { avg: 4.5, count: 2 } + }); + }); + }); + + it('scalar subquery zero results', async () => { + const reviewsCollName = `reviews_zero_${Date.now()}`; + + // No reviews for "1984" + + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .aggregate(average('rating').as('avg')); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define(field('title').as('bookTitle')) + .addFields(reviewsSub.toScalarExpression().as('averageRating')) + .select('title', 'averageRating') + ); + + expectResults(results, { title: '1984', averageRating: null }); + }); + + it('scalar subquery multiple results runtime error', async () => { + const reviewsCollName = `reviews_multiple_${Date.now()}`; + + const data = { + [`${reviewsCollName}/r1`]: { bookTitle: '1984', rating: 4 }, + [`${reviewsCollName}/r2`]: { bookTitle: '1984', rating: 5 } + }; + + await withSubqueryData(data, async () => { + // This subquery will return 2 documents, which is invalid for toScalarExpression() + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))); + + await expect( + execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define(field('title').as('bookTitle')) + .addFields(reviewsSub.toScalarExpression().as('reviewData')) + ) + ).to.be.rejectedWith(/Subpipeline returned multiple results/); + }); + }); + + it('mixed scalar and array subqueries', async () => { + const reviewsCollName = `reviews_mixed_${Date.now()}`; + + const data = { + [`${reviewsCollName}/r1`]: { + bookTitle: '1984', + reviewer: 'Alice', + rating: 4 + }, + [`${reviewsCollName}/r2`]: { + bookTitle: '1984', + reviewer: 'Bob', + rating: 5 + } + }; + + await withSubqueryData(data, async () => { + const arraySub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .select(field('reviewer').as('reviewer')) + .sort(field('reviewer').ascending()); + + const scalarSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookTitle', variable('bookTitle'))) + .aggregate(average('rating').as('val')); + + const results = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', '1984')) + .define(field('title').as('bookTitle')) + .addFields( + arraySub.toArrayExpression().as('allReviewers'), + scalarSub.toScalarExpression().as('averageRating') + ) + .select('title', 'allReviewers', 'averageRating') + ); + + expectResults(results, { + title: '1984', + allReviewers: ['Alice', 'Bob'], + averageRating: 4.5 + }); + }); + }); + + it('single scope variable usage', async () => { + const collName = `single_scope_${Date.now()}`; + + await withSubqueryData( + { [`${collName}/doc1`]: { price: 100 } }, + async () => { + let results = await execute( + firestore + .pipeline() + .collection(collName) + .define(field('price').multiply(0.8).as('discount')) + .where(variable('discount').lessThan(50.0)) + .select('price') + ); + + expect(results.results).to.be.empty; + + const doc2Ref = doc(firestore, `${collName}/doc2`); + await setDoc(doc2Ref, { price: 50 }); + + try { + results = await execute( + firestore + .pipeline() + .collection(collName) + .define(field('price').multiply(0.8).as('discount')) + .where(variable('discount').lessThan(50.0)) + .select('price') + ); + + expectResults(results, { price: 50 }); + } finally { + await deleteDoc(doc2Ref); + } + } + ); + }); + + it('explicit field binding scope bridging', async () => { + const outerCollName = `outer_scope_${Date.now()}`; + const reviewsCollName = `reviews_scope_${Date.now()}`; + + const data = { + [`${outerCollName}/doc1`]: { title: '1984', id: '1' }, + [`${reviewsCollName}/r1`]: { bookId: '1', reviewer: 'Alice' } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('bookId', variable('rid'))) + .select(field('reviewer').as('reviewer')); + + const results = await execute( + firestore + .pipeline() + .collection(outerCollName) + .where(equal('title', '1984')) + .define(field('id').as('rid')) + .addFields(reviewsSub.toArrayExpression().as('reviews')) + .select('title', 'reviews') + ); + + expectResults(results, { title: '1984', reviews: ['Alice'] }); + }); + }); + + it('multiple variable bindings', async () => { + const outerCollName = `outer_multi_${Date.now()}`; // distinct from earlier test + const reviewsCollName = `reviews_multi_${Date.now()}`; + + const data = { + [`${outerCollName}/doc1`]: { + title: '1984', + id: '1', + category: 'sci-fi' + }, + [`${reviewsCollName}/r1`]: { + bookId: '1', + category: 'sci-fi', + reviewer: 'Alice' + } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where( + and( + equal('bookId', variable('rid')), + equal('category', variable('rcat')) + ) + ) + .select(field('reviewer').as('reviewer')); + + const results = await execute( + firestore + .pipeline() + .collection(outerCollName) + .where(equal('title', '1984')) + .define(field('id').as('rid'), field('category').as('rcat')) + .addFields(reviewsSub.toArrayExpression().as('reviews')) + .select('title', 'reviews') + ); + + expectResults(results, { title: '1984', reviews: ['Alice'] }); + }); + }); + + it('current document binding', async () => { + const outerCollName = `outer_currentdoc_${Date.now()}`; + const reviewsCollName = `reviews_currentdoc_${Date.now()}`; + + const data = { + [`${outerCollName}/doc1`]: { title: '1984', author: 'George Orwell' }, + [`${reviewsCollName}/r1`]: { + authorName: 'George Orwell', + reviewer: 'Alice' + } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where(equal('authorName', variable('doc').getField('author'))) + .select(field('reviewer').as('reviewer')); + + const ppl = firestore + .pipeline() + .collection(outerCollName) + .where(equal('title', '1984')) + .define(currentDocument().as('doc')) + .addFields(reviewsSub.toArrayExpression().as('reviews')) + .select('title', 'reviews'); + + // TODO(dlarocque): Remove these target backend conditionals once the 'get_field' rename has rolled out to prod. + const host = firestore._getSettings().host; + const isProd = host === 'firestore.googleapis.com'; + const isNightly = host === 'test-firestore.sandbox.googleapis.com'; + + if (isProd) { + // The execution of this pipeline is expected to result in a network error + // from the backend until the breaking change to rename the 'field' expression to + // 'get_field' has rolled out to prod. + try { + const results = await execute(ppl); + + // If this is reached, the execution of the pipeline didn't throw an error, so the + // breaking change must have rolled out to prod. We can assert the newly expected behaviour. + logWarn( + "The 'get_field' expression rename has rolled out to the prod backend. Remove the target backend conditionals in this test." + ); + expectResults(results, { title: '1984', reviews: ['Alice'] }); + } catch (err: unknown) { + const error: Error = err as Error; + expect(error.message).to.equals( + "Request failed with error: The function 'get_field' does not exist, did you mean 'field'?" + ); + } + } else if (isNightly) { + const results = await execute(ppl); + expectResults(results, { title: '1984', reviews: ['Alice'] }); + } else { + expect(false).to.equal( + true, + `This test is only expected to run against firestore.googleapis.com or test-firestore.sandbox.googleapis.com, but it instead ran against ${host}` + ); + } + }); + }); + + it('unbound variable corner case', async () => { + const outerCollName = `outer_unbound_${Date.now()}`; + + try { + await execute( + firestore + .pipeline() + .collection(outerCollName) + .where(equal('title', variable('unknownVar'))) + ); + expect.fail('Should have thrown an error'); + } catch (e: unknown) { + expect(e).to.be.an.instanceOf(FirebaseError); + const err = e as FirestoreError; + expect(err.code).to.equal(Code.FAILED_PRECONDITION); + expect(err.message).to.match(/unknown variable/i); + } + }); + + it('variable shadowing collision', async () => { + const outerCollName = `outer_shadow_${Date.now()}`; + const innerCollName = `inner_shadow_${Date.now()}`; + + const data = { + [`${outerCollName}/doc1`]: { title: '1984' }, + [`${innerCollName}/i1`]: { id: 'test' } + }; + + await withSubqueryData(data, async () => { + // Inner subquery re-defines variable "x" to be "inner_val" + const sub = firestore + .pipeline() + .collection(innerCollName) + .define(constant('inner_val').as('x')) + .select(variable('x').as('val')); + + // Outer pipeline defines variable "x" to be "outer_val" + const results = await execute( + firestore + .pipeline() + .collection(outerCollName) + .where(equal('title', '1984')) + .limit(1) + .define(constant('outer_val').as('x')) + .addFields(sub.toArrayExpression().as('shadowed')) + .select('shadowed') + ); + + // Due to innermost scope winning, the result should use "inner_val" + expectResults(results, { shadowed: ['inner_val'] }); + }); + }); + + it('missing field on current document', async () => { + const outerCollName = `outer_missing_${Date.now()}`; + const reviewsCollName = `reviews_missing_${Date.now()}`; + + const data = { + [`${outerCollName}/doc1`]: { title: '1984' }, + [`${reviewsCollName}/r1`]: { bookId: '1', reviewer: 'Alice' } + }; + + await withSubqueryData(data, async () => { + // This references a non-existent field 'doesNotExist' on the current document 'doc' + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + // using mapGet explicitly or just field path if supported on maps + .where(equal('bookId', variable('doc').getField('doesNotExist'))) + .select(field('reviewer').as('reviewer')); + + const ppl = firestore + .pipeline() + .collection(outerCollName) + .where(equal('title', '1984')) + .define(currentDocument().as('doc')) + .addFields(reviewsSub.toArrayExpression().as('reviews')) + .select('title', 'reviews'); + + // TODO(dlarocque): Remove these target backend conditionals once the 'get_field' rename has rolled out to prod. + const host = firestore._getSettings().host; + const isProd = host === 'firestore.googleapis.com'; + const isNightly = host === 'test-firestore.sandbox.googleapis.com'; + + if (isProd) { + // The execution of this pipeline is expected to result in a network error + // from the backend until the breaking change to rename the 'field' expression to + // 'get_field' has rolled out to prod. + try { + const results = await execute(ppl); + + // If this is reached, the execution of the pipeline didn't throw an error, so the + // breaking change must have rolled out to prod. We can assert the newly expected behaviour. + logWarn( + "The 'get_field' expression rename has rolled out to the prod backend. Remove the target backend conditionals in this test." + ); + expectResults(results, { title: '1984', reviews: [] }); + } catch (err: unknown) { + const error: Error = err as Error; + expect(error.message).to.equals( + "Request failed with error: The function 'get_field' does not exist, did you mean 'field'?" + ); + } + } else if (isNightly) { + const results = await execute(ppl); + expectResults(results, { title: '1984', reviews: [] }); + } else { + expect(false).to.equal( + true, + `This test is only expected to run against firestore.googleapis.com or test-firestore.sandbox.googleapis.com, but it instead ran against ${host}` + ); + } + }); + }); + + it('3 level deep join', async () => { + const publishersCollName = `publishers_${Date.now()}`; + const booksCollName = `books_${Date.now()}`; + const reviewsCollName = `reviews_${Date.now()}`; + + const data = { + [`${publishersCollName}/p1`]: { publisherId: 'pub1', name: 'Penguin' }, + [`${booksCollName}/b1`]: { + bookId: 'book1', + publisherId: 'pub1', + title: '1984' + }, + [`${reviewsCollName}/r1`]: { bookId: 'book1', reviewer: 'Alice' } + }; + + await withSubqueryData(data, async () => { + const reviewsSub = firestore + .pipeline() + .collection(reviewsCollName) + .where( + and( + equal('bookId', variable('bookId')), + equal(variable('pubName'), 'Penguin') + ) + ) + .select(field('reviewer').as('reviewer')); + + const booksSub = firestore + .pipeline() + .collection(booksCollName) + .where(equal('publisherId', variable('pubId'))) + .define(field('bookId').as('bookId')) + .addFields(reviewsSub.toArrayExpression().as('reviews')) + .select('title', 'reviews'); + + const results = await execute( + firestore + .pipeline() + .collection(publishersCollName) + .where(equal('publisherId', 'pub1')) + .define( + field('publisherId').as('pubId'), + field('name').as('pubName') + ) + .addFields(booksSub.toArrayExpression().as('books')) + .select('name', 'books') + ); + + expectResults(results, { + name: 'Penguin', + books: [{ title: '1984', reviews: ['Alice'] }] + }); + }); + }); + + it('deep aggregation', async () => { + const outerColl = `outer_agg_${Date.now()}`; + const innerColl = `inner_agg_${Date.now()}`; + + const data = { + [`${outerColl}/doc1`]: { id: '1' }, + [`${outerColl}/doc2`]: { id: '2' }, + [`${innerColl}/i1`]: { outerId: '1', score: 10 }, + [`${innerColl}/i2`]: { outerId: '2', score: 20 }, + [`${innerColl}/i3`]: { outerId: '1', score: 30 } + }; + + await withSubqueryData(data, async () => { + const innerSub = firestore + .pipeline() + .collection(innerColl) + .where(equal('outerId', variable('oid'))) + .aggregate(average('score').as('s')); + + const results = await execute( + firestore + .pipeline() + .collection(outerColl) + .define(field('id').as('oid')) + .addFields(innerSub.toScalarExpression().as('docScore')) + // Aggregate over calculated subquery results + .aggregate(sum('docScore').as('totalScore')) + ); + + expectResults(results, { totalScore: 40.0 }); + }); + }); + + // NOTE: We aren't able to created nested pipelines deeper than 9 layer + // because JSON is more verbose than gRPC format used on other platforms. + it('pipeline stage support 9 layers', async () => { + const collName = `depth_${Date.now()}`; + + await withSubqueryData( + { [`${collName}/doc1`]: { val: 'hello' } }, + async () => { + // Create a nested pipeline of depth 9 + let currentSubquery = firestore + .pipeline() + .collection(collName) + .limit(1) + .select(field('val').as('val')); + + for (let i = 0; i < 8; i++) { + currentSubquery = firestore + .pipeline() + .collection(collName) + .limit(1) + .addFields(currentSubquery.toArrayExpression().as(`nested_${i}`)) + .select(`nested_${i}`); + } + + const results = await execute(currentSubquery); + expect(results.results.length).to.be.greaterThan(0); + } + ); + }); + + it('standard subcollection query', async () => { + const collName = `subcoll_test_${Date.now()}`; + + const doc1Ref = doc(firestore, `${collName}/doc1`); + await setDoc(doc1Ref, { title: '1984' }); + + const r1Ref = doc(firestore, `${collName}/doc1/reviews/r1`); + await setDoc(r1Ref, { reviewer: 'Alice' }); + + // Assuming Pipeline.subcollection API exists or similar + const reviewsSub = subcollection('reviews').select( + field('reviewer').as('reviewer') + ); + + const results = await execute( + firestore + .pipeline() + .collection(collName) + .where(equal('title', '1984')) + .addFields(reviewsSub.toArrayExpression().as('reviews')) + .select('title', 'reviews') + ); + + expectResults(results, { + title: '1984', + reviews: ['Alice'] + }); + + await Promise.all([deleteDoc(doc1Ref), deleteDoc(r1Ref)]); + }); + + it('missing subcollection', async () => { + const collName = `subcoll_missing_${Date.now()}`; + const doc1Ref = doc(firestore, `${collName}/doc1`); + + await setDoc(doc1Ref, { id: 'no_subcollection_here' }); + + const missingSub = subcollection('doesNotExist').select( + variable('p').as('subP') + ); + + const results = await execute( + firestore + .pipeline() + .collection(collName) + .define(currentDocument().as('p')) + .select(missingSub.toArrayExpression().as('missingData')) + .limit(1) + ); + + expectResults(results, { missingData: [] }); + + await deleteDoc(doc1Ref); + }); + + it('direct execution of subcollection pipeline', async () => { + const sub = subcollection('reviews'); + + await expect(execute(sub)).to.be.rejectedWith( + /This pipeline was created without a database/ + ); + }); + }); }); (getRunEnterpriseTests() && getTargetBackend() === TargetBackend.NIGHTLY From 2c271c9283eb8419d98b36f77a46045bbc64a38e Mon Sep 17 00:00:00 2001 From: macastelaz <34776182+macastelaz@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:27:34 -0500 Subject: [PATCH 124/174] Update dependencies for Coveralls workflow to point to job IDs not flag names (#9803) --- .github/workflows/test-all.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 4a7d81f685..ba6f00c54f 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -269,11 +269,11 @@ jobs: coveralls-finish: name: Finalize Coveralls - needs: [test-the-rest-coverage, test-auth-coverage, test-firestore-coverage] + needs: [test-the-rest, test-auth, test-firestore] runs-on: ubuntu-latest steps: - name: Coveralls Finished uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} - parallel-finished: true \ No newline at end of file + parallel-finished: true From b2c464643548e068f56d9f57a09b105b1b898ff1 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 7 Apr 2026 07:43:23 -0700 Subject: [PATCH 125/174] fix(app-types): Fix "dependency" typo (#9813) --- .changeset/eighty-cameras-smoke.md | 5 +++++ packages/app-types/package.json | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 .changeset/eighty-cameras-smoke.md diff --git a/.changeset/eighty-cameras-smoke.md b/.changeset/eighty-cameras-smoke.md new file mode 100644 index 0000000000..ecb3a6e188 --- /dev/null +++ b/.changeset/eighty-cameras-smoke.md @@ -0,0 +1,5 @@ +--- +'@firebase/app-types': patch +--- + +Fix typo in package.json (dependency => dependencies) diff --git a/packages/app-types/package.json b/packages/app-types/package.json index 4c49efb351..6c7fcee136 100644 --- a/packages/app-types/package.json +++ b/packages/app-types/package.json @@ -20,10 +20,10 @@ "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" }, - "dependency": { - "@firebase/logger": "0.2.6" + "dependencies": { + "@firebase/logger": "0.5.0" }, "devDependencies": { "typescript": "5.5.4" } -} +} \ No newline at end of file From 44c234c2ba5f8ba18a2f2c99fe63df7692010bf3 Mon Sep 17 00:00:00 2001 From: Yvonne Pan <103622026+yvonnep165@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:14:35 -0400 Subject: [PATCH 126/174] feat(firestore): add the parent expression (#9773) * Add support for parent expression * Add documentation and fix formatting * Add changeset * Change path in tests as suggested by gemini auto review * Update docs-devsite/firestore_pipelines.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update docs-devsite/firestore_pipelines.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update docs-devsite/firestore_lite_pipelines.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update docs-devsite/firestore_lite_pipelines.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update docs-devsite/firestore_pipelines.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update docs-devsite/firestore_pipelines.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * fix formatting and documentation * Update documentation to make the return value clearer * remove the ts ignore notation * Remove beta notation and timeout for tests and regenerate documentation --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .changeset/cold-moles-compare.md | 6 ++ .../firestore-lite-pipelines.api.md | 10 +++ common/api-review/firestore-pipelines.api.md | 10 +++ .../firestore_lite_pipelines.expression.md | 25 ++++++++ docs-devsite/firestore_lite_pipelines.md | 64 +++++++++++++++++++ .../firestore_pipelines.expression.md | 25 ++++++++ docs-devsite/firestore_pipelines.md | 64 +++++++++++++++++++ .../firestore/lite/pipelines/pipelines.ts | 1 + packages/firestore/src/api_pipelines.ts | 1 + .../firestore/src/lite-api/expressions.ts | 55 ++++++++++++++++ .../test/integration/api/pipeline.test.ts | 26 ++++++++ packages/firestore/test/lite/pipeline.test.ts | 26 ++++++++ 12 files changed, 313 insertions(+) create mode 100644 .changeset/cold-moles-compare.md diff --git a/.changeset/cold-moles-compare.md b/.changeset/cold-moles-compare.md new file mode 100644 index 0000000000..7c2e278a36 --- /dev/null +++ b/.changeset/cold-moles-compare.md @@ -0,0 +1,6 @@ +--- +'@firebase/firestore': minor +'firebase': minor +--- + +Add support for the parent expression diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index fff56b2587..2fc469a46a 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -719,6 +719,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ notEqualAny(arrayExpression: Expression): BooleanExpression; /* Excluded from this release type: _readUserData */ + parent(): FunctionExpression; + /* Excluded from this release type: _readUserData */ pow(exponent: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ pow(exponent: number): FunctionExpression; @@ -1206,6 +1208,14 @@ export class Ordering { readonly expr: Expression; } +// @public +function parent_2(documentPath: string | DocumentReference): FunctionExpression; + +// @public +function parent_2(documentPathExpr: Expression): FunctionExpression; + +export { parent_2 as parent } + // @public export class Pipeline { addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 07096bbe8e..7f09c8fa99 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -722,6 +722,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ notEqualAny(arrayExpression: Expression): BooleanExpression; /* Excluded from this release type: _readUserData */ + parent(): FunctionExpression; + /* Excluded from this release type: _readUserData */ pow(exponent: Expression): FunctionExpression; /* Excluded from this release type: _readUserData */ pow(exponent: number): FunctionExpression; @@ -1209,6 +1211,14 @@ export class Ordering { readonly expr: Expression; } +// @public +function parent_2(documentPath: string | DocumentReference): FunctionExpression; + +// @public +function parent_2(documentPathExpr: Expression): FunctionExpression; + +export { parent_2 as parent } + // @public (undocumented) export class Pipeline { addFields(field: Selectable, ...additionalFields: Selectable[]): Pipeline; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index b63c7bbdd2..c4612ebc8f 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -146,6 +146,7 @@ export declare abstract class Expression | [notEqual(value)](./firestore_lite_pipelines.expression.md#expressionnotequal) | | Creates an expression that checks if this expression is not equal to a constant value. | | [notEqualAny(values)](./firestore_lite_pipelines.expression.md#expressionnotequalany) | | Creates an expression that checks if this expression is not equal to any of the provided values or expressions. | | [notEqualAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionnotequalany) | | Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. | +| [parent()](./firestore_lite_pipelines.expression.md#expressionparent) | | Creates an expression that returns the parent document reference of a document reference. | | [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | Creates an expression that returns the value of this expression raised to the power of another expression. | | [pow(exponent)](./firestore_lite_pipelines.expression.md#expressionpow) | | Creates an expression that returns the value of this expression raised to the power of a constant value. | | [regexContains(pattern)](./firestore_lite_pipelines.expression.md#expressionregexcontains) | | Creates an expression that checks if a string contains a specified regular expression as a substring. | @@ -3475,6 +3476,30 @@ field("status").notEqualAny(field('rejectedStatuses')); ``` +## Expression.parent() + +Creates an expression that returns the parent document reference of a document reference. + +Signature: + +```typescript +parent(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the parent operation. + +### Example + + +```typescript +// Get the parent document reference of a document reference. +field("__path__").parent(); + +``` + ## Expression.pow() Creates an expression that returns the value of this expression raised to the power of another expression. diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index ac33350f9c..706c8f6508 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -68,8 +68,10 @@ https://github.com/firebase/firebase-js-sdk | [switchOn(condition, result, others)](./firestore_lite_pipelines.md#switchon_02b8caf) | Creates an expression that evaluates to the result corresponding to the first true condition. | | function(documentPath, ...) | | [documentId(documentPath)](./firestore_lite_pipelines.md#documentid_cef293c) | Creates an expression that returns the document ID from a path. | +| [parent\_2(documentPath)](./firestore_lite_pipelines.md#parent_2_cef293c) | Creates an expression that returns the parent document reference of a document reference. | | function(documentPathExpr, ...) | | [documentId(documentPathExpr)](./firestore_lite_pipelines.md#documentid_9a69021) | Creates an expression that returns the document ID from a path. | +| [parent\_2(documentPathExpr)](./firestore_lite_pipelines.md#parent_2_9a69021) | Creates an expression that returns the parent document reference of a document reference. | | function(element, ...) | | [notEqualAny(element, values)](./firestore_lite_pipelines.md#notequalany_c2c5bcb) | Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | | [notEqualAny(element, arrayExpression)](./firestore_lite_pipelines.md#notequalany_16b2851) | Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | @@ -1889,6 +1891,37 @@ documentId(myDocumentReference); ``` +### parent\_2(documentPath) {:#parent_2_cef293c} + +Creates an expression that returns the parent document reference of a document reference. + +Signature: + +```typescript +declare function parent_2(documentPath: string | DocumentReference): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| documentPath | string \| [DocumentReference](./firestore_lite.documentreference.md#documentreference_class) | A string path or DocumentReference to get the parent from. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the parent operation. + +### Example + + +```typescript +// Get the parent document reference of a document reference. +parent(myDocumentReference); + +``` + ## function(documentPathExpr, ...) ### documentId(documentPathExpr) {:#documentid_9a69021} @@ -1922,6 +1955,37 @@ documentId(field("__path__")); ``` +### parent\_2(documentPathExpr) {:#parent_2_9a69021} + +Creates an expression that returns the parent document reference of a document reference. + +Signature: + +```typescript +declare function parent_2(documentPathExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| documentPathExpr | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | An Expression evaluating to a document reference. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the parent operation. + +### Example + + +```typescript +// Get the parent document reference of a document reference. +parent(field("__path__")); + +``` + ## function(element, ...) ### notEqualAny(element, values) {:#notequalany_c2c5bcb} diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 942b76d5ee..06ec697985 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -146,6 +146,7 @@ export declare abstract class Expression | [notEqual(value)](./firestore_pipelines.expression.md#expressionnotequal) | | Creates an expression that checks if this expression is not equal to a constant value. | | [notEqualAny(values)](./firestore_pipelines.expression.md#expressionnotequalany) | | Creates an expression that checks if this expression is not equal to any of the provided values or expressions. | | [notEqualAny(arrayExpression)](./firestore_pipelines.expression.md#expressionnotequalany) | | Creates an expression that checks if this expression is not equal to any of the values in the evaluated expression. | +| [parent()](./firestore_pipelines.expression.md#expressionparent) | | Creates an expression that returns the parent document reference of a document reference. | | [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | Creates an expression that returns the value of this expression raised to the power of another expression. | | [pow(exponent)](./firestore_pipelines.expression.md#expressionpow) | | Creates an expression that returns the value of this expression raised to the power of a constant value. | | [regexContains(pattern)](./firestore_pipelines.expression.md#expressionregexcontains) | | Creates an expression that checks if a string contains a specified regular expression as a substring. | @@ -3475,6 +3476,30 @@ field("status").notEqualAny(field('rejectedStatuses')); ``` +## Expression.parent() + +Creates an expression that returns the parent document reference of a document reference. + +Signature: + +```typescript +parent(): FunctionExpression; +``` +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the parent operation. + +### Example + + +```typescript +// Get the parent document reference of a document reference. +field("__path__").parent(); + +``` + ## Expression.pow() Creates an expression that returns the value of this expression raised to the power of another expression. diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 1fef6a7820..63ba7a59fe 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -68,8 +68,10 @@ https://github.com/firebase/firebase-js-sdk | [switchOn(condition, result, others)](./firestore_pipelines.md#switchon_02b8caf) | Creates an expression that evaluates to the result corresponding to the first true condition. | | function(documentPath, ...) | | [documentId(documentPath)](./firestore_pipelines.md#documentid_cef293c) | Creates an expression that returns the document ID from a path. | +| [parent\_2(documentPath)](./firestore_pipelines.md#parent_2_cef293c) | Creates an expression that returns the parent document reference of a document reference. | | function(documentPathExpr, ...) | | [documentId(documentPathExpr)](./firestore_pipelines.md#documentid_9a69021) | Creates an expression that returns the document ID from a path. | +| [parent\_2(documentPathExpr)](./firestore_pipelines.md#parent_2_9a69021) | Creates an expression that returns the parent document reference of a document reference. | | function(element, ...) | | [notEqualAny(element, values)](./firestore_pipelines.md#notequalany_c2c5bcb) | Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | | [notEqualAny(element, arrayExpression)](./firestore_pipelines.md#notequalany_16b2851) | Creates an expression that checks if an expression is not equal to any of the provided values or expressions. | @@ -1894,6 +1896,37 @@ documentId(myDocumentReference); ``` +### parent\_2(documentPath) {:#parent_2_cef293c} + +Creates an expression that returns the parent document reference of a document reference. + +Signature: + +```typescript +declare function parent_2(documentPath: string | DocumentReference): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| documentPath | string \| [DocumentReference](./firestore_.documentreference.md#documentreference_class) | A string path or DocumentReference to get the parent from. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the parent operation. + +### Example + + +```typescript +// Get the parent document reference of a document reference. +parent(myDocumentReference); + +``` + ## function(documentPathExpr, ...) ### documentId(documentPathExpr) {:#documentid_9a69021} @@ -1927,6 +1960,37 @@ documentId(field("__path__")); ``` +### parent\_2(documentPathExpr) {:#parent_2_9a69021} + +Creates an expression that returns the parent document reference of a document reference. + +Signature: + +```typescript +declare function parent_2(documentPathExpr: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| documentPathExpr | [Expression](./firestore_pipelines.expression.md#expression_class) | An Expression evaluating to a document reference. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the parent operation. + +### Example + + +```typescript +// Get the parent document reference of a document reference. +parent(field("__path__")); + +``` + ## function(element, ...) ### notEqualAny(element, values) {:#notequalany_c2c5bcb} diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index 66a236f284..7c6a999e16 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -112,6 +112,7 @@ export { map, mod, documentId, + parent, equal, notEqual, lessThan, diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index 74ee09741d..7a2a948c01 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -163,6 +163,7 @@ export { mapRemove, mapMerge, documentId, + parent, substring, countDistinct, ceil, diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index 32dba9e343..d0165ae7f9 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -2612,6 +2612,22 @@ export abstract class Expression implements ProtoValueSerializable, UserData { return new FunctionExpression('document_id', [this], 'documentId'); } + /** + * + * Creates an expression that returns the parent document reference of a document reference. + * + * @example + * ```typescript + * // Get the parent document reference of a document reference. + * field("__path__").parent(); + * ``` + * + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the parent operation. + */ + parent(): FunctionExpression { + return new FunctionExpression('parent', [this], 'parent'); + } + /** * * Creates an expression that returns a substring of the results of this expression. @@ -4739,6 +4755,45 @@ export function documentId( return documentPathExpr.documentId(); } +/** + * + * Creates an expression that returns the parent document reference of a document reference. + * + * @example + * ```typescript + * // Get the parent document reference of a document reference. + * parent(myDocumentReference); + * ``` + * + * @param documentPath - A string path or DocumentReference to get the parent from. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the parent operation. + */ +export function parent( + documentPath: string | DocumentReference +): FunctionExpression; + +/** + * + * Creates an expression that returns the parent document reference of a document reference. + * + * @example + * ```typescript + * // Get the parent document reference of a document reference. + * parent(field("__path__")); + * ``` + * + * @param documentPathExpr - An Expression evaluating to a document reference. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the parent operation. + */ +export function parent(documentPathExpr: Expression): FunctionExpression; + +export function parent( + documentPath: Expression | string | DocumentReference +): FunctionExpression { + const documentPathExpr = valueToDefaultExpr(documentPath); + return documentPathExpr.parent(); +} + /** * * Creates an expression that returns a substring of a string or byte array. diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index af3cfeb6ef..1e8e1cd0c2 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -126,6 +126,7 @@ import { mapRemove, mapMerge, documentId, + parent, substring, xor, nor, @@ -4681,6 +4682,31 @@ apiDescribe.skipClassic('Pipelines', persistence => { }); }); + it('supports parent', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select( + parent(doc(randomCol, 'book4', 'reviews', 'review1')).as( + 'parentRefStatic' + ), + constant(doc(randomCol, 'book4', 'reviews', 'review1')) + .parent() + .as('parentRefInstance') + ) + .select( + field('parentRefStatic').documentId().as('parentIdStatic'), + field('parentRefInstance').documentId().as('parentIdInstance') + ) + ); + expectResults(snapshot, { + parentIdStatic: 'book4', + parentIdInstance: 'book4' + }); + }); + it('supports substring', async () => { let snapshot = await execute( firestore diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 0a86dcd3ed..bb32e70f2b 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -86,6 +86,7 @@ import { length, mod, documentId, + parent, equal, notEqual, lessThan, @@ -4739,6 +4740,31 @@ describe.skipClassic('Firestore Pipelines', () => { }); }); + it('supports parent', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .select( + parent(doc(randomCol, 'book4', 'reviews', 'review1')).as( + 'parentRefStatic' + ), + constant(doc(randomCol, 'book4', 'reviews', 'review1')) + .parent() + .as('parentRefInstance') + ) + .select( + field('parentRefStatic').documentId().as('parentIdStatic'), + field('parentRefInstance').documentId().as('parentIdInstance') + ) + ); + expectResults(snapshot, { + parentIdStatic: 'book4', + parentIdInstance: 'book4' + }); + }); + it('supports substring', async () => { let snapshot = await execute( firestore From 0e343c8706d2c1683fd802cadff8fa87f826698d Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 7 Apr 2026 11:34:10 -0400 Subject: [PATCH 127/174] feat(firestore): replace `Type` enum with raw string. (#9725) --- .changeset/thin-seas-accept.md | 6 +++ .../firestore-lite-pipelines.api.md | 9 ++-- common/api-review/firestore-pipelines.api.md | 9 ++-- .../firestore_lite_pipelines.expression.md | 6 +-- docs-devsite/firestore_lite_pipelines.md | 33 ++++-------- .../firestore_pipelines.expression.md | 6 +-- docs-devsite/firestore_pipelines.md | 33 ++++-------- .../firestore/lite/pipelines/pipelines.ts | 3 +- packages/firestore/src/api_pipelines.ts | 3 +- .../firestore/src/lite-api/expressions.ts | 52 ++++++------------- 10 files changed, 56 insertions(+), 104 deletions(-) create mode 100644 .changeset/thin-seas-accept.md diff --git a/.changeset/thin-seas-accept.md b/.changeset/thin-seas-accept.md new file mode 100644 index 0000000000..82b82d5743 --- /dev/null +++ b/.changeset/thin-seas-accept.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/firestore': minor +--- + +**Beta API Breaking Change**: Change `Type` string union to be a raw string. diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index 2fc469a46a..addb7e77c5 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -653,7 +653,7 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ isError(): BooleanExpression; /* Excluded from this release type: _readUserData */ - isType(type: Type): BooleanExpression; + isType(type: string): BooleanExpression; /* Excluded from this release type: _readUserData */ join(delimiterExpression: Expression): Expression; /* Excluded from this release type: _readUserData */ @@ -959,10 +959,10 @@ export function isAbsent(field: string): BooleanExpression; export function isError(value: Expression): BooleanExpression; // @public -export function isType(fieldName: string, type: Type): BooleanExpression; +export function isType(fieldName: string, type: string): BooleanExpression; // @public -export function isType(expression: Expression, type: Type): BooleanExpression; +export function isType(expression: Expression, type: string): BooleanExpression; // @public export function join(arrayFieldName: string, delimiter: string): Expression; @@ -1675,9 +1675,6 @@ export function trunc(fieldName: string, decimalPlaces: number | Expression): Fu // @public export function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; -// @public -export type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp'; - // @public export function type(fieldName: string): FunctionExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 7f09c8fa99..68654b0e1e 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -656,7 +656,7 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ isError(): BooleanExpression; /* Excluded from this release type: _readUserData */ - isType(type: Type): BooleanExpression; + isType(type: string): BooleanExpression; /* Excluded from this release type: _readUserData */ join(delimiterExpression: Expression): Expression; /* Excluded from this release type: _readUserData */ @@ -962,10 +962,10 @@ export function isAbsent(field: string): BooleanExpression; export function isError(value: Expression): BooleanExpression; // @public -export function isType(fieldName: string, type: Type): BooleanExpression; +export function isType(fieldName: string, type: string): BooleanExpression; // @public -export function isType(expression: Expression, type: Type): BooleanExpression; +export function isType(expression: Expression, type: string): BooleanExpression; // @public export function join(arrayFieldName: string, delimiter: string): Expression; @@ -1703,9 +1703,6 @@ export function trunc(fieldName: string, decimalPlaces: number | Expression): Fu // @public export function trunc(expression: Expression, decimalPlaces: number | Expression): FunctionExpression; -// @public -export type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp'; - // @public export function type(fieldName: string): FunctionExpression; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index c4612ebc8f..29d43633f7 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -2499,19 +2499,19 @@ field("title").arrayContains(1).isError(); Creates an expression that checks if the result of this expression is of the given type. -Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. Supported values for `type` are: `'null'`, `'array'`, `'boolean'`, `'bytes'`, `'timestamp'`, `'geo_point'`, `'number'`, `'int32'`, `'int64'`, `'float64'`, `'decimal128'`, `'map'`, `'reference'`, `'string'`, `'vector'`, `'max_key'`, `'min_key'`, `'object_id'`, `'regex'`, `'request_timestamp'`. Signature: ```typescript -isType(type: Type): BooleanExpression; +isType(type: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| type | [Type](./firestore_lite_pipelines.md#type) | The type to check for. | +| type | string | The type to check for. | Returns: diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 706c8f6508..4fe7ba807a 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -114,7 +114,7 @@ https://github.com/firebase/firebase-js-sdk | [first(expression)](./firestore_lite_pipelines.md#first_1138a27) | Creates an aggregation that finds the first value of an expression across multiple stage inputs. | | [greaterThan(expression, value)](./firestore_lite_pipelines.md#greaterthan_01df3cf) | Creates an expression that checks if an expression is greater than a constant value. | | [greaterThanOrEqual(expression, value)](./firestore_lite_pipelines.md#greaterthanorequal_01df3cf) | Creates an expression that checks if an expression is greater than or equal to a constant value. | -| [isType(expression, type)](./firestore_lite_pipelines.md#istype_27398ce) | Creates an expression that checks if the result of an expression is of the given type. | +| [isType(expression, type)](./firestore_lite_pipelines.md#istype_e58f382) | Creates an expression that checks if the result of an expression is of the given type. | | [last(expression)](./firestore_lite_pipelines.md#last_1138a27) | Creates an aggregation that finds the last value of an expression across multiple stage inputs. | | [length\_2(expression)](./firestore_lite_pipelines.md#length_2_1138a27) | Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(expression, value)](./firestore_lite_pipelines.md#lessthan_01df3cf) | Creates an expression that checks if an expression is less than a constant value. | @@ -210,7 +210,7 @@ https://github.com/firebase/firebase-js-sdk | [greaterThan(fieldName, value)](./firestore_lite_pipelines.md#greaterthan_65e2f32) | Creates an expression that checks if a field's value is greater than a constant value. | | [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_2e16acb) | Creates an expression that checks if a field's value is greater than or equal to an expression. | | [greaterThanOrEqual(fieldName, value)](./firestore_lite_pipelines.md#greaterthanorequal_65e2f32) | Creates an expression that checks if a field's value is greater than or equal to a constant value. | -| [isType(fieldName, type)](./firestore_lite_pipelines.md#istype_5da287e) | Creates an expression that checks if the value in the specified field is of the given type. | +| [isType(fieldName, type)](./firestore_lite_pipelines.md#istype_ec95173) | Creates an expression that checks if the value in the specified field is of the given type. | | [last(fieldName)](./firestore_lite_pipelines.md#last_e5b0480) | Creates an aggregation that finds the last value of a field across multiple stage inputs. | | [length\_2(fieldName)](./firestore_lite_pipelines.md#length_2_e5b0480) | Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(fieldName, expression)](./firestore_lite_pipelines.md#lessthan_1e91657) | Creates an expression that checks if a field's value is less than an expression. | @@ -479,7 +479,6 @@ https://github.com/firebase/firebase-js-sdk | [TimeGranularity](./firestore_lite_pipelines.md#timegranularity) | Specify time granularity for expressions. | | [TimePart](./firestore_lite_pipelines.md#timepart) | Specify time parts for timestampExtract expressions. | | [TimeUnit](./firestore_lite_pipelines.md#timeunit) | Specify time units for expressions. | -| [Type](./firestore_lite_pipelines.md#type) | An enumeration of the different types generated by the Firestore backend.
    • Numerics evaluate directly to backend representation (int64 or float64), not JS number.
    • JavaScript Date and firestore Timestamp objects strictly evaluate to 'timestamp'.
    • Advanced configurations parsing backend types (such as decimal128, max_key or min_key from BSON) are also incorporated in this union string type. Note that decimal128 is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    | | [UnionStageOptions](./firestore_lite_pipelines.md#unionstageoptions) | Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | | [UnnestStageOptions](./firestore_lite_pipelines.md#unneststageoptions) | Represents the specific options available for configuring an UnnestStage within a pipeline. | | [WhereStageOptions](./firestore_lite_pipelines.md#wherestageoptions) | Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). | @@ -3099,16 +3098,16 @@ greaterThanOrEqual(field("quantity"), 10); ``` -### isType(expression, type) {:#istype_27398ce} +### isType(expression, type) {:#istype_e58f382} Creates an expression that checks if the result of an expression is of the given type. -Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. Supported values for `type` are: `'null'`, `'array'`, `'boolean'`, `'bytes'`, `'timestamp'`, `'geo_point'`, `'number'`, `'int32'`, `'int64'`, `'float64'`, `'decimal128'`, `'map'`, `'reference'`, `'string'`, `'vector'`, `'max_key'`, `'min_key'`, `'object_id'`, `'regex'`, `'request_timestamp'`. Signature: ```typescript -export declare function isType(expression: Expression, type: Type): BooleanExpression; +export declare function isType(expression: Expression, type: string): BooleanExpression; ``` #### Parameters @@ -3116,7 +3115,7 @@ export declare function isType(expression: Expression, type: Type): BooleanExpre | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression to check. | -| type | [Type](./firestore_lite_pipelines.md#type) | The type to check for. | +| type | string | The type to check for. | Returns: @@ -6075,16 +6074,16 @@ greaterThanOrEqual("score", 80); ``` -### isType(fieldName, type) {:#istype_5da287e} +### isType(fieldName, type) {:#istype_ec95173} Creates an expression that checks if the value in the specified field is of the given type. -Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. Supported values for `type` are: `'null'`, `'array'`, `'boolean'`, `'bytes'`, `'timestamp'`, `'geo_point'`, `'number'`, `'int32'`, `'int64'`, `'float64'`, `'decimal128'`, `'map'`, `'reference'`, `'string'`, `'vector'`, `'max_key'`, `'min_key'`, `'object_id'`, `'regex'`, `'request_timestamp'`. Signature: ```typescript -export declare function isType(fieldName: string, type: Type): BooleanExpression; +export declare function isType(fieldName: string, type: string): BooleanExpression; ``` #### Parameters @@ -6092,7 +6091,7 @@ export declare function isType(fieldName: string, type: Type): BooleanExpression | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field to check. | -| type | [Type](./firestore_lite_pipelines.md#type) | The type to check for. | +| type | string | The type to check for. | Returns: @@ -12070,18 +12069,6 @@ Specify time units for expressions. export declare type TimeUnit = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'; ``` -## Type - -An enumeration of the different types generated by the Firestore backend. - -
    • Numerics evaluate directly to backend representation (`int64` or `float64`), not JS `number`.
    • JavaScript `Date` and firestore `Timestamp` objects strictly evaluate to `'timestamp'`.
    • Advanced configurations parsing backend types (such as `decimal128`, `max_key` or `min_key` from BSON) are also incorporated in this union string type. Note that `decimal128` is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    - -Signature: - -```typescript -export declare type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp'; -``` - ## UnionStageOptions Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 06ec697985..8a2b72cbe8 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -2499,19 +2499,19 @@ field("title").arrayContains(1).isError(); Creates an expression that checks if the result of this expression is of the given type. -Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. Supported values for `type` are: `'null'`, `'array'`, `'boolean'`, `'bytes'`, `'timestamp'`, `'geo_point'`, `'number'`, `'int32'`, `'int64'`, `'float64'`, `'decimal128'`, `'map'`, `'reference'`, `'string'`, `'vector'`, `'max_key'`, `'min_key'`, `'object_id'`, `'regex'`, `'request_timestamp'`. Signature: ```typescript -isType(type: Type): BooleanExpression; +isType(type: string): BooleanExpression; ``` #### Parameters | Parameter | Type | Description | | --- | --- | --- | -| type | [Type](./firestore_pipelines.md#type) | The type to check for. | +| type | string | The type to check for. | Returns: diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 63ba7a59fe..76ec495e4a 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -114,7 +114,7 @@ https://github.com/firebase/firebase-js-sdk | [first(expression)](./firestore_pipelines.md#first_1138a27) | Creates an aggregation that finds the first value of an expression across multiple stage inputs. | | [greaterThan(expression, value)](./firestore_pipelines.md#greaterthan_01df3cf) | Creates an expression that checks if an expression is greater than a constant value. | | [greaterThanOrEqual(expression, value)](./firestore_pipelines.md#greaterthanorequal_01df3cf) | Creates an expression that checks if an expression is greater than or equal to a constant value. | -| [isType(expression, type)](./firestore_pipelines.md#istype_27398ce) | Creates an expression that checks if the result of an expression is of the given type. | +| [isType(expression, type)](./firestore_pipelines.md#istype_e58f382) | Creates an expression that checks if the result of an expression is of the given type. | | [last(expression)](./firestore_pipelines.md#last_1138a27) | Creates an aggregation that finds the last value of an expression across multiple stage inputs. | | [length\_2(expression)](./firestore_pipelines.md#length_2_1138a27) | Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(expression, value)](./firestore_pipelines.md#lessthan_01df3cf) | Creates an expression that checks if an expression is less than a constant value. | @@ -210,7 +210,7 @@ https://github.com/firebase/firebase-js-sdk | [greaterThan(fieldName, value)](./firestore_pipelines.md#greaterthan_65e2f32) | Creates an expression that checks if a field's value is greater than a constant value. | | [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_2e16acb) | Creates an expression that checks if a field's value is greater than or equal to an expression. | | [greaterThanOrEqual(fieldName, value)](./firestore_pipelines.md#greaterthanorequal_65e2f32) | Creates an expression that checks if a field's value is greater than or equal to a constant value. | -| [isType(fieldName, type)](./firestore_pipelines.md#istype_5da287e) | Creates an expression that checks if the value in the specified field is of the given type. | +| [isType(fieldName, type)](./firestore_pipelines.md#istype_ec95173) | Creates an expression that checks if the value in the specified field is of the given type. | | [last(fieldName)](./firestore_pipelines.md#last_e5b0480) | Creates an aggregation that finds the last value of a field across multiple stage inputs. | | [length\_2(fieldName)](./firestore_pipelines.md#length_2_e5b0480) | Creates an expression that calculates the length of a string, array, map, vector, or bytes. | | [lessThan(fieldName, expression)](./firestore_pipelines.md#lessthan_1e91657) | Creates an expression that checks if a field's value is less than an expression. | @@ -484,7 +484,6 @@ https://github.com/firebase/firebase-js-sdk | [TimeGranularity](./firestore_pipelines.md#timegranularity) | Specify time granularity for expressions. | | [TimePart](./firestore_pipelines.md#timepart) | Specify time parts for timestampExtract expressions. | | [TimeUnit](./firestore_pipelines.md#timeunit) | Specify time units for expressions. | -| [Type](./firestore_pipelines.md#type) | An enumeration of the different types generated by the Firestore backend.
    • Numerics evaluate directly to backend representation (int64 or float64), not JS number.
    • JavaScript Date and firestore Timestamp objects strictly evaluate to 'timestamp'.
    • Advanced configurations parsing backend types (such as decimal128, max_key or min_key from BSON) are also incorporated in this union string type. Note that decimal128 is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    | | [UnionStageOptions](./firestore_pipelines.md#unionstageoptions) | Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). | | [UnnestStageOptions](./firestore_pipelines.md#unneststageoptions) | Represents the specific options available for configuring an UnnestStage within a pipeline. | | [WhereStageOptions](./firestore_pipelines.md#wherestageoptions) | Options defining how a WhereStage is evaluated. See [Pipeline.where()](./firestore_pipelines.pipeline.md#pipelinewhere). | @@ -3104,16 +3103,16 @@ greaterThanOrEqual(field("quantity"), 10); ``` -### isType(expression, type) {:#istype_27398ce} +### isType(expression, type) {:#istype_e58f382} Creates an expression that checks if the result of an expression is of the given type. -Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. Supported values for `type` are: `'null'`, `'array'`, `'boolean'`, `'bytes'`, `'timestamp'`, `'geo_point'`, `'number'`, `'int32'`, `'int64'`, `'float64'`, `'decimal128'`, `'map'`, `'reference'`, `'string'`, `'vector'`, `'max_key'`, `'min_key'`, `'object_id'`, `'regex'`, `'request_timestamp'`. Signature: ```typescript -export declare function isType(expression: Expression, type: Type): BooleanExpression; +export declare function isType(expression: Expression, type: string): BooleanExpression; ``` #### Parameters @@ -3121,7 +3120,7 @@ export declare function isType(expression: Expression, type: Type): BooleanExpre | Parameter | Type | Description | | --- | --- | --- | | expression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression to check. | -| type | [Type](./firestore_pipelines.md#type) | The type to check for. | +| type | string | The type to check for. | Returns: @@ -6080,16 +6079,16 @@ greaterThanOrEqual("score", 80); ``` -### isType(fieldName, type) {:#istype_5da287e} +### isType(fieldName, type) {:#istype_ec95173} Creates an expression that checks if the value in the specified field is of the given type. -Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. +Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. Supported values for `type` are: `'null'`, `'array'`, `'boolean'`, `'bytes'`, `'timestamp'`, `'geo_point'`, `'number'`, `'int32'`, `'int64'`, `'float64'`, `'decimal128'`, `'map'`, `'reference'`, `'string'`, `'vector'`, `'max_key'`, `'min_key'`, `'object_id'`, `'regex'`, `'request_timestamp'`. Signature: ```typescript -export declare function isType(fieldName: string, type: Type): BooleanExpression; +export declare function isType(fieldName: string, type: string): BooleanExpression; ``` #### Parameters @@ -6097,7 +6096,7 @@ export declare function isType(fieldName: string, type: Type): BooleanExpression | Parameter | Type | Description | | --- | --- | --- | | fieldName | string | The name of the field to check. | -| type | [Type](./firestore_pipelines.md#type) | The type to check for. | +| type | string | The type to check for. | Returns: @@ -12136,18 +12135,6 @@ Specify time units for expressions. export declare type TimeUnit = 'microsecond' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day'; ``` -## Type - -An enumeration of the different types generated by the Firestore backend. - -
    • Numerics evaluate directly to backend representation (`int64` or `float64`), not JS `number`.
    • JavaScript `Date` and firestore `Timestamp` objects strictly evaluate to `'timestamp'`.
    • Advanced configurations parsing backend types (such as `decimal128`, `max_key` or `min_key` from BSON) are also incorporated in this union string type. Note that `decimal128` is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    - -Signature: - -```typescript -export declare type Type = 'null' | 'array' | 'boolean' | 'bytes' | 'timestamp' | 'geo_point' | 'number' | 'int32' | 'int64' | 'float64' | 'decimal128' | 'map' | 'reference' | 'string' | 'vector' | 'max_key' | 'min_key' | 'object_id' | 'regex' | 'request_timestamp'; -``` - ## UnionStageOptions Options defining how a UnionStage is evaluated. See [Pipeline.union()](./firestore_pipelines.pipeline.md#pipelineunion). diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index 7c6a999e16..7a4375c777 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -245,6 +245,5 @@ export { AggregateFunction, TimeGranularity, TimePart, - TimeUnit, - Type + TimeUnit } from '../../src/lite-api/expressions'; diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index 7a2a948c01..fcf73819d3 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -212,8 +212,7 @@ export { Selectable, TimeGranularity, TimePart, - TimeUnit, - Type + TimeUnit } from './lite-api/expressions'; export { _internalPipelineToExecutePipelineRequestProto } from './remote/internal_serializer'; diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index d0165ae7f9..f00bc89ff8 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -63,38 +63,6 @@ export type ExpressionType = | 'Variable' | 'PipelineValue'; -/** - * - * An enumeration of the different types generated by the Firestore backend. - * - *
      - *
    • Numerics evaluate directly to backend representation (`int64` or `float64`), not JS `number`.
    • - *
    • JavaScript `Date` and firestore `Timestamp` objects strictly evaluate to `'timestamp'`.
    • - *
    • Advanced configurations parsing backend types (such as `decimal128`, `max_key` or `min_key` from BSON) are also incorporated in this union string type. Note that `decimal128` is a backend-only numeric type that the JavaScript SDK cannot create natively, but can be evaluated in pipelines.
    • - *
    - */ -export type Type = - | 'null' - | 'array' - | 'boolean' - | 'bytes' - | 'timestamp' - | 'geo_point' - | 'number' - | 'int32' - | 'int64' - | 'float64' - | 'decimal128' - | 'map' - | 'reference' - | 'string' - | 'vector' - | 'max_key' - | 'min_key' - | 'object_id' - | 'regex' - | 'request_timestamp'; - /** * Converts a value to an Expression, Returning either a Constant, MapFunction, * ArrayFunction, or the input itself (if it's already an expression). @@ -1275,6 +1243,10 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * 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. + * Supported values for `type` are: + * `'null'`, `'array'`, `'boolean'`, `'bytes'`, `'timestamp'`, `'geo_point'`, `'number'`, + * `'int32'`, `'int64'`, `'float64'`, `'decimal128'`, `'map'`, `'reference'`, `'string'`, + * `'vector'`, `'max_key'`, `'min_key'`, `'object_id'`, `'regex'`, `'request_timestamp'`. * * @example * ```typescript @@ -1285,7 +1257,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { * @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: Type): BooleanExpression { + isType(type: string): BooleanExpression { return new FunctionExpression( 'is_type', [this, constant(type)], @@ -8296,6 +8268,10 @@ export function type( * Creates an expression that checks if the value in the specified field is of the given type. * * @remarks Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. + * Supported values for `type` are: + * `'null'`, `'array'`, `'boolean'`, `'bytes'`, `'timestamp'`, `'geo_point'`, `'number'`, + * `'int32'`, `'int64'`, `'float64'`, `'decimal128'`, `'map'`, `'reference'`, `'string'`, + * `'vector'`, `'max_key'`, `'min_key'`, `'object_id'`, `'regex'`, `'request_timestamp'`. * * @example * ```typescript @@ -8307,12 +8283,16 @@ export function type( * @param type - The type to check for. * @returns A new `BooleanExpression` that evaluates to true if the field's value is of the given type, false otherwise. */ -export function isType(fieldName: string, type: Type): BooleanExpression; +export function isType(fieldName: string, type: string): BooleanExpression; /** * Creates an expression that checks if the result of an expression is of the given type. * * @remarks Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. + * Supported values for `type` are: + * `'null'`, `'array'`, `'boolean'`, `'bytes'`, `'timestamp'`, `'geo_point'`, `'number'`, + * `'int32'`, `'int64'`, `'float64'`, `'decimal128'`, `'map'`, `'reference'`, `'string'`, + * `'vector'`, `'max_key'`, `'min_key'`, `'object_id'`, `'regex'`, `'request_timestamp'`. * * @example * ```typescript @@ -8324,10 +8304,10 @@ export function isType(fieldName: string, type: Type): BooleanExpression; * @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. */ -export function isType(expression: Expression, type: Type): BooleanExpression; +export function isType(expression: Expression, type: string): BooleanExpression; export function isType( fieldNameOrExpression: string | Expression, - type: Type + type: string ): BooleanExpression { return fieldOrExpression(fieldNameOrExpression).isType(type); } From 2ca39c791890d163346e9d7afd1c674b8a928cd6 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 7 Apr 2026 13:02:55 -0700 Subject: [PATCH 128/174] Bump mock responses major version (#9818) --- scripts/update_vertexai_responses.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_vertexai_responses.sh b/scripts/update_vertexai_responses.sh index d32a7c83fc..aa01421a26 100755 --- a/scripts/update_vertexai_responses.sh +++ b/scripts/update_vertexai_responses.sh @@ -17,7 +17,7 @@ # This script replaces mock response files for Vertex AI unit tests with a fresh # clone of the shared repository of Vertex AI test data. -RESPONSES_VERSION='v15.*' # The major version of mock responses to use +RESPONSES_VERSION='v16.*' # The major version of mock responses to use REPO_NAME="vertexai-sdk-test-data" REPO_LINK="https://github.com/FirebaseExtended/$REPO_NAME.git" From 9620f9a670c0bc0dbfa73cc0c0aac639b2af8f4e Mon Sep 17 00:00:00 2001 From: Mila <107142260+milaGGL@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:37:48 -0400 Subject: [PATCH 129/174] feat(firestore): Add array expressions (#9788) --- .../firestore-lite-pipelines.api.md | 32 ++ common/api-review/firestore-pipelines.api.md | 32 ++ .../firestore_lite_pipelines.expression.md | 136 ++++++++ docs-devsite/firestore_lite_pipelines.md | 280 ++++++++++++++++ .../firestore_pipelines.expression.md | 136 ++++++++ docs-devsite/firestore_pipelines.md | 280 ++++++++++++++++ .../firestore/lite/pipelines/pipelines.ts | 4 + packages/firestore/src/api_pipelines.ts | 4 + .../firestore/src/lite-api/expressions.ts | 307 ++++++++++++++++++ .../test/integration/api/pipeline.test.ts | 183 +++++++++++ packages/firestore/test/lite/pipeline.test.ts | 183 +++++++++++ 11 files changed, 1577 insertions(+) diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index addb7e77c5..b701f1ffeb 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -119,6 +119,12 @@ export function arrayContainsAny(array: Expression, values: Expression): Boolean // @public export function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; +// @public +export function arrayFilter(fieldName: string, alias: string, filter: BooleanExpression): FunctionExpression; + +// @public +export function arrayFilter(arrayExpression: Expression, alias: string, filter: BooleanExpression): FunctionExpression; + // @public export function arrayFirst(fieldName: string): FunctionExpression; @@ -227,12 +233,30 @@ export function arrayMinimumN(arrayExpression: Expression, n: number): FunctionE // @public export function arrayMinimumN(arrayExpression: Expression, n: Expression): FunctionExpression; +// @public +export function arraySlice(fieldName: string, offset: number | Expression, length?: number | Expression): FunctionExpression; + +// @public +export function arraySlice(arrayExpression: Expression, offset: number | Expression, length?: number | Expression): FunctionExpression; + // @public export function arraySum(fieldName: string): FunctionExpression; // @public export function arraySum(expression: Expression): FunctionExpression; +// @public +export function arrayTransform(arrayExpression: Expression, elementAlias: string, transform: Expression): FunctionExpression; + +// @public +export function arrayTransform(fieldName: string, elementAlias: string, transform: Expression): FunctionExpression; + +// @public +export function arrayTransformWithIndex(arrayExpression: Expression, elementAlias: string, indexAlias: string, transform: Expression): FunctionExpression; + +// @public +export function arrayTransformWithIndex(fieldName: string, elementAlias: string, indexAlias: string, transform: Expression): FunctionExpression; + // @public export function ascending(expr: Expression): Ordering; @@ -514,6 +538,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ arrayContainsAny(arrayExpression: Expression): BooleanExpression; /* Excluded from this release type: _readUserData */ + arrayFilter(alias: string, filter: BooleanExpression): FunctionExpression; + /* Excluded from this release type: _readUserData */ arrayFirst(): FunctionExpression; /* Excluded from this release type: _readUserData */ arrayFirstN(n: number): FunctionExpression; @@ -558,8 +584,14 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ arrayReverse(): FunctionExpression; /* Excluded from this release type: _readUserData */ + arraySlice(offset: number | Expression, length?: number | Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ arraySum(): FunctionExpression; /* Excluded from this release type: _readUserData */ + arrayTransform(elementAlias: string, transform: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayTransformWithIndex(elementAlias: string, indexAlias: string, transform: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ as(name: string): AliasedExpression; /* Excluded from this release type: _readUserData */ asBoolean(): BooleanExpression; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index 68654b0e1e..cf7bff1fa8 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -119,6 +119,12 @@ export function arrayContainsAny(array: Expression, values: Expression): Boolean // @public export function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; +// @public +export function arrayFilter(fieldName: string, alias: string, filter: BooleanExpression): FunctionExpression; + +// @public +export function arrayFilter(arrayExpression: Expression, alias: string, filter: BooleanExpression): FunctionExpression; + // @public export function arrayFirst(fieldName: string): FunctionExpression; @@ -227,12 +233,30 @@ export function arrayMinimumN(arrayExpression: Expression, n: number): FunctionE // @public export function arrayMinimumN(arrayExpression: Expression, n: Expression): FunctionExpression; +// @public +export function arraySlice(fieldName: string, offset: number | Expression, length?: number | Expression): FunctionExpression; + +// @public +export function arraySlice(arrayExpression: Expression, offset: number | Expression, length?: number | Expression): FunctionExpression; + // @public export function arraySum(fieldName: string): FunctionExpression; // @public export function arraySum(expression: Expression): FunctionExpression; +// @public +export function arrayTransform(arrayExpression: Expression, elementAlias: string, transform: Expression): FunctionExpression; + +// @public +export function arrayTransform(fieldName: string, elementAlias: string, transform: Expression): FunctionExpression; + +// @public +export function arrayTransformWithIndex(arrayExpression: Expression, elementAlias: string, indexAlias: string, transform: Expression): FunctionExpression; + +// @public +export function arrayTransformWithIndex(fieldName: string, elementAlias: string, indexAlias: string, transform: Expression): FunctionExpression; + // @public export function ascending(expr: Expression): Ordering; @@ -517,6 +541,8 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ arrayContainsAny(arrayExpression: Expression): BooleanExpression; /* Excluded from this release type: _readUserData */ + arrayFilter(alias: string, filter: BooleanExpression): FunctionExpression; + /* Excluded from this release type: _readUserData */ arrayFirst(): FunctionExpression; /* Excluded from this release type: _readUserData */ arrayFirstN(n: number): FunctionExpression; @@ -561,8 +587,14 @@ export abstract class Expression { /* Excluded from this release type: _readUserData */ arrayReverse(): FunctionExpression; /* Excluded from this release type: _readUserData */ + arraySlice(offset: number | Expression, length?: number | Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ arraySum(): FunctionExpression; /* Excluded from this release type: _readUserData */ + arrayTransform(elementAlias: string, transform: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ + arrayTransformWithIndex(elementAlias: string, indexAlias: string, transform: Expression): FunctionExpression; + /* Excluded from this release type: _readUserData */ as(name: string): AliasedExpression; /* Excluded from this release type: _readUserData */ asBoolean(): BooleanExpression; diff --git a/docs-devsite/firestore_lite_pipelines.expression.md b/docs-devsite/firestore_lite_pipelines.expression.md index 29d43633f7..53f6eadf22 100644 --- a/docs-devsite/firestore_lite_pipelines.expression.md +++ b/docs-devsite/firestore_lite_pipelines.expression.md @@ -45,6 +45,7 @@ export declare abstract class Expression | [arrayContainsAll(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsall) | | Creates an expression that checks if an array contains all the specified elements. | | [arrayContainsAny(values)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | Creates an expression that checks if an array contains any of the specified elements. | | [arrayContainsAny(arrayExpression)](./firestore_lite_pipelines.expression.md#expressionarraycontainsany) | | Creates an expression that checks if an array contains any of the specified elements. | +| [arrayFilter(alias, filter)](./firestore_lite_pipelines.expression.md#expressionarrayfilter) | | Filters the array using a provided alias and predicate expression. | | [arrayFirst()](./firestore_lite_pipelines.expression.md#expressionarrayfirst) | | Returns the first element of the array. | | [arrayFirstN(n)](./firestore_lite_pipelines.expression.md#expressionarrayfirstn) | | Returns the first n elements of the array. | | [arrayFirstN(n)](./firestore_lite_pipelines.expression.md#expressionarrayfirstn) | | Returns the first n elements of the array. | @@ -67,7 +68,10 @@ export declare abstract class Expression | [arrayMinimumN(n)](./firestore_lite_pipelines.expression.md#expressionarrayminimumn) | | Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [arrayMinimumN(n)](./firestore_lite_pipelines.expression.md#expressionarrayminimumn) | | Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [arrayReverse()](./firestore_lite_pipelines.expression.md#expressionarrayreverse) | | Creates an expression that reverses an array. | +| [arraySlice(offset, length)](./firestore_lite_pipelines.expression.md#expressionarrayslice) | | Returns a subset of the array. | | [arraySum()](./firestore_lite_pipelines.expression.md#expressionarraysum) | | Creates an expression that computes the sum of the elements in an array. | +| [arrayTransform(elementAlias, transform)](./firestore_lite_pipelines.expression.md#expressionarraytransform) | | Creates an expression that applies a provided transformation to each element in an array. | +| [arrayTransformWithIndex(elementAlias, indexAlias, transform)](./firestore_lite_pipelines.expression.md#expressionarraytransformwithindex) | | Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. | | [as(name)](./firestore_lite_pipelines.expression.md#expressionas) | | 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. | | [asBoolean()](./firestore_lite_pipelines.expression.md#expressionasboolean) | | Wraps the expression in a \[BooleanExpression\]. | | [ascending()](./firestore_lite_pipelines.expression.md#expressionascending) | | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on this expression. | @@ -539,6 +543,38 @@ field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); ``` +## Expression.arrayFilter() + +Filters the array using a provided alias and predicate expression. + +Signature: + +```typescript +arrayFilter(alias: string, filter: BooleanExpression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| alias | string | The variable name to use for each element. | +| filter | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The predicate boolean expression to filter by. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the filtered array. + +### Example + + +```typescript +// Filter the 'items' array to only include those where the 'price' is greater than 10 +field("items").arrayFilter('item', greaterThan(variable('item.price'), 10)); + +``` + ## Expression.arrayFirst() Returns the first element of the array. @@ -1188,6 +1224,41 @@ field("myArray").arrayReverse(); ``` +## Expression.arraySlice() + +Returns a subset of the array. + +Signature: + +```typescript +arraySlice(offset: number | Expression, length?: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| offset | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The starting offset. | +| length | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The optional length of the slice. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the sliced array. + +### Example + + +```typescript +// Get 5 elements from the 'items' array starting from index 2 +field("items").arraySlice(2, 5); + +// Get n number of elements from the 'items' array starting from index 2 +field("items").arraySlice(2, field("count")); + +``` + ## Expression.arraySum() Creates an expression that computes the sum of the elements in an array. @@ -1212,6 +1283,71 @@ field("scores").arraySum(); ``` +## Expression.arrayTransform() + +Creates an expression that applies a provided transformation to each element in an array. + +Signature: + +```typescript +arrayTransform(elementAlias: string, transform: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elementAlias | string | The variable name to use for each element. | +| transform | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The lambda expression used to transform the elements. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the arrayTransform operation. + +### Example + + +```typescript +// Transform the 'scores' array by multiplying each score by 10 +field("scores").arrayTransform("score", multiply(variable("score"), 10)); + +``` + +## Expression.arrayTransformWithIndex() + +Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. + +Signature: + +```typescript +arrayTransformWithIndex(elementAlias: string, indexAlias: string, transform: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elementAlias | string | The variable name to use for each element. | +| indexAlias | string | The variable name to use for the current index. | +| transform | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The lambda expression used to transform the elements. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the arrayTransformWithIndex operation. + +### Example + + +```typescript +// Transform the 'scores' array by adding the index to each score +field("scores").arrayTransformWithIndex("score", "i", add(variable("score"), variable("i"))); + +``` + ## Expression.as() Assigns an alias to this expression. diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index 4fe7ba807a..b3c5fa4b3b 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -30,6 +30,7 @@ https://github.com/firebase/firebase-js-sdk | [arrayContainsAny(array, values)](./firestore_lite_pipelines.md#arraycontainsany_c381a96) | Creates an expression that checks if an array expression contains any of the specified elements. | | [arrayLength(array)](./firestore_lite_pipelines.md#arraylength_195e339) | Creates an expression that calculates the length of an array expression. | | function(arrayExpression, ...) | +| [arrayFilter(arrayExpression, alias, filter)](./firestore_lite_pipelines.md#arrayfilter_892d3c4) | Creates an expression that filters an array using a provided alias and predicate expression. | | [arrayFirst(arrayExpression)](./firestore_lite_pipelines.md#arrayfirst_f574e12) | Creates an expression that returns the first element of an array. | | [arrayFirstN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayfirstn_bff7f91) | Creates an expression that returns the first n elements of an array. | | [arrayFirstN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayfirstn_19b4ef8) | Creates an expression that returns the first n elements of an array. | @@ -47,6 +48,9 @@ https://github.com/firebase/firebase-js-sdk | [arrayMinimum(arrayExpression)](./firestore_lite_pipelines.md#arrayminimum_f574e12) | Creates an expression that returns the minimum value in an array. | | [arrayMinimumN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayminimumn_bff7f91) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [arrayMinimumN(arrayExpression, n)](./firestore_lite_pipelines.md#arrayminimumn_19b4ef8) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arraySlice(arrayExpression, offset, length)](./firestore_lite_pipelines.md#arrayslice_a349bee) | Creates an expression that returns a slice of an array from offset with length elements. | +| [arrayTransform(arrayExpression, elementAlias, transform)](./firestore_lite_pipelines.md#arraytransform_28967fa) | Creates an expression that applies a provided transformation to each element in an array. | +| [arrayTransformWithIndex(arrayExpression, elementAlias, indexAlias, transform)](./firestore_lite_pipelines.md#arraytransformwithindex_2f3b17f) | Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. | | [join(arrayExpression, delimiterExpression)](./firestore_lite_pipelines.md#join_313e6aa) | Creates an expression that joins the elements of an array into a string. | | [join(arrayExpression, delimiter)](./firestore_lite_pipelines.md#join_d088d29) | Creates an expression that joins the elements of an array into a string. | | function(arrayField, ...) | @@ -160,6 +164,7 @@ https://github.com/firebase/firebase-js-sdk | [arrayContainsAll(fieldName, arrayExpression)](./firestore_lite_pipelines.md#arraycontainsall_48da8d9) | Creates an expression that checks if a field's array value contains all the specified values or expressions. | | [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_8060b23) | Creates an expression that checks if a field's array value contains any of the specified elements. | | [arrayContainsAny(fieldName, values)](./firestore_lite_pipelines.md#arraycontainsany_1b4f7cd) | Creates an expression that checks if a field's array value contains any of the specified elements. | +| [arrayFilter(fieldName, alias, filter)](./firestore_lite_pipelines.md#arrayfilter_ab67868) | Creates an expression that filters an array using a provided alias and predicate expression. | | [arrayFirst(fieldName)](./firestore_lite_pipelines.md#arrayfirst_e5b0480) | Creates an expression that returns the first element of an array. | | [arrayFirstN(fieldName, n)](./firestore_lite_pipelines.md#arrayfirstn_597a4d9) | Creates an expression that returns the first n elements of an array. | | [arrayFirstN(fieldName, n)](./firestore_lite_pipelines.md#arrayfirstn_1a86a2c) | Creates an expression that returns the first n elements of an array. | @@ -176,7 +181,10 @@ https://github.com/firebase/firebase-js-sdk | [arrayMinimum(fieldName)](./firestore_lite_pipelines.md#arrayminimum_e5b0480) | Creates an expression that returns the minimum value in an array. | | [arrayMinimumN(fieldName, n)](./firestore_lite_pipelines.md#arrayminimumn_597a4d9) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [arrayMinimumN(fieldName, n)](./firestore_lite_pipelines.md#arrayminimumn_1a86a2c) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arraySlice(fieldName, offset, length)](./firestore_lite_pipelines.md#arrayslice_821aa43) | Creates an expression that returns a slice of an array from offset with length elements. | | [arraySum(fieldName)](./firestore_lite_pipelines.md#arraysum_e5b0480) | Creates an expression that computes the sum of the elements in an array. | +| [arrayTransform(fieldName, elementAlias, transform)](./firestore_lite_pipelines.md#arraytransform_328a090) | Creates an expression that applies a provided transformation to each element in an array. | +| [arrayTransformWithIndex(fieldName, elementAlias, indexAlias, transform)](./firestore_lite_pipelines.md#arraytransformwithindex_e6629b2) | Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. | | [ascending(fieldName)](./firestore_lite_pipelines.md#ascending_e5b0480) | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. | | [average(fieldName)](./firestore_lite_pipelines.md#average_e5b0480) | Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. | | [byteLength(fieldName)](./firestore_lite_pipelines.md#bytelength_e5b0480) | Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. | @@ -841,6 +849,39 @@ arrayLength(field("cart")); ## function(arrayExpression, ...) +### arrayFilter(arrayExpression, alias, filter) {:#arrayfilter_892d3c4} + +Creates an expression that filters an array using a provided alias and predicate expression. + +Signature: + +```typescript +export declare function arrayFilter(arrayExpression: Expression, alias: string, filter: BooleanExpression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | +| alias | string | The variable name to use for each element. | +| filter | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The predicate boolean expression to filter by. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the filtered array. + +### Example + + +```typescript +// Filter "scores" to include only values greater than 50 +arrayFilter(field("scores"), "score", greaterThan(variable("score"), 50)); + +``` + ### arrayFirst(arrayExpression) {:#arrayfirst_f574e12} Creates an expression that returns the first element of an array. @@ -1390,6 +1431,109 @@ arrayMinimumN(field("scores"), field("count")); ``` +### arraySlice(arrayExpression, offset, length) {:#arrayslice_a349bee} + +Creates an expression that returns a slice of an array from `offset` with `length` elements. + +Signature: + +```typescript +export declare function arraySlice(arrayExpression: Expression, offset: number | Expression, length?: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | +| offset | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The starting offset. | +| length | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The optional length of the slice. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the sliced array. + +### Example + + +```typescript +// Get 5 elements from an array expression starting from index 2 +arraySlice(field("items"), 2, 5); + +// Get n elements from an array expression starting from index 2 +arraySlice(field("items"), 2, field("length")); + +``` + +### arrayTransform(arrayExpression, elementAlias, transform) {:#arraytransform_28967fa} + +Creates an expression that applies a provided transformation to each element in an array. + +Signature: + +```typescript +export declare function arrayTransform(arrayExpression: Expression, elementAlias: string, transform: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | +| elementAlias | string | The variable name to use for each element. | +| transform | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The lambda expression used to transform the elements. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the transformed array. + +### Example + + +```typescript +// Transform "scores" array by multiplying each score by 10 +arrayTransform(field("scores"), "score", multiply(variable("score"), 10)); + +``` + +### arrayTransformWithIndex(arrayExpression, elementAlias, indexAlias, transform) {:#arraytransformwithindex_2f3b17f} + +Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. + +Signature: + +```typescript +export declare function arrayTransformWithIndex(arrayExpression: Expression, elementAlias: string, indexAlias: string, transform: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression representing the array. | +| elementAlias | string | The variable name to use for each element. | +| indexAlias | string | The variable name to use for the current index. | +| transform | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression used to transform the elements. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the transformed array. + +### Example + + +```typescript +// Transform "scores" array by adding the index to each score +arrayTransformWithIndex(field("scores"), "score", "i", add(variable("score"), variable("i"))); + +``` + ### join(arrayExpression, delimiterExpression) {:#join_313e6aa} Creates an expression that joins the elements of an array into a string. @@ -4483,6 +4627,39 @@ arrayContainsAny("categories", array([field("cate1"), "Science"])); ``` +### arrayFilter(fieldName, alias, filter) {:#arrayfilter_ab67868} + +Creates an expression that filters an array using a provided alias and predicate expression. + +Signature: + +```typescript +export declare function arrayFilter(fieldName: string, alias: string, filter: BooleanExpression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the array. | +| alias | string | The variable name to use for each element. | +| filter | [BooleanExpression](./firestore_lite_pipelines.booleanexpression.md#booleanexpression_class) | The predicate boolean expression to evaluate for each element. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the filtered array. + +### Example + + +```typescript +// Get a filtered array of the 'scores' field containing only elements greater than 50. +arrayFilter("scores", "score", greaterThan(variable("score"), 50)); + +``` + ### arrayFirst(fieldName) {:#arrayfirst_e5b0480} Creates an expression that returns the first element of an array. @@ -4998,6 +5175,42 @@ arrayMinimumN(field("scores"), field("count")); ``` +### arraySlice(fieldName, offset, length) {:#arrayslice_821aa43} + +Creates an expression that returns a slice of an array from `offset` with `length` elements. + +Signature: + +```typescript +export declare function arraySlice(fieldName: string, offset: number | Expression, length?: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the array. | +| offset | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The starting offset. | +| length | number \| [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The optional length of the slice. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the sliced array. + +### Example + + +```typescript +// Get 5 elements from the 'items' array field starting from index 2 +arraySlice("items", 2, 5); + +// Get n elements from the 'items' array field starting from index 2 +arraySlice("items", 2, field("length")); + +``` + ### arraySum(fieldName) {:#arraysum_e5b0480} Creates an expression that computes the sum of the elements in an array. @@ -5029,6 +5242,73 @@ arraySum("scores"); ``` +### arrayTransform(fieldName, elementAlias, transform) {:#arraytransform_328a090} + +Creates an expression that applies a provided transformation to each element in an array. + +Signature: + +```typescript +export declare function arrayTransform(fieldName: string, elementAlias: string, transform: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the array. | +| elementAlias | string | The variable name to use for each element. | +| transform | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The expression used to transform the elements. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the transformed array. + +### Example + + +```typescript +// Transform "scores" array by multiplying each score by 10 +arrayTransform("scores", "score", multiply(variable("score"), 10)); + +``` + +### arrayTransformWithIndex(fieldName, elementAlias, indexAlias, transform) {:#arraytransformwithindex_e6629b2} + +Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. + +Signature: + +```typescript +export declare function arrayTransformWithIndex(fieldName: string, elementAlias: string, indexAlias: string, transform: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the array. | +| elementAlias | string | The variable name to use for each element. | +| indexAlias | string | The variable name to use for the current index. | +| transform | [Expression](./firestore_lite_pipelines.expression.md#expression_class) | The lambda expression used to transform the elements. | + +Returns: + +[FunctionExpression](./firestore_lite_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the transformed array. + +### Example + + +```typescript +// Transform "scores" array by adding the index to each score +arrayTransformWithIndex("scores", "score", "i", add(variable("score"), variable("i"))); + +``` + ### ascending(fieldName) {:#ascending_e5b0480} Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. diff --git a/docs-devsite/firestore_pipelines.expression.md b/docs-devsite/firestore_pipelines.expression.md index 8a2b72cbe8..e5f2a09f55 100644 --- a/docs-devsite/firestore_pipelines.expression.md +++ b/docs-devsite/firestore_pipelines.expression.md @@ -45,6 +45,7 @@ export declare abstract class Expression | [arrayContainsAll(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsall) | | Creates an expression that checks if an array contains all the specified elements. | | [arrayContainsAny(values)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | Creates an expression that checks if an array contains any of the specified elements. | | [arrayContainsAny(arrayExpression)](./firestore_pipelines.expression.md#expressionarraycontainsany) | | Creates an expression that checks if an array contains any of the specified elements. | +| [arrayFilter(alias, filter)](./firestore_pipelines.expression.md#expressionarrayfilter) | | Filters the array using a provided alias and predicate expression. | | [arrayFirst()](./firestore_pipelines.expression.md#expressionarrayfirst) | | Returns the first element of the array. | | [arrayFirstN(n)](./firestore_pipelines.expression.md#expressionarrayfirstn) | | Returns the first n elements of the array. | | [arrayFirstN(n)](./firestore_pipelines.expression.md#expressionarrayfirstn) | | Returns the first n elements of the array. | @@ -67,7 +68,10 @@ export declare abstract class Expression | [arrayMinimumN(n)](./firestore_pipelines.expression.md#expressionarrayminimumn) | | Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [arrayMinimumN(n)](./firestore_pipelines.expression.md#expressionarrayminimumn) | | Returns the smallest n elements of the array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [arrayReverse()](./firestore_pipelines.expression.md#expressionarrayreverse) | | Creates an expression that reverses an array. | +| [arraySlice(offset, length)](./firestore_pipelines.expression.md#expressionarrayslice) | | Returns a subset of the array. | | [arraySum()](./firestore_pipelines.expression.md#expressionarraysum) | | Creates an expression that computes the sum of the elements in an array. | +| [arrayTransform(elementAlias, transform)](./firestore_pipelines.expression.md#expressionarraytransform) | | Creates an expression that applies a provided transformation to each element in an array. | +| [arrayTransformWithIndex(elementAlias, indexAlias, transform)](./firestore_pipelines.expression.md#expressionarraytransformwithindex) | | Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. | | [as(name)](./firestore_pipelines.expression.md#expressionas) | | 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. | | [asBoolean()](./firestore_pipelines.expression.md#expressionasboolean) | | Wraps the expression in a \[BooleanExpression\]. | | [ascending()](./firestore_pipelines.expression.md#expressionascending) | | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on this expression. | @@ -539,6 +543,38 @@ field("groups").arrayContainsAny(array([field("userGroup"), "guest"])); ``` +## Expression.arrayFilter() + +Filters the array using a provided alias and predicate expression. + +Signature: + +```typescript +arrayFilter(alias: string, filter: BooleanExpression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| alias | string | The variable name to use for each element. | +| filter | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The predicate boolean expression to filter by. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the filtered array. + +### Example + + +```typescript +// Filter the 'items' array to only include those where the 'price' is greater than 10 +field("items").arrayFilter('item', greaterThan(variable('item.price'), 10)); + +``` + ## Expression.arrayFirst() Returns the first element of the array. @@ -1188,6 +1224,41 @@ field("myArray").arrayReverse(); ``` +## Expression.arraySlice() + +Returns a subset of the array. + +Signature: + +```typescript +arraySlice(offset: number | Expression, length?: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| offset | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | The starting offset. | +| length | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | The optional length of the slice. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the sliced array. + +### Example + + +```typescript +// Get 5 elements from the 'items' array starting from index 2 +field("items").arraySlice(2, 5); + +// Get n number of elements from the 'items' array starting from index 2 +field("items").arraySlice(2, field("count")); + +``` + ## Expression.arraySum() Creates an expression that computes the sum of the elements in an array. @@ -1212,6 +1283,71 @@ field("scores").arraySum(); ``` +## Expression.arrayTransform() + +Creates an expression that applies a provided transformation to each element in an array. + +Signature: + +```typescript +arrayTransform(elementAlias: string, transform: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elementAlias | string | The variable name to use for each element. | +| transform | [Expression](./firestore_pipelines.expression.md#expression_class) | The lambda expression used to transform the elements. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the arrayTransform operation. + +### Example + + +```typescript +// Transform the 'scores' array by multiplying each score by 10 +field("scores").arrayTransform("score", multiply(variable("score"), 10)); + +``` + +## Expression.arrayTransformWithIndex() + +Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. + +Signature: + +```typescript +arrayTransformWithIndex(elementAlias: string, indexAlias: string, transform: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| elementAlias | string | The variable name to use for each element. | +| indexAlias | string | The variable name to use for the current index. | +| transform | [Expression](./firestore_pipelines.expression.md#expression_class) | The lambda expression used to transform the elements. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new `Expression` representing the arrayTransformWithIndex operation. + +### Example + + +```typescript +// Transform the 'scores' array by adding the index to each score +field("scores").arrayTransformWithIndex("score", "i", add(variable("score"), variable("i"))); + +``` + ## Expression.as() Assigns an alias to this expression. diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 76ec495e4a..1b2dce4ea0 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -30,6 +30,7 @@ https://github.com/firebase/firebase-js-sdk | [arrayContainsAny(array, values)](./firestore_pipelines.md#arraycontainsany_c381a96) | Creates an expression that checks if an array expression contains any of the specified elements. | | [arrayLength(array)](./firestore_pipelines.md#arraylength_195e339) | Creates an expression that calculates the length of an array expression. | | function(arrayExpression, ...) | +| [arrayFilter(arrayExpression, alias, filter)](./firestore_pipelines.md#arrayfilter_892d3c4) | Creates an expression that filters an array using a provided alias and predicate expression. | | [arrayFirst(arrayExpression)](./firestore_pipelines.md#arrayfirst_f574e12) | Creates an expression that returns the first element of an array. | | [arrayFirstN(arrayExpression, n)](./firestore_pipelines.md#arrayfirstn_bff7f91) | Creates an expression that returns the first n elements of an array. | | [arrayFirstN(arrayExpression, n)](./firestore_pipelines.md#arrayfirstn_19b4ef8) | Creates an expression that returns the first n elements of an array. | @@ -47,6 +48,9 @@ https://github.com/firebase/firebase-js-sdk | [arrayMinimum(arrayExpression)](./firestore_pipelines.md#arrayminimum_f574e12) | Creates an expression that returns the minimum value in an array. | | [arrayMinimumN(arrayExpression, n)](./firestore_pipelines.md#arrayminimumn_bff7f91) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [arrayMinimumN(arrayExpression, n)](./firestore_pipelines.md#arrayminimumn_19b4ef8) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arraySlice(arrayExpression, offset, length)](./firestore_pipelines.md#arrayslice_a349bee) | Creates an expression that returns a slice of an array from offset with length elements. | +| [arrayTransform(arrayExpression, elementAlias, transform)](./firestore_pipelines.md#arraytransform_28967fa) | Creates an expression that applies a provided transformation to each element in an array. | +| [arrayTransformWithIndex(arrayExpression, elementAlias, indexAlias, transform)](./firestore_pipelines.md#arraytransformwithindex_2f3b17f) | Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. | | [join(arrayExpression, delimiterExpression)](./firestore_pipelines.md#join_313e6aa) | Creates an expression that joins the elements of an array into a string. | | [join(arrayExpression, delimiter)](./firestore_pipelines.md#join_d088d29) | Creates an expression that joins the elements of an array into a string. | | function(arrayField, ...) | @@ -160,6 +164,7 @@ https://github.com/firebase/firebase-js-sdk | [arrayContainsAll(fieldName, arrayExpression)](./firestore_pipelines.md#arraycontainsall_48da8d9) | Creates an expression that checks if a field's array value contains all the specified values or expressions. | | [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_8060b23) | Creates an expression that checks if a field's array value contains any of the specified elements. | | [arrayContainsAny(fieldName, values)](./firestore_pipelines.md#arraycontainsany_1b4f7cd) | Creates an expression that checks if a field's array value contains any of the specified elements. | +| [arrayFilter(fieldName, alias, filter)](./firestore_pipelines.md#arrayfilter_ab67868) | Creates an expression that filters an array using a provided alias and predicate expression. | | [arrayFirst(fieldName)](./firestore_pipelines.md#arrayfirst_e5b0480) | Creates an expression that returns the first element of an array. | | [arrayFirstN(fieldName, n)](./firestore_pipelines.md#arrayfirstn_597a4d9) | Creates an expression that returns the first n elements of an array. | | [arrayFirstN(fieldName, n)](./firestore_pipelines.md#arrayfirstn_1a86a2c) | Creates an expression that returns the first n elements of an array. | @@ -176,7 +181,10 @@ https://github.com/firebase/firebase-js-sdk | [arrayMinimum(fieldName)](./firestore_pipelines.md#arrayminimum_e5b0480) | Creates an expression that returns the minimum value in an array. | | [arrayMinimumN(fieldName, n)](./firestore_pipelines.md#arrayminimumn_597a4d9) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | | [arrayMinimumN(fieldName, n)](./firestore_pipelines.md#arrayminimumn_1a86a2c) | Creates an expression that returns the smallest n elements of an array.Note: Returns the n smallest non-null elements in the array, in ascending order. This does not use a stable sort, meaning the order of equivalent elements is undefined. | +| [arraySlice(fieldName, offset, length)](./firestore_pipelines.md#arrayslice_821aa43) | Creates an expression that returns a slice of an array from offset with length elements. | | [arraySum(fieldName)](./firestore_pipelines.md#arraysum_e5b0480) | Creates an expression that computes the sum of the elements in an array. | +| [arrayTransform(fieldName, elementAlias, transform)](./firestore_pipelines.md#arraytransform_328a090) | Creates an expression that applies a provided transformation to each element in an array. | +| [arrayTransformWithIndex(fieldName, elementAlias, indexAlias, transform)](./firestore_pipelines.md#arraytransformwithindex_e6629b2) | Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. | | [ascending(fieldName)](./firestore_pipelines.md#ascending_e5b0480) | Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. | | [average(fieldName)](./firestore_pipelines.md#average_e5b0480) | Creates an aggregation that calculates the average (mean) of a field's values across multiple stage inputs. | | [byteLength(fieldName)](./firestore_pipelines.md#bytelength_e5b0480) | Creates an expression that calculates the length of a string represented by a field in UTF-8 bytes, or just the length of a Blob. | @@ -846,6 +854,39 @@ arrayLength(field("cart")); ## function(arrayExpression, ...) +### arrayFilter(arrayExpression, alias, filter) {:#arrayfilter_892d3c4} + +Creates an expression that filters an array using a provided alias and predicate expression. + +Signature: + +```typescript +export declare function arrayFilter(arrayExpression: Expression, alias: string, filter: BooleanExpression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | +| alias | string | The variable name to use for each element. | +| filter | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The predicate boolean expression to filter by. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the filtered array. + +### Example + + +```typescript +// Filter "scores" to include only values greater than 50 +arrayFilter(field("scores"), "score", greaterThan(variable("score"), 50)); + +``` + ### arrayFirst(arrayExpression) {:#arrayfirst_f574e12} Creates an expression that returns the first element of an array. @@ -1395,6 +1436,109 @@ arrayMinimumN(field("scores"), field("count")); ``` +### arraySlice(arrayExpression, offset, length) {:#arrayslice_a349bee} + +Creates an expression that returns a slice of an array from `offset` with `length` elements. + +Signature: + +```typescript +export declare function arraySlice(arrayExpression: Expression, offset: number | Expression, length?: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | +| offset | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | The starting offset. | +| length | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | The optional length of the slice. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the sliced array. + +### Example + + +```typescript +// Get 5 elements from an array expression starting from index 2 +arraySlice(field("items"), 2, 5); + +// Get n elements from an array expression starting from index 2 +arraySlice(field("items"), 2, field("length")); + +``` + +### arrayTransform(arrayExpression, elementAlias, transform) {:#arraytransform_28967fa} + +Creates an expression that applies a provided transformation to each element in an array. + +Signature: + +```typescript +export declare function arrayTransform(arrayExpression: Expression, elementAlias: string, transform: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | +| elementAlias | string | The variable name to use for each element. | +| transform | [Expression](./firestore_pipelines.expression.md#expression_class) | The lambda expression used to transform the elements. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the transformed array. + +### Example + + +```typescript +// Transform "scores" array by multiplying each score by 10 +arrayTransform(field("scores"), "score", multiply(variable("score"), 10)); + +``` + +### arrayTransformWithIndex(arrayExpression, elementAlias, indexAlias, transform) {:#arraytransformwithindex_2f3b17f} + +Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. + +Signature: + +```typescript +export declare function arrayTransformWithIndex(arrayExpression: Expression, elementAlias: string, indexAlias: string, transform: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| arrayExpression | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression representing the array. | +| elementAlias | string | The variable name to use for each element. | +| indexAlias | string | The variable name to use for the current index. | +| transform | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression used to transform the elements. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the transformed array. + +### Example + + +```typescript +// Transform "scores" array by adding the index to each score +arrayTransformWithIndex(field("scores"), "score", "i", add(variable("score"), variable("i"))); + +``` + ### join(arrayExpression, delimiterExpression) {:#join_313e6aa} Creates an expression that joins the elements of an array into a string. @@ -4488,6 +4632,39 @@ arrayContainsAny("categories", array([field("cate1"), "Science"])); ``` +### arrayFilter(fieldName, alias, filter) {:#arrayfilter_ab67868} + +Creates an expression that filters an array using a provided alias and predicate expression. + +Signature: + +```typescript +export declare function arrayFilter(fieldName: string, alias: string, filter: BooleanExpression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the array. | +| alias | string | The variable name to use for each element. | +| filter | [BooleanExpression](./firestore_pipelines.booleanexpression.md#booleanexpression_class) | The predicate boolean expression to evaluate for each element. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the filtered array. + +### Example + + +```typescript +// Get a filtered array of the 'scores' field containing only elements greater than 50. +arrayFilter("scores", "score", greaterThan(variable("score"), 50)); + +``` + ### arrayFirst(fieldName) {:#arrayfirst_e5b0480} Creates an expression that returns the first element of an array. @@ -5003,6 +5180,42 @@ arrayMinimumN(field("scores"), field("count")); ``` +### arraySlice(fieldName, offset, length) {:#arrayslice_821aa43} + +Creates an expression that returns a slice of an array from `offset` with `length` elements. + +Signature: + +```typescript +export declare function arraySlice(fieldName: string, offset: number | Expression, length?: number | Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the array. | +| offset | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | The starting offset. | +| length | number \| [Expression](./firestore_pipelines.expression.md#expression_class) | The optional length of the slice. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the sliced array. + +### Example + + +```typescript +// Get 5 elements from the 'items' array field starting from index 2 +arraySlice("items", 2, 5); + +// Get n elements from the 'items' array field starting from index 2 +arraySlice("items", 2, field("length")); + +``` + ### arraySum(fieldName) {:#arraysum_e5b0480} Creates an expression that computes the sum of the elements in an array. @@ -5034,6 +5247,73 @@ arraySum("scores"); ``` +### arrayTransform(fieldName, elementAlias, transform) {:#arraytransform_328a090} + +Creates an expression that applies a provided transformation to each element in an array. + +Signature: + +```typescript +export declare function arrayTransform(fieldName: string, elementAlias: string, transform: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the array. | +| elementAlias | string | The variable name to use for each element. | +| transform | [Expression](./firestore_pipelines.expression.md#expression_class) | The expression used to transform the elements. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the transformed array. + +### Example + + +```typescript +// Transform "scores" array by multiplying each score by 10 +arrayTransform("scores", "score", multiply(variable("score"), 10)); + +``` + +### arrayTransformWithIndex(fieldName, elementAlias, indexAlias, transform) {:#arraytransformwithindex_e6629b2} + +Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. + +Signature: + +```typescript +export declare function arrayTransformWithIndex(fieldName: string, elementAlias: string, indexAlias: string, transform: Expression): FunctionExpression; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | The name of the field containing the array. | +| elementAlias | string | The variable name to use for each element. | +| indexAlias | string | The variable name to use for the current index. | +| transform | [Expression](./firestore_pipelines.expression.md#expression_class) | The lambda expression used to transform the elements. | + +Returns: + +[FunctionExpression](./firestore_pipelines.functionexpression.md#functionexpression_class) + +A new [Expression](./firestore_pipelines.expression.md#expression_class) representing the transformed array. + +### Example + + +```typescript +// Transform "scores" array by adding the index to each score +arrayTransformWithIndex("scores", "score", "i", add(variable("score"), variable("i"))); + +``` + ### ascending(fieldName) {:#ascending_e5b0480} Creates an [Ordering](./firestore_pipelines.ordering.md#ordering_class) that sorts documents in ascending order based on a field. diff --git a/packages/firestore/lite/pipelines/pipelines.ts b/packages/firestore/lite/pipelines/pipelines.ts index 7a4375c777..21d5da9cfa 100644 --- a/packages/firestore/lite/pipelines/pipelines.ts +++ b/packages/firestore/lite/pipelines/pipelines.ts @@ -125,9 +125,13 @@ export { arrayContains, arrayContainsAny, arrayContainsAll, + arrayFilter, arrayFirst, arrayFirstN, + arrayTransform, + arrayTransformWithIndex, arrayGet, + arraySlice, arrayIndexOf, arrayIndexOfAll, arrayLast, diff --git a/packages/firestore/src/api_pipelines.ts b/packages/firestore/src/api_pipelines.ts index fcf73819d3..8cd2731d4e 100644 --- a/packages/firestore/src/api_pipelines.ts +++ b/packages/firestore/src/api_pipelines.ts @@ -77,9 +77,13 @@ export { arrayContains, arrayContainsAny, arrayContainsAll, + arrayFilter, + arrayTransform, + arrayTransformWithIndex, arrayFirst, arrayFirstN, arrayGet, + arraySlice, arrayIndexOf, arrayIndexOfAll, arrayLast, diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index f00bc89ff8..20c4426306 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -1416,6 +1416,109 @@ export abstract class Expression implements ProtoValueSerializable, UserData { return new FunctionExpression('reverse', [this], 'reverse'); } + /** + * Filters the array using a provided alias and predicate expression. + * + * @example + * ```typescript + * // Filter the 'items' array to only include those where the 'price' is greater than 10 + * field("items").arrayFilter('item', greaterThan(variable('item.price'), 10)); + * ``` + * + * @param alias - The variable name to use for each element. + * @param filter - The predicate boolean expression to filter by. + * @returns A new `Expression` representing the filtered array. + */ + arrayFilter(alias: string, filter: BooleanExpression): FunctionExpression { + return new FunctionExpression( + 'array_filter', + [this, valueToDefaultExpr(alias), filter], + 'arrayFilter' + ); + } + + /** + * Creates an expression that applies a provided transformation to each element in an array. + * + * @example + * ```typescript + * // Transform the 'scores' array by multiplying each score by 10 + * field("scores").arrayTransform("score", multiply(variable("score"), 10)); + * ``` + * + * @param elementAlias - The variable name to use for each element. + * @param transform - The lambda expression used to transform the elements. + * @returns A new `Expression` representing the arrayTransform operation. + */ + arrayTransform( + elementAlias: string, + transform: Expression + ): FunctionExpression { + return new FunctionExpression( + 'array_transform', + [this, valueToDefaultExpr(elementAlias), transform], + 'arrayTransform' + ); + } + + /** + * Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. + * + * @example + * ```typescript + * // Transform the 'scores' array by adding the index to each score + * field("scores").arrayTransformWithIndex("score", "i", add(variable("score"), variable("i"))); + * ``` + * + * @param elementAlias - The variable name to use for each element. + * @param indexAlias - The variable name to use for the current index. + * @param transform - The lambda expression used to transform the elements. + * @returns A new `Expression` representing the arrayTransformWithIndex operation. + */ + arrayTransformWithIndex( + elementAlias: string, + indexAlias: string, + transform: Expression + ): FunctionExpression { + return new FunctionExpression( + 'array_transform', + [ + this, + valueToDefaultExpr(elementAlias), + valueToDefaultExpr(indexAlias), + transform + ], + 'arrayTransformWithIndex' + ); + } + + /** + * Returns a subset of the array. + * + * @example + * ```typescript + * // Get 5 elements from the 'items' array starting from index 2 + * field("items").arraySlice(2, 5); + * + * // Get n number of elements from the 'items' array starting from index 2 + * field("items").arraySlice(2, field("count")); + * ``` + * + * @param offset - The starting offset. + * @param length - The optional length of the slice. + * @returns A new `Expression` representing the sliced array. + */ + arraySlice( + offset: number | Expression, + length?: number | Expression + ): FunctionExpression { + const args: Expression[] = [this, valueToDefaultExpr(offset)]; + if (length !== undefined) { + args.push(valueToDefaultExpr(length)); + } + return new FunctionExpression('array_slice', args, 'arraySlice'); + } + /** * Returns the first element of the array. * @@ -6875,6 +6978,210 @@ export function regexContains( /** * + * Creates an expression that filters an array using a provided alias and predicate expression. + * + * @example + * ```typescript + * // Get a filtered array of the 'scores' field containing only elements greater than 50. + * arrayFilter("scores", "score", greaterThan(variable("score"), 50)); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @param alias - The variable name to use for each element. + * @param filter - The predicate boolean expression to evaluate for each element. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the filtered array. + */ +export function arrayFilter( + fieldName: string, + alias: string, + filter: BooleanExpression +): FunctionExpression; + +/** + * Creates an expression that filters an array using a provided alias and predicate expression. + * + * @example + * ```typescript + * // Filter "scores" to include only values greater than 50 + * arrayFilter(field("scores"), "score", greaterThan(variable("score"), 50)); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @param alias - The variable name to use for each element. + * @param filter - The predicate boolean expression to filter by. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the filtered array. + */ +export function arrayFilter( + arrayExpression: Expression, + alias: string, + filter: BooleanExpression +): FunctionExpression; + +export function arrayFilter( + array: Expression | string, + alias: string, + filter: BooleanExpression +): FunctionExpression { + return fieldOrExpression(array).arrayFilter(alias, filter); +} + +/** + * Creates an expression that applies a provided transformation to each element in an array. + * + * @example + * ```typescript + * // Transform "scores" array by multiplying each score by 10 + * arrayTransform(field("scores"), "score", multiply(variable("score"), 10)); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @param elementAlias - The variable name to use for each element. + * @param transform - The lambda expression used to transform the elements. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the transformed array. + */ +export function arrayTransform( + arrayExpression: Expression, + elementAlias: string, + transform: Expression +): FunctionExpression; + +/** + * Creates an expression that applies a provided transformation to each element in an array. + * + * @example + * ```typescript + * // Transform "scores" array by multiplying each score by 10 + * arrayTransform("scores", "score", multiply(variable("score"), 10)); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @param elementAlias - The variable name to use for each element. + * @param transform - The expression used to transform the elements. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the transformed array. + */ +export function arrayTransform( + fieldName: string, + elementAlias: string, + transform: Expression +): FunctionExpression; +export function arrayTransform( + array: Expression | string, + elementAlias: string, + transform: Expression +): FunctionExpression { + return fieldOrExpression(array).arrayTransform(elementAlias, transform); +} + +/** + * Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. + * + * @example + * ```typescript + * // Transform "scores" array by adding the index to each score + * arrayTransformWithIndex(field("scores"), "score", "i", add(variable("score"), variable("i"))); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @param elementAlias - The variable name to use for each element. + * @param indexAlias - The variable name to use for the current index. + * @param transform - The expression used to transform the elements. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the transformed array. + */ +export function arrayTransformWithIndex( + arrayExpression: Expression, + elementAlias: string, + indexAlias: string, + transform: Expression +): FunctionExpression; + +/** + * Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression. + * + * @example + * ```typescript + * // Transform "scores" array by adding the index to each score + * arrayTransformWithIndex("scores", "score", "i", add(variable("score"), variable("i"))); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @param elementAlias - The variable name to use for each element. + * @param indexAlias - The variable name to use for the current index. + * @param transform - The lambda expression used to transform the elements. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the transformed array. + */ +export function arrayTransformWithIndex( + fieldName: string, + elementAlias: string, + indexAlias: string, + transform: Expression +): FunctionExpression; +export function arrayTransformWithIndex( + array: Expression | string, + elementAlias: string, + indexAlias: string, + transform: Expression +): FunctionExpression { + return fieldOrExpression(array).arrayTransformWithIndex( + elementAlias, + indexAlias, + transform + ); +} + +/** + * Creates an expression that returns a slice of an array from `offset` with `length` elements. + * + * @example + * ```typescript + * // Get 5 elements from the 'items' array field starting from index 2 + * arraySlice("items", 2, 5); + * + * // Get n elements from the 'items' array field starting from index 2 + * arraySlice("items", 2, field("length")); + * ``` + * + * @param fieldName - The name of the field containing the array. + * @param offset - The starting offset. + * @param length - The optional length of the slice. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the sliced array. + */ +export function arraySlice( + fieldName: string, + offset: number | Expression, + length?: number | Expression +): FunctionExpression; + +/** + * Creates an expression that returns a slice of an array from `offset` with `length` elements. + * + * @example + * ```typescript + * // Get 5 elements from an array expression starting from index 2 + * arraySlice(field("items"), 2, 5); + * + * // Get n elements from an array expression starting from index 2 + * arraySlice(field("items"), 2, field("length")); + * ``` + * + * @param arrayExpression - The expression representing the array. + * @param offset - The starting offset. + * @param length - The optional length of the slice. + * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the sliced array. + */ +export function arraySlice( + arrayExpression: Expression, + offset: number | Expression, + length?: number | Expression +): FunctionExpression; +export function arraySlice( + array: Expression | string, + offset: number | Expression, + length?: number | Expression +): FunctionExpression { + return fieldOrExpression(array).arraySlice(offset, length); +} + +/** * Creates an expression that returns the first element of an array. * * @example diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 1e8e1cd0c2..5f222ac24a 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -138,6 +138,10 @@ import { arrayGet, arrayFirst, arrayFirstN, + arrayFilter, + arrayTransform, + arrayTransformWithIndex, + arraySlice, arrayLast, arrayLastN, arrayMaximum, @@ -3340,6 +3344,185 @@ apiDescribe.skipClassic('Pipelines', persistence => { }); }); + it('supports arrayFilter', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', 'The Lord of the Rings')) + .select( + arrayFilter('tags', 'tag', notEqual(variable('tag'), 'magic')).as( + 'notMagicTags' + ), + field('tags') + .arrayFilter('tag', notEqual(variable('tag'), 'epic')) + .as('notEpicTags'), + field('tags') + .arrayFilter('tag', equal(variable('tag'), 'fantasy')) + .as('noMatchingTags') + ) + ); + + expectResults(snapshot, { + notMagicTags: ['adventure', 'epic'], + notEpicTags: ['adventure', 'magic'], + noMatchingTags: [] + }); + }); + + it('supports arrayFilter with mixed types and nulls', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, 'foo', null, 20.0, 'bar', 30, '40', null] + }) + ) + .select( + arrayFilter( + 'arr', + 'element', + greaterThan(variable('element'), 10) + ).as('filtered') + ) + ); + + expectResults(snapshot, { + filtered: [20.0, 30] + }); + }); + + it('supports arrayTransform and arrayTransformWithIndex', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ arr: [10, 20, 30] })) + .select( + arrayTransform( + 'arr', + 'element', + multiply(variable('element'), 10) + ).as('staticTransform'), + field('arr') + .arrayTransform('element', multiply(variable('element'), 10)) + .as('instanceTransform'), + arrayTransformWithIndex( + 'arr', + 'element', + 'i', + add(variable('element'), variable('i')) + ).as('staticTransformWithIndex'), + field('arr') + .arrayTransformWithIndex( + 'element', + 'i', + add(variable('element'), variable('i')) + ) + .as('instanceTransformWithIndex') + ) + ); + + expectResults(snapshot, { + staticTransform: [100, 200, 300], + instanceTransform: [100, 200, 300], + staticTransformWithIndex: [10, 21, 32], + instanceTransformWithIndex: [10, 21, 32] + }); + }); + + it('supports arrayTransform with empty array and nulls', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, null, 3], + empty: [] + }) + ) + .select( + field('arr') + .arrayTransform('element', add(variable('element'), 1)) + .as('transformedWithNulls'), + field('empty') + .arrayTransform('element', add(variable('element'), 1)) + .as('transformedEmpty'), + field('arr') + .arrayTransformWithIndex( + 'element', + 'idx', + add(variable('element'), variable('idx')) + ) + .as('transformedWithIndex'), + field('empty') + .arrayTransformWithIndex( + 'element', + 'idx', + add(variable('element'), variable('idx')) + ) + .as('transformedEmptyWithIndex') + ) + ); + + expectResults(snapshot, { + transformedWithNulls: [2, null, 4], + transformedEmpty: [], + transformedWithIndex: [1, null, 5], + transformedEmptyWithIndex: [] + }); + }); + + it('supports arraySlice', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', 'The Lord of the Rings')) + .select( + arraySlice('tags', 1, 1).as('staticMethodSlice'), + arraySlice('tags', 1).as('staticMethodSliceToEnd'), + field('tags').arraySlice(1, 1).as('instanceMethodSlice'), + field('tags').arraySlice(1).as('instanceMethodSliceToEnd'), + field('tags').arraySlice(1, 10).as('overflowLength'), + field('tags').arraySlice(-1, 1).as('negativeOffset'), + field('tags').arraySlice(-1).as('negativeOffsetSliceToEnd'), + field('tags').arraySlice(10).as('overflowOffset'), + field('tags').arraySlice(-10).as('negativeOverflowOffset') + ) + ); + + expectResults(snapshot, { + staticMethodSlice: ['magic'], + staticMethodSliceToEnd: ['magic', 'epic'], + instanceMethodSlice: ['magic'], + instanceMethodSliceToEnd: ['magic', 'epic'], + overflowLength: ['magic', 'epic'], + overflowOffset: [], + negativeOffset: ['epic'], + negativeOffsetSliceToEnd: ['epic'], + negativeOverflowOffset: ['adventure', 'magic', 'epic'] + }); + }); + + it('arraySlice throws error for negative length', async () => { + await expect( + execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', 'The Lord of the Rings')) + .select(arraySlice('tags', 1, -1).as('negativeLengthSlice')) + ) + ).to.be.rejectedWith(/length must be non-negative/); + }); + it('supports arrayFirstN', async () => { let snapshot = await execute( firestore diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index bb32e70f2b..f268750e47 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -188,6 +188,10 @@ import { arraySum, arrayFirst, arrayFirstN, + arrayFilter, + arrayTransform, + arrayTransformWithIndex, + arraySlice, arrayLast, arrayLastN, arrayMaximum, @@ -3302,6 +3306,185 @@ describe.skipClassic('Firestore Pipelines', () => { expectResults(snapshot, ...expectedResults); }); + it('supports arrayFilter', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', 'The Lord of the Rings')) + .select( + arrayFilter('tags', 'tag', notEqual(variable('tag'), 'magic')).as( + 'notMagicTags' + ), + field('tags') + .arrayFilter('tag', notEqual(variable('tag'), 'epic')) + .as('notEpicTags'), + field('tags') + .arrayFilter('tag', equal(variable('tag'), 'fantasy')) + .as('noMatchingTags') + ) + ); + + expectResults(snapshot, { + notMagicTags: ['adventure', 'epic'], + notEpicTags: ['adventure', 'magic'], + noMatchingTags: [] + }); + }); + + it('supports arrayFilter with mixed types and nulls', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, 'foo', null, 20.0, 'bar', 30, '40', null] + }) + ) + .select( + arrayFilter( + 'arr', + 'element', + greaterThan(variable('element'), 10) + ).as('filtered') + ) + ); + + expectResults(snapshot, { + filtered: [20.0, 30] + }); + }); + + it('supports arrayTransform and arrayTransformWithIndex', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith(map({ arr: [10, 20, 30] })) + .select( + arrayTransform( + 'arr', + 'element', + multiply(variable('element'), 10) + ).as('staticTransform'), + field('arr') + .arrayTransform('element', multiply(variable('element'), 10)) + .as('instanceTransform'), + arrayTransformWithIndex( + 'arr', + 'element', + 'i', + add(variable('element'), variable('i')) + ).as('staticTransformWithIndex'), + field('arr') + .arrayTransformWithIndex( + 'element', + 'i', + add(variable('element'), variable('i')) + ) + .as('instanceTransformWithIndex') + ) + ); + + expectResults(snapshot, { + staticTransform: [100, 200, 300], + instanceTransform: [100, 200, 300], + staticTransformWithIndex: [10, 21, 32], + instanceTransformWithIndex: [10, 21, 32] + }); + }); + + it('supports arrayTransform with empty array and nulls', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, null, 3], + empty: [] + }) + ) + .select( + field('arr') + .arrayTransform('element', add(variable('element'), 1)) + .as('transformedWithNulls'), + field('empty') + .arrayTransform('element', add(variable('element'), 1)) + .as('transformedEmpty'), + field('arr') + .arrayTransformWithIndex( + 'element', + 'idx', + add(variable('element'), variable('idx')) + ) + .as('transformedWithIndex'), + field('empty') + .arrayTransformWithIndex( + 'element', + 'idx', + add(variable('element'), variable('idx')) + ) + .as('transformedEmptyWithIndex') + ) + ); + + expectResults(snapshot, { + transformedWithNulls: [2, null, 4], + transformedEmpty: [], + transformedWithIndex: [1, null, 5], + transformedEmptyWithIndex: [] + }); + }); + + it('supports arraySlice', async () => { + const snapshot = await execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', 'The Lord of the Rings')) + .select( + arraySlice('tags', 1, 1).as('staticMethodSlice'), + arraySlice('tags', 1).as('staticMethodSliceToEnd'), + field('tags').arraySlice(1, 1).as('instanceMethodSlice'), + field('tags').arraySlice(1).as('instanceMethodSliceToEnd'), + field('tags').arraySlice(1, 10).as('overflowLength'), + field('tags').arraySlice(-1, 1).as('negativeOffset'), + field('tags').arraySlice(-1).as('negativeOffsetSliceToEnd'), + field('tags').arraySlice(10).as('overflowOffset'), + field('tags').arraySlice(-10).as('negativeOverflowOffset') + ) + ); + + expectResults(snapshot, { + staticMethodSlice: ['magic'], + staticMethodSliceToEnd: ['magic', 'epic'], + instanceMethodSlice: ['magic'], + instanceMethodSliceToEnd: ['magic', 'epic'], + overflowLength: ['magic', 'epic'], + overflowOffset: [], + negativeOffset: ['epic'], + negativeOffsetSliceToEnd: ['epic'], + negativeOverflowOffset: ['adventure', 'magic', 'epic'] + }); + }); + + it('arraySlice throws error for negative length', async () => { + await expect( + execute( + firestore + .pipeline() + .collection(randomCol.path) + .where(equal('title', 'The Lord of the Rings')) + .select(arraySlice('tags', 1, -1).as('negativeLengthSlice')) + ) + ).to.be.rejectedWith(/length must be non-negative/); + }); + it('supports arrayFirstN', async () => { let snapshot = await execute( firestore From 6cbe86569cc49ed12e9e53173bb66e8624bc8d6e Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 8 Apr 2026 13:09:08 -0700 Subject: [PATCH 130/174] fix(ai): deprecate topK and temperature for hybrid (#9816) --- .changeset/gold-chefs-jam.md | 6 ++++++ common/api-review/ai.api.md | 4 ++-- docs-devsite/ai.languagemodelcreatecoreoptions.md | 8 ++++++++ packages/ai/src/types/language-model.ts | 6 ++++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 .changeset/gold-chefs-jam.md diff --git a/.changeset/gold-chefs-jam.md b/.changeset/gold-chefs-jam.md new file mode 100644 index 0000000000..c7d57e9f46 --- /dev/null +++ b/.changeset/gold-chefs-jam.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +Deprecate `topK` and `temperature` properties for hybrid inference mode. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 0a4dcfe1ce..d11b0f656d 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -896,9 +896,9 @@ export type Language = (typeof Language)[keyof typeof Language]; export interface LanguageModelCreateCoreOptions { // (undocumented) expectedInputs?: LanguageModelExpected[]; - // (undocumented) + // @deprecated (undocumented) temperature?: number; - // (undocumented) + // @deprecated (undocumented) topK?: number; } diff --git a/docs-devsite/ai.languagemodelcreatecoreoptions.md b/docs-devsite/ai.languagemodelcreatecoreoptions.md index 299d5d1060..38413a3b4e 100644 --- a/docs-devsite/ai.languagemodelcreatecoreoptions.md +++ b/docs-devsite/ai.languagemodelcreatecoreoptions.md @@ -45,6 +45,10 @@ expectedInputs?: LanguageModelExpected[]; > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > +> Warning: This API is now obsolete. +> +> + Signature: ```typescript @@ -56,6 +60,10 @@ temperature?: number; > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > +> Warning: This API is now obsolete. +> +> + Signature: ```typescript diff --git a/packages/ai/src/types/language-model.ts b/packages/ai/src/types/language-model.ts index 9ac4c7202e..bf9821045a 100644 --- a/packages/ai/src/types/language-model.ts +++ b/packages/ai/src/types/language-model.ts @@ -54,7 +54,13 @@ export enum Availability { * @beta */ export interface LanguageModelCreateCoreOptions { + /** + * @deprecated + */ topK?: number; + /** + * @deprecated + */ temperature?: number; expectedInputs?: LanguageModelExpected[]; } From 9c8e8640e5ba91f2a3b1aa9229059dc35d0c427e Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 8 Apr 2026 13:14:49 -0700 Subject: [PATCH 131/174] feat(ai): Chat history and auto function calling for server templates (#9763) --- .changeset/slimy-carpets-flow.md | 6 + .changeset/smooth-apes-lick.md | 6 + common/api-review/ai.api.md | 131 ++++- docs-devsite/_toc.yaml | 12 + docs-devsite/ai.chatsession.md | 17 +- docs-devsite/ai.chatsessionbase.md | 104 ++++ docs-devsite/ai.md | 20 + docs-devsite/ai.requestoptions.md | 6 +- docs-devsite/ai.starttemplatechatparams.md | 68 +++ docs-devsite/ai.templatechatsession.md | 135 +++++ .../ai.templatefunctiondeclaration.md | 83 +++ .../ai.templatefunctiondeclarationstool.md | 41 ++ .../ai.templategeneratecontentrequest.md | 75 +++ docs-devsite/ai.templategenerativemodel.md | 32 +- packages/ai/src/api.ts | 2 + packages/ai/src/methods/chat-session-base.ts | 450 +++++++++++++++++ packages/ai/src/methods/chat-session.test.ts | 9 +- packages/ai/src/methods/chat-session.ts | 404 ++------------- packages/ai/src/methods/generate-content.ts | 6 +- .../src/methods/template-chat-session.test.ts | 472 ++++++++++++++++++ .../ai/src/methods/template-chat-session.ts | 165 ++++++ .../models/template-generative-model.test.ts | 28 ++ .../src/models/template-generative-model.ts | 25 +- packages/ai/src/types/requests.ts | 113 ++++- 24 files changed, 2018 insertions(+), 392 deletions(-) create mode 100644 .changeset/slimy-carpets-flow.md create mode 100644 .changeset/smooth-apes-lick.md create mode 100644 docs-devsite/ai.chatsessionbase.md create mode 100644 docs-devsite/ai.starttemplatechatparams.md create mode 100644 docs-devsite/ai.templatechatsession.md create mode 100644 docs-devsite/ai.templatefunctiondeclaration.md create mode 100644 docs-devsite/ai.templatefunctiondeclarationstool.md create mode 100644 docs-devsite/ai.templategeneratecontentrequest.md create mode 100644 packages/ai/src/methods/chat-session-base.ts create mode 100644 packages/ai/src/methods/template-chat-session.test.ts create mode 100644 packages/ai/src/methods/template-chat-session.ts diff --git a/.changeset/slimy-carpets-flow.md b/.changeset/slimy-carpets-flow.md new file mode 100644 index 0000000000..83c246a138 --- /dev/null +++ b/.changeset/slimy-carpets-flow.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +Add `startChat()` for `TemplateGenerativeModel`. diff --git a/.changeset/smooth-apes-lick.md b/.changeset/smooth-apes-lick.md new file mode 100644 index 0000000000..1d5c162db9 --- /dev/null +++ b/.changeset/smooth-apes-lick.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +Add automatic function calling and chat history for server prompt templates. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index d11b0f656d..47121f9346 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -140,16 +140,15 @@ export class BooleanSchema extends Schema { } // @public -export class ChatSession { +export class ChatSession extends ChatSessionBase { // Warning: (ae-incompatible-release-tags) The symbol "__constructor" is marked as @public, but its signature references "ChromeAdapter" which is marked as @beta constructor(apiSettings: ApiSettings, model: string, chromeAdapter?: ChromeAdapter | undefined, params?: StartChatParams | undefined, requestOptions?: RequestOptions | undefined); // @internal - _callFunctionsAsNeeded(functionCalls: FunctionCall[]): Promise; + _callGenerateContent(formattedRequest: GenerateContentRequest, singleRequestOptions?: RequestOptions): Promise; // @internal - _formatRequest(incomingContent: Content, tempHistory: Content[]): GenerateContentRequest; + _callGenerateContentStream(formattedRequest: GenerateContentRequest, singleRequestOptions?: RequestOptions): Promise; // @internal - _getCallableFunctionCalls(response?: GenerateContentResponse): FunctionCall[] | undefined; - getHistory(): Promise; + _formatRequest(incomingContent: Content, tempHistory: Content[]): GenerateContentRequest; // (undocumented) model: string; // (undocumented) @@ -158,7 +157,40 @@ export class ChatSession { requestOptions?: RequestOptions | undefined; sendMessage(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; sendMessageStream(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; - } +} + +// Warning: (ae-incompatible-release-tags) The symbol "ChatSessionBase" is marked as @public, but its signature references "StartTemplateChatParams" which is marked as @beta +// Warning: (ae-incompatible-release-tags) The symbol "ChatSessionBase" is marked as @public, but its signature references "TemplateFunctionDeclarationsTool" which is marked as @beta +// +// @public +export abstract class ChatSessionBase { + constructor(apiSettings: ApiSettings, params?: ParamsType | undefined, requestOptions?: RequestOptions | undefined); + // (undocumented) + protected _apiSettings: ApiSettings; + // @internal + _callFunctionsAsNeeded(functionCalls: FunctionCall[]): Promise; + // @internal + abstract _callGenerateContent(formattedRequest: RequestType, singleRequestOptions?: RequestOptions): Promise; + // @internal + abstract _callGenerateContentStream(formattedRequest: RequestType, singleRequestOptions?: RequestOptions): Promise; + // @internal + abstract _formatRequest(incomingContent: Content, tempHistory: Content[]): RequestType; + // @internal + _getCallableFunctionCalls(response?: GenerateContentResponse): FunctionCall[] | undefined; + getHistory(): Promise; + // (undocumented) + protected _history: Content[]; + // (undocumented) + params?: ParamsType | undefined; + // (undocumented) + requestOptions?: RequestOptions | undefined; + // @internal + _sendMessage(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; + // @internal + _sendMessageStream(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; + // @internal + protected _sendPromise: Promise; +} // @beta export interface ChromeAdapter { @@ -1157,7 +1189,7 @@ export interface PromptFeedback { // @public export interface RequestOptions { baseUrl?: string; - maxSequentalFunctionCalls?: number; + maxSequentialFunctionCalls?: number; timeout?: number; } @@ -1340,6 +1372,14 @@ export interface StartChatParams extends BaseParams { tools?: Tool[]; } +// @beta +export interface StartTemplateChatParams extends Omit { + templateId: string; + templateVariables?: Record; + // (undocumented) + tools?: TemplateTool[]; +} + // @public export class StringSchema extends Schema { constructor(schemaParams?: SchemaParams, enumValues?: string[]); @@ -1349,14 +1389,76 @@ export class StringSchema extends Schema { toJSON(): SchemaRequest; } +// Warning: (ae-incompatible-release-tags) The symbol "TemplateChatSession" is marked as @beta, but its signature references "TemplateRequestInternal" which is marked as @internal +// +// @beta +export class TemplateChatSession extends ChatSessionBase { + constructor(apiSettings: ApiSettings, params: StartTemplateChatParams, requestOptions?: RequestOptions | undefined); + // @internal + _callGenerateContent(formattedRequest: TemplateRequestInternal, singleRequestOptions?: RequestOptions): Promise; + // @internal + _callGenerateContentStream(formattedRequest: TemplateRequestInternal, singleRequestOptions?: RequestOptions): Promise; + // @internal + _formatRequest(incomingContent: Content, tempHistory: Content[]): TemplateRequestInternal; + // (undocumented) + params: StartTemplateChatParams; + // (undocumented) + requestOptions?: RequestOptions | undefined; + sendMessage(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; + sendMessageStream(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; +} + +// @beta +export interface TemplateFunctionDeclaration { + description?: never; + functionReference?: Function; + name: string; + parameters?: ObjectSchema | ObjectSchemaRequest; +} + +// Warning: (ae-internal-missing-underscore) The name "TemplateFunctionDeclarationInternal" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal (undocumented) +export interface TemplateFunctionDeclarationInternal extends Omit { + // (undocumented) + inputSchema?: ObjectSchema | ObjectSchemaRequest; +} + +// @beta +export interface TemplateFunctionDeclarationsTool { + functionDeclarations?: TemplateFunctionDeclaration[]; +} + +// Warning: (ae-internal-missing-underscore) The name "TemplateFunctionDeclarationsToolInternal" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface TemplateFunctionDeclarationsToolInternal { + templateFunctions?: TemplateFunctionDeclarationInternal[]; +} + +// @beta +export interface TemplateGenerateContentRequest { + // (undocumented) + [key: string]: unknown; + // (undocumented) + history?: Content[]; + // (undocumented) + inputs?: Record; + // (undocumented) + toolConfig?: ToolConfig; + // (undocumented) + tools?: TemplateFunctionDeclarationsTool[]; +} + // @beta export class TemplateGenerativeModel { constructor(ai: AI, requestOptions?: RequestOptions); // @internal (undocumented) _apiSettings: ApiSettings; - generateContent(templateId: string, templateVariables: object, singleRequestOptions?: SingleRequestOptions): Promise; - generateContentStream(templateId: string, templateVariables: object, singleRequestOptions?: SingleRequestOptions): Promise; + generateContent(templateId: string, templateVariables: Record, singleRequestOptions?: SingleRequestOptions): Promise; + generateContentStream(templateId: string, templateVariables: Record, singleRequestOptions?: SingleRequestOptions): Promise; requestOptions?: RequestOptions; + startChat(params: StartTemplateChatParams): TemplateChatSession; } // @public @deprecated @@ -1369,6 +1471,17 @@ export class TemplateImagenModel { requestOptions?: RequestOptions; } +// Warning: (ae-internal-missing-underscore) The name "TemplateRequestInternal" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface TemplateRequestInternal extends Omit { + // (undocumented) + tools?: TemplateFunctionDeclarationsToolInternal[]; +} + +// @beta +export type TemplateTool = TemplateFunctionDeclarationsTool; + // @public export interface TextPart { // (undocumented) diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index cdad1d79cb..669c4763d7 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -28,6 +28,8 @@ toc: path: /docs/reference/js/ai.booleanschema.md - title: ChatSession path: /docs/reference/js/ai.chatsession.md + - title: ChatSessionBase + path: /docs/reference/js/ai.chatsessionbase.md - title: ChromeAdapter path: /docs/reference/js/ai.chromeadapter.md - title: Citation @@ -200,8 +202,18 @@ toc: path: /docs/reference/js/ai.startaudioconversationoptions.md - title: StartChatParams path: /docs/reference/js/ai.startchatparams.md + - title: StartTemplateChatParams + path: /docs/reference/js/ai.starttemplatechatparams.md - title: StringSchema path: /docs/reference/js/ai.stringschema.md + - title: TemplateChatSession + path: /docs/reference/js/ai.templatechatsession.md + - title: TemplateFunctionDeclaration + path: /docs/reference/js/ai.templatefunctiondeclaration.md + - title: TemplateFunctionDeclarationsTool + path: /docs/reference/js/ai.templatefunctiondeclarationstool.md + - title: TemplateGenerateContentRequest + path: /docs/reference/js/ai.templategeneratecontentrequest.md - title: TemplateGenerativeModel path: /docs/reference/js/ai.templategenerativemodel.md - title: TemplateImagenModel diff --git a/docs-devsite/ai.chatsession.md b/docs-devsite/ai.chatsession.md index 2062f9868f..533681b971 100644 --- a/docs-devsite/ai.chatsession.md +++ b/docs-devsite/ai.chatsession.md @@ -15,8 +15,9 @@ ChatSession class that enables sending chat messages and stores history of sent Signature: ```typescript -export declare class ChatSession +export declare class ChatSession extends ChatSessionBase ``` +Extends: [ChatSessionBase](./ai.chatsessionbase.md#chatsessionbase_class)<[StartChatParams](./ai.startchatparams.md#startchatparams_interface), [GenerateContentRequest](./ai.generatecontentrequest.md#generatecontentrequest_interface), [FunctionDeclarationsTool](./ai.functiondeclarationstool.md#functiondeclarationstool_interface)> ## Constructors @@ -36,7 +37,6 @@ export declare class ChatSession | Method | Modifiers | Description | | --- | --- | --- | -| [getHistory()](./ai.chatsession.md#chatsessiongethistory) | | Gets the chat history so far. Blocked prompts are not added to history. Neither blocked candidates nor the prompts that generated them are added to history. | | [sendMessage(request, singleRequestOptions)](./ai.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface) | | [sendMessageStream(request, singleRequestOptions)](./ai.chatsession.md#chatsessionsendmessagestream) | | Sends a chat message and receives the response as a [GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. | @@ -84,19 +84,6 @@ params?: StartChatParams | undefined; requestOptions?: RequestOptions | undefined; ``` -## ChatSession.getHistory() - -Gets the chat history so far. Blocked prompts are not added to history. Neither blocked candidates nor the prompts that generated them are added to history. - -Signature: - -```typescript -getHistory(): Promise; -``` -Returns: - -Promise<[Content](./ai.content.md#content_interface)\[\]> - ## ChatSession.sendMessage() Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface) diff --git a/docs-devsite/ai.chatsessionbase.md b/docs-devsite/ai.chatsessionbase.md new file mode 100644 index 0000000000..f85c2be495 --- /dev/null +++ b/docs-devsite/ai.chatsessionbase.md @@ -0,0 +1,104 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# ChatSessionBase class +Base class for various `ChatSession` classes that enables sending chat messages and stores history of sent and received messages so far. + +Signature: + +```typescript +export declare abstract class ChatSessionBase +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(apiSettings, params, requestOptions)](./ai.chatsessionbase.md#chatsessionbaseconstructor) | | Constructs a new instance of the ChatSessionBase class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [\_apiSettings](./ai.chatsessionbase.md#chatsessionbase_apisettings) | | ApiSettings | | +| [\_history](./ai.chatsessionbase.md#chatsessionbase_history) | | [Content](./ai.content.md#content_interface)\[\] | | +| [params](./ai.chatsessionbase.md#chatsessionbaseparams) | | ParamsType \| undefined | | +| [requestOptions](./ai.chatsessionbase.md#chatsessionbaserequestoptions) | | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) \| undefined | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [getHistory()](./ai.chatsessionbase.md#chatsessionbasegethistory) | | Gets the chat history so far. Blocked prompts are not added to history. Neither blocked candidates nor the prompts that generated them are added to history. | + +## ChatSessionBase.(constructor) + +Constructs a new instance of the `ChatSessionBase` class + +Signature: + +```typescript +constructor(apiSettings: ApiSettings, params?: ParamsType | undefined, requestOptions?: RequestOptions | undefined); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| apiSettings | ApiSettings | | +| params | ParamsType \| undefined | | +| requestOptions | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) \| undefined | | + +## ChatSessionBase.\_apiSettings + +Signature: + +```typescript +protected _apiSettings: ApiSettings; +``` + +## ChatSessionBase.\_history + +Signature: + +```typescript +protected _history: Content[]; +``` + +## ChatSessionBase.params + +Signature: + +```typescript +params?: ParamsType | undefined; +``` + +## ChatSessionBase.requestOptions + +Signature: + +```typescript +requestOptions?: RequestOptions | undefined; +``` + +## ChatSessionBase.getHistory() + +Gets the chat history so far. Blocked prompts are not added to history. Neither blocked candidates nor the prompts that generated them are added to history. + +Signature: + +```typescript +getHistory(): Promise; +``` +Returns: + +Promise<[Content](./ai.content.md#content_interface)\[\]> + diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index 1ed2527a81..783a307535 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -38,6 +38,7 @@ The Firebase AI Web SDK. | [Backend](./ai.backend.md#backend_class) | Abstract base class representing the configuration for an AI service backend. This class should not be instantiated directly. Use its subclasses; [GoogleAIBackend](./ai.googleaibackend.md#googleaibackend_class) for the Gemini Developer API (via [Google AI](https://ai.google/)), and [VertexAIBackend](./ai.vertexaibackend.md#vertexaibackend_class) for the Vertex AI Gemini API. | | [BooleanSchema](./ai.booleanschema.md#booleanschema_class) | Schema class for "boolean" types. | | [ChatSession](./ai.chatsession.md#chatsession_class) | ChatSession class that enables sending chat messages and stores history of sent and received messages so far. | +| [ChatSessionBase](./ai.chatsessionbase.md#chatsessionbase_class) | Base class for various ChatSession classes that enables sending chat messages and stores history of sent and received messages so far. | | [GenerativeModel](./ai.generativemodel.md#generativemodel_class) | Class for generative model APIs. | | [GoogleAIBackend](./ai.googleaibackend.md#googleaibackend_class) | Configuration class for the Gemini Developer API.Use this with [AIOptions](./ai.aioptions.md#aioptions_interface) when initializing the AI service via [getAI()](./ai.md#getai_a94a413) to specify the Gemini Developer API as the backend. | | [ImagenImageFormat](./ai.imagenimageformat.md#imagenimageformat_class) | Defines the image format for images generated by Imagen.Use this class to specify the desired format (JPEG or PNG) and compression quality for images generated by Imagen. This is typically included as part of [ImagenModelParams](./ai.imagenmodelparams.md#imagenmodelparams_interface). | @@ -49,6 +50,7 @@ The Firebase AI Web SDK. | [ObjectSchema](./ai.objectschema.md#objectschema_class) | Schema class for "object" types. The properties param must be a map of Schema objects. | | [Schema](./ai.schema.md#schema_class) | Parent class encompassing all Schema types, with static methods that allow building specific Schema types. This class can be converted with JSON.stringify() into a JSON string accepted by Vertex AI REST endpoints. (This string conversion is automatically done when calling SDK methods.) | | [StringSchema](./ai.stringschema.md#stringschema_class) | Schema class for "string" types. Can be used with or without enum values. | +| [TemplateChatSession](./ai.templatechatsession.md#templatechatsession_class) | (Public Preview) ChatSession class for use with server prompt templates that enables sending chat messages and stores history of sent and received messages so far. | | [TemplateGenerativeModel](./ai.templategenerativemodel.md#templategenerativemodel_class) | (Public Preview) [GenerativeModel](./ai.generativemodel.md#generativemodel_class) APIs that execute on a server-side template.This class should only be instantiated with [getTemplateGenerativeModel()](./ai.md#gettemplategenerativemodel_9476bbc). | | [TemplateImagenModel](./ai.templateimagenmodel.md#templateimagenmodel_class) | Class for Imagen model APIs that execute on a server-side template.This class should only be instantiated with [getTemplateImagenModel()](./ai.md#gettemplateimagenmodel_9476bbc). | | [VertexAIBackend](./ai.vertexaibackend.md#vertexaibackend_class) | Configuration class for the Vertex AI Gemini API.Use this with [AIOptions](./ai.aioptions.md#aioptions_interface) when initializing the AI service via [getAI()](./ai.md#getai_a94a413) to specify the Vertex AI Gemini API as the backend. | @@ -138,6 +140,10 @@ The Firebase AI Web SDK. | [SpeechConfig](./ai.speechconfig.md#speechconfig_interface) | (Public Preview) Configures speech synthesis. | | [StartAudioConversationOptions](./ai.startaudioconversationoptions.md#startaudioconversationoptions_interface) | (Public Preview) Options for [startAudioConversation()](./ai.md#startaudioconversation_01c8e7f). | | [StartChatParams](./ai.startchatparams.md#startchatparams_interface) | Params for [GenerativeModel.startChat()](./ai.generativemodel.md#generativemodelstartchat). | +| [StartTemplateChatParams](./ai.starttemplatechatparams.md#starttemplatechatparams_interface) | (Public Preview) Params for [TemplateGenerativeModel.startChat()](./ai.templategenerativemodel.md#templategenerativemodelstartchat). | +| [TemplateFunctionDeclaration](./ai.templatefunctiondeclaration.md#templatefunctiondeclaration_interface) | (Public Preview) Structured representation of a template function declaration. Included in this declaration are the function name and parameters. This TemplateFunctionDeclaration is a representation of a block of code that can be used as a Tool by the model and executed by the client. Note: Template function declarations do not support description fields. | +| [TemplateFunctionDeclarationsTool](./ai.templatefunctiondeclarationstool.md#templatefunctiondeclarationstool_interface) | (Public Preview) A piece of code that enables the system to interact with external systems. | +| [TemplateGenerateContentRequest](./ai.templategeneratecontentrequest.md#templategeneratecontentrequest_interface) | (Public Preview) Request sent through [TemplateGenerativeModel.generateContent()](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontent) | | [TextPart](./ai.textpart.md#textpart_interface) | Content part interface if the part represents a text string. | | [ThinkingConfig](./ai.thinkingconfig.md#thinkingconfig_interface) | Configuration for "thinking" behavior of compatible Gemini models.Certain models utilize a thinking process before generating a response. This allows them to reason through complex problems and plan a more coherent and accurate answer. | | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. | @@ -211,6 +217,7 @@ The Firebase AI Web SDK. | [ResponseModality](./ai.md#responsemodality) | (Public Preview) Generation modalities to be returned in generation responses. | | [Role](./ai.md#role) | Role is the producer of the content. | | [SchemaType](./ai.md#schematype) | Contains the list of OpenAPI data types as defined by the [OpenAPI specification](https://swagger.io/docs/specification/data-models/data-types/) | +| [TemplateTool](./ai.md#templatetool) | (Public Preview) Defines a tool that a [TemplateGenerativeModel](./ai.templategenerativemodel.md#templategenerativemodel_class) can call to access external knowledge. Only function declarations are currently supported for templates. | | [ThinkingLevel](./ai.md#thinkinglevel) | A preset that controls the model's "thinking" process. Use ThinkingLevel.LOW for faster responses on less complex tasks, and ThinkingLevel.HIGH for better reasoning on more complex tasks. | | [Tool](./ai.md#tool) | Defines a tool that model can call to access external knowledge. | | [TypedSchema](./ai.md#typedschema) | A type that includes all specific Schema types. | @@ -1184,6 +1191,19 @@ Contains the list of OpenAPI data types as defined by the [OpenAPI specification export type SchemaType = (typeof SchemaType)[keyof typeof SchemaType]; ``` +## TemplateTool + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Defines a tool that a [TemplateGenerativeModel](./ai.templategenerativemodel.md#templategenerativemodel_class) can call to access external knowledge. Only function declarations are currently supported for templates. + +Signature: + +```typescript +export type TemplateTool = TemplateFunctionDeclarationsTool; +``` + ## ThinkingLevel A preset that controls the model's "thinking" process. Use `ThinkingLevel.LOW` for faster responses on less complex tasks, and `ThinkingLevel.HIGH` for better reasoning on more complex tasks. diff --git a/docs-devsite/ai.requestoptions.md b/docs-devsite/ai.requestoptions.md index e7e8aeb828..f1b90af88e 100644 --- a/docs-devsite/ai.requestoptions.md +++ b/docs-devsite/ai.requestoptions.md @@ -23,7 +23,7 @@ export interface RequestOptions | Property | Type | Description | | --- | --- | --- | | [baseUrl](./ai.requestoptions.md#requestoptionsbaseurl) | string | Base url for endpoint. Defaults to https://firebasevertexai.googleapis.com, which is the [Firebase AI Logic API](https://console.cloud.google.com/apis/library/firebasevertexai.googleapis.com?project=_) (used regardless of your chosen Gemini API provider). | -| [maxSequentalFunctionCalls](./ai.requestoptions.md#requestoptionsmaxsequentalfunctioncalls) | number | Limits amount of sequential function calls the SDK can make during automatic function calling, in order to prevent infinite loops. If not specified, this value defaults to 10.When it reaches this limit, it will return the last response received from the model, whether it is a text response or further function calls. | +| [maxSequentialFunctionCalls](./ai.requestoptions.md#requestoptionsmaxsequentialfunctioncalls) | number | Limits amount of sequential function calls the SDK can make during automatic function calling, in order to prevent infinite loops. If not specified, this value defaults to 10.When it reaches this limit, it will return the last response received from the model, whether it is a text response or further function calls. | | [timeout](./ai.requestoptions.md#requestoptionstimeout) | number | Request timeout in milliseconds. Defaults to 180 seconds (180000ms). | ## RequestOptions.baseUrl @@ -36,7 +36,7 @@ Base url for endpoint. Defaults to https://firebasevertexai.googleapis.com, whic baseUrl?: string; ``` -## RequestOptions.maxSequentalFunctionCalls +## RequestOptions.maxSequentialFunctionCalls Limits amount of sequential function calls the SDK can make during automatic function calling, in order to prevent infinite loops. If not specified, this value defaults to 10. @@ -45,7 +45,7 @@ When it reaches this limit, it will return the last response received from the m Signature: ```typescript -maxSequentalFunctionCalls?: number; +maxSequentialFunctionCalls?: number; ``` ## RequestOptions.timeout diff --git a/docs-devsite/ai.starttemplatechatparams.md b/docs-devsite/ai.starttemplatechatparams.md new file mode 100644 index 0000000000..8dfa57e7d0 --- /dev/null +++ b/docs-devsite/ai.starttemplatechatparams.md @@ -0,0 +1,68 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# StartTemplateChatParams interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Params for [TemplateGenerativeModel.startChat()](./ai.templategenerativemodel.md#templategenerativemodelstartchat). + +Signature: + +```typescript +export interface StartTemplateChatParams extends Omit +``` +Extends: Omit<[StartChatParams](./ai.startchatparams.md#startchatparams_interface), 'tools'> + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [templateId](./ai.starttemplatechatparams.md#starttemplatechatparamstemplateid) | string | (Public Preview) The ID of the server-side template to execute. | +| [templateVariables](./ai.starttemplatechatparams.md#starttemplatechatparamstemplatevariables) | Record<string, unknown> | (Public Preview) A key-value map of variables to populate the template with. | +| [tools](./ai.starttemplatechatparams.md#starttemplatechatparamstools) | [TemplateTool](./ai.md#templatetool)\[\] | (Public Preview) | + +## StartTemplateChatParams.templateId + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The ID of the server-side template to execute. + +Signature: + +```typescript +templateId: string; +``` + +## StartTemplateChatParams.templateVariables + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +A key-value map of variables to populate the template with. + +Signature: + +```typescript +templateVariables?: Record; +``` + +## StartTemplateChatParams.tools + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +tools?: TemplateTool[]; +``` diff --git a/docs-devsite/ai.templatechatsession.md b/docs-devsite/ai.templatechatsession.md new file mode 100644 index 0000000000..2cee825089 --- /dev/null +++ b/docs-devsite/ai.templatechatsession.md @@ -0,0 +1,135 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# TemplateChatSession class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +`ChatSession` class for use with server prompt templates that enables sending chat messages and stores history of sent and received messages so far. + +Signature: + +```typescript +export declare class TemplateChatSession extends ChatSessionBase +``` +Extends: [ChatSessionBase](./ai.chatsessionbase.md#chatsessionbase_class)<[StartTemplateChatParams](./ai.starttemplatechatparams.md#starttemplatechatparams_interface), TemplateRequestInternal, [TemplateFunctionDeclarationsTool](./ai.templatefunctiondeclarationstool.md#templatefunctiondeclarationstool_interface)> + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(apiSettings, params, requestOptions)](./ai.templatechatsession.md#templatechatsessionconstructor) | | (Public Preview) Constructs a new instance of the TemplateChatSession class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [params](./ai.templatechatsession.md#templatechatsessionparams) | | [StartTemplateChatParams](./ai.starttemplatechatparams.md#starttemplatechatparams_interface) | (Public Preview) | +| [requestOptions](./ai.templatechatsession.md#templatechatsessionrequestoptions) | | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) \| undefined | (Public Preview) | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [sendMessage(request, singleRequestOptions)](./ai.templatechatsession.md#templatechatsessionsendmessage) | | (Public Preview) Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface) | +| [sendMessageStream(request, singleRequestOptions)](./ai.templatechatsession.md#templatechatsessionsendmessagestream) | | (Public Preview) Sends a chat message and receives the response as a [GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. | + +## TemplateChatSession.(constructor) + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Constructs a new instance of the `TemplateChatSession` class + +Signature: + +```typescript +constructor(apiSettings: ApiSettings, params: StartTemplateChatParams, requestOptions?: RequestOptions | undefined); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| apiSettings | ApiSettings | | +| params | [StartTemplateChatParams](./ai.starttemplatechatparams.md#starttemplatechatparams_interface) | | +| requestOptions | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) \| undefined | | + +## TemplateChatSession.params + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +params: StartTemplateChatParams; +``` + +## TemplateChatSession.requestOptions + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +requestOptions?: RequestOptions | undefined; +``` + +## TemplateChatSession.sendMessage() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface) + +Signature: + +```typescript +sendMessage(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | string \| Array<string \| [Part](./ai.md#part)> | | +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | + +Returns: + +Promise<[GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface)> + +## TemplateChatSession.sendMessageStream() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Sends a chat message and receives the response as a [GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. + +Signature: + +```typescript +sendMessageStream(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | string \| Array<string \| [Part](./ai.md#part)> | | +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | + +Returns: + +Promise<[GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface)> + diff --git a/docs-devsite/ai.templatefunctiondeclaration.md b/docs-devsite/ai.templatefunctiondeclaration.md new file mode 100644 index 0000000000..9d5d9b0e46 --- /dev/null +++ b/docs-devsite/ai.templatefunctiondeclaration.md @@ -0,0 +1,83 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# TemplateFunctionDeclaration interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Structured representation of a template function declaration. Included in this declaration are the function name and parameters. This `TemplateFunctionDeclaration` is a representation of a block of code that can be used as a Tool by the model and executed by the client. Note: Template function declarations do not support description fields. + +Signature: + +```typescript +export interface TemplateFunctionDeclaration +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [description](./ai.templatefunctiondeclaration.md#templatefunctiondeclarationdescription) | never | (Public Preview) Description is intentionally unsupported for template function declarations. | +| [functionReference](./ai.templatefunctiondeclaration.md#templatefunctiondeclarationfunctionreference) | Function | (Public Preview) Reference to an actual function to call. Specifying this will cause the function to be called automatically when requested by the model. | +| [name](./ai.templatefunctiondeclaration.md#templatefunctiondeclarationname) | string | (Public Preview) The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a max length of 64. | +| [parameters](./ai.templatefunctiondeclaration.md#templatefunctiondeclarationparameters) | [ObjectSchema](./ai.objectschema.md#objectschema_class) \| [ObjectSchemaRequest](./ai.objectschemarequest.md#objectschemarequest_interface) | (Public Preview) Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. Parameter names are case-sensitive. For a function with no parameters, this can be left unset. | + +## TemplateFunctionDeclaration.description + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Description is intentionally unsupported for template function declarations. + +Signature: + +```typescript +description?: never; +``` + +## TemplateFunctionDeclaration.functionReference + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Reference to an actual function to call. Specifying this will cause the function to be called automatically when requested by the model. + +Signature: + +```typescript +functionReference?: Function; +``` + +## TemplateFunctionDeclaration.name + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a max length of 64. + +Signature: + +```typescript +name: string; +``` + +## TemplateFunctionDeclaration.parameters + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. Parameter names are case-sensitive. For a function with no parameters, this can be left unset. + +Signature: + +```typescript +parameters?: ObjectSchema | ObjectSchemaRequest; +``` diff --git a/docs-devsite/ai.templatefunctiondeclarationstool.md b/docs-devsite/ai.templatefunctiondeclarationstool.md new file mode 100644 index 0000000000..f2dbd3138d --- /dev/null +++ b/docs-devsite/ai.templatefunctiondeclarationstool.md @@ -0,0 +1,41 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# TemplateFunctionDeclarationsTool interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +A piece of code that enables the system to interact with external systems. + +Signature: + +```typescript +export interface TemplateFunctionDeclarationsTool +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [functionDeclarations](./ai.templatefunctiondeclarationstool.md#templatefunctiondeclarationstoolfunctiondeclarations) | [TemplateFunctionDeclaration](./ai.templatefunctiondeclaration.md#templatefunctiondeclaration_interface)\[\] | (Public Preview) Optional. One or more function declarations to be passed to the server-side template execution. | + +## TemplateFunctionDeclarationsTool.functionDeclarations + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Optional. One or more function declarations to be passed to the server-side template execution. + +Signature: + +```typescript +functionDeclarations?: TemplateFunctionDeclaration[]; +``` diff --git a/docs-devsite/ai.templategeneratecontentrequest.md b/docs-devsite/ai.templategeneratecontentrequest.md new file mode 100644 index 0000000000..c912d50a84 --- /dev/null +++ b/docs-devsite/ai.templategeneratecontentrequest.md @@ -0,0 +1,75 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# TemplateGenerateContentRequest interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Request sent through [TemplateGenerativeModel.generateContent()](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontent) + +Signature: + +```typescript +export interface TemplateGenerateContentRequest +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [history](./ai.templategeneratecontentrequest.md#templategeneratecontentrequesthistory) | [Content](./ai.content.md#content_interface)\[\] | (Public Preview) | +| [inputs](./ai.templategeneratecontentrequest.md#templategeneratecontentrequestinputs) | Record<string, unknown> | (Public Preview) | +| [toolConfig](./ai.templategeneratecontentrequest.md#templategeneratecontentrequesttoolconfig) | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | (Public Preview) | +| [tools](./ai.templategeneratecontentrequest.md#templategeneratecontentrequesttools) | [TemplateFunctionDeclarationsTool](./ai.templatefunctiondeclarationstool.md#templatefunctiondeclarationstool_interface)\[\] | (Public Preview) | + +## TemplateGenerateContentRequest.history + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +history?: Content[]; +``` + +## TemplateGenerateContentRequest.inputs + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +inputs?: Record; +``` + +## TemplateGenerateContentRequest.toolConfig + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +toolConfig?: ToolConfig; +``` + +## TemplateGenerateContentRequest.tools + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +tools?: TemplateFunctionDeclarationsTool[]; +``` diff --git a/docs-devsite/ai.templategenerativemodel.md b/docs-devsite/ai.templategenerativemodel.md index 9410443f61..9b7d7349a8 100644 --- a/docs-devsite/ai.templategenerativemodel.md +++ b/docs-devsite/ai.templategenerativemodel.md @@ -41,6 +41,7 @@ export declare class TemplateGenerativeModel | --- | --- | --- | | [generateContent(templateId, templateVariables, singleRequestOptions)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontent) | | (Public Preview) Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | | [generateContentStream(templateId, templateVariables, singleRequestOptions)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontentstream) | | (Public Preview) Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. | +| [startChat(params)](./ai.templategenerativemodel.md#templategenerativemodelstartchat) | | (Public Preview) Starts a [TemplateChatSession](./ai.templatechatsession.md#templatechatsession_class) that will use this template to respond to messages. | ## TemplateGenerativeModel.(constructor) @@ -85,7 +86,7 @@ Makes a single non-streaming call to the model and returns an object containing Signature: ```typescript -generateContent(templateId: string, templateVariables: object, singleRequestOptions?: SingleRequestOptions): Promise; +generateContent(templateId: string, templateVariables: Record, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -93,7 +94,7 @@ generateContent(templateId: string, templateVariables: object, singleRequestOpti | Parameter | Type | Description | | --- | --- | --- | | templateId | string | The ID of the server-side template to execute. | -| templateVariables | object | A key-value map of variables to populate the template with. | +| templateVariables | Record<string, unknown> | A key-value map of variables to populate the template with. | | singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: @@ -110,7 +111,7 @@ Makes a single streaming call to the model and returns an object containing an i Signature: ```typescript -generateContentStream(templateId: string, templateVariables: object, singleRequestOptions?: SingleRequestOptions): Promise; +generateContentStream(templateId: string, templateVariables: Record, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -118,10 +119,33 @@ generateContentStream(templateId: string, templateVariables: object, singleReque | Parameter | Type | Description | | --- | --- | --- | | templateId | string | The ID of the server-side template to execute. | -| templateVariables | object | A key-value map of variables to populate the template with. | +| templateVariables | Record<string, unknown> | A key-value map of variables to populate the template with. | | singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: Promise<[GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface)> +## TemplateGenerativeModel.startChat() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Starts a [TemplateChatSession](./ai.templatechatsession.md#templatechatsession_class) that will use this template to respond to messages. + +Signature: + +```typescript +startChat(params: StartTemplateChatParams): TemplateChatSession; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| params | [StartTemplateChatParams](./ai.starttemplatechatparams.md#starttemplatechatparams_interface) | Configurations for the chat, including the template ID and input variables. | + +Returns: + +[TemplateChatSession](./ai.templatechatsession.md#templatechatsession_class) + diff --git a/packages/ai/src/api.ts b/packages/ai/src/api.ts index e1e23eac87..e7c631498e 100644 --- a/packages/ai/src/api.ts +++ b/packages/ai/src/api.ts @@ -44,7 +44,9 @@ import { TemplateImagenModel } from './models/template-imagen-model'; import { logger } from './logger'; export { ChatSession } from './methods/chat-session'; +export { ChatSessionBase } from './methods/chat-session-base'; export { LiveSession } from './methods/live-session'; +export { TemplateChatSession } from './methods/template-chat-session'; export * from './requests/schema-builder'; export { ImagenImageFormat } from './requests/imagen-image-format'; export { diff --git a/packages/ai/src/methods/chat-session-base.ts b/packages/ai/src/methods/chat-session-base.ts new file mode 100644 index 0000000000..96c724f6f1 --- /dev/null +++ b/packages/ai/src/methods/chat-session-base.ts @@ -0,0 +1,450 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AIErrorCode, + Content, + FunctionCall, + FunctionDeclarationsTool, + FunctionResponse, + FunctionResponsePart, + GenerateContentResponse, + GenerateContentResult, + GenerateContentStreamResult, + Part, + RequestOptions, + SingleRequestOptions, + StartChatParams, + StartTemplateChatParams, + TemplateFunctionDeclarationsTool +} from '../types'; +import { formatNewContent } from '../requests/request-helpers'; +import { + formatBlockErrorMessage, + getFunctionCalls +} from '../requests/response-helpers'; +import { ApiSettings } from '../types/internal'; +import { logger } from '../logger'; +import { AIError } from '../errors'; + +/** + * Used to break the internal promise chain when an error is already handled + * by the user, preventing duplicate console logs. + */ +const SILENT_ERROR = 'SILENT_ERROR'; + +/** + * Prevent infinite loop if the model continues to request sequential + * function calls during automatic function calling. + */ +const DEFAULT_MAX_SEQUENTIAL_FUNCTION_CALLS = 10; + +/** + * Base class for various `ChatSession` classes that enables sending chat + * messages and stores history of sent and received messages so far. + * + * @public + */ +export abstract class ChatSessionBase< + ParamsType extends StartChatParams | StartTemplateChatParams, + RequestType, + FunctionDeclarationsToolType extends + | FunctionDeclarationsTool + | TemplateFunctionDeclarationsTool +> { + protected _apiSettings: ApiSettings; + protected _history: Content[] = []; + + /** + * Ensures sequential execution of chat messages to maintain history order. + * Each call waits for the previous one to settle before proceeding. + * @internal + */ + protected _sendPromise: Promise = Promise.resolve(); + + constructor( + apiSettings: ApiSettings, + public params?: ParamsType, + public requestOptions?: RequestOptions + ) { + this._apiSettings = apiSettings; + } + + /** + * Gets the chat history so far. Blocked prompts are not added to history. + * Neither blocked candidates nor the prompts that generated them are added + * to history. + */ + async getHistory(): Promise { + await this._sendPromise; + return this._history; + } + + /** + * Format Content into a request for `generateContent` or + * `generateContentStream` (or their template versions). + * @internal + */ + abstract _formatRequest( + incomingContent: Content, + tempHistory: Content[] + ): RequestType; + + /** + * Type-specific generate content calls (inherited classes may implement this + * to call basic `generateContent()` or the template version) + * @internal + */ + abstract _callGenerateContent( + formattedRequest: RequestType, + singleRequestOptions?: RequestOptions + ): Promise; + + /** + * Type-specific generate content stream calls (inherited classes may implement this + * to call basic `generateContentStream()` or the template version) + * @internal + */ + abstract _callGenerateContentStream( + formattedRequest: RequestType, + singleRequestOptions?: RequestOptions + ): Promise; + + /** + * Sends a chat message and receives a non-streaming + * {@link GenerateContentResult} + * @internal + */ + async _sendMessage( + request: string | Array, + singleRequestOptions?: SingleRequestOptions + ): Promise { + let finalResult = {} as GenerateContentResult; + await this._sendPromise; + /** + * Temporarily store multiple turns for cases like automatic function + * calling, only writing them to official history when the entire + * sequence has completed successfully. + */ + const tempHistory: Content[] = []; + + this._sendPromise = this._sendPromise.then(async () => { + let functionCalls: FunctionCall[] | undefined; + let functionCallTurnCount = 0; + const functionCallMaxTurns = + this.requestOptions?.maxSequentialFunctionCalls ?? + DEFAULT_MAX_SEQUENTIAL_FUNCTION_CALLS; + + // Repeats until model returns a response with no function calls + // or until `functionCallMaxTurns` is met or exceeded. + do { + let formattedContent; + + if (functionCalls) { + functionCallTurnCount++; + const functionResponseParts = await this._callFunctionsAsNeeded( + functionCalls + ); + formattedContent = formatNewContent(functionResponseParts); + } else { + formattedContent = formatNewContent(request); + } + const formattedRequest = this._formatRequest( + formattedContent, + tempHistory + ); + + tempHistory.push(formattedContent); + + const result = await this._callGenerateContent( + formattedRequest, + singleRequestOptions + ); + if (result) { + finalResult = result; + functionCalls = this._getCallableFunctionCalls(result.response); + if ( + result.response.candidates && + result.response.candidates.length > 0 + ) { + // TODO: Make this update atomic. If creating `responseContent` throws, + // history will contain the user message but not the response, causing + // validation errors on the next request. + const responseContent: Content = { + parts: result.response.candidates?.[0].content.parts || [], + // Response seems to come back without a role set. + role: result.response.candidates?.[0].content.role || 'model' + }; + tempHistory.push(responseContent); + } else { + const blockErrorMessage = formatBlockErrorMessage(result.response); + if (blockErrorMessage) { + logger.warn( + `sendMessage() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.` + ); + } + } + } else { + functionCalls = undefined; + } + } while (functionCalls && functionCallTurnCount < functionCallMaxTurns); + + if (functionCalls && functionCallTurnCount >= functionCallMaxTurns) { + logger.warn( + `Automatic function calling exceeded the limit of` + + ` ${functionCallMaxTurns} function calls. Returning last model response.` + ); + } + }); + + await this._sendPromise; + this._history = this._history.concat(tempHistory); + return finalResult; + } + + /** + * Sends a chat message and receives the response as a + * {@link GenerateContentStreamResult} containing an iterable stream + * and a response promise. + * @internal + */ + async _sendMessageStream( + request: string | Array, + singleRequestOptions?: SingleRequestOptions + ): Promise { + await this._sendPromise; + /** + * Temporarily store multiple turns for cases like automatic function + * calling, only writing them to official history when the entire + * sequence has completed successfully. + */ + const tempHistory: Content[] = []; + + const callGenerateContentStream = + async (): Promise => { + let functionCalls: FunctionCall[] | undefined; + let functionCallTurnCount = 0; + const functionCallMaxTurns = + this.requestOptions?.maxSequentialFunctionCalls ?? + DEFAULT_MAX_SEQUENTIAL_FUNCTION_CALLS; + let result: GenerateContentStreamResult & { + firstValue?: GenerateContentResponse; + }; + + // Repeats until model returns a response with no function calls + // or until `functionCallMaxTurns` is met or exceeded. + do { + let formattedContent; + + if (functionCalls) { + functionCallTurnCount++; + const functionResponseParts = await this._callFunctionsAsNeeded( + functionCalls + ); + formattedContent = formatNewContent(functionResponseParts); + } else { + formattedContent = formatNewContent(request); + } + + tempHistory.push(formattedContent); + const formattedRequest = this._formatRequest( + formattedContent, + tempHistory + ); + + result = await this._callGenerateContentStream( + formattedRequest, + singleRequestOptions + ); + + functionCalls = this._getCallableFunctionCalls(result.firstValue); + + if ( + functionCalls && + result.firstValue && + result.firstValue.candidates && + result.firstValue.candidates.length > 0 + ) { + const responseContent = { + ...result.firstValue.candidates[0].content + }; + if (!responseContent.role) { + responseContent.role = 'model'; + } + tempHistory.push(responseContent); + } + } while (functionCalls && functionCallTurnCount < functionCallMaxTurns); + + if (functionCalls && functionCallTurnCount >= functionCallMaxTurns) { + logger.warn( + `Automatic function calling exceeded the limit of` + + ` ${functionCallMaxTurns} function calls. Returning last model response.` + ); + } + return { stream: result.stream, response: result.response }; + }; + + const streamPromise = callGenerateContentStream(); + + // Add onto the chain. + this._sendPromise = this._sendPromise + .then(async () => streamPromise) + // This must be handled to avoid unhandled rejection, but jump + // to the final catch block with a label to not log this error. + .catch(_ignored => { + // If the initial fetch fails, the user's `streamPromise` rejects. + // We swallow the error here to prevent double logging in the final catch. + throw new Error(SILENT_ERROR); + }) + .then(streamResult => streamResult.response) + .then(response => { + // This runs after the stream completes. Runtime errors here cannot be + // caught by the user because their promise has likely already resolved. + // TODO: Move response validation logic upstream to `stream-reader` so + // errors propagate to the user's `result.response` promise. + if (response.candidates && response.candidates.length > 0) { + this._history = this._history.concat(tempHistory); + // TODO: Validate that `response.candidates[0].content` is not null. + const responseContent = { ...response.candidates[0].content }; + if (!responseContent.role) { + responseContent.role = 'model'; + } + this._history.push(responseContent); + } else { + const blockErrorMessage = formatBlockErrorMessage(response); + if (blockErrorMessage) { + logger.warn( + `sendMessageStream() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.` + ); + } + } + }) + .catch(e => { + // Filter out errors already handled by the user or initiated by them. + if (e.message !== SILENT_ERROR && e.name !== 'AbortError') { + logger.error(e); + } + }); + return streamPromise; + } + + /** + * Get function calls that the SDK has references to actually call. + * This is all-or-nothing. If the model is requesting multiple + * function calls, all of them must have references in order for + * automatic function calling to work. + * + * @internal + */ + _getCallableFunctionCalls( + response?: GenerateContentResponse + ): FunctionCall[] | undefined { + const functionDeclarationsTool = this.params?.tools?.find( + tool => (tool as FunctionDeclarationsToolType).functionDeclarations + ) as FunctionDeclarationsTool; + if (!functionDeclarationsTool?.functionDeclarations) { + return; + } + const functionCalls = getFunctionCalls(response); + if (!functionCalls) { + return; + } + for (const functionCall of functionCalls) { + const hasFunctionReference = + functionDeclarationsTool.functionDeclarations?.some( + declaration => + declaration.name === functionCall.name && + typeof declaration.functionReference === 'function' + ); + if (!hasFunctionReference) { + return; + } + } + return functionCalls; + } + + /** + * Call user-defined functions if requested by the model, and return + * the response that should be sent to the model. + * @internal + */ + async _callFunctionsAsNeeded( + functionCalls: FunctionCall[] + ): Promise { + const activeCallList: Array<{ + name: string; + id?: string; + results: Promise>; + }> = []; + const promiseList = []; + const functionDeclarationsTool = this.params?.tools?.find( + tool => (tool as FunctionDeclarationsTool).functionDeclarations + ) as FunctionDeclarationsTool; + if ( + functionDeclarationsTool && + functionDeclarationsTool.functionDeclarations + ) { + for (const functionCall of functionCalls) { + const functionDeclaration = + functionDeclarationsTool.functionDeclarations.find( + declaration => declaration.name === functionCall.name + ); + if (functionDeclaration?.functionReference) { + const results = Promise.resolve( + functionDeclaration.functionReference!(functionCall.args) + ).catch(e => { + const wrappedError = new AIError( + AIErrorCode.ERROR, + `Error in user-defined function "${functionDeclaration.name}": ${ + (e as Error).message + }` + ); + wrappedError.stack = (e as Error).stack; + throw wrappedError; + }); + activeCallList.push({ + name: functionCall.name, + id: functionCall.id, + results + }); + promiseList.push(results); + } + } + // Wait for promises to finish. + await Promise.all(promiseList); + const functionResponseParts = []; + for (const { name, id, results } of activeCallList) { + const functionResponse: FunctionResponse = { + name, + response: await results + }; + if (id) { + functionResponse.id = id; + } + functionResponseParts.push({ + functionResponse + }); + } + return functionResponseParts; + } else { + throw new AIError( + AIErrorCode.REQUEST_ERROR, + `No function declarations were provided in "tools".` + ); + } + } +} diff --git a/packages/ai/src/methods/chat-session.test.ts b/packages/ai/src/methods/chat-session.test.ts index 3ebf0edae8..e3fa2f1e58 100644 --- a/packages/ai/src/methods/chat-session.test.ts +++ b/packages/ai/src/methods/chat-session.test.ts @@ -441,6 +441,7 @@ describe('ChatSession', () => { }); const functionCallPartGreeting = { functionCall: { + id: 123, name: 'getGreeting', args: { username: 'Bob' } } @@ -509,6 +510,7 @@ describe('ChatSession', () => { functionResponseContents[functionResponseContents.length - 1].parts[0] .functionResponse ).to.deep.equal({ + id: 123, name: 'getGreeting', response: { greeting: 'Hi, Bob' } }); @@ -576,6 +578,7 @@ describe('ChatSession', () => { functionResponseContents[functionResponseContents.length - 1].parts[0] .functionResponse ).to.deep.equal({ + id: 123, name: 'getGreeting', response: { greeting: 'Hi, Bob' } }); @@ -632,7 +635,7 @@ describe('ChatSession', () => { ] }, { - maxSequentalFunctionCalls: 0 + maxSequentialFunctionCalls: 0 } ); const result = await chatSession.sendMessage('My name is Bob'); @@ -702,6 +705,7 @@ describe('ChatSession', () => { functionResponseContents[functionResponseContents.length - 1].parts[0] .functionResponse ).to.deep.equal({ + id: 123, name: 'getGreeting', response: { greeting: 'Hi, Bob' } }); @@ -768,6 +772,7 @@ describe('ChatSession', () => { functionResponseContents[functionResponseContents.length - 1].parts[0] .functionResponse ).to.deep.equal({ + id: 123, name: 'getGreeting', response: { greeting: 'Hi, Bob' } }); @@ -827,7 +832,7 @@ describe('ChatSession', () => { ] }, { - maxSequentalFunctionCalls: 0 + maxSequentialFunctionCalls: 0 } ); const result = await chatSession.sendMessageStream('My name is Bob'); diff --git a/packages/ai/src/methods/chat-session.ts b/packages/ai/src/methods/chat-session.ts index 63e34e54c1..e50304fe60 100644 --- a/packages/ai/src/methods/chat-session.ts +++ b/packages/ai/src/methods/chat-session.ts @@ -16,13 +16,9 @@ */ import { - AIErrorCode, Content, - FunctionCall, FunctionDeclarationsTool, - FunctionResponsePart, GenerateContentRequest, - GenerateContentResponse, GenerateContentResult, GenerateContentStreamResult, Part, @@ -30,29 +26,11 @@ import { SingleRequestOptions, StartChatParams } from '../types'; -import { formatNewContent } from '../requests/request-helpers'; -import { - formatBlockErrorMessage, - getFunctionCalls -} from '../requests/response-helpers'; -import { validateChatHistory } from './chat-session-helpers'; import { generateContent, generateContentStream } from './generate-content'; import { ApiSettings } from '../types/internal'; -import { logger } from '../logger'; import { ChromeAdapter } from '../types/chrome-adapter'; -import { AIError } from '../errors'; - -/** - * Used to break the internal promise chain when an error is already handled - * by the user, preventing duplicate console logs. - */ -const SILENT_ERROR = 'SILENT_ERROR'; - -/** - * Prevent infinite loop if the model continues to request sequential - * function calls during automatic function calling. - */ -const DEFAULT_MAX_SEQUENTIAL_FUNCTION_CALLS = 10; +import { ChatSessionBase } from './chat-session-base'; +import { validateChatHistory } from './chat-session-helpers'; /** * ChatSession class that enables sending chat messages and stores @@ -60,16 +38,11 @@ const DEFAULT_MAX_SEQUENTIAL_FUNCTION_CALLS = 10; * * @public */ -export class ChatSession { - private _apiSettings: ApiSettings; - private _history: Content[] = []; - - /** - * Ensures sequential execution of chat messages to maintain history order. - * Each call waits for the previous one to settle before proceeding. - */ - private _sendPromise: Promise = Promise.resolve(); - +export class ChatSession extends ChatSessionBase< + StartChatParams, + GenerateContentRequest, + FunctionDeclarationsTool +> { constructor( apiSettings: ApiSettings, public model: string, @@ -77,23 +50,13 @@ export class ChatSession { public params?: StartChatParams, public requestOptions?: RequestOptions ) { - this._apiSettings = apiSettings; + super(apiSettings, params, requestOptions); if (params?.history) { validateChatHistory(params.history); this._history = params.history; } } - /** - * Gets the chat history so far. Blocked prompts are not added to history. - * Neither blocked candidates nor the prompts that generated them are added - * to history. - */ - async getHistory(): Promise { - await this._sendPromise; - return this._history; - } - /** * Format Content into a request for generateContent or * generateContentStream. @@ -113,6 +76,48 @@ export class ChatSession { }; } + /** + * Calls default generateContent() (versus a specialized one like + * templateGenerateContent). + * @internal + */ + _callGenerateContent( + formattedRequest: GenerateContentRequest, + singleRequestOptions?: RequestOptions + ): Promise { + return generateContent( + this._apiSettings, + this.model, + formattedRequest, + this.chromeAdapter, + { + ...this.requestOptions, + ...singleRequestOptions + } + ); + } + + /** + * Calls default generateContentStream() (versus a specialized one like + * templateGenerateContentStream). + * @internal + */ + _callGenerateContentStream( + formattedRequest: GenerateContentRequest, + singleRequestOptions?: RequestOptions + ): Promise { + return generateContentStream( + this._apiSettings, + this.model, + formattedRequest, + this.chromeAdapter, + { + ...this.requestOptions, + ...singleRequestOptions + } + ); + } + /** * Sends a chat message and receives a non-streaming * {@link GenerateContentResult} @@ -121,93 +126,7 @@ export class ChatSession { request: string | Array, singleRequestOptions?: SingleRequestOptions ): Promise { - let finalResult = {} as GenerateContentResult; - await this._sendPromise; - /** - * Temporarily store multiple turns for cases like automatic function - * calling, only writing them to official history when the entire - * sequence has completed successfully. - */ - const tempHistory: Content[] = []; - - this._sendPromise = this._sendPromise.then(async () => { - let functionCalls: FunctionCall[] | undefined; - let functionCallTurnCount = 0; - const functionCallMaxTurns = - this.requestOptions?.maxSequentalFunctionCalls ?? - DEFAULT_MAX_SEQUENTIAL_FUNCTION_CALLS; - - // Repeats until model returns a response with no function calls - // or until `functionCallMaxTurns` is met or exceeded. - do { - let formattedContent; - - if (functionCalls) { - functionCallTurnCount++; - const functionResponseParts = await this._callFunctionsAsNeeded( - functionCalls - ); - formattedContent = formatNewContent(functionResponseParts); - } else { - formattedContent = formatNewContent(request); - } - const formattedRequest = this._formatRequest( - formattedContent, - tempHistory - ); - - tempHistory.push(formattedContent); - - const result = await generateContent( - this._apiSettings, - this.model, - formattedRequest, - this.chromeAdapter, - { - ...this.requestOptions, - ...singleRequestOptions - } - ); - if (result) { - finalResult = result; - functionCalls = this._getCallableFunctionCalls(result.response); - if ( - result.response.candidates && - result.response.candidates.length > 0 - ) { - // TODO: Make this update atomic. If creating `responseContent` throws, - // history will contain the user message but not the response, causing - // validation errors on the next request. - const responseContent: Content = { - parts: result.response.candidates?.[0].content.parts || [], - // Response seems to come back without a role set. - role: result.response.candidates?.[0].content.role || 'model' - }; - tempHistory.push(responseContent); - } else { - const blockErrorMessage = formatBlockErrorMessage(result.response); - if (blockErrorMessage) { - logger.warn( - `sendMessage() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.` - ); - } - } - } else { - functionCalls = undefined; - } - } while (functionCalls && functionCallTurnCount < functionCallMaxTurns); - - if (functionCalls && functionCallTurnCount >= functionCallMaxTurns) { - logger.warn( - `Automatic function calling exceeded the limit of` + - ` ${functionCallMaxTurns} function calls. Returning last model response.` - ); - } - }); - - await this._sendPromise; - this._history = this._history.concat(tempHistory); - return finalResult; + return this._sendMessage(request, singleRequestOptions); } /** @@ -219,225 +138,6 @@ export class ChatSession { request: string | Array, singleRequestOptions?: SingleRequestOptions ): Promise { - await this._sendPromise; - /** - * Temporarily store multiple turns for cases like automatic function - * calling, only writing them to official history when the entire - * sequence has completed successfully. - */ - const tempHistory: Content[] = []; - - const callGenerateContentStream = - async (): Promise => { - let functionCalls: FunctionCall[] | undefined; - let functionCallTurnCount = 0; - const functionCallMaxTurns = - this.requestOptions?.maxSequentalFunctionCalls ?? - DEFAULT_MAX_SEQUENTIAL_FUNCTION_CALLS; - let result: GenerateContentStreamResult & { - firstValue?: GenerateContentResponse; - }; - - // Repeats until model returns a response with no function calls - // or until `functionCallMaxTurns` is met or exceeded. - do { - let formattedContent; - - if (functionCalls) { - functionCallTurnCount++; - const functionResponseParts = await this._callFunctionsAsNeeded( - functionCalls - ); - formattedContent = formatNewContent(functionResponseParts); - } else { - formattedContent = formatNewContent(request); - } - - tempHistory.push(formattedContent); - const formattedRequest = this._formatRequest( - formattedContent, - tempHistory - ); - - result = await generateContentStream( - this._apiSettings, - this.model, - formattedRequest, - this.chromeAdapter, - { - ...this.requestOptions, - ...singleRequestOptions - } - ); - - functionCalls = this._getCallableFunctionCalls(result.firstValue); - - if ( - functionCalls && - result.firstValue && - result.firstValue.candidates && - result.firstValue.candidates.length > 0 - ) { - const responseContent = { - ...result.firstValue.candidates[0].content - }; - if (!responseContent.role) { - responseContent.role = 'model'; - } - tempHistory.push(responseContent); - } - } while (functionCalls && functionCallTurnCount < functionCallMaxTurns); - - if (functionCalls && functionCallTurnCount >= functionCallMaxTurns) { - logger.warn( - `Automatic function calling exceeded the limit of` + - ` ${functionCallMaxTurns} function calls. Returning last model response.` - ); - } - return { stream: result.stream, response: result.response }; - }; - - const streamPromise = callGenerateContentStream(); - - // Add onto the chain. - this._sendPromise = this._sendPromise - .then(async () => streamPromise) - // This must be handled to avoid unhandled rejection, but jump - // to the final catch block with a label to not log this error. - .catch(_ignored => { - // If the initial fetch fails, the user's `streamPromise` rejects. - // We swallow the error here to prevent double logging in the final catch. - throw new Error(SILENT_ERROR); - }) - .then(streamResult => streamResult.response) - .then(response => { - // This runs after the stream completes. Runtime errors here cannot be - // caught by the user because their promise has likely already resolved. - // TODO: Move response validation logic upstream to `stream-reader` so - // errors propagate to the user's `result.response` promise. - if (response.candidates && response.candidates.length > 0) { - this._history = this._history.concat(tempHistory); - // TODO: Validate that `response.candidates[0].content` is not null. - const responseContent = { ...response.candidates[0].content }; - if (!responseContent.role) { - responseContent.role = 'model'; - } - this._history.push(responseContent); - } else { - const blockErrorMessage = formatBlockErrorMessage(response); - if (blockErrorMessage) { - logger.warn( - `sendMessageStream() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.` - ); - } - } - }) - .catch(e => { - // Filter out errors already handled by the user or initiated by them. - if (e.message !== SILENT_ERROR && e.name !== 'AbortError') { - logger.error(e); - } - }); - return streamPromise; - } - - /** - * Get function calls that the SDK has references to actually call. - * This is all-or-nothing. If the model is requesting multiple - * function calls, all of them must have references in order for - * automatic function calling to work. - * - * @internal - */ - _getCallableFunctionCalls( - response?: GenerateContentResponse - ): FunctionCall[] | undefined { - const functionDeclarationsTool = this.params?.tools?.find( - tool => (tool as FunctionDeclarationsTool).functionDeclarations - ) as FunctionDeclarationsTool; - if (!functionDeclarationsTool?.functionDeclarations) { - return; - } - const functionCalls = getFunctionCalls(response); - if (!functionCalls) { - return; - } - for (const functionCall of functionCalls) { - const hasFunctionReference = - functionDeclarationsTool.functionDeclarations?.some( - declaration => - declaration.name === functionCall.name && - typeof declaration.functionReference === 'function' - ); - if (!hasFunctionReference) { - return; - } - } - return functionCalls; - } - - /** - * Call user-defined functions if requested by the model, and return - * the response that should be sent to the model. - * @internal - */ - async _callFunctionsAsNeeded( - functionCalls: FunctionCall[] - ): Promise { - const activeCallList = new Map< - string, - { id?: string; results: Promise> } - >(); - const promiseList = []; - const functionDeclarationsTool = this.params?.tools?.find( - tool => (tool as FunctionDeclarationsTool).functionDeclarations - ) as FunctionDeclarationsTool; - if ( - functionDeclarationsTool && - functionDeclarationsTool.functionDeclarations - ) { - for (const functionCall of functionCalls) { - const functionDeclaration = - functionDeclarationsTool.functionDeclarations.find( - declaration => declaration.name === functionCall.name - ); - if (functionDeclaration?.functionReference) { - const results = Promise.resolve( - functionDeclaration.functionReference!(functionCall.args) - ).catch(e => { - const wrappedError = new AIError( - AIErrorCode.ERROR, - `Error in user-defined function "${functionDeclaration.name}": ${ - (e as Error).message - }` - ); - wrappedError.stack = (e as Error).stack; - throw wrappedError; - }); - activeCallList.set(functionCall.name, { - id: functionCall.id, - results - }); - promiseList.push(results); - } - } - // Wait for promises to finish. - await Promise.all(promiseList); - const functionResponseParts = []; - for (const [name, callData] of activeCallList) { - functionResponseParts.push({ - functionResponse: { - name, - response: await callData.results - } - }); - } - return functionResponseParts; - } else { - throw new AIError( - AIErrorCode.REQUEST_ERROR, - `No function declarations were provided in "tools".` - ); - } + return this._sendMessageStream(request, singleRequestOptions); } } diff --git a/packages/ai/src/methods/generate-content.ts b/packages/ai/src/methods/generate-content.ts index 8b7efc3ef1..0b85b0c777 100644 --- a/packages/ai/src/methods/generate-content.ts +++ b/packages/ai/src/methods/generate-content.ts @@ -31,7 +31,7 @@ import { createEnhancedContentResponse } from '../requests/response-helpers'; import { processStream } from '../requests/stream-reader'; import { ApiSettings } from '../types/internal'; import * as GoogleAIMapper from '../googleai-mappers'; -import { BackendType } from '../public-types'; +import { BackendType, TemplateRequestInternal } from '../public-types'; import { ChromeAdapter } from '../types/chrome-adapter'; import { callCloudOrDevice } from '../requests/hybrid-helpers'; @@ -108,7 +108,7 @@ async function generateContentOnCloud( export async function templateGenerateContent( apiSettings: ApiSettings, templateId: string, - templateParams: object, + templateParams: TemplateRequestInternal, singleRequestOptions?: SingleRequestOptions ): Promise { const response = await makeRequest( @@ -136,7 +136,7 @@ export async function templateGenerateContent( export async function templateGenerateContentStream( apiSettings: ApiSettings, templateId: string, - templateParams: object, + templateParams: TemplateRequestInternal, singleRequestOptions?: SingleRequestOptions ): Promise { const response = await makeRequest( diff --git a/packages/ai/src/methods/template-chat-session.test.ts b/packages/ai/src/methods/template-chat-session.test.ts new file mode 100644 index 0000000000..f1807373bd --- /dev/null +++ b/packages/ai/src/methods/template-chat-session.test.ts @@ -0,0 +1,472 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect, use } from 'chai'; +import { match, restore, SinonSpy, spy, stub } from 'sinon'; +import sinonChai from 'sinon-chai'; +import chaiAsPromised from 'chai-as-promised'; +import * as generateContentMethods from './generate-content'; +import { Content, TemplateFunctionDeclaration } from '../types'; +import { TemplateChatSession } from './template-chat-session'; +import { ApiSettings } from '../types/internal'; +import { VertexAIBackend } from '../backend'; +import { logger } from '../logger'; +import { Schema } from '../api'; + +use(sinonChai); +use(chaiAsPromised); + +const fakeApiSettings: ApiSettings = { + apiKey: 'key', + project: 'my-project', + appId: 'my-appid', + location: 'us-central1', + backend: new VertexAIBackend('us-central1') +}; + +const TEMPLATE_ID = 'my-template'; + +function getGreeting({ + username +}: Record): Record { + return { greeting: `Hi, ${username}` }; +} + +function getFarewell({ + username +}: Record): Record { + return { farewell: `Bye, ${username}` }; +} + +describe('TemplateChatSession', () => { + afterEach(() => { + restore(); + }); + describe('formatRequest()', () => { + it( + 'should rename functionDeclarations to templateFunctions' + + ' and parameters to inputSchema', + () => { + const chatSession = new TemplateChatSession(fakeApiSettings, { + templateId: TEMPLATE_ID, + tools: [ + { + functionDeclarations: [ + { + name: 'imAFunction', + parameters: { type: 'object' } + } + ] + } + ] + }); + const formattedRequest = chatSession._formatRequest( + { role: 'user', parts: [] }, + [] + ); + //@ts-expect-error + expect(formattedRequest.tools?.[0].functionDeclarations).to.not.exist; + //@ts-expect-error + expect(formattedRequest.tools?.[0].templateFunctions?.[0].parameters).to + .not.exist; + expect( + formattedRequest.tools?.[0].templateFunctions?.[0]?.inputSchema?.type + ).to.equal('object'); + expect( + formattedRequest.tools?.[0].templateFunctions?.[0]?.name + ).to.equal('imAFunction'); + } + ); + it('should not include any properties not provided in params', () => { + const chatSession = new TemplateChatSession(fakeApiSettings, { + templateId: TEMPLATE_ID + }); + const formattedRequest = chatSession._formatRequest( + { role: 'user', parts: [] }, + [] + ); + expect(formattedRequest.tools).to.not.exist; + expect(formattedRequest.toolConfig).to.not.exist; + expect(formattedRequest.templateVariables).to.not.exist; + expect(formattedRequest.history).to.exist; + }); + }); + + describe('sendMessage()', () => { + it('generateContent errors should be catchable', async () => { + const templateGenerateContentStub = stub( + generateContentMethods, + 'templateGenerateContent' + ).rejects(new Error('templateGenerateContent failed')); + const chatSession = new TemplateChatSession(fakeApiSettings, { + templateId: TEMPLATE_ID + }); + await expect(chatSession.sendMessage('hello')).to.be.rejected; + expect(templateGenerateContentStub).to.be.calledWith( + fakeApiSettings, + TEMPLATE_ID, + match.any + ); + }); + + it('adds message and response to history', async () => { + const fakeContent: Content = { + role: 'model', + parts: [{ text: 'hi' }] + }; + const fakeResponse = { + candidates: [ + { + index: 1, + content: fakeContent + } + ] + }; + const templateGenerateContentStub = stub( + generateContentMethods, + 'templateGenerateContent' + ).resolves({ + // @ts-ignore + response: fakeResponse + }); + const chatSession = new TemplateChatSession(fakeApiSettings, { + templateId: TEMPLATE_ID + }); + const result = await chatSession.sendMessage('hello'); + // @ts-ignore + expect(result.response).to.equal(fakeResponse); + + // Test: stores history correctly? + const history = await chatSession.getHistory(); + expect(history[0].role).to.equal('user'); + expect(history[0].parts[0].text).to.equal('hello'); + expect(history[1]).to.deep.equal(fakeResponse.candidates[0].content); + + // Test: sends history correctly? + await chatSession.sendMessage('hello 2'); + expect( + (templateGenerateContentStub.args[1][2] as any).history[0].parts[0].text + ).to.equal('hello'); + expect( + (templateGenerateContentStub.args[1][2] as any).history[1] + ).to.deep.equal(fakeResponse.candidates[0].content); + expect( + (templateGenerateContentStub.args[1][2] as any).history[2].parts[0].text + ).to.equal('hello 2'); + }); + }); + + describe('Automatic function calling', () => { + const finalResponse = { + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [ + { + text: 'final response' + } + ] + } + } + ] + }; + const getFunctionDeclarationGreeting = ( + greetingSpy: SinonSpy + ): TemplateFunctionDeclaration => ({ + name: 'getGreeting', + functionReference: greetingSpy, + parameters: Schema.object({ + properties: { + username: Schema.string({ + description: "The user's name" + }) + } + }) + }); + const getFunctionDeclarationFarewell = ( + farewellSpy: SinonSpy + ): TemplateFunctionDeclaration => ({ + name: 'getFarewell', + functionReference: farewellSpy, + parameters: Schema.object({ + properties: { + username: Schema.string({ + description: "The user's name" + }) + } + }) + }); + const functionCallPartGreeting = { + functionCall: { + name: 'getGreeting', + args: { username: 'Bob' } + } + }; + const functionCallPartFarewell = { + functionCall: { + id: 789, + name: 'getFarewell', + args: { username: 'Bob' } + } + }; + + describe('sendMessage()', () => { + it('calls one function automatically', async () => { + const greetingSpy = spy(getGreeting); + const templateGenerateContentStub = stub( + generateContentMethods, + 'templateGenerateContent' + // @ts-ignore + ).callsFake(async (apiSettings, templateId, params: any) => { + const parts = params.history[params.history.length - 1].parts; + if (parts[0].text?.includes('Bob')) { + return { + response: { + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [functionCallPartGreeting] + } + } + ] + } + }; + } else if (parts[0].functionResponse) { + return { + response: finalResponse + }; + } + }); + const chatSession = new TemplateChatSession(fakeApiSettings, { + templateId: TEMPLATE_ID, + tools: [ + { + functionDeclarations: [ + getFunctionDeclarationGreeting(greetingSpy) + ] + } + ] + }); + const result = await chatSession.sendMessage('My name is Bob'); + expect( + result.response.candidates?.[0].content.parts[0].text + ).to.include('final response'); + expect(templateGenerateContentStub).to.be.calledTwice; + + const functionResponseHistory = ( + templateGenerateContentStub.secondCall.args[2] as any + ).history; + const lastTurnParts = + functionResponseHistory[functionResponseHistory.length - 1].parts; + + expect(lastTurnParts.length).to.equal(1); + expect(lastTurnParts[0].functionResponse).to.deep.equal({ + name: 'getGreeting', + response: { greeting: 'Hi, Bob' } + }); + expect(greetingSpy).to.be.calledWith({ username: 'Bob' }); + }); + + it('calls two functions automatically', async () => { + const greetingSpy = spy(getGreeting); + const farewellSpy = spy(getFarewell); + const templateGenerateContentStub = stub( + generateContentMethods, + 'templateGenerateContent' + // @ts-ignore + ).callsFake(async (apiSettings, templateId, params: any) => { + const parts = params.history[params.history.length - 1].parts; + if (parts[0].text?.includes('Bob')) { + return { + response: { + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [ + functionCallPartGreeting, + functionCallPartFarewell + ] + } + } + ] + } + }; + } else if (parts[0].functionResponse) { + return { + response: finalResponse + }; + } + }); + const chatSession = new TemplateChatSession(fakeApiSettings, { + templateId: TEMPLATE_ID, + tools: [ + { + functionDeclarations: [ + getFunctionDeclarationGreeting(greetingSpy), + getFunctionDeclarationFarewell(farewellSpy) + ] + } + ] + }); + const result = await chatSession.sendMessage('My name is Bob'); + expect( + result.response.candidates?.[0].content.parts[0].text + ).to.include('final response'); + expect(templateGenerateContentStub).to.be.calledTwice; + + const functionResponseHistory = ( + templateGenerateContentStub.secondCall.args[2] as any + ).history; + const lastTurnParts = + functionResponseHistory[functionResponseHistory.length - 1].parts; + + expect(lastTurnParts.length).to.equal(2); + expect(lastTurnParts[0].functionResponse).to.deep.equal({ + name: 'getGreeting', + response: { greeting: 'Hi, Bob' } + }); + expect(lastTurnParts[1].functionResponse).to.deep.equal({ + id: 789, + name: 'getFarewell', + response: { farewell: 'Bye, Bob' } + }); + expect(greetingSpy).to.be.calledWith({ username: 'Bob' }); + expect(farewellSpy).to.be.calledWith({ username: 'Bob' }); + }); + + it('does not call any functions if sequential limit is set to 0', async () => { + const greetingSpy = spy(getGreeting); + const warnStub = stub(logger, 'warn'); + const templateGenerateContentStub = stub( + generateContentMethods, + 'templateGenerateContent' + // @ts-ignore + ).callsFake(async (apiSettings, templateId, params: any) => { + const parts = params.history[params.history.length - 1].parts; + if (parts[0].text?.includes('Bob')) { + return { + response: { + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [functionCallPartGreeting] + } + } + ] + } + }; + } else if (parts[0].functionResponse) { + return { + response: finalResponse + }; + } + }); + const chatSession = new TemplateChatSession( + fakeApiSettings, + { + templateId: TEMPLATE_ID, + tools: [ + { + functionDeclarations: [ + getFunctionDeclarationGreeting(greetingSpy) + ] + } + ] + }, + { + maxSequentialFunctionCalls: 0 + } + ); + const result = await chatSession.sendMessage('My name is Bob'); + expect( + result.response.candidates?.[0].content.parts[0].functionCall?.name + ).to.equal('getGreeting'); + expect(templateGenerateContentStub).to.be.calledOnce; + expect(warnStub).calledWithMatch('exceeded the limit'); + expect(greetingSpy).to.not.be.called; + }); + }); + + describe('sendMessageStream()', () => { + it('calls one function automatically on stream', async () => { + const greetingSpy = spy(getGreeting); + const templateGenerateContentStreamStub = stub( + generateContentMethods, + 'templateGenerateContentStream' + // @ts-ignore + ).callsFake(async (apiSettings, templateId, params: any) => { + const parts = params.history[params.history.length - 1].parts; + if (parts[0].text?.includes('Bob')) { + return { + firstValue: { + candidates: [ + { + index: 1, + content: { + role: 'model', + parts: [functionCallPartGreeting] + } + } + ] + } + }; + } else if (parts[0].functionResponse) { + return { + firstValue: finalResponse, + response: finalResponse + }; + } + }); + const chatSession = new TemplateChatSession(fakeApiSettings, { + templateId: TEMPLATE_ID, + tools: [ + { + functionDeclarations: [ + getFunctionDeclarationGreeting(greetingSpy) + ] + } + ] + }); + const result = await chatSession.sendMessageStream('My name is Bob'); + + await result.response; + expect(templateGenerateContentStreamStub).to.be.calledTwice; + + const functionResponseHistory = ( + templateGenerateContentStreamStub.secondCall.args[2] as any + ).history; + const lastTurnParts = + functionResponseHistory[functionResponseHistory.length - 1].parts; + + expect(lastTurnParts.length).to.equal(1); + expect(lastTurnParts[0].functionResponse).to.deep.equal({ + name: 'getGreeting', + response: { greeting: 'Hi, Bob' } + }); + expect(greetingSpy).to.be.calledWith({ username: 'Bob' }); + }); + }); + }); +}); diff --git a/packages/ai/src/methods/template-chat-session.ts b/packages/ai/src/methods/template-chat-session.ts new file mode 100644 index 0000000000..e8e17fdbf0 --- /dev/null +++ b/packages/ai/src/methods/template-chat-session.ts @@ -0,0 +1,165 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Content, + GenerateContentResult, + GenerateContentStreamResult, + Part, + RequestOptions, + SingleRequestOptions, + StartTemplateChatParams, + TemplateFunctionDeclarationInternal, + TemplateFunctionDeclarationsTool, + TemplateFunctionDeclarationsToolInternal, + TemplateRequestInternal +} from '../types'; +import { validateChatHistory } from './chat-session-helpers'; +import { + templateGenerateContent, + templateGenerateContentStream +} from './generate-content'; +import { ApiSettings } from '../types/internal'; +import { ChatSessionBase } from './chat-session-base'; + +/** + * `ChatSession` class for use with server prompt templates that + * enables sending chat messages and stores history of sent and + * received messages so far. + * + * @beta + */ +export class TemplateChatSession extends ChatSessionBase< + StartTemplateChatParams, + TemplateRequestInternal, + TemplateFunctionDeclarationsTool +> { + constructor( + apiSettings: ApiSettings, + public params: StartTemplateChatParams, + public requestOptions?: RequestOptions + ) { + super(apiSettings, params, requestOptions); + if (params.history) { + validateChatHistory(params.history); + this._history = params.history; + } + } + + /** + * Format the internal state to the body payload for `templateGenerateContent`. + * @internal + */ + _formatRequest( + incomingContent: Content, + tempHistory: Content[] + ): TemplateRequestInternal { + const request: TemplateRequestInternal = { + history: [...this._history, ...tempHistory, incomingContent] + }; + if (this.params.templateVariables) { + request.inputs = this.params.templateVariables; + } + if (this.params.tools) { + request.tools = this.params.tools?.map(tool => { + if (tool.functionDeclarations) { + return { + templateFunctions: tool.functionDeclarations.map(declaration => { + if (declaration.parameters) { + const newDeclaration = { ...declaration }; + delete newDeclaration.parameters; + ( + newDeclaration as TemplateFunctionDeclarationInternal + ).inputSchema = declaration.parameters; + return newDeclaration; + } + return declaration; + }) + }; + } + return tool as TemplateFunctionDeclarationsToolInternal; + }); + } + if (this.params.toolConfig) { + request.toolConfig = this.params.toolConfig; + } + return request; + } + + /** + * Calls the specific templateGenerateContent() function needed for + * this specialized TemplateChatSession. + * @internal + */ + _callGenerateContent( + formattedRequest: TemplateRequestInternal, + singleRequestOptions?: RequestOptions + ): Promise { + return templateGenerateContent( + this._apiSettings, + this.params.templateId, + formattedRequest, + { + ...this.requestOptions, + ...singleRequestOptions + } + ); + } + + /** + * Calls the specific templateGenerateContentStream() function needed for + * this specialized TemplateChatSession. + * @internal + */ + _callGenerateContentStream( + formattedRequest: TemplateRequestInternal, + singleRequestOptions?: RequestOptions + ): Promise { + return templateGenerateContentStream( + this._apiSettings, + this.params.templateId, + formattedRequest, + { + ...this.requestOptions, + ...singleRequestOptions + } + ); + } + + /** + * Sends a chat message and receives a non-streaming + * {@link GenerateContentResult} + */ + async sendMessage( + request: string | Array, + singleRequestOptions?: SingleRequestOptions + ): Promise { + return this._sendMessage(request, singleRequestOptions); + } + + /** + * Sends a chat message and receives the response as a + * {@link GenerateContentStreamResult} containing an iterable stream + * and a response promise. + */ + async sendMessageStream( + request: string | Array, + singleRequestOptions?: SingleRequestOptions + ): Promise { + return this._sendMessageStream(request, singleRequestOptions); + } +} diff --git a/packages/ai/src/models/template-generative-model.test.ts b/packages/ai/src/models/template-generative-model.test.ts index d3f7ec28ff..c33cc27d20 100644 --- a/packages/ai/src/models/template-generative-model.test.ts +++ b/packages/ai/src/models/template-generative-model.test.ts @@ -183,4 +183,32 @@ describe('TemplateGenerativeModel', () => { ); }); }); + + describe('startChat', () => { + it('returns a TemplateChatSession initialized with params and requestOptions', () => { + const model = new TemplateGenerativeModel(fakeAI, { timeout: 1000 }); + const chat = model.startChat({ + templateId: TEMPLATE_ID, + templateVariables: TEMPLATE_VARS, + tools: [ + { + functionDeclarations: [{ name: 'testFunction' }] // Testing that tools are passed along + } + ], + toolConfig: { + functionCallingConfig: { + mode: 'ANY' + } + } + }); + + expect(chat.params.templateId).to.equal(TEMPLATE_ID); + expect(chat.params.templateVariables).to.deep.equal(TEMPLATE_VARS); + expect(chat.params.tools?.length).to.equal(1); + expect(chat.params.toolConfig?.functionCallingConfig?.mode).to.equal( + 'ANY' + ); + expect(chat.requestOptions?.timeout).to.equal(1000); + }); + }); }); diff --git a/packages/ai/src/models/template-generative-model.ts b/packages/ai/src/models/template-generative-model.ts index 7c3b99062e..0ab1383e87 100644 --- a/packages/ai/src/models/template-generative-model.ts +++ b/packages/ai/src/models/template-generative-model.ts @@ -23,10 +23,12 @@ import { GenerateContentResult, RequestOptions } from '../types'; import { AI, GenerateContentStreamResult, - SingleRequestOptions + SingleRequestOptions, + StartTemplateChatParams } from '../public-types'; import { ApiSettings } from '../types/internal'; import { initApiSettings } from './utils'; +import { TemplateChatSession } from '../methods/template-chat-session'; /** * {@link GenerativeModel} APIs that execute on a server-side template. @@ -66,7 +68,7 @@ export class TemplateGenerativeModel { */ async generateContent( templateId: string, - templateVariables: object, + templateVariables: Record, singleRequestOptions?: SingleRequestOptions ): Promise { return templateGenerateContent( @@ -94,7 +96,7 @@ export class TemplateGenerativeModel { */ async generateContentStream( templateId: string, - templateVariables: object, + templateVariables: Record, singleRequestOptions?: SingleRequestOptions ): Promise { return templateGenerateContentStream( @@ -107,4 +109,21 @@ export class TemplateGenerativeModel { } ); } + + /** + * Starts a {@link TemplateChatSession} that will use this template to + * respond to messages. + * + * @param params - Configurations for the chat, including the template + * ID and input variables. + * + * @beta + */ + startChat(params: StartTemplateChatParams): TemplateChatSession { + return new TemplateChatSession( + this._apiSettings, + params, + this.requestOptions + ); + } } diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index cee42fc5a1..0866371f48 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -74,6 +74,27 @@ export interface GenerateContentRequest extends BaseParams { systemInstruction?: string | Part | Content; } +/** + * Request sent through {@link TemplateGenerativeModel.generateContent} + * @beta + */ +export interface TemplateGenerateContentRequest { + inputs?: Record; + history?: Content[]; + tools?: TemplateFunctionDeclarationsTool[]; + toolConfig?: ToolConfig; + [key: string]: unknown; +} + +/** + * Internal version of the template generate content request. + * @internal + */ +export interface TemplateRequestInternal + extends Omit { + tools?: TemplateFunctionDeclarationsToolInternal[]; +} + /** * Safety setting that can be sent as part of request parameters. * @public @@ -224,6 +245,23 @@ export interface StartChatParams extends BaseParams { systemInstruction?: string | Part | Content; } +/** + * Params for {@link TemplateGenerativeModel.startChat}. + * @beta + */ +export interface StartTemplateChatParams + extends Omit { + /** + * The ID of the server-side template to execute. + */ + templateId: string; + /** + * A key-value map of variables to populate the template with. + */ + templateVariables?: Record; + tools?: TemplateTool[]; +} + /** * Params for calling {@link GenerativeModel.countTokens} * @public @@ -268,7 +306,7 @@ export interface RequestOptions { * When it reaches this limit, it will return the last response received * from the model, whether it is a text response or further function calls. */ - maxSequentalFunctionCalls?: number; + maxSequentialFunctionCalls?: number; } /** @@ -444,6 +482,79 @@ export interface FunctionDeclarationsTool { functionDeclarations?: FunctionDeclaration[]; } +/** + * Structured representation of a template function declaration. + * Included in this declaration are the function name and parameters. This + * `TemplateFunctionDeclaration` is a representation of a block of code that can be used + * as a Tool by the model and executed by the client. + * Note: Template function declarations do not support description fields. + * @beta + */ +export interface TemplateFunctionDeclaration { + /** + * The name of the function to call. Must start with a letter or an + * underscore. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with + * a max length of 64. + */ + name: string; + /** + * Description is intentionally unsupported for template function declarations. + */ + description?: never; + /** + * Optional. Describes the parameters to this function in JSON Schema Object + * format. Reflects the Open API 3.03 Parameter Object. Parameter names are + * case-sensitive. For a function with no parameters, this can be left unset. + */ + parameters?: ObjectSchema | ObjectSchemaRequest; + /** + * Reference to an actual function to call. Specifying this will cause the + * function to be called automatically when requested by the model. + */ + // eslint-disable-next-line @typescript-eslint/ban-types + functionReference?: Function; +} + +/** + * @internal + */ +export interface TemplateFunctionDeclarationInternal + extends Omit { + inputSchema?: ObjectSchema | ObjectSchemaRequest; +} + +/** + * A piece of code that enables the system to interact with external systems. + * @beta + */ +export interface TemplateFunctionDeclarationsTool { + /** + * Optional. One or more function declarations + * to be passed to the server-side template execution. + */ + functionDeclarations?: TemplateFunctionDeclaration[]; +} + +/** + * The modified interface for the tool that is sent to the backend. + * @internal + */ +export interface TemplateFunctionDeclarationsToolInternal { + /** + * Optional. One or more function declarations + * to be passed to the server-side template execution. + */ + templateFunctions?: TemplateFunctionDeclarationInternal[]; +} + +/** + * Defines a tool that a {@link TemplateGenerativeModel} can call + * to access external knowledge. + * Only function declarations are currently supported for templates. + * @beta + */ +export type TemplateTool = TemplateFunctionDeclarationsTool; + /** * Tool config. This config is shared for all tools provided in the request. * @public From 87d5cc1ba0107cb9a7a07bc6033dcec360f78d28 Mon Sep 17 00:00:00 2001 From: Stephen Rosa <84193009+stephenarosaj@users.noreply.github.com> Date: Wed, 8 Apr 2026 15:15:58 -0700 Subject: [PATCH 132/174] feat(data-connect): add support for streaming transport (#9809) --- .changeset/thick-roses-lick.md | 6 + packages/data-connect/src/api/DataConnect.ts | 16 +- packages/data-connect/src/api/Mutation.ts | 4 +- packages/data-connect/src/api/query.ts | 2 +- .../src/core/query/QueryManager.ts | 159 ++- packages/data-connect/src/index.node.ts | 12 +- packages/data-connect/src/network/index.ts | 11 +- packages/data-connect/src/network/manager.ts | 200 +++ .../src/network/{ => rest}/fetch.ts | 63 +- .../data-connect/src/network/rest/index.ts | 19 + .../src/network/rest/restTransport.ts | 159 +++ .../src/network/stream/streamTransport.ts | 710 ++++++++++ .../src/network/stream/websocket.ts | 341 +++++ .../data-connect/src/network/stream/wire.ts | 157 +++ .../data-connect/src/network/transport.ts | 370 +++++ .../src/network/transport/index.ts | 115 -- .../src/network/transport/rest.ts | 232 ---- packages/data-connect/src/util/url.ts | 26 +- packages/data-connect/test/queries.test.ts | 9 + .../data-connect/test/unit/caching.test.ts | 12 +- packages/data-connect/test/unit/fetch.test.ts | 4 +- packages/data-connect/test/unit/gmpid.test.ts | 2 +- .../data-connect/test/unit/queries.test.ts | 11 +- .../test/unit/streamTransport.test.ts | 1225 +++++++++++++++++ .../data-connect/test/unit/streaming.test.ts | 446 ++++++ packages/data-connect/test/unit/testUtils.ts | 114 ++ .../test/unit/transportManager.test.ts | 618 +++++++++ .../data-connect/test/unit/userAgent.test.ts | 2 +- .../test/unit/websocketTransport.test.ts | 374 +++++ 29 files changed, 5004 insertions(+), 415 deletions(-) create mode 100644 .changeset/thick-roses-lick.md create mode 100644 packages/data-connect/src/network/manager.ts rename packages/data-connect/src/network/{ => rest}/fetch.ts (74%) create mode 100644 packages/data-connect/src/network/rest/index.ts create mode 100644 packages/data-connect/src/network/rest/restTransport.ts create mode 100644 packages/data-connect/src/network/stream/streamTransport.ts create mode 100644 packages/data-connect/src/network/stream/websocket.ts create mode 100644 packages/data-connect/src/network/stream/wire.ts create mode 100644 packages/data-connect/src/network/transport.ts delete mode 100644 packages/data-connect/src/network/transport/index.ts delete mode 100644 packages/data-connect/src/network/transport/rest.ts create mode 100644 packages/data-connect/test/unit/streamTransport.test.ts create mode 100644 packages/data-connect/test/unit/streaming.test.ts create mode 100644 packages/data-connect/test/unit/testUtils.ts create mode 100644 packages/data-connect/test/unit/transportManager.test.ts create mode 100644 packages/data-connect/test/unit/websocketTransport.test.ts diff --git a/.changeset/thick-roses-lick.md b/.changeset/thick-roses-lick.md new file mode 100644 index 0000000000..37735e6a02 --- /dev/null +++ b/.changeset/thick-roses-lick.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/data-connect': minor +--- + +Add streaming support for Firebase Data Connect. diff --git a/packages/data-connect/src/api/DataConnect.ts b/packages/data-connect/src/api/DataConnect.ts index 3c463a399a..ebd457de81 100644 --- a/packages/data-connect/src/api/DataConnect.ts +++ b/packages/data-connect/src/api/DataConnect.ts @@ -37,12 +37,12 @@ import { import { QueryManager } from '../core/query/QueryManager'; import { logDebug, logError } from '../logger'; import { + DataConnectTransportInterface, + TransportClass, CallerSdkType, - CallerSdkTypeEnum, - DataConnectTransport, - TransportClass + CallerSdkTypeEnum } from '../network'; -import { RESTTransport } from '../network/transport/rest'; +import { DataConnectTransportManager } from '../network/manager'; import { PROD_HOST } from '../util/url'; import { MutationManager } from './Mutation'; @@ -96,7 +96,7 @@ export class DataConnect { _mutationManager!: MutationManager; isEmulator = false; _initialized = false; - private _transport!: DataConnectTransport; + private _transport!: DataConnectTransportInterface; private _transportClass: TransportClass | undefined; private _transportOptions?: TransportOptions; private _authTokenProvider?: AuthTokenProvider; @@ -172,8 +172,10 @@ export class DataConnect { return; } if (this._transportClass === undefined) { - logDebug('transportClass not provided. Defaulting to RESTTransport.'); - this._transportClass = RESTTransport; + logDebug( + 'transportClass not provided. Defaulting to DataConnectTransportManager.' + ); + this._transportClass = DataConnectTransportManager; } this._authTokenProvider = new FirebaseAuthProvider( diff --git a/packages/data-connect/src/api/Mutation.ts b/packages/data-connect/src/api/Mutation.ts index 570b28b0ea..f775757d46 100644 --- a/packages/data-connect/src/api/Mutation.ts +++ b/packages/data-connect/src/api/Mutation.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { DataConnectTransport } from '../network/transport'; +import { DataConnectTransportInterface } from '../network'; import { DataConnect } from './DataConnect'; import { @@ -77,7 +77,7 @@ export function mutationRef( */ export class MutationManager { private _inflight: Array> = []; - constructor(private _transport: DataConnectTransport) {} + constructor(private _transport: DataConnectTransportInterface) {} executeMutation( mutationRef: MutationRef ): MutationPromise { diff --git a/packages/data-connect/src/api/query.ts b/packages/data-connect/src/api/query.ts index e336de747e..1536df5fc7 100644 --- a/packages/data-connect/src/api/query.ts +++ b/packages/data-connect/src/api/query.ts @@ -20,7 +20,7 @@ import { ExecuteQueryOptions, QueryFetchPolicy } from '../core/query/queryOptions'; -import { DataConnectExtensionWithMaxAge } from '../network/transport'; +import { DataConnectExtensionWithMaxAge } from '../network'; import { DataConnect, getDataConnect } from './DataConnect'; import { diff --git a/packages/data-connect/src/core/query/QueryManager.ts b/packages/data-connect/src/core/query/QueryManager.ts index 8e0ab242bd..8846750427 100644 --- a/packages/data-connect/src/core/query/QueryManager.ts +++ b/packages/data-connect/src/core/query/QueryManager.ts @@ -28,13 +28,21 @@ import { DataConnectSubscription } from '../../api.browser'; import { DataConnectCache, ServerValues } from '../../cache/Cache'; import { parseEntityIds } from '../../cache/cacheUtils'; import { EncodingMode } from '../../cache/EntityNode'; -import { DataConnectTransport, Extensions } from '../../network'; import { + DataConnectTransportInterface, + Extensions, DataConnectExtensionWithMaxAge, - ExtensionsWithMaxAge -} from '../../network/transport'; + ExtensionsWithMaxAge, + SubscribeObserver, + DataConnectResponse +} from '../../network'; import { decoderImpl, encoderImpl } from '../../util/encoder'; -import { Code, DataConnectError } from '../error'; +import { + Code, + DataConnectError, + DataConnectOperationError, + DataConnectOperationFailureResponse +} from '../error'; import { OnCompleteSubscription, @@ -85,9 +93,13 @@ export class QueryManager { string, Array> >(); + /** + * Map of serialized query keys to most recent Query Result. Used as a simple fallback cache + * for subsciptions if caching is not enabled. + */ private subscriptionCache = new Map>(); constructor( - private transport: DataConnectTransport, + private transport: DataConnectTransportInterface, private dc: DataConnect, private cache?: DataConnectCache ) {} @@ -154,10 +166,15 @@ export class QueryManager { const unsubscribe = (): void => { if (this.callbacks.has(key)) { const callbackList = this.callbacks.get(key)!; - this.callbacks.set( - key, - callbackList.filter(callback => callback !== subscription) + const newList = callbackList.filter( + callback => callback !== subscription ); + this.callbacks.set(key, newList); + + if (newList.length === 0) { + this.callbacks.delete(key); + this.transport.invokeUnsubscribe(queryRef.name, queryRef.variables); + } onCompleteCallback?.(); } }; @@ -175,12 +192,22 @@ export class QueryManager { // We want to ignore the error and let subscriptions handle it promise.then(undefined, err => {}); - if (!this.callbacks.has(key)) { - this.callbacks.set(key, []); + if (this.callbacks.has(key)) { + this.callbacks + .get(key)! + .push(subscription as DataConnectSubscription); + } else { + this.callbacks.set(key, [ + subscription as DataConnectSubscription + ]); + + // only invoke subscription if we don't already have an active subscription + this.transport.invokeSubscribe( + this.makeSubscribeObserver(queryRef), + queryRef.name, + queryRef.variables + ); } - this.callbacks - .get(key)! - .push(subscription as DataConnectSubscription); return unsubscribe; } @@ -215,8 +242,7 @@ export class QueryManager { fetchTime ) }; - let updatedKeys: string[] = []; - updatedKeys = await this.updateCache( + const updatedKeys = await this.updateCache( queryResult, originalExtensions?.dataConnect ); @@ -342,6 +368,7 @@ export class QueryManager { return result as QueryResult; } + /** Call the registered onNext callbacks for the given key */ publishDataToSubscribers( key: string, queryResult: QueryResult @@ -391,6 +418,108 @@ export class QueryManager { enableEmulator(host: string, port: number): void { this.transport.useEmulator(host, port); } + + /** + * Create a new {@link SubscribeObserver} for the given QueryRef. This will be passed to + * {@link DataConnectTransportInterface.invokeSubscribe | invokeSubscribe()} to notify the query + * layer of data update notifications or if the stream disconnected. + */ + private makeSubscribeObserver( + queryRef: QueryRef + ): SubscribeObserver { + const key = encoderImpl({ + name: queryRef.name, + variables: queryRef.variables, + refType: QUERY_STR + }); + return { + onData: async response => { + await this.handleStreamNotification(key, response, queryRef); + }, + onDisconnect: (code, reason) => { + this.handleStreamDisconnect(key, code, reason); + }, + onError: error => { + this.publishErrorToSubscribers(key, error); + } + }; + } + + /** + * Handle a data update notification from the stream. Notify subscribers of results/errors, and + * update the cache. + */ + private async handleStreamNotification( + key: string, + response: DataConnectResponse, + queryRef: QueryRef + ): Promise { + if (response.errors && response.errors.length > 0) { + const stringified = JSON.stringify( + response.errors.map(e => { + if (e && typeof e === 'object') { + return { + message: (e as unknown as { message: string }).message, + code: (e as unknown as { code?: unknown }).code + }; + } + return e; + }) + ); + const failureResponse: DataConnectOperationFailureResponse = { + errors: response.errors as [], + data: response.data as Record + }; + const error = new DataConnectOperationError( + 'DataConnect error received from subscribe notification: ' + + stringified, + failureResponse + ); + this.publishErrorToSubscribers(key, error); + return; + } + + const fetchTime = Date.now().toString(); + const queryResult: QueryResult = { + ref: queryRef, + source: SOURCE_SERVER, + fetchTime, + data: response.data, + extensions: getDataConnectExtensionsWithoutMaxAge(response.extensions), + toJSON: getRefSerializer( + queryRef, + response.data, + SOURCE_SERVER, + fetchTime + ) + }; + const updatedKeys = await this.updateCache( + queryResult, + response.extensions?.dataConnect + ); + this.publishDataToSubscribers(key, queryResult); + if (this.cache) { + await this.publishCacheResultsToSubscribers(updatedKeys, fetchTime); + } + } + + /** + * Handle a disconnect from the stream. Unsubscribe all callbacks for the given key. + */ + private handleStreamDisconnect( + key: string, + code: string, + reason: string + ): void { + const error = new DataConnectError(code as Code, reason); + this.publishErrorToSubscribers(key, error); + + const callbacks = this.callbacks.get(key); + if (callbacks) { + [...callbacks].forEach(cb => cb.unsubscribe()); + } + return; + } } export function getMaxAgeFromExtensions( diff --git a/packages/data-connect/src/index.node.ts b/packages/data-connect/src/index.node.ts index 0a4970e485..9433fa43b5 100644 --- a/packages/data-connect/src/index.node.ts +++ b/packages/data-connect/src/index.node.ts @@ -15,11 +15,21 @@ * limitations under the License. */ -import { initializeFetch } from './network/fetch'; +import { initializeFetch } from './network/rest'; +import { initializeWebSocket } from './network/stream/websocket'; import { registerDataConnect } from './register'; export * from './api'; export * from './api.node'; + initializeFetch(fetch); +if (typeof WebSocket !== 'undefined') { + initializeWebSocket(WebSocket); +} else { + console.warn( + 'WebSocket is not available in this environment. Use a polyfill or upgrade your Node version to one that supports WebSockets.' + ); +} + registerDataConnect('node'); diff --git a/packages/data-connect/src/network/index.ts b/packages/data-connect/src/network/index.ts index 72dcdb1d0c..33a2202d57 100644 --- a/packages/data-connect/src/network/index.ts +++ b/packages/data-connect/src/network/index.ts @@ -15,13 +15,4 @@ * limitations under the License. */ -export { - CallerSdkType, - CallerSdkTypeEnum, - DataConnectTransport, - DataConnectEntityArray, - DataConnectSingleEntity, - DataConnectExtension, - Extensions, - TransportClass -} from './transport'; +export * from './transport'; diff --git a/packages/data-connect/src/network/manager.ts b/packages/data-connect/src/network/manager.ts new file mode 100644 index 0000000000..6b8c6179e8 --- /dev/null +++ b/packages/data-connect/src/network/manager.ts @@ -0,0 +1,200 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DataConnectOptions, TransportOptions } from '../api/DataConnect'; +import { AppCheckTokenProvider } from '../core/AppCheckTokenProvider'; +import { Code, DataConnectError } from '../core/error'; +import { AuthTokenProvider } from '../core/FirebaseAuthProvider'; + +import { RESTTransport } from './rest'; +import { AbstractDataConnectStreamTransport } from './stream/streamTransport'; +import { WebSocketTransport } from './stream/websocket'; +import { + CallerSdkType, + DataConnectResponse, + DataConnectResponseWithMaxAge, + DataConnectTransportInterface, + SubscribeObserver +} from './transport'; + +/** + * Entry point for the transport layer. Manages routing between transport implementations. + * @internal + */ +export class DataConnectTransportManager + implements DataConnectTransportInterface +{ + private restTransport: RESTTransport; + private streamTransport?: AbstractDataConnectStreamTransport; + private isUsingEmulator = false; + + constructor( + private options: DataConnectOptions, + private apiKey?: string, + private appId?: string | null, + private authProvider?: AuthTokenProvider, + private appCheckProvider?: AppCheckTokenProvider, + private transportOptions?: TransportOptions, + private _isUsingGen = false, + private _callerSdkType?: CallerSdkType + ) { + this.restTransport = new RESTTransport( + options, + apiKey, + appId, + authProvider, + appCheckProvider, + transportOptions, + _isUsingGen, + _callerSdkType + ); + } + + /** + * Initializes the stream transport if it hasn't been already. + */ + private initStreamTransport(): AbstractDataConnectStreamTransport { + if (!this.streamTransport) { + this.streamTransport = new WebSocketTransport( + this.options, + this.apiKey, + this.appId, + this.authProvider, + this.appCheckProvider, + this.transportOptions, + this._isUsingGen, + this._callerSdkType + ); + if (this.isUsingEmulator && this.transportOptions) { + this.streamTransport.useEmulator( + this.transportOptions.host!, + this.transportOptions.port, + this.transportOptions.sslEnabled + ); + } + this.streamTransport.onGracefulStreamClose = () => { + this.streamTransport = undefined; + }; + } + return this.streamTransport; + } + + /** + * Returns true if the stream is in a healthy, ready connection state and has active subscriptions. + */ + private executeShouldUseStream(): boolean { + return ( + !!this.streamTransport && + !this.streamTransport.isPendingClose && + this.streamTransport.streamIsReady && + this.streamTransport.hasActiveSubscriptions && + !this.streamTransport.isUnableToConnect + ); + } + + /** + * Prefer to use Streaming Transport connection when one is available. + * @inheritdoc + */ + invokeQuery( + queryName: string, + body?: Variables + ): Promise> { + if (this.executeShouldUseStream()) { + return this.streamTransport!.invokeQuery( + queryName, + body + ).catch(err => { + if (this.executeShouldUseStream()) { + throw err; + } + return this.restTransport.invokeQuery(queryName, body); + }); + } + return this.restTransport.invokeQuery(queryName, body); + } + + /** + * Prefer to use Streaming Transport connection when one is available. + * @inheritdoc + */ + invokeMutation( + queryName: string, + body?: Variables + ): Promise> { + if (this.executeShouldUseStream()) { + return this.streamTransport!.invokeMutation( + queryName, + body + ).catch(err => { + if (this.executeShouldUseStream()) { + throw err; + } + return this.restTransport.invokeMutation( + queryName, + body + ); + }); + } + return this.restTransport.invokeMutation(queryName, body); + } + + invokeSubscribe( + observer: SubscribeObserver, + queryName: string, + body?: Variables + ): void { + const streamTransport = this.initStreamTransport(); + if (streamTransport.isUnableToConnect) { + throw new DataConnectError( + Code.OTHER, + 'Unable to connect streaming connection to server. Subscriptions are unavailable.' + ); + } + streamTransport.invokeSubscribe(observer, queryName, body); + } + + invokeUnsubscribe(queryName: string, body?: Variables): void { + if (this.streamTransport) { + this.streamTransport.invokeUnsubscribe(queryName, body); + } + } + + useEmulator(host: string, port?: number, sslEnabled?: boolean): void { + this.isUsingEmulator = true; + this.transportOptions = { host, port, sslEnabled }; + this.restTransport.useEmulator(host, port, sslEnabled); + if (this.streamTransport) { + this.streamTransport.useEmulator(host, port, sslEnabled); + } + } + + onAuthTokenChanged(token: string | null): void { + this.restTransport.onAuthTokenChanged(token); + if (this.streamTransport) { + this.streamTransport.onAuthTokenChanged(token); + } + } + + _setCallerSdkType(callerSdkType: CallerSdkType): void { + this._callerSdkType = callerSdkType; + this.restTransport._setCallerSdkType(callerSdkType); + if (this.streamTransport) { + this.streamTransport._setCallerSdkType(callerSdkType); + } + } +} diff --git a/packages/data-connect/src/network/fetch.ts b/packages/data-connect/src/network/rest/fetch.ts similarity index 74% rename from packages/data-connect/src/network/fetch.ts rename to packages/data-connect/src/network/rest/fetch.ts index ee9bae4826..783e999388 100644 --- a/packages/data-connect/src/network/fetch.ts +++ b/packages/data-connect/src/network/rest/fetch.ts @@ -17,26 +17,33 @@ import { isCloudWorkstation } from '@firebase/util'; +import { + CallerSdkType, + CallerSdkTypeEnum, + DataConnectResponse, + Extensions +} from '..'; import { Code, DataConnectError, DataConnectOperationError, DataConnectOperationFailureResponse -} from '../core/error'; -import { SDK_VERSION } from '../core/version'; -import { logError } from '../logger'; - -import { - CallerSdkType, - CallerSdkTypeEnum, - Extensions, - DataConnectResponse -} from './transport'; +} from '../../core/error'; +import { SDK_VERSION } from '../../core/version'; +import { logError } from '../../logger'; +/** The fetch implementation to be used by the {@link RESTTransport}. */ let connectFetch: typeof fetch | null = globalThis.fetch; + +/** + * This function is ONLY used for testing and for ensuring compatability in environments which may + * be using a poyfill and/or bundlers. It should not be called by users of the Firebase JS SDK. + * @internal + */ export function initializeFetch(fetchImpl: typeof fetch): void { connectFetch = fetchImpl; } + function getGoogApiClientValue( _isUsingGen: boolean, _callerSdkType: CallerSdkType @@ -52,14 +59,14 @@ function getGoogApiClientValue( } return str; } -export interface DataConnectFetchBody { +export interface DataConnectFetchBody { name: string; operationName: string; - variables: T; + variables: Variables; } -export async function dcFetch( +export async function dcFetch( url: string, - body: DataConnectFetchBody, + body: DataConnectFetchBody, { signal }: AbortController, appId: string | null | undefined, accessToken: string | null, @@ -67,7 +74,7 @@ export async function dcFetch( _isUsingGen: boolean, _callerSdkType: CallerSdkType, _isUsingEmulator: boolean -): Promise> { +): Promise> { if (!connectFetch) { throw new DataConnectError(Code.OTHER, 'No Fetch Implementation detected!'); } @@ -99,16 +106,24 @@ export async function dcFetch( try { response = await connectFetch(url, fetchOptions); } catch (err) { - throw new DataConnectError( - Code.OTHER, - 'Failed to fetch: ' + JSON.stringify(err) - ); + const message = + err && typeof err === 'object' && 'message' in err + ? (err as unknown as Record)['message'] + : String(err); + throw new DataConnectError(Code.OTHER, 'Failed to fetch: ' + message); } - let jsonResponse: JsonResponse; + let jsonResponse: JsonResponse; try { jsonResponse = await response.json(); } catch (e) { - throw new DataConnectError(Code.OTHER, JSON.stringify(e)); + const message = + e && typeof e === 'object' && 'message' in e + ? (e as unknown as Record)['message'] + : String(e); + throw new DataConnectError( + Code.OTHER, + 'Failed to parse JSON response: ' + message + ); } const message = getErrorMessage(jsonResponse); if (response.status >= 400) { @@ -134,12 +149,12 @@ export async function dcFetch( dataConnect: [] }; } - return jsonResponse as DataConnectResponse; + return jsonResponse as DataConnectResponse; } -interface JsonResponse { +interface JsonResponse { message?: string; errors: []; - data: Record | T | null; + data: Record | Data | null; extensions?: Extensions; } function getErrorMessage(obj: JsonResponse): string { diff --git a/packages/data-connect/src/network/rest/index.ts b/packages/data-connect/src/network/rest/index.ts new file mode 100644 index 0000000000..1074e76dd3 --- /dev/null +++ b/packages/data-connect/src/network/rest/index.ts @@ -0,0 +1,19 @@ +/** + * @license + * Copyright 2026 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. + */ + +export * from './fetch'; +export * from './restTransport'; diff --git a/packages/data-connect/src/network/rest/restTransport.ts b/packages/data-connect/src/network/rest/restTransport.ts new file mode 100644 index 0000000000..6769b10faf --- /dev/null +++ b/packages/data-connect/src/network/rest/restTransport.ts @@ -0,0 +1,159 @@ +/** + * @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. + */ + +import { + CallerSdkType, + CallerSdkTypeEnum, + DataConnectResponse, + DataConnectResponseWithMaxAge, + AbstractDataConnectTransport, + SubscribeObserver +} from '..'; +import { DataConnectOptions, TransportOptions } from '../../api/DataConnect'; +import { AppCheckTokenProvider } from '../../core/AppCheckTokenProvider'; +import { Code, DataConnectError } from '../../core/error'; +import { AuthTokenProvider } from '../../core/FirebaseAuthProvider'; +import { addToken, restUrlBuilder } from '../../util/url'; + +import { dcFetch } from './fetch'; + +/** + * Fetch-based REST implementation of {@link AbstractDataConnectTransport}. + * @internal + */ +export class RESTTransport extends AbstractDataConnectTransport { + constructor( + options: DataConnectOptions, + apiKey?: string | undefined, + appId?: string | null, + authProvider?: AuthTokenProvider | undefined, + appCheckProvider?: AppCheckTokenProvider | undefined, + transportOptions?: TransportOptions | undefined, + _isUsingGen = false, + _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base + ) { + super( + options, + apiKey, + appId, + authProvider, + appCheckProvider, + transportOptions, + _isUsingGen, + _callerSdkType + ); + } + + get endpointUrl(): string { + return restUrlBuilder( + { + connector: this._connectorName, + location: this._location, + projectId: this._project, + service: this._serviceName + }, + { + host: this._host, + sslEnabled: this._secure, + port: this._port + } + ); + } + + invokeQuery: ( + queryName: string, + body?: Variables + ) => Promise> = < + Data, + Variables = unknown + >( + queryName: string, + body: Variables + ) => { + const abortController = new AbortController(); + + // TODO(mtewani): Update to proper value + const withAuth = this.withRetry(() => + dcFetch( + addToken(`${this.endpointUrl}:executeQuery`, this.apiKey), + { + name: this._connectorResourcePath, + operationName: queryName, + variables: body + }, + abortController, + this.appId, + this._authToken, + this._appCheckToken, + this._isUsingGen, + this._callerSdkType, + this._isUsingEmulator + ) + ); + return withAuth; + }; + + invokeMutation: ( + queryName: string, + body?: Variables + ) => Promise> = ( + mutationName: string, + body: Variables + ) => { + const abortController = new AbortController(); + const taskResult = this.withRetry(() => { + return dcFetch( + addToken(`${this.endpointUrl}:executeMutation`, this.apiKey), + { + name: this._connectorResourcePath, + operationName: mutationName, + variables: body + }, + abortController, + this.appId, + this._authToken, + this._appCheckToken, + this._isUsingGen, + this._callerSdkType, + this._isUsingEmulator + ); + }); + return taskResult; + }; + + invokeSubscribe( + observer: SubscribeObserver, + queryName: string, + body?: Variables + ): void { + throw new DataConnectError( + Code.NOT_SUPPORTED, + 'Subscriptions are not supported using REST!' + ); + } + + invokeUnsubscribe(queryName: string, body?: Variables): void { + throw new DataConnectError( + Code.NOT_SUPPORTED, + 'Unsubscriptions are not supported using REST!' + ); + } + + onAuthTokenChanged(newToken: string | null): void { + this._authToken = newToken; + } +} diff --git a/packages/data-connect/src/network/stream/streamTransport.ts b/packages/data-connect/src/network/stream/streamTransport.ts new file mode 100644 index 0000000000..2028bf44b2 --- /dev/null +++ b/packages/data-connect/src/network/stream/streamTransport.ts @@ -0,0 +1,710 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Code, + DataConnectError, + DataConnectOperationError, + DataConnectOperationFailureResponse +} from '../../core/error'; +import { logError } from '../../logger'; +import { + AbstractDataConnectTransport, + DataConnectResponse, + SubscribeObserver, + getGoogApiClientValue +} from '../transport'; + +import { + CancelStreamRequest, + DataConnectStreamRequest, + ExecuteStreamRequest, + ResumeStreamRequest, + StreamRequestHeaders, + SubscribeStreamRequest +} from './wire'; + +/** The request id of the first request over the stream */ +const FIRST_REQUEST_ID = 1; + +/** Time to wait before closing an idle connection (no active subscriptions) */ +const IDLE_CONNECTION_TIMEOUT_MS = 60 * 1000; // 1 minute + +/** + * A promise that is settled for a request is received, and the functions that resolve or reject it. + */ +interface TrackedExecuteRequestPromise { + responsePromise: Promise>; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + resolveFn: (data: any) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + rejectFn: (err: any) => void; +} + +/** + * The base class for all {@link DataConnectStreamTransport | Stream Transport} implementations. + * Handles management of logical streams (requests), authentication, data routing to query layer, etc. + * @internal + */ +export abstract class AbstractDataConnectStreamTransport extends AbstractDataConnectTransport { + /** Optional callback invoked when the stream closes gracefully. */ + onGracefulStreamClose?: () => void; + + /** True if the physical stream connection is fully open and ready to transmit data. */ + abstract get streamIsReady(): boolean; + + /** Is the stream currently waiting to close connection? */ + get isPendingClose(): boolean { + return this.pendingClose; + } + private pendingClose = false; + + /** True if the transport is unable to connect to the server */ + isUnableToConnect = false; + + /** True if there are active subscriptions on the stream */ + get hasActiveSubscriptions(): boolean { + return this.activeSubscribeRequests.size > 0; + } + + /** True if there are active execute or mutation requests on the stream */ + get hasActiveExecuteRequests(): boolean { + return ( + this.activeQueryExecuteRequests.size > 0 || + this.activeMutationExecuteRequests.size > 0 + ); + } + + /** + * Open a physical connection to the server. + * @returns a promise which resolves when the connection is ready, or rejects if it fails to open. + */ + protected abstract openConnection(): Promise; + + /** + * Close the physical connection with the server. Handles no cleanup - simply closes the + * implementation-specific connection. + * @returns a promise which resolves when the connection is closed, or rejects if it fails to close. + * On failure to close, the connection is still considered closed. + */ + protected abstract closeConnection(): Promise; + + /** + * Queue a message to be sent over the stream. + * @param requestBody The body of the message to be sent. + * @throws DataConnectError if sending fails. + */ + protected abstract sendMessage( + requestBody: DataConnectStreamRequest + ): Promise; + + /** + * Ensures that that there is an open connection. If there is none, it initiates a new one. + * If a connection attempt is already in progress, it returns the existing connection promise. + * @returns A promise that resolves when the stream is open and ready. + */ + protected abstract ensureConnection(): Promise; + + /** The request ID of the next message to be sent. Monotonically increasing sequence number. */ + private requestNumber = FIRST_REQUEST_ID; + /** + * Generates and returns the next request ID. + */ + private nextRequestId(): string { + return (this.requestNumber++).toString(); + } + + /** + * Map of query/variables to their active execute/resume request bodies. + */ + private activeQueryExecuteRequests = new Map< + string, + ExecuteStreamRequest | ResumeStreamRequest + >(); + + /** + * Map of mutation/variables to their active execute request bodies. + */ + private activeMutationExecuteRequests = new Map< + string, + Array> + >(); + + /** + * Map of query/variables to their active subscribe request bodies. + */ + private activeSubscribeRequests = new Map< + string, + SubscribeStreamRequest + >(); + + /** + * Map of active execution RequestIds and their corresponding Promises and resolvers. + */ + private executeRequestPromises = new Map< + string, + TrackedExecuteRequestPromise + >(); + + /** + * Map of active subscription RequestIds and their corresponding observers. + */ + private subscribeObservers = new Map>(); + + /** current close timeout from setTimeout(), if any */ + private closeTimeout: NodeJS.Timeout | null = null; + /** has the close timeout finished? */ + private closeTimeoutFinished = false; + /** current auth uid. used to detect if a different user logs in */ + private authUid: string | null | undefined; + + /** + * Tracks a query execution request, storing the request body and creating and storing a promise that + * will be resolved when the response is received. + * @returns The reject function and the response promise. + * + * @remarks + * This method returns a promise, but is synchronous. + */ + private trackQueryExecuteRequest( + requestId: string, + mapKey: string, + executeBody: ExecuteStreamRequest + ): TrackedExecuteRequestPromise { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let resolveFn: (data: any) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let rejectFn: (err: any) => void; + const responsePromise = new Promise>( + (resolve, reject) => { + resolveFn = resolve; + rejectFn = reject; + } + ); + const executeRequestPromise: TrackedExecuteRequestPromise = { + responsePromise, + resolveFn: resolveFn!, + rejectFn: rejectFn! + }; + + this.activeQueryExecuteRequests.set(mapKey, executeBody); + this.executeRequestPromises.set(requestId, executeRequestPromise); + + return executeRequestPromise; + } + + /** + * Tracks a mutation execution request, storing the request body and creating and storing a promise + * that will be resolved when the response is received. + * @returns The reject function and the response promise. + * + * @remarks + * This method returns a promise, but is synchronous. + */ + private trackMutationExecuteRequest( + requestId: string, + mapKey: string, + executeBody: ExecuteStreamRequest + ): TrackedExecuteRequestPromise { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let resolveFn: (data: any) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let rejectFn: (err: any) => void; + const responsePromise = new Promise>( + (resolve, reject) => { + resolveFn = resolve; + rejectFn = reject; + } + ); + const executeRequestPromise: TrackedExecuteRequestPromise = { + responsePromise, + resolveFn: resolveFn!, + rejectFn: rejectFn! + }; + + const activeRequests = this.activeMutationExecuteRequests.get(mapKey) || []; + activeRequests.push(executeBody); + this.activeMutationExecuteRequests.set(mapKey, activeRequests); + this.executeRequestPromises.set(requestId, executeRequestPromise); + + return executeRequestPromise; + } + + /** + * Tracks a subscribe request, storing the request body and the notification observer. + * @remarks + * This method is synchronous. + */ + private trackSubscribeRequest( + requestId: string, + mapKey: string, + subscribeBody: SubscribeStreamRequest, + observer: SubscribeObserver + ): void { + this.activeSubscribeRequests.set(mapKey, subscribeBody); + this.subscribeObservers.set( + requestId, + observer as SubscribeObserver + ); + } + + /** + * Cleans up the query execute request tracking data structures, deleting the tracked request and + * it's associated promise. + */ + private cleanupQueryExecuteRequest(requestId: string, mapKey: string): void { + this.activeQueryExecuteRequests.delete(mapKey); + this.executeRequestPromises.delete(requestId); + } + + /** + * Cleans up the mutation execute request tracking data structures, deleting the tracked request and + * it's associated promise. + */ + private cleanupMutationExecuteRequest( + requestId: string, + mapKey: string + ): void { + const executeRequests = this.activeMutationExecuteRequests.get(mapKey); + if (executeRequests) { + const updatedRequests = executeRequests.filter( + req => req.requestId !== requestId + ); + if (updatedRequests.length > 0) { + this.activeMutationExecuteRequests.set(mapKey, updatedRequests); + } else { + this.activeMutationExecuteRequests.delete(mapKey); + } + } + this.executeRequestPromises.delete(requestId); + } + + /** + * Cleans up the subscribe request tracking data structures, deleting the tracked request and + * it's associated promise. + */ + private cleanupSubscribeRequest(requestId: string, mapKey: string): void { + this.activeSubscribeRequests.delete(mapKey); + this.subscribeObservers.delete(requestId); + } + + /** + * Tracks if the next message to be sent is the first message of the stream. + */ + private isFirstStreamMessage = true; + /** + * Tracks the last auth token sent to the server. + * Used to detect if the token has changed and needs to be resent. + */ + private lastSentAuthToken: string | null = null; + /** + * Indicates whether we should include the auth token in the next message. + * Only true if there is an auth token and it is different from the last sent auth token, or this + * is the first message. + */ + private get shouldIncludeAuth(): boolean { + return ( + this.isFirstStreamMessage || + (!!this._authToken && this._authToken !== this.lastSentAuthToken) + ); + } + + /** + * Called by the concrete transport implementation when the physical connection is ready. + */ + protected onConnectionReady(): void { + this.isFirstStreamMessage = true; + this.lastSentAuthToken = null; + } + + /** + * Attempt to close the connection. Will only close if there are no active requests preventing it + * from doing so. + */ + private async attemptClose(): Promise { + if (this.hasActiveSubscriptions || this.hasActiveExecuteRequests) { + return; + } + this.cancelClose(); + await this.closeConnection(); + this.onGracefulStreamClose?.(); + } + + /** + * Begin closing the connection. Waits for and cleans up all active requests, and waits for + * {@link IDLE_CONNECTION_TIMEOUT_MS}. This is a graceful close - it will be called when there are + * no more active subscriptions, so there's no need to cleanup. + */ + private prepareToCloseGracefully(): void { + if (this.pendingClose) { + return; + } + this.pendingClose = true; + this.closeTimeoutFinished = false; + this.closeTimeout = setTimeout(() => { + this.closeTimeoutFinished = true; + void this.attemptClose(); + }, IDLE_CONNECTION_TIMEOUT_MS); + } + + /** + * Cancel closing the connection. + */ + private cancelClose(): void { + if (this.closeTimeout) { + clearTimeout(this.closeTimeout); + } + this.pendingClose = false; + this.closeTimeoutFinished = false; + } + + /** + * Reject all active execute promises and notify all subscribe observers with the given error. + * Clear active request tracking maps without cancelling or re-invoking any requests. + */ + private rejectAllActiveRequests(code: Code, reason: string): void { + this.activeQueryExecuteRequests.clear(); + this.activeMutationExecuteRequests.clear(); + this.activeSubscribeRequests.clear(); + + const error = new DataConnectError(code, reason); + for (const [requestId, { rejectFn }] of this.executeRequestPromises) { + this.executeRequestPromises.delete(requestId); + rejectFn(error); + } + + for (const [requestId, observer] of this.subscribeObservers) { + this.subscribeObservers.delete(requestId); + observer.onDisconnect(code, reason); + } + } + + /** + * Called by concrete implementations when the stream is successfully closed, gracefully or otherwise. + */ + protected onStreamClose(code: number, reason: string): void { + this.rejectAllActiveRequests( + Code.OTHER, + `Stream disconnected with code ${code}: ${reason}` + ); + } + + /** + * Prepares a stream request message by adding necessary headers and metadata. + * If this is the first message on the stream, it includes the resource name, auth token, and App Check token. + * If the auth token has refreshed since the last message, it includes the new auth token. + * + * This method is called by the concrete transport implementation before sending a message. + * + * @returns the requestBody, with attached headers and initial request fields + */ + protected prepareMessage< + Variables, + StreamBody extends DataConnectStreamRequest + >(requestBody: StreamBody): StreamBody { + const preparedRequestBody: StreamBody = { ...requestBody }; + const headers: StreamRequestHeaders = {}; + if (this.appId) { + headers['x-firebase-gmpid'] = this.appId; + } + headers['X-Goog-Api-Client'] = getGoogApiClientValue( + this._isUsingGen, + this._callerSdkType + ); + if (this.shouldIncludeAuth && this._authToken) { + headers.authToken = this._authToken; + this.lastSentAuthToken = this._authToken; + } + if (this.isFirstStreamMessage) { + if (this._appCheckToken) { + headers.appCheckToken = this._appCheckToken; + } + preparedRequestBody.name = this._connectorResourcePath; + } + preparedRequestBody.headers = headers; + this.isFirstStreamMessage = false; + return preparedRequestBody; + } + + /** + * Sends a request message to the server via the concrete implementation. + * Ensures the connection is ready and prepares the message before sending. + * @returns A promise that resolves when the request message has been sent. + */ + private sendRequestMessage( + requestBody: DataConnectStreamRequest + ): Promise { + if (this.streamIsReady) { + const prepared = this.prepareMessage(requestBody); + return this.sendMessage(prepared); + } + return this.ensureConnection().then(() => { + const prepared = this.prepareMessage(requestBody); + return this.sendMessage(prepared); + }); + } + + /** + * Helper to generate a consistent string key for the tracking maps. + */ + private getMapKey(operationName: string, variables?: unknown): string { + const sortedVariables = this.sortObjectKeys(variables); + return JSON.stringify({ operationName, variables: sortedVariables }); + } + + /** + * Recursively sorts the keys of an object. + */ + private sortObjectKeys(obj: unknown): unknown { + if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) { + return obj; + } + const sortedObj: Record = {}; + Object.keys(obj as Record) + .sort() + .forEach(key => { + sortedObj[key] = this.sortObjectKeys( + (obj as Record)[key] + ); + }); + return sortedObj; + } + + /** + * @inheritdoc + * @remarks + * This method synchronously updates the request tracking data structures before sending any message. + * If any asynchronous functionality is added to this function, it MUST be done in a way that + * preserves the synchronous update of the tracking data structures before the method returns. + */ + invokeQuery( + queryName: string, + variables?: Variables + ): Promise> { + const requestId = this.nextRequestId(); + const activeRequestKey = { operationName: queryName, variables }; + const mapKey = this.getMapKey(queryName, variables); + const executeBody: ExecuteStreamRequest = { + requestId, + execute: activeRequestKey + }; + + let { responsePromise, rejectFn } = this.trackQueryExecuteRequest( + requestId, + mapKey, + executeBody + ); + responsePromise = responsePromise.finally(() => { + this.cleanupQueryExecuteRequest(requestId, mapKey); + if ( + !this.hasActiveSubscriptions && + !this.hasActiveExecuteRequests && + this.closeTimeoutFinished + ) { + void this.attemptClose(); + } + }); + + // asynchronous, fire and forget + this.sendRequestMessage(executeBody).catch(err => { + rejectFn(err); + }); + return responsePromise; + } + + /** + * @inheritdoc + * @remarks + * This method synchronously updates the request tracking data structures before sending any message. + * If any asynchronous functionality is added to this function, it MUST be done in a way that + * preserves the synchronous update of the tracking data structures before the method returns. + */ + invokeMutation( + mutationName: string, + variables?: Variables + ): Promise> { + const requestId = this.nextRequestId(); + const activeRequestKey = { operationName: mutationName, variables }; + const mapKey = this.getMapKey(mutationName, variables); + const executeBody: ExecuteStreamRequest = { + requestId, + execute: activeRequestKey + }; + + let { responsePromise, rejectFn } = this.trackMutationExecuteRequest( + requestId, + mapKey, + executeBody + ); + responsePromise = responsePromise.finally(() => { + this.cleanupMutationExecuteRequest(requestId, mapKey); + if ( + !this.hasActiveSubscriptions && + !this.hasActiveExecuteRequests && + this.closeTimeoutFinished + ) { + void this.attemptClose(); + } + }); + + // asynchronous, fire and forget + this.sendRequestMessage(executeBody).catch(err => { + rejectFn(err); + }); + return responsePromise; + } + + /** + * @inheritdoc + * @remarks + * This method synchronously updates the request tracking data structures before sending any message + * or cancelling the closing of the stream. If any asynchronous functionality is added to this function, + * it MUST be done in a way that preserves the synchronous update of the tracking data structures + * before the method returns. + */ + invokeSubscribe( + observer: SubscribeObserver, + queryName: string, + variables: Variables + ): void { + // if we are waiting to close the stream, cancel closing! + this.cancelClose(); + + const requestId = this.nextRequestId(); + const activeRequestKey = { operationName: queryName, variables }; + const mapKey = this.getMapKey(queryName, variables); + const subscribeBody: SubscribeStreamRequest = { + requestId, + subscribe: activeRequestKey + }; + + this.trackSubscribeRequest( + requestId, + mapKey, + subscribeBody, + observer + ); + + // asynchronous, fire and forget + this.sendRequestMessage(subscribeBody).catch(err => { + observer.onError(err instanceof Error ? err : new Error(String(err))); + this.cleanupSubscribeRequest(requestId, mapKey); + if (!this.hasActiveSubscriptions) { + this.prepareToCloseGracefully(); + } + }); + } + + /** + * @inheritdoc + * @remarks + * This method synchronously updates the request tracking data structures before sending any message. + * If any asynchronous functionality is added to this function, it MUST be done in a way that + * preserves the synchronous update of the tracking data structures before the method returns. + */ + invokeUnsubscribe(queryName: string, variables: Variables): void { + const mapKey = this.getMapKey(queryName, variables); + const subscribeRequest = this.activeSubscribeRequests.get(mapKey); + if (!subscribeRequest) { + return; + } + const requestId = subscribeRequest.requestId; + const cancelBody: CancelStreamRequest = { + requestId, + cancel: {} + }; + + this.cleanupSubscribeRequest(requestId, mapKey); + + // asynchronous, fire and forget + this.sendRequestMessage(cancelBody).catch(err => { + logError(`Stream Transport failed to send unsubscribe message: ${err}`); + }); + + if (!this.hasActiveSubscriptions) { + this.prepareToCloseGracefully(); + } + } + + onAuthTokenChanged(newToken: string | null): void { + const oldAuthToken = this._authToken; + this._authToken = newToken; + + const oldAuthUid = this.authUid; + const newAuthUid = this.authProvider?.getAuth()?.getUid(); + this.authUid = newAuthUid; + + // onAuthTokenChanged gets called by the auth provider once it initializes, so we must make sure + // we don't prematurely disconnect the stream if this is the initial call. + const isInitialAuth = oldAuthUid === undefined; + if (isInitialAuth) { + return; + } + + if ( + (oldAuthToken && newToken === null) || // user logged out + (!oldAuthUid && newAuthUid) || // user logged in + (oldAuthUid && newAuthUid !== oldAuthUid) // logged in user changed + ) { + this.rejectAllActiveRequests( + Code.UNAUTHORIZED, + 'Stream disconnected due to auth change.' + ); + void this.attemptClose(); + } + } + + /** + * Handle a response message from the server. Called by the connection-specific implementation after + * it's transformed a message from the server into a {@link DataConnectResponse}. + * @param requestId the requestId associated with this response. + * @param response the response from the server. + */ + protected async handleResponse( + requestId: string, + response: DataConnectResponse + ): Promise { + if (this.executeRequestPromises.has(requestId)) { + // don't clean up the tracking maps here, they're handled automatically when the execute promise settles + const { resolveFn, rejectFn } = + this.executeRequestPromises.get(requestId)!; + if (response.errors && response.errors.length) { + const failureResponse: DataConnectOperationFailureResponse = { + errors: response.errors as [], + data: response.data as Record + }; + const stringified = JSON.stringify(response.errors); + rejectFn( + new DataConnectOperationError( + 'DataConnect error while performing request: ' + stringified, + failureResponse + ) + ); + } else { + resolveFn(response); + } + } else if (this.subscribeObservers.has(requestId)) { + const observer = this.subscribeObservers.get(requestId)!; + await observer.onData(response); + } else { + throw new DataConnectError( + Code.OTHER, + `Stream response contained unrecognized requestId '${requestId}'` + ); + } + } +} diff --git a/packages/data-connect/src/network/stream/websocket.ts b/packages/data-connect/src/network/stream/websocket.ts new file mode 100644 index 0000000000..a7f08d55af --- /dev/null +++ b/packages/data-connect/src/network/stream/websocket.ts @@ -0,0 +1,341 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DataConnectOptions, TransportOptions } from '../../api/DataConnect'; +import { AppCheckTokenProvider } from '../../core/AppCheckTokenProvider'; +import { Code, DataConnectError } from '../../core/error'; +import { AuthTokenProvider } from '../../core/FirebaseAuthProvider'; +import { logError } from '../../logger'; +import { websocketUrlBuilder } from '../../util/url'; +import { + CallerSdkType, + CallerSdkTypeEnum, + DataConnectResponse +} from '../transport'; + +import { AbstractDataConnectStreamTransport } from './streamTransport'; +import { DataConnectStreamRequest, DataConnectStreamResponse } from './wire'; + +/** The WebSocket implementation to be used by the {@link WebSocketTransport}. */ +let connectWebSocket: typeof WebSocket | null = globalThis.WebSocket; + +/** + * This function is ONLY used for testing and for ensuring compatability in environments which may + * be using a poyfill and/or bundlers. It should not be called by users of the Firebase JS SDK. + * @internal + */ +export function initializeWebSocket(webSocketImpl: typeof WebSocket): void { + connectWebSocket = webSocketImpl; +} + +/** + * The code used to close the WebSocket connection. + * This is a protocol-level code, and is not the same as the {@link Code | DataConnect error code}. + * @internal + */ +export const WEBSOCKET_CLOSE_CODE = 1000; + +/** + * An {@link AbstractDataConnectStreamTransport | Stream Transport} implementation that uses {@link WebSocket | WebSockets} to stream requests and responses. + * This class handles the lifecycle of the WebSocket connection, including automatic + * reconnection and request correlation. + * @internal + */ +export class WebSocketTransport extends AbstractDataConnectStreamTransport { + get endpointUrl(): string { + return websocketUrlBuilder( + { + connector: this._connectorName, + location: this._location, + projectId: this._project, + service: this._serviceName + }, + { + host: this._host, + sslEnabled: this._secure, + port: this._port + } + ); + } + + /** Decodes binary WebSocket responses to strings */ + private decoder: TextDecoder | undefined = undefined; + + /** + * Decodes a WebSocket response from a Uint8Array to a JSON object. + * Emulator does not send messages as Uint8Arrays, but prod does. + */ + private decodeBinaryResponse(data: ArrayBuffer): string { + if (!this.decoder) { + this.decoder = new TextDecoder('utf-8'); + } + return this.decoder.decode(data); + } + + /** The current connection to the server. Undefined if disconnected. */ + private connection: WebSocket | undefined = undefined; + + get streamIsReady(): boolean { + return this.connection?.readyState === WebSocket.OPEN; + } + + /** + * Current connection attempt. If null, we are not currently attemping to connect (not connected, + * or already connected). Will be resolved or rejected when the connection is opened or fails to open. + */ + private connectionAttempt: Promise | null = null; + + constructor( + options: DataConnectOptions, + protected apiKey?: string | undefined, + protected appId?: string | null, + protected authProvider?: AuthTokenProvider | undefined, + protected appCheckProvider?: AppCheckTokenProvider | undefined, + transportOptions?: TransportOptions | undefined, + protected _isUsingGen = false, + protected _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base + ) { + super( + options, + apiKey, + appId, + authProvider, + appCheckProvider, + transportOptions, + _isUsingGen, + _callerSdkType + ); + } + + protected ensureConnection(): Promise { + try { + if (this.streamIsReady) { + return Promise.resolve(); + } + if (this.connectionAttempt) { + return this.connectionAttempt; + } + this.connectionAttempt = new Promise((resolve, reject) => { + if (!connectWebSocket) { + throw new DataConnectError( + Code.OTHER, + 'No WebSocket Implementation detected!' + ); + } + const ws = new connectWebSocket(this.endpointUrl); + this.connection = ws; + this.connection!.binaryType = 'arraybuffer'; + + ws.onopen = () => { + this.isUnableToConnect = false; + this.onConnectionReady(); + resolve(); + }; + + ws.onerror = event => { + this.connectionAttempt = null; + this.isUnableToConnect = true; + const error = new DataConnectError( + Code.OTHER, + `Error using WebSocket connection, closing WebSocket` + ); + this.handleError(error); + reject(error); + }; + + ws.onmessage = ev => + this.handleWebSocketMessage(ev).catch(async reason => { + this.handleError(reason); + }); + + ws.onclose = ev => this.handleWebsocketDisconnect(ev); + }); + + return this.connectionAttempt; + } catch (error) { + this.handleError(error); + throw error; + } + } + + protected openConnection(): Promise { + return this.ensureConnection().catch(err => { + throw new DataConnectError( + Code.OTHER, + `Failed to open connection: ${err}` + ); + }); + } + + protected closeConnection(code?: number, reason?: string): Promise { + if (!this.connection) { + this.connectionAttempt = null; + return Promise.resolve(); + } + let error; + try { + if (reason) { + // reason string can be max 123 bytes (not characters, bytes) + // https://developer.mozilla.org/en-US/docs/Web/API/WebSocketStream/close#parameters + const MAX_BYTES = 123; + const encoder = new TextEncoder(); + const bytes = encoder.encode(reason); + if (bytes.length <= MAX_BYTES) { + this.connection.close(code, reason); + } else { + const buf = new Uint8Array(MAX_BYTES); + const { read } = encoder.encodeInto(reason, buf); + const truncatedReason = reason.substring(0, read); + this.connection.close(code, truncatedReason); + } + } else { + this.connection.close(code); + } + } catch (e) { + error = e; + } finally { + this.connection = undefined; + this.connectionAttempt = null; + } + if (error) { + return Promise.reject(error); + } + return Promise.resolve(); + } + + /** + * Handle a disconnection from the server. Initiates graceful clean up and reconnection attempts. + * @param ev the {@link CloseEvent} that closed the WebSocket. + */ + private handleWebsocketDisconnect(ev: CloseEvent): void { + this.connection = undefined; + this.connectionAttempt = null; + this.onStreamClose(ev.code, ev.reason); + } + + /** + * Handle an error that occurred on the WebSocket. Close the connection and reject all active requests. + */ + private handleError(error?: unknown): void { + logError(`DataConnect WebSocket error, closing stream: ${error}`); + let reason = error ? String(error) : 'Unknown Error'; + if (error instanceof DataConnectError) { + reason = error.message; + } + void this.closeConnection(WEBSOCKET_CLOSE_CODE, reason); + } + + protected sendMessage( + requestBody: DataConnectStreamRequest + ): Promise { + return this.ensureConnection().then(() => { + try { + this.connection!.send(JSON.stringify(requestBody)); + return Promise.resolve(); + } catch (err) { + this.handleError(err); + throw new DataConnectError( + Code.OTHER, + `Failed to send message: ${String(err)}` + ); + } + }); + } + + /** + * Handles incoming WebSocket messages. + * @param ev The {@link MessageEvent} from the WebSocket. + */ + private async handleWebSocketMessage(ev: MessageEvent): Promise { + const result: DataConnectStreamResponse = this.parseWebSocketData( + ev.data + ); + const requestId = result.requestId; + + const response: DataConnectResponse = { + data: result.data, + errors: result.errors, + extensions: result.extensions || { dataConnect: [] } + }; + + await this.handleResponse(requestId, response); + } + + /** + * Parse a response from the server. Assert that it has a {@link DataConnectStreamResponse.requestId | requestId}. + * @param data the message from the server to be parsed + * @returns the parsed message as a {@link DataConnectStreamResponse} + * @throws {DataConnectError} if parsing fails or message is malformed. + */ + private parseWebSocketData( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data: any + ): DataConnectStreamResponse { + const dataIsString = typeof data === 'string'; + /** raw websocket message */ + let webSocketMessage; + /** object containing data, errors, and extensions */ + let result; + try { + if (dataIsString) { + webSocketMessage = JSON.parse(data); + } else { + webSocketMessage = JSON.parse(this.decodeBinaryResponse(data)); + } + } catch (err) { + throw new DataConnectError( + Code.OTHER, + `Could not parse WebSocket message: ${ + err instanceof Error ? err.message : String(err) + }` + ); + } + if (typeof webSocketMessage !== 'object' || webSocketMessage === null) { + throw new DataConnectError( + Code.OTHER, + 'WebSocket message is not an object' + ); + } + if (dataIsString) { + if (!('result' in webSocketMessage)) { + throw new DataConnectError( + Code.OTHER, + 'WebSocket message from emulator did not include result' + ); + } + if ( + typeof webSocketMessage.result !== 'object' || + webSocketMessage.result === null + ) { + throw new DataConnectError( + Code.OTHER, + 'WebSocket message result is not an object' + ); + } + result = webSocketMessage.result; + } else { + result = webSocketMessage; + } + if (!('requestId' in result)) { + throw new DataConnectError( + Code.OTHER, + 'WebSocket message did not include requestId' + ); + } + return result as DataConnectStreamResponse; + } +} diff --git a/packages/data-connect/src/network/stream/wire.ts b/packages/data-connect/src/network/stream/wire.ts new file mode 100644 index 0000000000..a214d46c1f --- /dev/null +++ b/packages/data-connect/src/network/stream/wire.ts @@ -0,0 +1,157 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Extensions } from '../index'; + +/** + * Shape of response from the server. + * @internal + */ +export interface DataConnectStreamResponse { + requestId: string; + data: Data; + extensions: Extensions; + dataEtag: string; + errors: Error[]; + cancelled: boolean; +} + +/** + * Base interface for stream request payloads sent over the stream to the server. + * @internal + */ +export interface StreamRequest { + /** monotonically increasing request ID */ + requestId: string; + /** connectorResourcePath - only required on initial connection */ + name?: string; + /** optional headers for this request, for authentication + telemetry */ + headers?: StreamRequestHeaders; + /** received from server on previous response, included to optimize bandwidth */ + dataEtag?: string; +} + +/** + * Optional headers for a stream request, for authentication + telemetry + * @internal + */ +export interface StreamRequestHeaders { + /** used to initially authenticate or re-authenticate */ + authToken?: string; + /** used to initially authenticate or re-authenticate */ + appCheckToken?: string; + /** SDK telemetry header */ + 'X-Goog-Api-Client'?: string; + /** firebase appid */ + 'x-firebase-gmpid'?: string; +} + +/** + * Fields for an execute request payload. + * @internal + */ +interface ExecuteRequestKind { + operationName: string; + variables?: Variables; +} + +/** + * Fields for a subscribe request payload. + * @internal + */ +interface SubscribeRequestKind { + operationName: string; + variables?: Variables; +} + +/** + * Fields for a resume request payload. + * @internal + */ +interface ResumeRequestKind {} + +/** + * Fields for a cancel request payload. + * @internal + */ +interface CancelRequestKind {} + +/** + * Fields for a subscribe request payload. + * @internal + */ +export interface SubscribeStreamRequest extends StreamRequest { + subscribe: SubscribeRequestKind; + execute?: never; + resume?: never; + cancel?: never; +} + +/** + * Fields for an execute request payload. + * @internal + */ +export interface ExecuteStreamRequest extends StreamRequest { + execute: ExecuteRequestKind; + subscribe?: never; + resume?: never; + cancel?: never; +} + +/** + * Fields for a resume (subscribe) request payload. + * @internal + */ +export interface ResumeStreamRequest extends StreamRequest { + resume: ResumeRequestKind; + subscribe?: never; + execute?: never; + cancel?: never; +} + +/** + * Fields for a cancel (unsubscribe) request payload. + * @internal + */ +export interface CancelStreamRequest extends StreamRequest { + cancel: CancelRequestKind; + subscribe?: never; + execute?: never; + resume?: never; +} + +/** + * Shape of the request body to be sent over the stream to the server. + * @internal + */ +export type DataConnectStreamRequest = + | ExecuteStreamRequest + | SubscribeStreamRequest + | ResumeStreamRequest + | CancelStreamRequest; + +/** + * Determines whether the provided request to execute a query is an execution request or a resume + * request + * @returns true if the requestBody is a resume request + * @internal + */ +export function queryRequestIsResume( + requestBody: ExecuteStreamRequest | ResumeStreamRequest +): requestBody is ResumeStreamRequest { + return 'resume' in requestBody; +} diff --git a/packages/data-connect/src/network/transport.ts b/packages/data-connect/src/network/transport.ts new file mode 100644 index 0000000000..f028824bfa --- /dev/null +++ b/packages/data-connect/src/network/transport.ts @@ -0,0 +1,370 @@ +/** + * @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. + */ + +import { DataConnectOptions, TransportOptions } from '../api/DataConnect'; +import { AppCheckTokenProvider } from '../core/AppCheckTokenProvider'; +import { Code, DataConnectError } from '../core/error'; +import { AuthTokenProvider } from '../core/FirebaseAuthProvider'; +import { SDK_VERSION } from '../core/version'; +import { logDebug } from '../logger'; + +/** + * enum representing different flavors of the SDK used by developers + * use the CallerSdkType for type-checking, and the CallerSdkTypeEnum for value-checking/assigning + */ +export type CallerSdkType = + | 'Base' // Core JS SDK + | 'Generated' // Generated JS SDK + | 'TanstackReactCore' // Tanstack non-generated React SDK + | 'GeneratedReact' // Generated React SDK + | 'TanstackAngularCore' // Tanstack non-generated Angular SDK + | 'GeneratedAngular'; // Generated Angular SDK +export const CallerSdkTypeEnum = { + Base: 'Base', // Core JS SDK + Generated: 'Generated', // Generated JS SDK + TanstackReactCore: 'TanstackReactCore', // Tanstack non-generated React SDK + GeneratedReact: 'GeneratedReact', // Tanstack non-generated Angular SDK + TanstackAngularCore: 'TanstackAngularCore', // Tanstack non-generated Angular SDK + GeneratedAngular: 'GeneratedAngular' // Generated Angular SDK +} as const; + +export interface DataConnectEntityArray { + entityIds: string[]; +} + +export interface DataConnectSingleEntity { + entityId: string; +} + +export type DataConnectExtension = { + path: Array; +} & (DataConnectEntityArray | DataConnectSingleEntity); + +/** @internal */ +export interface DataConnectMaxAge { + maxAge: string; +} + +/** @internal */ +export type DataConnectExtensionWithMaxAge = { + path: Array; +} & (DataConnectEntityArray | DataConnectSingleEntity | DataConnectMaxAge); + +export interface Extensions { + dataConnect?: DataConnectExtension[]; +} + +/** @internal */ +export interface ExtensionsWithMaxAge { + dataConnect?: DataConnectExtensionWithMaxAge[]; +} + +/** @internal */ +export interface DataConnectResponse { + data: T; + errors: Error[]; + extensions: Extensions; +} + +/** @internal */ +export interface DataConnectResponseWithMaxAge { + data: T; + errors: Error[]; + extensions: ExtensionsWithMaxAge; +} + +/** + * Observer defined by the Query Layer for receiving notifications from the Transport Layer. + * @internal + */ +export interface SubscribeObserver { + onData(response: DataConnectResponse): Promise | void; + onDisconnect(code: string, reason: string): void; + onError(error: Error): void; +} + +/** + * Interface defining the external API of the transport layer. + * @internal + */ +export interface DataConnectTransportInterface { + /** + * Invoke a query execution request. + * @param queryName The name of the query to execute. + * @param body The variables associated with the query. + * @returns A promise resolving to the DataConnectResponse. + */ + invokeQuery( + queryName: string, + body?: Variables + ): Promise>; + + /** + * Invoke a mutation execution request. + * @param queryName The name of the mutation to execute. + * @param body The variables associated with the mutation. + * @returns A promise resolving to the DataConnectResponse. + */ + invokeMutation( + queryName: string, + body?: Variables + ): Promise>; + + /** + * Subscribes to a query to receive push notifications of updates. + * @param observer the observer passed to the transport layer to notify the query layer of events. + * @param queryName The name of the query to subscribe to. + * @param body The variables associated with the subscription. + */ + invokeSubscribe( + observer: SubscribeObserver, + queryName: string, + body?: Variables + ): void; + + /** + * Unsubscribes from an active subscription. + * @param queryName The name of the query to unsubscribe from. + * @param body The variables associated with the subscription. + */ + invokeUnsubscribe(queryName: string, body?: Variables): void; + + /** + * Configures the transport to use a local Data Connect emulator. + * @param host The host address of the emulator (e.g., '127.0.0.1'). + * @param port The port number the emulator is listening on. + * @param sslEnabled Whether to use SSL (HTTPS/WSS) for the emulator connection. + */ + useEmulator(host: string, port?: number, sslEnabled?: boolean): void; + + /** + * Callback invoked when the Firebase Auth token is refreshed or changed. Note that this callback + * is called immediately asynchronously when the Auth Provider is initialized to provide + * the initial auth state. + * @param token The new access token or null if signed out. + */ + onAuthTokenChanged: (token: string | null) => void; + + /** + * Internal method to set the SDK type for metrics and logging purposes. + * @param callerSdkType The type of SDK making the call (e.g., generated vs base). + */ + _setCallerSdkType(callerSdkType: CallerSdkType): void; +} + +/** + * Type signature of a transport class constructor. + * @internal + */ +export type TransportClass = new ( + options: DataConnectOptions, + apiKey?: string, + appId?: string, + authProvider?: AuthTokenProvider, + appCheckProvider?: AppCheckTokenProvider, + transportOptions?: TransportOptions, + _isUsingGen?: boolean, + _callerSdkType?: CallerSdkType +) => DataConnectTransportInterface; + +/** + * Constructs the value for the X-Goog-Api-Client header + * @internal + */ +export function getGoogApiClientValue( + isUsingGen: boolean, + callerSdkType: CallerSdkType +): string { + let str = 'gl-js/ fire/' + SDK_VERSION; + if ( + callerSdkType !== CallerSdkTypeEnum.Base && + callerSdkType !== CallerSdkTypeEnum.Generated + ) { + str += ' js/' + callerSdkType.toLowerCase(); + } else if (isUsingGen || callerSdkType === CallerSdkTypeEnum.Generated) { + str += ' js/gen'; + } + return str; +} + +/** + * The base class for all DataConnectTransportInterface implementations. Handles common logic such as + * URL construction, auth token management, and emulator usage. Concrete transport implementations + * should extend this class and implement the abstract {@link DataConnectTransportInterface} methods. + * @internal + */ +export abstract class AbstractDataConnectTransport + implements DataConnectTransportInterface +{ + protected _host = ''; + protected _port: number | undefined; + protected _location = 'l'; + protected _connectorName = ''; + /** The resource path for requests from this Data Connect instance. */ + protected _connectorResourcePath: string; + protected _secure = true; + protected _project = 'p'; + protected _serviceName: string; + protected _authToken: string | null = null; + protected _appCheckToken: string | null | undefined = null; + protected _lastToken: string | null = null; + protected _isUsingEmulator = false; + + constructor( + options: DataConnectOptions, + protected apiKey?: string | undefined, + protected appId?: string | null, + protected authProvider?: AuthTokenProvider | undefined, + protected appCheckProvider?: AppCheckTokenProvider | undefined, + transportOptions?: TransportOptions | undefined, + protected _isUsingGen = false, + protected _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base + ) { + if (transportOptions) { + if (typeof transportOptions.port === 'number') { + this._port = transportOptions.port; + } + if (typeof transportOptions.sslEnabled !== 'undefined') { + this._secure = transportOptions.sslEnabled; + } + this._host = transportOptions.host; + } + const { location, projectId: project, connector, service } = options; + if (location) { + this._location = location; + } + if (project) { + this._project = project; + } + this._serviceName = service; + if (!connector) { + throw new DataConnectError( + Code.INVALID_ARGUMENT, + 'Connector Name required!' + ); + } + this._connectorName = connector; + this._connectorResourcePath = `projects/${this._project}/locations/${this._location}/services/${this._serviceName}/connectors/${this._connectorName}`; + this.authProvider?.addTokenChangeListener(token => { + logDebug(`New Token Available: ${token}`); + this.onAuthTokenChanged(token); + }); + this.appCheckProvider?.addTokenChangeListener(result => { + const { token } = result; + logDebug(`New App Check Token Available: ${token}`); + this._appCheckToken = token; + }); + } + + /** Get the endpoint URL this transport should use to communicate with the backend. */ + abstract get endpointUrl(): string; + + useEmulator(host: string, port?: number, isSecure?: boolean): void { + this._host = host; + this._isUsingEmulator = true; + if (typeof port === 'number') { + this._port = port; + } + if (typeof isSecure !== 'undefined') { + this._secure = isSecure; + } + } + + async getWithAuth(forceToken = false): Promise { + let starterPromise: Promise = new Promise(resolve => + resolve(this._authToken) + ); + if (this.appCheckProvider) { + const appCheckToken = await this.appCheckProvider.getToken(); + if (appCheckToken) { + this._appCheckToken = appCheckToken.token; + } + } + if (this.authProvider) { + starterPromise = this.authProvider + .getToken(/*forceToken=*/ forceToken) + .then(data => { + if (!data) { + return null; + } + this._authToken = data.accessToken; + return this._authToken; + }); + } else { + starterPromise = new Promise(resolve => resolve('')); + } + return starterPromise; + } + + async withRetry( + promiseFactory: () => Promise>, + retry = false + ): Promise> { + let isNewToken = false; + return this.getWithAuth(retry) + .then(res => { + isNewToken = this._lastToken !== res; + this._lastToken = res; + return res; + }) + .then(promiseFactory) + .catch(err => { + // Only retry if the result is unauthorized and the last token isn't the same as the new one. + if ( + 'code' in err && + err.code === Code.UNAUTHORIZED && + !retry && + isNewToken + ) { + logDebug('Retrying due to unauthorized'); + return this.withRetry(promiseFactory, true); + } + throw err; + }); + } + + _setLastToken(lastToken: string | null): void { + this._lastToken = lastToken; + } + + abstract invokeQuery( + queryName: string, + body?: Variables + ): Promise>; + + abstract invokeMutation( + queryName: string, + body?: Variables + ): Promise>; + + abstract invokeSubscribe( + observer: SubscribeObserver, + queryName: string, + body?: Variables + ): void; + + abstract invokeUnsubscribe( + queryName: string, + variables: Variables + ): void; + + abstract onAuthTokenChanged(newToken: string | null): void; + + _setCallerSdkType(callerSdkType: CallerSdkType): void { + this._callerSdkType = callerSdkType; + } +} diff --git a/packages/data-connect/src/network/transport/index.ts b/packages/data-connect/src/network/transport/index.ts deleted file mode 100644 index b3856ed30d..0000000000 --- a/packages/data-connect/src/network/transport/index.ts +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @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. - */ - -import { DataConnectOptions, TransportOptions } from '../../api/DataConnect'; -import { AppCheckTokenProvider } from '../../core/AppCheckTokenProvider'; -import { AuthTokenProvider } from '../../core/FirebaseAuthProvider'; - -/** - * enum representing different flavors of the SDK used by developers - * use the CallerSdkType for type-checking, and the CallerSdkTypeEnum for value-checking/assigning - */ -export type CallerSdkType = - | 'Base' // Core JS SDK - | 'Generated' // Generated JS SDK - | 'TanstackReactCore' // Tanstack non-generated React SDK - | 'GeneratedReact' // Generated React SDK - | 'TanstackAngularCore' // Tanstack non-generated Angular SDK - | 'GeneratedAngular'; // Generated Angular SDK -export const CallerSdkTypeEnum = { - Base: 'Base', // Core JS SDK - Generated: 'Generated', // Generated JS SDK - TanstackReactCore: 'TanstackReactCore', // Tanstack non-generated React SDK - GeneratedReact: 'GeneratedReact', // Tanstack non-generated Angular SDK - TanstackAngularCore: 'TanstackAngularCore', // Tanstack non-generated Angular SDK - GeneratedAngular: 'GeneratedAngular' // Generated Angular SDK -} as const; - -export interface DataConnectEntityArray { - entityIds: string[]; -} - -export interface DataConnectSingleEntity { - entityId: string; -} - -export type DataConnectExtension = { - path: Array; -} & (DataConnectEntityArray | DataConnectSingleEntity); - -/** @internal */ -export interface DataConnectMaxAge { - maxAge: string; -} - -/** @internal */ -export type DataConnectExtensionWithMaxAge = { - path: Array; -} & (DataConnectEntityArray | DataConnectSingleEntity | DataConnectMaxAge); - -export interface Extensions { - dataConnect?: DataConnectExtension[]; -} - -/** @internal */ -export interface ExtensionsWithMaxAge { - dataConnect?: DataConnectExtensionWithMaxAge[]; -} - -export interface DataConnectResponse { - data: T; - errors: Error[]; - extensions: Extensions; -} - -/** @internal */ -export interface DataConnectResponseWithMaxAge { - data: T; - errors: Error[]; - extensions: ExtensionsWithMaxAge; -} - -/** - * @internal - */ -export interface DataConnectTransport { - invokeQuery( - queryName: string, - body?: U - ): Promise>; - invokeMutation( - queryName: string, - body?: U - ): Promise>; - useEmulator(host: string, port?: number, sslEnabled?: boolean): void; - onTokenChanged: (token: string | null) => void; - _setCallerSdkType(callerSdkType: CallerSdkType): void; -} - -/** - * @internal - */ -export type TransportClass = new ( - options: DataConnectOptions, - apiKey?: string, - appId?: string, - authProvider?: AuthTokenProvider, - appCheckProvider?: AppCheckTokenProvider, - transportOptions?: TransportOptions, - _isUsingGen?: boolean, - _callerSdkType?: CallerSdkType -) => DataConnectTransport; diff --git a/packages/data-connect/src/network/transport/rest.ts b/packages/data-connect/src/network/transport/rest.ts deleted file mode 100644 index 5f5fa320ef..0000000000 --- a/packages/data-connect/src/network/transport/rest.ts +++ /dev/null @@ -1,232 +0,0 @@ -/** - * @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. - */ - -import { DataConnectOptions, TransportOptions } from '../../api/DataConnect'; -import { AppCheckTokenProvider } from '../../core/AppCheckTokenProvider'; -import { DataConnectError, Code } from '../../core/error'; -import { AuthTokenProvider } from '../../core/FirebaseAuthProvider'; -import { logDebug } from '../../logger'; -import { addToken, urlBuilder } from '../../util/url'; -import { dcFetch } from '../fetch'; - -import { - CallerSdkType, - CallerSdkTypeEnum, - DataConnectResponse, - DataConnectTransport -} from '.'; - -export class RESTTransport implements DataConnectTransport { - private _host = ''; - private _port: number | undefined; - private _location = 'l'; - private _connectorName = ''; - private _secure = true; - private _project = 'p'; - private _serviceName: string; - private _accessToken: string | null = null; - private _appCheckToken: string | null | undefined = null; - private _lastToken: string | null = null; - private _isUsingEmulator = false; - constructor( - options: DataConnectOptions, - private apiKey?: string | undefined, - private appId?: string | null, - private authProvider?: AuthTokenProvider | undefined, - private appCheckProvider?: AppCheckTokenProvider | undefined, - transportOptions?: TransportOptions | undefined, - private _isUsingGen = false, - private _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base - ) { - if (transportOptions) { - if (typeof transportOptions.port === 'number') { - this._port = transportOptions.port; - } - if (typeof transportOptions.sslEnabled !== 'undefined') { - this._secure = transportOptions.sslEnabled; - } - this._host = transportOptions.host; - } - const { location, projectId: project, connector, service } = options; - if (location) { - this._location = location; - } - if (project) { - this._project = project; - } - this._serviceName = service; - if (!connector) { - throw new DataConnectError( - Code.INVALID_ARGUMENT, - 'Connector Name required!' - ); - } - this._connectorName = connector; - this.authProvider?.addTokenChangeListener(token => { - logDebug(`New Token Available: ${token}`); - this._accessToken = token; - }); - this.appCheckProvider?.addTokenChangeListener(result => { - const { token } = result; - logDebug(`New App Check Token Available: ${token}`); - this._appCheckToken = token; - }); - } - get endpointUrl(): string { - return urlBuilder( - { - connector: this._connectorName, - location: this._location, - projectId: this._project, - service: this._serviceName - }, - { host: this._host, sslEnabled: this._secure, port: this._port } - ); - } - useEmulator(host: string, port?: number, isSecure?: boolean): void { - this._host = host; - this._isUsingEmulator = true; - if (typeof port === 'number') { - this._port = port; - } - if (typeof isSecure !== 'undefined') { - this._secure = isSecure; - } - } - onTokenChanged(newToken: string | null): void { - this._accessToken = newToken; - } - - async getWithAuth(forceToken = false): Promise { - let starterPromise: Promise = new Promise(resolve => - resolve(this._accessToken) - ); - if (this.appCheckProvider) { - const appCheckToken = await this.appCheckProvider.getToken(); - if (appCheckToken) { - this._appCheckToken = appCheckToken.token; - } - } - if (this.authProvider) { - starterPromise = this.authProvider - .getToken(/*forceToken=*/ forceToken) - .then(data => { - if (!data) { - return null; - } - this._accessToken = data.accessToken; - return this._accessToken; - }); - } else { - starterPromise = new Promise(resolve => resolve('')); - } - return starterPromise; - } - - _setLastToken(lastToken: string | null): void { - this._lastToken = lastToken; - } - - withRetry( - promiseFactory: () => Promise>, - retry = false - ): Promise> { - let isNewToken = false; - return this.getWithAuth(retry) - .then(res => { - isNewToken = this._lastToken !== res; - this._lastToken = res; - return res; - }) - .then(promiseFactory) - .catch(err => { - // Only retry if the result is unauthorized and the last token isn't the same as the new one. - if ( - 'code' in err && - err.code === Code.UNAUTHORIZED && - !retry && - isNewToken - ) { - logDebug('Retrying due to unauthorized'); - return this.withRetry(promiseFactory, true); - } - throw err; - }); - } - - // TODO(mtewani): Update U to include shape of body defined in line 13. - invokeQuery: ( - queryName: string, - body?: U - ) => Promise> = ( - queryName: string, - body: U - ) => { - const abortController = new AbortController(); - - // TODO(mtewani): Update to proper value - const withAuth = this.withRetry(() => - dcFetch( - addToken(`${this.endpointUrl}:executeQuery`, this.apiKey), - { - name: `projects/${this._project}/locations/${this._location}/services/${this._serviceName}/connectors/${this._connectorName}`, - operationName: queryName, - variables: body - }, - abortController, - this.appId, - this._accessToken, - this._appCheckToken, - this._isUsingGen, - this._callerSdkType, - this._isUsingEmulator - ) - ); - return withAuth; - }; - invokeMutation: ( - queryName: string, - body?: U - ) => Promise> = ( - mutationName: string, - body: U - ) => { - const abortController = new AbortController(); - const taskResult = this.withRetry(() => { - return dcFetch( - addToken(`${this.endpointUrl}:executeMutation`, this.apiKey), - { - name: `projects/${this._project}/locations/${this._location}/services/${this._serviceName}/connectors/${this._connectorName}`, - operationName: mutationName, - variables: body - }, - abortController, - this.appId, - this._accessToken, - this._appCheckToken, - this._isUsingGen, - this._callerSdkType, - this._isUsingEmulator - ); - }); - return taskResult; - }; - - _setCallerSdkType(callerSdkType: CallerSdkType): void { - this._callerSdkType = callerSdkType; - } -} diff --git a/packages/data-connect/src/util/url.ts b/packages/data-connect/src/util/url.ts index 16fb28750d..8b628185ab 100644 --- a/packages/data-connect/src/util/url.ts +++ b/packages/data-connect/src/util/url.ts @@ -20,8 +20,10 @@ import { Code, DataConnectError } from '../core/error'; import { logError } from '../logger'; export const PROD_HOST = 'firebasedataconnect.googleapis.com'; +export const WEBSOCKET_PATH = + 'ws/google.firebase.dataconnect.v1.ConnectorStreamService'; -export function urlBuilder( +export function restUrlBuilder( projectConfig: DataConnectOptions, transportOptions: TransportOptions ): string { @@ -41,6 +43,28 @@ export function urlBuilder( } return `${baseUrl}/v1/projects/${project}/locations/${location}/services/${service}/connectors/${connector}`; } + +export function websocketUrlBuilder( + projectConfig: DataConnectOptions, + transportOptions: TransportOptions +): string { + const { location } = projectConfig; + const { host, sslEnabled, port } = transportOptions; + const protocol = sslEnabled ? 'wss' : 'ws'; + const realHost = host || PROD_HOST; + let baseUrl = `${protocol}://${realHost}`; + if (typeof port === 'number') { + baseUrl += `:${port}`; + } else if (typeof port !== 'undefined') { + logError('Port type is of an invalid type'); + throw new DataConnectError( + Code.INVALID_ARGUMENT, + 'Incorrect type for port passed in!' + ); + } + return `${baseUrl}/${WEBSOCKET_PATH}/Connect/locations/${location}`; +} + export function addToken(url: string, apiKey?: string): string { if (!apiKey) { return url; diff --git a/packages/data-connect/test/queries.test.ts b/packages/data-connect/test/queries.test.ts index 7c8a48a8c5..66fd927757 100644 --- a/packages/data-connect/test/queries.test.ts +++ b/packages/data-connect/test/queries.test.ts @@ -18,6 +18,7 @@ import { deleteApp, initializeApp, FirebaseApp } from '@firebase/app'; import { expect, use } from 'chai'; import chaiAsPromised from 'chai-as-promised'; +import * as sinon from 'sinon'; import { connectDataConnectEmulator, @@ -35,6 +36,7 @@ import { subscribe, terminate } from '../src'; +import { DataConnectTransportManager } from '../src/network/manager'; import { getConnectionConfig, initDatabase, PROJECT_ID } from './util'; @@ -94,11 +96,18 @@ describe('DataConnect Tests', async () => { }); dc = initDatabase(); await seedDatabase(dc, TEST_ID); + sinon + .stub(DataConnectTransportManager.prototype, 'invokeSubscribe') + .returns(); + sinon + .stub(DataConnectTransportManager.prototype, 'invokeUnsubscribe') + .returns(); }); afterEach(async () => { await deleteDatabase(dc); await deleteApp(app); await terminate(dc); + sinon.restore(); }); function getPostsRef(): QueryRef { return queryRef(dc, 'ListPosts', { diff --git a/packages/data-connect/test/unit/caching.test.ts b/packages/data-connect/test/unit/caching.test.ts index 114f448ffa..bab3eae768 100644 --- a/packages/data-connect/test/unit/caching.test.ts +++ b/packages/data-connect/test/unit/caching.test.ts @@ -30,7 +30,8 @@ import { DataConnectExtension, OpResult } from '../../src'; -import { initializeFetch } from '../../src/network/fetch'; +import { DataConnectTransportManager } from '../../src/network/manager'; +import { initializeFetch } from '../../src/network/rest'; describe('caching', () => { let dc: DataConnect; @@ -39,9 +40,18 @@ describe('caching', () => { const { firebaseApp, dc: newDC } = setup(); dc = newDC; app = firebaseApp; + + // Stub transport to prevent real network calls for subscribe. + sinon + .stub(DataConnectTransportManager.prototype, 'invokeSubscribe') + .returns(); + sinon + .stub(DataConnectTransportManager.prototype, 'invokeUnsubscribe') + .returns(); }); afterEach(async () => { await deleteApp(app); + sinon.restore(); }); it('should resolve from cache with an interdependent query', async () => { interface Q1Data { diff --git a/packages/data-connect/test/unit/fetch.test.ts b/packages/data-connect/test/unit/fetch.test.ts index 43060c90cd..98796fc797 100644 --- a/packages/data-connect/test/unit/fetch.test.ts +++ b/packages/data-connect/test/unit/fetch.test.ts @@ -20,8 +20,8 @@ import chaiAsPromised from 'chai-as-promised'; import * as sinon from 'sinon'; import sinonChai from 'sinon-chai'; -import { dcFetch, initializeFetch } from '../../src/network/fetch'; -import { CallerSdkType, CallerSdkTypeEnum } from '../../src/network/transport'; +import { CallerSdkType, CallerSdkTypeEnum } from '../../src/network'; +import { dcFetch, initializeFetch } from '../../src/network/rest'; use(chaiAsPromised); use(sinonChai); function mockFetch(json: object, reject: boolean): sinon.SinonStub { diff --git a/packages/data-connect/test/unit/gmpid.test.ts b/packages/data-connect/test/unit/gmpid.test.ts index 281a8fe85c..251227adeb 100644 --- a/packages/data-connect/test/unit/gmpid.test.ts +++ b/packages/data-connect/test/unit/gmpid.test.ts @@ -21,7 +21,7 @@ import * as sinon from 'sinon'; import sinonChai from 'sinon-chai'; import { DataConnect, executeQuery, getDataConnect, queryRef } from '../../src'; -import { initializeFetch } from '../../src/network/fetch'; +import { initializeFetch } from '../../src/network/rest'; use(sinonChai); const json = { diff --git a/packages/data-connect/test/unit/queries.test.ts b/packages/data-connect/test/unit/queries.test.ts index 51f12c5b21..c2b355b916 100644 --- a/packages/data-connect/test/unit/queries.test.ts +++ b/packages/data-connect/test/unit/queries.test.ts @@ -31,8 +31,8 @@ import { AuthTokenListener, AuthTokenProvider } from '../../src/core/FirebaseAuthProvider'; -import { initializeFetch } from '../../src/network/fetch'; -import { RESTTransport } from '../../src/network/transport/rest'; +import { DataConnectTransportManager } from '../../src/network/manager'; +import { initializeFetch, RESTTransport } from '../../src/network/rest'; import { initDatabase } from '../util'; chai.use(chaiAsPromised); chai.use(sinonChai); @@ -93,9 +93,16 @@ describe('Queries', () => { initializeApp({ projectId: 'p' }); + sinon + .stub(DataConnectTransportManager.prototype, 'invokeSubscribe') + .returns(); + sinon + .stub(DataConnectTransportManager.prototype, 'invokeUnsubscribe') + .returns(); }); afterEach(() => { fakeFetchImpl.resetHistory(); + sinon.restore(); }); it('should call onComplete callback after subscribe is called', async () => { const taskListQuery = getPostsRef(); diff --git a/packages/data-connect/test/unit/streamTransport.test.ts b/packages/data-connect/test/unit/streamTransport.test.ts new file mode 100644 index 0000000000..fc8b613583 --- /dev/null +++ b/packages/data-connect/test/unit/streamTransport.test.ts @@ -0,0 +1,1225 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai'; +import * as chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import * as sinon from 'sinon'; +import sinonChai from 'sinon-chai'; + +import { DataConnectOptions } from '../../src/api/DataConnect'; +import { AuthTokenProvider } from '../../src/core/FirebaseAuthProvider'; +import * as logger from '../../src/logger'; +import { + CallerSdkType, + CallerSdkTypeEnum, + DataConnectResponse, + getGoogApiClientValue +} from '../../src/network'; +import { AbstractDataConnectStreamTransport } from '../../src/network/stream/streamTransport'; +import { + DataConnectStreamRequest, + ExecuteStreamRequest, + ResumeStreamRequest, + SubscribeStreamRequest +} from '../../src/network/stream/wire'; + +import { expectIsNotSettled, sleep } from './testUtils'; + +chai.use(sinonChai); +chai.use(chaiAsPromised); + +class TestStreamTransport extends AbstractDataConnectStreamTransport { + get streamIsReady(): boolean { + return true; + } + + get endpointUrl(): string { + return 'https://endpoint.url'; + } + + protected openConnection(): Promise { + return Promise.resolve(); + } + protected closeConnection(): Promise { + return Promise.resolve(); + } + protected ensureConnection(): Promise { + return Promise.resolve(); + } + protected sendMessage( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + requestBody: DataConnectStreamRequest + ): Promise { + return Promise.resolve(); + } + + /** Manually trigger onConnectionReady for testing purposes. */ + triggerOnConnectionReady(): void { + this.onConnectionReady(); + } + + /** Manually invoke token change for testing purposes. */ + invokeOnAuthTokenChanged(token: string | null): void { + this.onAuthTokenChanged(token); + } + + /** Manually set auth token for testing purposes. */ + setAuthToken(token: string | null): void { + this._authToken = token; + } + + authProvider = { + getAuth: () => ({ getUid: () => this._authToken }) + } as AuthTokenProvider; + + /** Manually set app check token for testing purposes. */ + setAppCheckToken(token: string | null): void { + this._appCheckToken = token; + } + + /** Manually resolve a request for testing purposes. */ + invokeHandleResponse( + requestId: string, + response: DataConnectResponse + ): Promise { + return this.handleResponse(requestId, response); + } +} + +/** Interface that exposes some private fields and methods of TestStreamTransport for testing purposes. */ +interface TransportWithInternals { + _connectorResourcePath: string; + _isUsingGen: boolean; + appId: string | undefined; + _callerSdkType: CallerSdkType; + _setCallerSdkType(type: CallerSdkType): void; + invokeOnAuthTokenChanged(token: string | null): void; + setAuthToken(token: string | null): void; + authProvider: { getAuth: () => { getUid(): string | null } }; + setAppCheckToken(token: string | null): void; + nextRequestId(): string; + triggerOnConnectionReady(): void; + closeConnection(): Promise; + cancelClose(): void; + prepareMessage< + Variables, + StreamBody extends DataConnectStreamRequest + >( + requestBody: StreamBody + ): StreamBody; + activeQueryExecuteRequests: Map< + string, + ExecuteStreamRequest | ResumeStreamRequest + >; + activeMutationExecuteRequests: Map< + string, + Array> + >; + activeSubscribeRequests: Map>; + executeRequestPromises: Map< + string, + { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + resolve: (data: any) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + reject: (err: any) => void; + promise: Promise>; + } + >; + subscribeObservers: Map; + getMapKey(operationName: string, variables?: unknown): string; + invokeQuery<_Data, Variables>( + queryName: string, + variables?: Variables + ): Promise; + invokeMutation<_Data, Variables>( + mutationName: string, + variables?: Variables + ): Promise; + invokeSubscribe<_Data, Variables>( + notify: unknown, + queryName: string, + variables: Variables + ): void; + invokeUnsubscribe(queryName: string, variables: Variables): void; + sendMessage( + requestBody: DataConnectStreamRequest + ): Promise; + invokeHandleResponse( + requestId: string, + response: DataConnectResponse + ): Promise; +} + +describe('AbstractDataConnectStreamTransport', () => { + const dcOptions: DataConnectOptions = { + projectId: 'p', + location: 'l', + service: 's', + connector: 'c' + }; + let transport: TransportWithInternals; + let expectedName: string; + let expectedInitialGoogApiClientValue: string; + const firstRequestId = '1'; + const unpreparedMessage: DataConnectStreamRequest = { + requestId: firstRequestId, + execute: { operationName: 'test' } + }; + const initialAuthToken = 'initial-auth-token'; + const newAuthToken = 'new-auth-token'; + const initialAppCheckToken = 'initial-app-check-token'; + const newAppCheckToken = 'new-app-check-token'; + const initialAppId = 'initial-app-id'; + const newAppId = 'new-app-id'; + const queryName1 = 'testQuery1'; + const queryName2 = 'testQuery2'; + const variables1 = { foo: 'bar', num: 1 }; + const variables2 = { abc: 'xyz', num: 2 }; + const mutationName1 = 'testMutation1'; + const mutationName2 = 'testMutation2'; + const expectedError = new Error('test error'); + + beforeEach(() => { + transport = new TestStreamTransport( + dcOptions + ) as unknown as TransportWithInternals; + expectedName = transport._connectorResourcePath; + transport._isUsingGen = true; + transport._callerSdkType = CallerSdkTypeEnum.Generated; + expectedInitialGoogApiClientValue = getGoogApiClientValue( + transport._isUsingGen, + transport._callerSdkType + ); + transport.setAuthToken(initialAuthToken); + transport.setAppCheckToken(initialAppCheckToken); + transport.appId = initialAppId; + }); + + afterEach(() => { + sinon.restore(); + }); + + describe('prepareMessage', () => { + it('should not change data fields', () => { + const preparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(preparedMessage.requestId).to.equal(unpreparedMessage.requestId); + expect(preparedMessage.execute).to.equal(unpreparedMessage.execute); + expect(preparedMessage.resume).to.equal(unpreparedMessage.resume); + expect(preparedMessage.subscribe).to.equal(unpreparedMessage.subscribe); + expect(preparedMessage.cancel).to.equal(unpreparedMessage.cancel); + expect(preparedMessage.dataEtag).to.equal(unpreparedMessage.dataEtag); + }); + + describe('should handle headers properly', () => { + describe('auth token', () => { + it('should add auth token to the first message', () => { + const preparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(preparedMessage.headers).to.exist; + expect(preparedMessage.headers?.authToken).to.equal(initialAuthToken); + }); + + it('should NOT add the same auth token to subsequent messages', () => { + transport.prepareMessage(unpreparedMessage); + const secondPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(secondPreparedMessage.headers?.authToken).to.be.undefined; + }); + + it('should include auth token when it changes', () => { + transport.prepareMessage(unpreparedMessage); + const secondPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(secondPreparedMessage.headers?.authToken).to.be.undefined; + transport.setAuthToken(newAuthToken); + const thirdPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(thirdPreparedMessage.headers?.authToken).to.equal( + newAuthToken + ); + }); + }); + + describe('app check token', () => { + it('should add app check token to the first message', () => { + const firstPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(firstPreparedMessage.headers).to.exist; + expect(firstPreparedMessage.headers?.appCheckToken).to.equal( + initialAppCheckToken + ); + }); + + it('should NOT add the same app check token to subsequent messages', () => { + transport.prepareMessage(unpreparedMessage); + const secondPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(secondPreparedMessage.headers?.appCheckToken).to.be.undefined; + }); + + it('should NOT include app check token when it changes', () => { + transport.prepareMessage(unpreparedMessage); + const secondPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(secondPreparedMessage.headers?.appCheckToken).to.be.undefined; + transport.setAppCheckToken(newAppCheckToken); + const thirdPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(thirdPreparedMessage.headers?.appCheckToken).to.be.undefined; + }); + }); + + describe('x-firebase-gmpid', () => { + it('should add x-firebase-gmpid to every message if appId is set', () => { + const firstPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(firstPreparedMessage.headers).to.exist; + expect(firstPreparedMessage.headers?.['x-firebase-gmpid']).to.equal( + initialAppId + ); + + const secondPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(secondPreparedMessage.headers?.['x-firebase-gmpid']).to.equal( + initialAppId + ); + + transport.appId = newAppId; + const thirdPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(thirdPreparedMessage.headers?.['x-firebase-gmpid']).to.equal( + newAppId + ); + }); + }); + + it('should add X-Goog-Api-Client to every message based on caller sdk type', () => { + const firstPreparedMessage = + transport.prepareMessage(unpreparedMessage); + expect(firstPreparedMessage.headers?.['X-Goog-Api-Client']).to.equal( + expectedInitialGoogApiClientValue + ); + const secondPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(secondPreparedMessage.headers?.['X-Goog-Api-Client']).to.equal( + expectedInitialGoogApiClientValue + ); + transport._isUsingGen = true; + transport._setCallerSdkType(CallerSdkTypeEnum.GeneratedReact); + const expectedThirdGoogApiClientValue = getGoogApiClientValue( + true, + CallerSdkTypeEnum.GeneratedReact + ); + const thirdPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(thirdPreparedMessage.headers?.['X-Goog-Api-Client']).to.equal( + expectedThirdGoogApiClientValue + ); + }); + }); + + describe('should handle name properly', () => { + it('should add name to the first message', () => { + const firstPreparedMessage = + transport.prepareMessage(unpreparedMessage); + expect(firstPreparedMessage.name).to.equal(expectedName); + }); + + it('should NOT add name to subsequent messages', () => { + transport.prepareMessage(unpreparedMessage); + const secondPreparedMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(secondPreparedMessage.name).to.be.undefined; + }); + }); + + it('should reset connection state on onConnectionReady()', () => { + // First message receives the initial payload (name, appCheckToken, authToken) + transport.prepareMessage(unpreparedMessage); + + // Second message should not have any of these initial fields + const secondMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(secondMessage.name).to.be.undefined; + expect(secondMessage.headers?.appCheckToken).to.be.undefined; + expect(secondMessage.headers?.authToken).to.be.undefined; + + // Trigger the physical connection reset + transport.triggerOnConnectionReady(); + + // The next message should be treated as a "first" message again + const thirdMessage = transport.prepareMessage( + unpreparedMessage + ) as DataConnectStreamRequest; + expect(thirdMessage.name).to.equal(expectedName); + expect(thirdMessage.headers?.appCheckToken).to.equal( + initialAppCheckToken + ); + expect(thirdMessage.headers?.authToken).to.equal(initialAuthToken); + }); + }); + + describe('Request Tracking', () => { + it('getMapKey should sort keys consistently for map lookups', () => { + const queryName = 'sortQuery'; + const variables1 = { a: 1, b: 2, c: 3, d: 4 }; + const variables2 = { b: 2, a: 1, d: 4, c: 3 }; + expect(transport.getMapKey(queryName, variables1)).to.equal( + transport.getMapKey(queryName, variables2) + ); + }); + + it('should generate unique request IDs', () => { + const id1 = transport.nextRequestId(); + const id2 = transport.nextRequestId(); + expect(id1).to.not.equal(id2); + expect(Number(id1)).to.be.lessThan(Number(id2)); + }); + + describe('Incoming Requests from Transport Layer', () => { + describe('invokeQuery', () => { + it('should populate tracking maps synchronously and then call sendMessage', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + + const queryPromise = transport.invokeQuery(queryName1, variables1); + + const expectedKey = transport.getMapKey(queryName1, variables1); + expect(transport.activeQueryExecuteRequests.has(expectedKey)).to.be + .true; + const request = transport.activeQueryExecuteRequests.get(expectedKey); + expect(request?.execute?.operationName).to.equal(queryName1); + expect(request?.execute?.variables).to.deep.equal(variables1); + + const requestId = (request as ExecuteStreamRequest) + .requestId; + expect(transport.executeRequestPromises.has(requestId)).to.be.true; + + expect(sendMessageSpy).to.have.been.calledOnce; + const sentMessage = sendMessageSpy.firstCall.args[0]; + expect(sentMessage.requestId).to.equal(requestId); + expect(sentMessage.execute).to.not.be.undefined; + expect(sentMessage.execute?.operationName).to.equal(queryName1); + expect(sentMessage.execute?.variables).to.deep.equal(variables1); + await expectIsNotSettled(queryPromise); + }); + + it('should asynchronously clean up and reject if sendMessage fails', async () => { + const sendMessageStub = sinon + .stub(transport, 'sendMessage') + .rejects(expectedError); + + const queryPromise = transport.invokeQuery(queryName1, variables1); + await expect(queryPromise).to.be.rejectedWith(expectedError); + + const mapKey = transport.getMapKey(queryName1, variables1); + expect(transport.activeQueryExecuteRequests.has(mapKey)).to.be.false; + + const requestId = sendMessageStub.firstCall.args[0].requestId; + expect(transport.executeRequestPromises.has(requestId)).to.be.false; + }); + }); + + describe('invokeMutation', () => { + it('should populate tracking maps synchronously and then call sendMessage', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + + const mutationPromise = transport.invokeMutation( + mutationName1, + variables1 + ); + + const expectedKey = transport.getMapKey(mutationName1, variables1); + const requests = + transport.activeMutationExecuteRequests.get(expectedKey); + expect(requests).to.have.lengthOf(1); + expect(requests![0].execute?.operationName).to.equal(mutationName1); + const requestId = requests![0].requestId; + expect(transport.executeRequestPromises.has(requestId)).to.be.true; + + expect(sendMessageSpy).to.have.been.calledOnce; + const sentMessage = sendMessageSpy.firstCall.args[0]; + expect(sentMessage.requestId).to.equal(requestId); + expect(sentMessage.execute).to.not.be.undefined; + expect(sentMessage.execute?.operationName).to.equal(mutationName1); + expect(sentMessage.execute?.variables).to.deep.equal(variables1); + await expectIsNotSettled(mutationPromise); + }); + + it('should asynchronously clean up and reject if sendMessage fails', async () => { + const sendMessageStub = sinon + .stub(transport, 'sendMessage') + .rejects(expectedError); + + const mutationPromise = transport.invokeMutation( + mutationName1, + variables1 + ); + await expect(mutationPromise).to.be.rejectedWith(expectedError); + + const mapKey = transport.getMapKey(mutationName1, variables1); + expect(transport.activeMutationExecuteRequests.has(mapKey)).to.be + .false; + + const requestId = sendMessageStub.firstCall.args[0].requestId; + expect(transport.executeRequestPromises.has(requestId)).to.be.false; + }); + }); + + describe('invokeSubscribe', () => { + it('should populate tracking maps synchronously and then call sendMessage', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.invokeSubscribe(observer, queryName1, variables1); + + const expectedKey = transport.getMapKey(queryName1, variables1); + expect(transport.activeSubscribeRequests.has(expectedKey)).to.be.true; + const request = transport.activeSubscribeRequests.get(expectedKey); + expect(request?.subscribe?.operationName).to.equal(queryName1); + expect(request?.subscribe?.variables).to.deep.equal(variables1); + + const requestId = (request as SubscribeStreamRequest) + .requestId; + expect(transport.subscribeObservers.has(requestId)).to.be.true; + + expect(sendMessageSpy).to.have.been.calledOnce; + const sentMessage = sendMessageSpy.firstCall.args[0]; + expect(sentMessage.requestId).to.equal(requestId); + expect(sentMessage.subscribe).to.not.be.undefined; + expect(sentMessage.subscribe?.operationName).to.equal(queryName1); + expect(sentMessage.subscribe?.variables).to.deep.equal(variables1); + }); + + it('should asynchronously call observer with error and clean up if sendMessage fails', async () => { + const sendMessageStub = sinon + .stub(transport, 'sendMessage') + .rejects(expectedError); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.invokeSubscribe(observer, queryName1, variables1); + + // invokeSubscribe's sendMessage is fire and forget + await sleep(500); + expect(observer.onError).to.have.been.calledOnce; + const result = observer.onError.firstCall.args[0]; + expect(result).to.equal(expectedError); + + const mapKey = transport.getMapKey(queryName1, variables1); + expect(transport.activeSubscribeRequests.has(mapKey)).to.be.false; + const requestId = sendMessageStub.firstCall.args[0].requestId; + expect(transport.subscribeObservers.has(requestId)).to.be.false; + }); + }); + + describe('invokeUnsubscribe', () => { + it('should de-populate tracking maps and call sendMessage', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.invokeSubscribe(observer, queryName1, variables1); + + const expectedKey = transport.getMapKey(queryName1, variables1); + expect(transport.activeSubscribeRequests.has(expectedKey)).to.be.true; + const subscribeRequest = + transport.activeSubscribeRequests.get(expectedKey); + const subscribeRequestId = ( + subscribeRequest as SubscribeStreamRequest + ).requestId; + expect(transport.subscribeObservers.has(subscribeRequestId)).to.be + .true; + + transport.invokeUnsubscribe(queryName1, variables1); + + expect(sendMessageSpy).to.have.been.calledTwice; + const unsubscribeMessage = sendMessageSpy.secondCall.args[0]; + + expect(transport.activeSubscribeRequests.has(expectedKey)).to.be + .false; + expect(transport.subscribeObservers.has(subscribeRequestId)).to.be + .false; + expect(unsubscribeMessage.cancel).to.not.be.undefined; + }); + + it('should asynchronously clean up and log error if sendMessage fails', async () => { + const logErrorStub = sinon.stub(logger, 'logError'); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + transport.invokeSubscribe(observer, queryName1, variables1); + + const expectedKey = transport.getMapKey(queryName1, variables1); + const subscribeRequest = + transport.activeSubscribeRequests.get(expectedKey); + const subscribeRequestId = subscribeRequest?.requestId!; + + const sendMessageStub = sinon + .stub(transport, 'sendMessage') + .rejects(expectedError); + transport.invokeUnsubscribe(queryName1, variables1); + // invokeUnsubscribe's sendMessage is fire and forget + await sleep(500); + + expect(sendMessageStub).to.have.been.calledOnce; + expect(logErrorStub).to.have.been.calledOnce; + expect(logErrorStub).to.have.been.calledWithMatch( + 'Stream Transport failed to send unsubscribe message' + ); + + expect(transport.activeSubscribeRequests.has(expectedKey)).to.be + .false; + expect(transport.subscribeObservers.has(subscribeRequestId)).to.be + .false; + }); + }); + }); + + describe('Incoming Responses from Server', () => { + const expectedData1 = { result: 'result', num: 1 }; + const expectedData2 = { result: 'result', num: 2 }; + const expectedData3 = { result: 'result', num: 3 }; + const expectedData4 = { result: 'result', num: 4 }; + const response1: DataConnectResponse = { + data: expectedData1, + errors: [], + extensions: {} + }; + const response2: DataConnectResponse = { + data: expectedData2, + errors: [], + extensions: {} + }; + const response3: DataConnectResponse = { + data: expectedData3, + errors: [], + extensions: {} + }; + const response4: DataConnectResponse = { + data: expectedData4, + errors: [], + extensions: {} + }; + + const errorResponse: DataConnectResponse = { + data: {}, + errors: [expectedError], + extensions: {} + }; + + it('should throw an error if an unrecognized requestId is received', async () => { + const unknownRequestId = 'unknown-999'; + const response: DataConnectResponse = { + data: {}, + errors: [], + extensions: {} + }; + const errorPromise = transport.invokeHandleResponse( + unknownRequestId, + response + ); + await expect(errorPromise).to.be.rejectedWith( + `Stream response contained unrecognized requestId '${unknownRequestId}'` + ); + }); + + describe('invokeQuery tracking', async () => { + it('should route data to resolve the correct query promise when response is received', async () => { + const queryPromise1 = transport.invokeQuery(queryName1, variables1); + const queryPromise2 = transport.invokeQuery(queryName2, variables2); + + const expectedKey1 = transport.getMapKey(queryName1, variables1); + const request1 = + transport.activeQueryExecuteRequests.get(expectedKey1); + const requestId1 = (request1 as ExecuteStreamRequest) + .requestId; + const expectedKey2 = transport.getMapKey(queryName2, variables2); + const request2 = + transport.activeQueryExecuteRequests.get(expectedKey2); + const requestId2 = (request2 as ExecuteStreamRequest) + .requestId; + + await transport.invokeHandleResponse(requestId1, response1); + const result1 = await queryPromise1; + expect(result1).to.deep.equal(response1); + + await transport.invokeHandleResponse(requestId2, response2); + const result2 = await queryPromise2; + expect(result2).to.deep.equal(response2); + }); + + it('should clean map when response is received', async () => { + const queryPromise1 = transport.invokeQuery(queryName1, variables1); + const queryPromise2 = transport.invokeQuery(queryName2, variables2); + + const expectedKey1 = transport.getMapKey(queryName1, variables1); + const request1 = + transport.activeQueryExecuteRequests.get(expectedKey1); + const requestId1 = (request1 as ExecuteStreamRequest) + .requestId; + const expectedKey2 = transport.getMapKey(queryName2, variables2); + const request2 = + transport.activeQueryExecuteRequests.get(expectedKey2); + const requestId2 = (request2 as ExecuteStreamRequest) + .requestId; + + await transport.invokeHandleResponse(requestId1, response1); + await queryPromise1; + expect(transport.activeQueryExecuteRequests.has(expectedKey1)).to.be + .false; + expect(transport.activeQueryExecuteRequests.has(expectedKey2)).to.be + .true; + + await transport.invokeHandleResponse(requestId2, response2); + await queryPromise2; + + expect(transport.activeQueryExecuteRequests.has(expectedKey1)).to.be + .false; + expect(transport.activeQueryExecuteRequests.has(expectedKey2)).to.be + .false; + }); + + it('should reject the correct query promise with DataConnectOperationError if response has errors', async () => { + const queryPromise1 = transport.invokeQuery(queryName1, variables1); + const queryPromise2 = transport.invokeQuery(queryName2, variables2); + const expectedKey1 = transport.getMapKey(queryName1, variables1); + const expectedKey2 = transport.getMapKey(queryName2, variables2); + const request1 = + transport.activeQueryExecuteRequests.get(expectedKey1); + const requestId1 = (request1 as ExecuteStreamRequest) + .requestId; + const request2 = + transport.activeQueryExecuteRequests.get(expectedKey2); + const requestId2 = (request2 as ExecuteStreamRequest) + .requestId; + + await transport.invokeHandleResponse(requestId1, errorResponse); + await transport.invokeHandleResponse(requestId2, errorResponse); + await expect(queryPromise1).to.be.rejectedWith( + `DataConnect error while performing request: ${JSON.stringify([ + expectedError + ])}` + ); + await expect(queryPromise2).to.be.rejectedWith( + `DataConnect error while performing request: ${JSON.stringify([ + expectedError + ])}` + ); + }); + + it('should clean map correctly when handleResponse rejects', async () => { + void transport.invokeQuery(queryName1, variables1); + void transport.invokeQuery(queryName2, variables2); + + const expectedKey1 = transport.getMapKey(queryName1, variables1); + const request1 = + transport.activeQueryExecuteRequests.get(expectedKey1); + const requestId1 = (request1 as ExecuteStreamRequest) + .requestId; + const expectedKey2 = transport.getMapKey(queryName2, variables2); + const request2 = + transport.activeQueryExecuteRequests.get(expectedKey2); + const requestId2 = (request2 as ExecuteStreamRequest) + .requestId; + + await transport.invokeHandleResponse(requestId1, errorResponse); + expect(transport.activeQueryExecuteRequests.has(expectedKey1)).to.be + .false; + expect(transport.executeRequestPromises.has(requestId1)).to.be.false; + expect(transport.activeQueryExecuteRequests.has(expectedKey2)).to.be + .true; + expect(transport.executeRequestPromises.has(requestId2)).to.be.true; + + await transport.invokeHandleResponse(requestId2, errorResponse); + expect(transport.activeQueryExecuteRequests.has(expectedKey2)).to.be + .false; + expect(transport.executeRequestPromises.has(requestId2)).to.be.false; + }); + }); + + describe('invokeMutation tracking', async () => { + it('should route data to resolve the correct mutation promise when response is received', async () => { + const mutationPromise1 = transport.invokeMutation( + mutationName1, + variables1 + ); + const mutationPromise2 = transport.invokeMutation( + mutationName2, + variables2 + ); + + const expectedKey1 = transport.getMapKey(mutationName1, variables1); + const activeRequests1 = + transport.activeMutationExecuteRequests.get(expectedKey1); + const requestId1 = activeRequests1![0].requestId; + const expectedKey2 = transport.getMapKey(mutationName2, variables2); + const activeRequests2 = + transport.activeMutationExecuteRequests.get(expectedKey2); + const requestId2 = activeRequests2![0].requestId; + + await transport.invokeHandleResponse(requestId1, response1); + const result1 = await mutationPromise1; + expect(result1).to.deep.equal(response1); + await expectIsNotSettled(mutationPromise2); + + await transport.invokeHandleResponse(requestId2, response2); + const result2 = await mutationPromise2; + expect(result2).to.deep.equal(response2); + }); + + it('should clean map of the correct tracked request when response is received', async () => { + const mutationPromise1 = transport.invokeMutation( + mutationName1, + variables1 + ); + const mutationPromise2 = transport.invokeMutation( + mutationName2, + variables2 + ); + + const expectedKey1 = transport.getMapKey(mutationName1, variables1); + const activeRequests1 = + transport.activeMutationExecuteRequests.get(expectedKey1); + const requestId1 = activeRequests1![0].requestId; + const expectedKey2 = transport.getMapKey(mutationName2, variables2); + const activeRequests2 = + transport.activeMutationExecuteRequests.get(expectedKey2); + const requestId2 = activeRequests2![0].requestId; + + await transport.invokeHandleResponse(requestId1, response1); + await mutationPromise1; + expect(transport.executeRequestPromises.has(requestId1)).to.be.false; + expect(transport.activeMutationExecuteRequests.has(expectedKey1)).to + .be.false; + expect(transport.executeRequestPromises.has(requestId2)).to.be.true; + expect(transport.activeMutationExecuteRequests.has(expectedKey2)).to + .be.true; + + await transport.invokeHandleResponse(requestId2, response2); + await mutationPromise2; + expect(transport.executeRequestPromises.has(requestId2)).to.be.false; + expect(transport.activeMutationExecuteRequests.has(expectedKey2)).to + .be.false; + }); + + it('should reject the correct mutation promise with DataConnectOperationError if response has errors', async () => { + const mutationPromise1 = transport.invokeMutation( + mutationName1, + variables1 + ); + const mutationPromise2 = transport.invokeMutation( + mutationName2, + variables2 + ); + const expectedKey1 = transport.getMapKey(mutationName1, variables1); + const activeRequests1 = + transport.activeMutationExecuteRequests.get(expectedKey1); + const requestId1 = activeRequests1![0].requestId; + const expectedKey2 = transport.getMapKey(mutationName2, variables2); + const activeRequests2 = + transport.activeMutationExecuteRequests.get(expectedKey2); + const requestId2 = activeRequests2![0].requestId; + + await transport.invokeHandleResponse(requestId1, errorResponse); + await expect(mutationPromise1).to.be.rejectedWith( + `DataConnect error while performing request: ${JSON.stringify([ + expectedError + ])}` + ); + await expectIsNotSettled(mutationPromise2); + + await transport.invokeHandleResponse(requestId2, errorResponse); + await expect(mutationPromise2).to.be.rejectedWith( + `DataConnect error while performing request: ${JSON.stringify([ + expectedError + ])}` + ); + }); + + it('should clean map correctly when handleResponse rejects', async () => { + transport.invokeMutation(mutationName1, variables1).catch(() => {}); + transport.invokeMutation(mutationName2, variables2).catch(() => {}); + const expectedKey1 = transport.getMapKey(mutationName1, variables1); + const expectedKey2 = transport.getMapKey(mutationName2, variables2); + const activeRequests1 = + transport.activeMutationExecuteRequests.get(expectedKey1); + const activeRequests2 = + transport.activeMutationExecuteRequests.get(expectedKey2); + const requestId1 = activeRequests1![0].requestId; + const requestId2 = activeRequests2![0].requestId; + + await transport.invokeHandleResponse(requestId1, errorResponse); + expect(transport.activeMutationExecuteRequests.has(expectedKey1)).to + .be.false; + expect(transport.executeRequestPromises.has(requestId1)).to.be.false; + expect(transport.activeMutationExecuteRequests.has(expectedKey2)).to + .be.true; + expect(transport.executeRequestPromises.has(requestId2)).to.be.true; + + await transport.invokeHandleResponse(requestId2, errorResponse); + expect(transport.activeMutationExecuteRequests.has(expectedKey2)).to + .be.false; + expect(transport.executeRequestPromises.has(requestId2)).to.be.false; + }); + }); + + describe('invokeSubscribe tracking', async () => { + const observer1 = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + const observer2 = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + afterEach(() => { + observer1.onData.resetHistory(); + observer1.onDisconnect.resetHistory(); + observer1.onError.resetHistory(); + observer2.onData.resetHistory(); + observer2.onDisconnect.resetHistory(); + observer2.onError.resetHistory(); + }); + + it('should route data to the correct subscribe observer whenever a response is received', async () => { + transport.invokeSubscribe(observer1, queryName1, variables1); + transport.invokeSubscribe(observer2, queryName2, variables2); + + const expectedKey1 = transport.getMapKey(queryName1, variables1); + const request1 = transport.activeSubscribeRequests.get(expectedKey1); + const requestId1 = request1?.requestId!; + + await transport.invokeHandleResponse(requestId1, response1); + expect(observer1.onData).to.have.been.calledOnce; + expect(observer1.onData).to.have.been.calledWithExactly(response1); + await transport.invokeHandleResponse(requestId1, response2); + expect(observer1.onData).to.have.been.calledTwice; + expect(observer1.onData).to.have.been.calledWithExactly(response2); + + const expectedKey2 = transport.getMapKey(queryName2, variables2); + const request2 = transport.activeSubscribeRequests.get(expectedKey2); + const requestId2 = request2?.requestId!; + + await transport.invokeHandleResponse(requestId2, response3); + expect(observer2.onData).to.have.been.calledOnce; + expect(observer2.onData).to.have.been.calledWithExactly(response3); + await transport.invokeHandleResponse(requestId2, response4); + expect(observer2.onData).to.have.been.calledTwice; + expect(observer2.onData).to.have.been.calledWithExactly(response4); + }); + + it('should route error response to the correct subscribe observer whenever an error response is received', async () => { + transport.invokeSubscribe(observer1, queryName1, variables1); + transport.invokeSubscribe(observer2, queryName2, variables2); + + const expectedKey1 = transport.getMapKey(queryName1, variables1); + const request1 = transport.activeSubscribeRequests.get(expectedKey1); + const requestId1 = request1?.requestId!; + const expectedKey2 = transport.getMapKey(queryName2, variables2); + const request2 = transport.activeSubscribeRequests.get(expectedKey2); + const requestId2 = request2?.requestId!; + + await transport.invokeHandleResponse(requestId1, errorResponse); + expect(observer1.onData).to.have.been.calledOnce; + expect(observer1.onData).to.have.been.calledWithExactly( + errorResponse + ); + await transport.invokeHandleResponse(requestId2, errorResponse); + expect(observer2.onData).to.have.been.calledOnce; + expect(observer2.onData).to.have.been.calledWithExactly( + errorResponse + ); + }); + + it('should NOT clean map when handleResponse rejects', async () => { + transport.invokeSubscribe(observer1, queryName1, variables1); + transport.invokeSubscribe(observer2, queryName2, variables2); + const expectedKey1 = transport.getMapKey(queryName1, variables1); + const expectedKey2 = transport.getMapKey(queryName2, variables2); + const request1 = transport.activeSubscribeRequests.get(expectedKey1); + const request2 = transport.activeSubscribeRequests.get(expectedKey2); + const requestId1 = request1?.requestId!; + const requestId2 = request2?.requestId!; + + await transport.invokeHandleResponse(requestId1, errorResponse); + await transport.invokeHandleResponse(requestId2, errorResponse); + expect(transport.activeSubscribeRequests.has(expectedKey1)).to.be + .true; + expect(transport.subscribeObservers.has(requestId1)).to.be.true; + expect(transport.activeSubscribeRequests.has(expectedKey2)).to.be + .true; + expect(transport.subscribeObservers.has(requestId2)).to.be.true; + }); + }); + }); + }); + + describe('Disconnects', () => { + let clock: sinon.SinonFakeTimers; + + beforeEach(() => { + clock = sinon.useFakeTimers(); + }); + + afterEach(() => { + clock.restore(); + }); + + it('should close connection after 60 seconds of idle (no active subscriptions)', async () => { + const closeSpy = sinon.spy(transport, 'closeConnection'); + sinon.stub(transport, 'sendMessage').resolves(); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + await transport.invokeSubscribe(observer, queryName1, variables1); + await transport.invokeUnsubscribe(queryName1, variables1); + + clock.tick(1000 * 59); + expect(closeSpy).to.not.have.been.called; + + clock.tick(1000 * 2); + expect(closeSpy).to.have.been.calledOnce; + }); + + it('should cancel close if a new subscription arrives during timeout', async () => { + const closeSpy = sinon.spy(transport, 'closeConnection'); + sinon.stub(transport, 'sendMessage').resolves(); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + await transport.invokeSubscribe(observer, queryName1, variables1); + await transport.invokeUnsubscribe(queryName1, variables1); + + clock.tick(1000 * 30); + expect(closeSpy).to.not.have.been.called; + + await transport.invokeSubscribe(observer, queryName2, variables2); + + clock.tick(1000 * 65); + expect(closeSpy).to.not.have.been.called; + }); + + it('should restart close timeout if subscribe fails and leaves no active subscriptions', async () => { + const closeSpy = sinon.spy(transport, 'closeConnection'); + const sendMessageStub = sinon.stub(transport, 'sendMessage'); + sendMessageStub.resolves(); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + await transport.invokeSubscribe(observer, queryName1, variables1); + await transport.invokeUnsubscribe(queryName1, variables1); + + clock.tick(1000 * 30); + expect(closeSpy).to.not.have.been.called; + + sendMessageStub.rejects(); + await transport.invokeSubscribe(observer, queryName2, variables2); + + clock.tick(1000 * 30); + expect(closeSpy).to.not.have.been.called; + + clock.tick(1000 * 35); + expect(closeSpy).to.have.been.calledOnce; + }); + + it('should not close connection if there are active execute requests', async () => { + const closeSpy = sinon.spy(transport, 'closeConnection'); + sinon.stub(transport, 'sendMessage').resolves(); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + await transport.invokeSubscribe(observer, queryName1, variables1); + await transport.invokeUnsubscribe(queryName1, variables1); + + void transport.invokeQuery(queryName2, variables2); + + clock.tick(1000 * 65); + expect(closeSpy).to.not.have.been.called; + }); + + it('should close connection when last execute request finishes after idle timeout', async () => { + const closeSpy = sinon.spy(transport, 'closeConnection'); + sinon.stub(transport, 'sendMessage').resolves(); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + await transport.invokeSubscribe(observer, queryName1, variables1); + await transport.invokeUnsubscribe(queryName1, variables1); + + const queryPromise = transport.invokeQuery(queryName2, variables2); + + clock.tick(1000 * 65); + expect(closeSpy).to.not.have.been.called; + + const expectedKey = transport.getMapKey(queryName2, variables2); + const request = transport.activeQueryExecuteRequests.get(expectedKey); + const requestId = (request as ExecuteStreamRequest).requestId; + + const dummyResponse = { + data: { result: 'result' }, + errors: [], + extensions: {} + }; + await transport.invokeHandleResponse(requestId, dummyResponse); + await queryPromise; + + expect(closeSpy).to.have.been.calledOnce; + }); + + describe('Auth Disconnects', () => { + it('should close stream immediately on illegal auth change (login)', async () => { + const closeSpy = sinon.spy(transport, 'closeConnection'); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.setAuthToken(null); + const getAuthStub = sinon.stub(transport.authProvider, 'getAuth'); + getAuthStub.returns({ getUid: () => null }); + transport.invokeOnAuthTokenChanged(null); // Establish baseline (unauth) + + transport.invokeSubscribe(observer, queryName1, variables1); + + transport.setAuthToken('new-token'); + getAuthStub.returns({ getUid: () => 'some-uid' }); + transport.invokeOnAuthTokenChanged('new-token'); // Change (login) + + expect(closeSpy).to.have.been.calledOnce; + }); + + it('should close stream immediately on illegal auth change (logout)', async () => { + const closeSpy = sinon.spy(transport, 'closeConnection'); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.setAuthToken('initial-token'); + const getAuthStub = sinon.stub(transport.authProvider, 'getAuth'); + getAuthStub.returns({ getUid: () => 'some-uid' }); + transport.invokeOnAuthTokenChanged('initial-token'); // Establish baseline (auth) + + transport.invokeSubscribe(observer, queryName1, variables1); + + transport.setAuthToken(null); + getAuthStub.returns({ getUid: () => null }); + transport.invokeOnAuthTokenChanged(null); // Change (logout) + + expect(closeSpy).to.have.been.calledOnce; + }); + + it('should close stream immediately on illegal auth change (user change)', async () => { + const closeSpy = sinon.spy(transport, 'closeConnection'); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.setAuthToken('token-a'); + const getAuthStub = sinon.stub(transport.authProvider, 'getAuth'); + getAuthStub.returns({ getUid: () => 'user-a' }); + transport.invokeOnAuthTokenChanged('token-a'); // Establish baseline (user A) + + transport.invokeSubscribe(observer, queryName1, variables1); + + transport.setAuthToken('token-b'); + getAuthStub.returns({ getUid: () => 'user-b' }); + transport.invokeOnAuthTokenChanged('token-b'); // Change (user B) + + expect(closeSpy).to.have.been.calledOnce; + }); + + it('should NOT close stream on valid auth token refresh (same user)', async () => { + const closeSpy = sinon.spy(transport, 'closeConnection'); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.setAuthToken('initial-token'); + + // Stub getUid to return the same user ID regardless of token + sinon + .stub(transport.authProvider, 'getAuth') + .returns({ getUid: () => 'same-user' }); + + transport.invokeOnAuthTokenChanged('initial-token'); // Establish baseline + + transport.invokeSubscribe(observer, queryName1, variables1); + + transport.setAuthToken('refreshed-token'); + transport.invokeOnAuthTokenChanged('refreshed-token'); // Refresh + + expect(closeSpy).to.not.have.been.called; + }); + }); + }); +}); diff --git a/packages/data-connect/test/unit/streaming.test.ts b/packages/data-connect/test/unit/streaming.test.ts new file mode 100644 index 0000000000..1e1551a940 --- /dev/null +++ b/packages/data-connect/test/unit/streaming.test.ts @@ -0,0 +1,446 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { deleteApp, FirebaseApp, initializeApp } from '@firebase/app'; +import { expect } from 'chai'; +import * as chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import * as sinon from 'sinon'; +import sinonChai from 'sinon-chai'; + +import { + Code, + DataConnect, + DataConnectResponse, + DataConnectResponseWithMaxAge, + executeMutation, + executeQuery, + getDataConnect, + mutationRef, + QueryRef, + queryRef, + QueryResult, + subscribe, + SubscribeObserver +} from '../../src'; +import { DataConnectTransportManager } from '../../src/network/manager'; +import { RESTTransport } from '../../src/network/rest'; +import { AbstractDataConnectStreamTransport } from '../../src/network/stream/streamTransport'; +import { WebSocketTransport } from '../../src/network/stream/websocket'; +import { DataConnectStreamRequest } from '../../src/network/stream/wire'; + +import { MockWebSocket } from './testUtils'; + +chai.use(sinonChai); +chai.use(chaiAsPromised); + +/** Interface that exposes private fields of DataConnect for testing purposes. */ +interface DataConnectWithInternals { + _queryManager: QueryManagerWithInternals; +} + +/** Interface that exposes private fields of QueryManager for testing purposes. */ +interface QueryManagerWithInternals { + transport: ManagerWithInternals; + preferCacheResults( + queryRef: QueryRef, + allowStale: boolean + ): Promise>; + updateSSR(updatedData: QueryResult): void; + waitForQueuedWrites(): Promise; +} + +/** Interface that exposes private fields of TransportManager for testing purposes. */ +interface ManagerWithInternals { + streamTransport?: StreamTransportWithInternals; + restTransport: RESTTransport; + invokeQuery( + queryName: string, + body?: Variables + ): Promise>; + invokeMutation( + queryName: string, + body?: Variables + ): Promise>; + invokeSubscribe( + observer: SubscribeObserver, + queryName: string, + body?: Variables + ): void; + invokeUnsubscribe(queryName: string, body?: Variables): void; + initStreamTransport(): AbstractDataConnectStreamTransport; +} + +/** Interface that exposes private fields of AbstractDataConnectStreamTransport for testing purposes. */ +interface StreamTransportWithInternals { + sendMessage( + requestBody: DataConnectStreamRequest + ): Promise; + invokeQuery( + queryName: string, + body?: Variables + ): Promise>; + isUnableToConnect: boolean; + connection?: MockWebSocket; + hasActiveSubscriptions: boolean; + streamIsReady: boolean; +} + +describe('Streaming & Query Layer Integration', () => { + let dc: DataConnect; + let app: FirebaseApp; + let stubStreamTransport: sinon.SinonStubbedInstance; + let initStreamTransportStub: sinon.SinonStub; + + beforeEach(() => { + stubStreamTransport = { + invokeQuery: sinon.stub(), + invokeMutation: sinon.stub(), + invokeSubscribe: sinon.stub(), + invokeUnsubscribe: sinon.stub(), + useEmulator: sinon.stub(), + onAuthTokenChanged: sinon.stub(), + hasActiveSubscriptions: false + } as unknown as sinon.SinonStubbedInstance; + + initStreamTransportStub = sinon + .stub( + DataConnectTransportManager.prototype as unknown as ManagerWithInternals, + 'initStreamTransport' + ) + .callsFake(function (this: ManagerWithInternals) { + this.streamTransport = + stubStreamTransport as unknown as StreamTransportWithInternals; + return stubStreamTransport as unknown as AbstractDataConnectStreamTransport; + }); + + app = initializeApp({ projectId: 'p', appId: 'a' }, 'n'); + dc = getDataConnect(app, { + connector: 'c', + location: 'l', + service: 's' + }); + dc.setInitialized(); + }); + + afterEach(async () => { + await dc._delete(); + await deleteApp(app); + sinon.restore(); + }); + + const testVariables = { foo: 'bar' }; + type TestVariables = typeof testVariables; + const testData = { abc: 'xyz' }; + type TestData = typeof testData; + + const queryName = 'testQuery'; + + describe('using stream via user-facing API', () => { + it('executeQuery / executeMutation should not initialize stream', async () => { + const q = queryRef(dc, queryName, testVariables); + const m = mutationRef( + dc, + queryName, + testVariables + ); + + void executeQuery(q); + expect(initStreamTransportStub).to.not.have.been.called; + void executeMutation(m); + expect(initStreamTransportStub).to.not.have.been.called; + }); + + it('subscribe should initialize stream', async () => { + const q = queryRef(dc, queryName, testVariables); + subscribe(q, () => {}); + expect(initStreamTransportStub).to.have.been.calledOnce; + expect(stubStreamTransport.invokeSubscribe).to.have.been.calledOnce; + }); + + it('query layer should call invokeUnsubscribe on last unsubscribe', async () => { + const onNextSpy1 = sinon.spy(); + const onNextSpy2 = sinon.spy(); + const onNextSpy3 = sinon.spy(); + const q = queryRef(dc, queryName, testVariables); + + const unsub1 = subscribe(q, onNextSpy1); + const unsub2 = subscribe(q, onNextSpy2); + const unsub3 = subscribe(q, onNextSpy3); + + unsub1(); + expect(stubStreamTransport.invokeUnsubscribe).to.not.have.been.called; + unsub2(); + expect(stubStreamTransport.invokeUnsubscribe).to.not.have.been.called; + unsub3(); + expect(stubStreamTransport.invokeUnsubscribe).to.have.been.calledOnceWith( + queryName, + testVariables + ); + }); + + it('executeQuery should use stream when stream is active', async () => { + const q = queryRef(dc, queryName, testVariables); + + stubStreamTransport.invokeQuery.resolves({ + data: testData, + errors: [], + extensions: {} + }); + + // stub preferCacheResults to avoid race condition where subscribe calls invokeQuery asynchronously + sinon + .stub( + (dc as unknown as DataConnectWithInternals)._queryManager, + 'preferCacheResults' + ) + .resolves({ data: testData, source: 'CACHE' } as QueryResult< + TestData, + TestVariables + >); + + // open a subscription to activate the stream + subscribe(q, { onNext: () => {} }); + + // force hasActiveSubscriptions and streamIsReady to true so TransportManager routes to stream + ( + stubStreamTransport as unknown as StreamTransportWithInternals + ).hasActiveSubscriptions = true; + ( + stubStreamTransport as unknown as StreamTransportWithInternals + ).streamIsReady = true; + + // reset history because subscribe might have triggered calls before stub was active or otherwise + stubStreamTransport.invokeQuery.resetHistory(); + + const result = await executeQuery(q, { fetchPolicy: 'SERVER_ONLY' }); + + expect(stubStreamTransport.invokeQuery).to.have.been.calledOnceWith( + queryName, + testVariables + ); + expect(result.data).to.deep.equal(testData); + }); + + it('executeMutation should use stream when stream is active', async () => { + const m = mutationRef( + dc, + 'testMutation', + testVariables + ); + const q = queryRef(dc, queryName, testVariables); + + // open a subscription to activate the stream + subscribe(q, { onNext: () => {} }); + + // force hasActiveSubscriptions and streamIsReady to true so TransportManager routes to stream + ( + stubStreamTransport as unknown as StreamTransportWithInternals + ).hasActiveSubscriptions = true; + ( + stubStreamTransport as unknown as StreamTransportWithInternals + ).streamIsReady = true; + + stubStreamTransport.invokeMutation.resolves({ + data: testData, + errors: [], + extensions: {} + }); + + const result = await executeMutation(m); + + expect(stubStreamTransport.invokeMutation).to.have.been.calledOnceWith( + 'testMutation', + testVariables + ); + expect(result.data).to.deep.equal(testData); + }); + }); + + describe('incoming notifications', () => { + it('should notify all relevant subscribers when data is received', async () => { + const relevantQuery = queryRef( + dc, + queryName, + testVariables + ); + const irrelevantQuery = queryRef( + dc, + 'otherQuery', + { foo: 'xyz' } + ); + const relevantSpy1 = sinon.spy(); + const relevantSpy2 = sinon.spy(); + const relevantSpy3 = sinon.spy(); + const irrelevantSpy = sinon.spy(); + subscribe(relevantQuery, relevantSpy1); + subscribe(relevantQuery, relevantSpy2); + subscribe(relevantQuery, relevantSpy3); + subscribe(irrelevantQuery, irrelevantSpy); + + // get the query layer's observer was passed to invokeSubscribe + const observer = stubStreamTransport.invokeSubscribe.firstCall.args[0]; + + // call the observer with data + await observer.onData({ data: testData, errors: [], extensions: {} }); + + expect(relevantSpy1.calledOnce).to.be.true; + expect(relevantSpy2.calledOnce).to.be.true; + expect(relevantSpy3.calledOnce).to.be.true; + expect(irrelevantSpy).to.not.have.been.called; + const result1 = relevantSpy1.firstCall.args[0]; + const result2 = relevantSpy2.firstCall.args[0]; + const result3 = relevantSpy3.firstCall.args[0]; + expect(result1.data).to.deep.equal(testData); + expect(result2.data).to.deep.equal(testData); + expect(result3.data).to.deep.equal(testData); + }); + + it('should update cache when data is pushed', async () => { + const q = queryRef(dc, queryName, testVariables); + const onNextSpy = sinon.spy(); + subscribe(q, onNextSpy); + + // get the query layer's observer which was passed to invokeSubscribe + const observer = stubStreamTransport.invokeSubscribe.firstCall.args[0]; + + // call the observer with data + await observer.onData({ data: testData, errors: [], extensions: {} }); + + // verify CACHE_ONLY executions see the data returned from the observer + const cacheResult1 = await executeQuery(q, { fetchPolicy: 'CACHE_ONLY' }); + expect(cacheResult1.data).to.deep.equal(testData); + + // simulate second notification + const newData: TestData = { abc: 'NEW DATA' }; + await observer.onData({ data: newData, errors: [], extensions: {} }); + + // verify CACHE_ONLY again + const cacheResult2 = await executeQuery(q, { fetchPolicy: 'CACHE_ONLY' }); + expect(cacheResult2.data).to.deep.equal(newData); + }); + + it('should notify all relevant subscribers of errors when they are pushed', async () => { + const relevantQuery = queryRef( + dc, + queryName, + testVariables + ); + const newVars: TestVariables = { foo: 'NEW VARS' }; + const irrelevantQuery = queryRef( + dc, + 'otherQuery', + newVars + ); + const relevantSpy1 = sinon.spy(); + const relevantSpy2 = sinon.spy(); + const relevantSpy3 = sinon.spy(); + const irrelevantSpy = sinon.spy(); + + subscribe(relevantQuery, { onNext: () => {}, onErr: relevantSpy1 }); + subscribe(relevantQuery, { onNext: () => {}, onErr: relevantSpy2 }); + subscribe(relevantQuery, { onNext: () => {}, onErr: relevantSpy3 }); + subscribe(irrelevantQuery, { onNext: () => {}, onErr: irrelevantSpy }); + + // get the query layer's observer which was passed to invokeSubscribe + const observer = stubStreamTransport.invokeSubscribe.firstCall.args[0]; + + // call the observer with errors + const expectedError = new Error('test error'); + await observer.onData({ + data: {}, + errors: [expectedError], + extensions: {} + }); + + expect(relevantSpy1.calledOnce).to.be.true; + expect(relevantSpy2.calledOnce).to.be.true; + expect(relevantSpy3.calledOnce).to.be.true; + expect(irrelevantSpy).to.not.have.been.called; + const result1 = relevantSpy1.firstCall.args[0]; + const result2 = relevantSpy2.firstCall.args[0]; + const result3 = relevantSpy3.firstCall.args[0]; + expect(result1).to.be.an.instanceOf(Error); + expect(result1.message).to.include( + 'DataConnect error received from subscribe notification' + ); + expect(result2).to.be.an.instanceOf(Error); + expect(result2.message).to.include( + 'DataConnect error received from subscribe notification' + ); + expect(result3).to.be.an.instanceOf(Error); + expect(result3.message).to.include( + 'DataConnect error received from subscribe notification' + ); + }); + + it('should clean up subscriptions in query layer when observer receives a disconnect error', async () => { + const q = queryRef(dc, queryName, testVariables); + const onNextSpy = sinon.spy(); + const onErrSpy = sinon.spy(); + + subscribe(q, { onNext: onNextSpy, onErr: onErrSpy }); + + const notificationObserver = + stubStreamTransport.invokeSubscribe.firstCall.args[0]; + + await notificationObserver.onDisconnect( + Code.OTHER, + 'WebSocket disconnected externally' + ); + + expect(onErrSpy).to.have.been.calledOnce; + expect(stubStreamTransport.invokeUnsubscribe).to.have.been.calledOnce; + + // Call observer again with data, should not reach subscriber because it was cleaned up + await notificationObserver.onData({ + data: { abc: 'new data' }, + errors: [], + extensions: {} + }); + expect(onNextSpy).to.not.have.been.called; + }); + + it('should NOT clean up subscriptions in query layer when observer receives a non-disconnect error', async () => { + const q = queryRef(dc, queryName, testVariables); + const onNextSpy = sinon.spy(); + const onErrSpy = sinon.spy(); + + subscribe(q, { onNext: onNextSpy, onErr: onErrSpy }); + + const observer = stubStreamTransport.invokeSubscribe.firstCall.args[0]; + + const expectedError = new Error('test error'); + await observer.onData({ + data: {}, + errors: [expectedError], + extensions: {} + }); + + expect(onErrSpy).to.have.been.calledOnce; + + // Call observer again with data, should STILL reach subscriber because it was NOT cleaned up + const testData: TestData = { abc: 'new data' }; + await observer.onData({ data: testData, errors: [], extensions: {} }); + expect(onNextSpy).to.have.been.calledOnce; + expect(onNextSpy.firstCall.args[0].data).to.deep.equal(testData); + + // Verify that invokeUnsubscribe was NOT called + expect(stubStreamTransport.invokeUnsubscribe).to.not.have.been.called; + }); + }); +}); diff --git a/packages/data-connect/test/unit/testUtils.ts b/packages/data-connect/test/unit/testUtils.ts new file mode 100644 index 0000000000..fc08f106b5 --- /dev/null +++ b/packages/data-connect/test/unit/testUtils.ts @@ -0,0 +1,114 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai'; +import * as chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import * as sinon from 'sinon'; + +chai.use(chaiAsPromised); + +/** + * Asserts that a promise does not settle within the given timeout. + * @param promise The promise to test. + * @param timeout The timeout in milliseconds (defaults to 1000ms). Note that the test runner's timeout defaults to 5000ms. + * @internal + */ +export async function expectIsNotSettled( + promise: Promise, + timeout: number = 1000 +): Promise { + const unsettled = { settled: false }; + const result = await Promise.race<{ + settled: boolean; + resolvedWith?: unknown; + rejectedWith?: unknown; + }>([ + promise + .then(resolvedWith => ({ settled: true, resolvedWith })) + .catch(rejectedWith => ({ settled: true, rejectedWith })), + new Promise(resolve => { + setTimeout(() => resolve(unsettled), timeout); + }) + ]); + expect(result).to.equal( + unsettled, + `expected promise to not settle within ${timeout}ms!` + ); +} + +/** + * Sleeps for the given number of milliseconds. + * @param ms The number of milliseconds to sleep. + * @internal + */ +export function sleep(ms: number): Promise { + return new Promise(resolve => { + setTimeout(resolve, ms); + }); +} + +/** + * Mock WebSocket class for testing purposes. + * @internal + */ +export class MockWebSocket { + static readonly CONNECTING = WebSocket.CONNECTING; + static readonly OPEN = WebSocket.OPEN; + static readonly CLOSING = WebSocket.CLOSING; + static readonly CLOSED = WebSocket.CLOSED; + + readyState: number = MockWebSocket.CONNECTING; + send: sinon.SinonSpy = sinon.spy(); + close: sinon.SinonSpy = sinon.spy(); + + onopen: (() => void | Promise) | null = null; + onerror: ((err: Error) => void | Promise) | null = null; + onmessage: ((ev: MessageEvent) => void | Promise) | null = null; + onclose: ((ev: CloseEvent) => void | Promise) | null = null; + + url: string; + constructor(url: string) { + this.url = url; + } + + simulateOpen(): void | Promise { + this.readyState = MockWebSocket.OPEN; + if (this.onopen) { + return this.onopen(); + } + } + + simulateError(err: Error): void | Promise { + if (this.onerror) { + return this.onerror(err); + } + } + + simulateMessage(data: string): void | Promise { + if (this.onmessage) { + return this.onmessage({ data } as MessageEvent); + } + } + + simulateClose(code = 1000, reason = 'Normal Closure'): void | Promise { + this.readyState = MockWebSocket.CLOSED; + if (this.onclose) { + return this.onclose({ code, reason } as CloseEvent); + } + } +} diff --git a/packages/data-connect/test/unit/transportManager.test.ts b/packages/data-connect/test/unit/transportManager.test.ts new file mode 100644 index 0000000000..e64e411d60 --- /dev/null +++ b/packages/data-connect/test/unit/transportManager.test.ts @@ -0,0 +1,618 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect, use } from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import * as sinon from 'sinon'; +import sinonChai from 'sinon-chai'; + +import { DataConnectOptions } from '../../src/api/DataConnect'; +import { Code } from '../../src/core/error'; +import { + DataConnectResponse, + DataConnectResponseWithMaxAge, + SubscribeObserver +} from '../../src/network'; +import { DataConnectTransportManager } from '../../src/network/manager'; +import { RESTTransport } from '../../src/network/rest'; +import { AbstractDataConnectStreamTransport } from '../../src/network/stream/streamTransport'; +import { WebSocketTransport } from '../../src/network/stream/websocket'; + +use(chaiAsPromised); +use(sinonChai); + +/** Interface that exposes private fields of stream transport for testing purposes. */ +interface StreamTransportWithInternals { + onStreamClose(code: number, reason: string): void; +} + +/** Interface that exposes private fields of TransportManager for testing purposes. */ +interface ManagerWithInternals { + invokeQuery( + queryName: string, + body?: Variables + ): Promise>; + invokeMutation( + queryName: string, + body?: Variables + ): Promise>; + invokeSubscribe( + observer: SubscribeObserver, + queryName: string, + body?: Variables + ): void; + invokeUnsubscribe(queryName: string, body?: Variables): void; + useEmulator(host: string, port?: number, sslEnabled?: boolean): void; + onAuthTokenChanged: (token: string | null) => void; + restTransport: RESTTransport; + streamTransport?: AbstractDataConnectStreamTransport; + initStreamTransport(): AbstractDataConnectStreamTransport; + executeShouldUseStream(): boolean; +} + +describe('DataConnectTransportManager', () => { + let manager: ManagerWithInternals; + const options: DataConnectOptions = { + projectId: 'test-project', + location: 'us-central1', + connector: 'test-connector', + service: 'test-service' + }; + + beforeEach(() => { + manager = new DataConnectTransportManager( + options + ) as unknown as ManagerWithInternals; + }); + + afterEach(() => { + sinon.restore(); + }); + + interface TestVariables { + key: string; + } + const queryName1 = 'testQuery1'; + // const queryName2 = 'testQuery2'; + const mutationName1 = 'testMutation1'; + const variables1: TestVariables = { key: 'one' }; + // const variables2: TestVariables = { key: 'two' }; + + interface TestData { + value: number; + } + const testResponse = { data: { value: 1 } } as DataConnectResponse; + + const expectedError = new Error('stream error'); + + describe('stream transport initialization', () => { + it('initStreamTransport should initialize stream transport only once', () => { + expect(manager.streamTransport).to.be.undefined; + + const transport1 = manager.initStreamTransport(); + expect(transport1).to.exist; + expect(manager.streamTransport).to.equal(transport1); + + const transport2 = manager.initStreamTransport(); + expect(transport2).to.equal(transport1); + }); + }); + + describe('default transport routing', () => { + let stubRestTransport: sinon.SinonStubbedInstance; + let stubStreamTransport: sinon.SinonStubbedInstance; + let initStreamStub: sinon.SinonStub; + beforeEach(() => { + stubRestTransport = { + invokeQuery: sinon.stub(), + invokeMutation: sinon.stub(), + invokeSubscribe: sinon.stub(), + invokeUnsubscribe: sinon.stub(), + useEmulator: sinon.stub(), + onAuthTokenChanged: sinon.stub() + } as unknown as sinon.SinonStubbedInstance; + stubStreamTransport = { + invokeQuery: sinon.stub(), + invokeMutation: sinon.stub(), + invokeSubscribe: sinon.stub(), + invokeUnsubscribe: sinon.stub(), + useEmulator: sinon.stub(), + onAuthTokenChanged: sinon.stub(), + hasActiveSubscriptions: false + } as unknown as sinon.SinonStubbedInstance; + manager.restTransport = stubRestTransport as unknown as RESTTransport; + initStreamStub = sinon + .stub(manager, 'initStreamTransport') + .callsFake(() => { + manager.streamTransport = + stubStreamTransport as unknown as AbstractDataConnectStreamTransport; + return stubStreamTransport as unknown as AbstractDataConnectStreamTransport; + }); + }); + + it('stream transport should not be initialized by default', () => { + expect(manager.streamTransport).to.be.undefined; + expect(initStreamStub).to.not.have.been.called; + }); + + it('invokeQuery should route to REST by default and not initialize stream transport', async () => { + stubRestTransport.invokeQuery.resolves(testResponse); + await manager.invokeQuery( + queryName1, + variables1 + ); + expect(stubRestTransport.invokeQuery).to.have.been.calledWith( + queryName1, + variables1 + ); + expect(manager.streamTransport).to.be.undefined; + expect(initStreamStub).to.not.have.been.called; + }); + + it('invokeMutation should route to REST by default and not initialize stream transport', async () => { + stubRestTransport.invokeMutation.resolves(testResponse); + await manager.invokeMutation( + mutationName1, + variables1 + ); + expect(stubRestTransport.invokeMutation).to.have.been.calledWith( + mutationName1, + variables1 + ); + expect(manager.streamTransport).to.be.undefined; + expect(initStreamStub).to.not.have.been.called; + }); + + it('invokeSubscribe should route to streaming by default and initialize stream transport', () => { + const observer: SubscribeObserver = { + onData: () => {}, + onDisconnect: () => {}, + onError: () => {} + }; + manager.invokeSubscribe( + observer, + queryName1, + variables1 + ); + expect(stubRestTransport.invokeSubscribe).to.not.have.been.called; + expect(stubStreamTransport.invokeSubscribe).to.have.been.calledWith( + observer, + queryName1, + variables1 + ); + expect(manager.streamTransport).to.exist; + expect(initStreamStub).to.have.been.called; + }); + + it('invokeUnsubscribe should route to streaming by default when stream transport is already initialized and not initialize stream transport', () => { + manager.invokeUnsubscribe(queryName1, variables1); + expect(manager.streamTransport).to.be.undefined; + expect(initStreamStub).to.not.have.been.called; + expect(stubRestTransport.invokeUnsubscribe).to.not.have.been.called; + expect(stubStreamTransport.invokeUnsubscribe).to.not.have.been.called; + + manager.initStreamTransport(); + manager.invokeUnsubscribe(queryName1, variables1); + expect(stubRestTransport.invokeUnsubscribe).to.not.have.been.called; + expect(stubStreamTransport.invokeUnsubscribe).to.have.been.calledWith( + queryName1, + variables1 + ); + }); + + it('useEmulator should route to REST and streaming', () => { + manager.initStreamTransport(); + + manager.useEmulator('localhost', 9000, false); + + expect(stubRestTransport.useEmulator).to.have.been.calledOnceWith( + 'localhost', + 9000, + false + ); + expect(stubStreamTransport.useEmulator).to.have.been.calledOnceWith( + 'localhost', + 9000, + false + ); + }); + + it('onAuthTokenChanged should route to REST and streaming', () => { + manager.initStreamTransport(); + + manager.onAuthTokenChanged('new-token'); + + expect(stubRestTransport.onAuthTokenChanged).to.have.been.calledOnceWith( + 'new-token' + ); + expect( + stubStreamTransport.onAuthTokenChanged + ).to.have.been.calledOnceWith('new-token'); + }); + }); + + describe('dynamic transport routing', () => { + it('executeShouldUseStream should return false if streamTransport is not initialized', () => { + expect(manager.executeShouldUseStream()).to.be.false; + }); + + it('executeShouldUseStream should return true only when all stream conditions are met', () => { + const streamTransport = manager.initStreamTransport(); + + // Default state: not ready, no subs, no pending close + const streamIsReadyStub = sinon + .stub(streamTransport, 'streamIsReady') + .get(() => false); + const hasActiveSubscriptionsStub = sinon + .stub(streamTransport, 'hasActiveSubscriptions') + .get(() => false); + const isPendingCloseStub = sinon + .stub(streamTransport, 'isPendingClose') + .get(() => false); + + expect(manager.executeShouldUseStream()).to.be.false; + + // make stream ready, but still no active subscriptions + streamIsReadyStub.get(() => true); + expect(manager.executeShouldUseStream()).to.be.false; + + // add active subscriptions + hasActiveSubscriptionsStub.get(() => true); + expect(manager.executeShouldUseStream()).to.be.true; + + // pending close overrides readiness / active subscriptions + isPendingCloseStub.get(() => true); + expect(manager.executeShouldUseStream()).to.be.false; + }); + + describe('invokeQuery dynamic routing', () => { + it('invokeQuery should route to stream if executeShouldUseStream returns true', async () => { + const streamTransport = manager.initStreamTransport(); + sinon.stub(streamTransport, 'streamIsReady').get(() => true); + sinon.stub(streamTransport, 'isPendingClose').get(() => false); + sinon.stub(streamTransport, 'hasActiveSubscriptions').get(() => true); + sinon.stub(streamTransport, 'isUnableToConnect').get(() => false); + + const restSpy = sinon.stub(manager.restTransport, 'invokeQuery'); + const streamSpy = sinon + .stub(streamTransport, 'invokeQuery') + .resolves(testResponse); + + await manager.invokeQuery(queryName1, variables1); + + expect(streamSpy).to.have.been.calledOnceWith(queryName1, variables1); + expect(restSpy).to.have.not.been.called; + }); + + it('invokeQuery should throw an error if stream transport throws an error and executeShouldUseStream remains true', async () => { + const streamTransport = manager.initStreamTransport(); + sinon.stub(streamTransport, 'streamIsReady').get(() => true); + sinon.stub(streamTransport, 'isPendingClose').get(() => false); + sinon.stub(streamTransport, 'hasActiveSubscriptions').get(() => true); + sinon.stub(streamTransport, 'isUnableToConnect').get(() => false); + + const streamStub = sinon + .stub(streamTransport, 'invokeQuery') + .rejects(expectedError); + const restStub = sinon + .stub(manager.restTransport, 'invokeQuery') + .resolves(testResponse); + + await expect( + manager.invokeQuery(queryName1, variables1) + ).to.be.rejectedWith(expectedError); + + expect(streamStub).to.have.been.calledOnceWith(queryName1, variables1); + expect(restStub).to.not.have.been.called; + }); + + it('invokeQuery should fallback to REST if stream transport throws an error and then executeShouldUseStream becomes false', async () => { + const streamTransport = manager.initStreamTransport(); + sinon.stub(streamTransport, 'streamIsReady').get(() => true); + sinon.stub(streamTransport, 'isPendingClose').get(() => false); + sinon.stub(streamTransport, 'hasActiveSubscriptions').get(() => true); + sinon.stub(streamTransport, 'isUnableToConnect').get(() => false); + + const streamStub = sinon + .stub(streamTransport, 'invokeQuery') + .callsFake(async () => { + sinon.stub(streamTransport, 'isUnableToConnect').get(() => true); + throw expectedError; + }); + const restStub = sinon + .stub(manager.restTransport, 'invokeQuery') + .resolves(testResponse); + + await manager.invokeQuery(queryName1, variables1); + + expect(streamStub).to.have.been.calledOnceWith(queryName1, variables1); + expect(restStub).to.have.been.calledOnceWith(queryName1, variables1); + }); + }); + + describe('invokeMutation dynamic routing', () => { + it('invokeMutation should route to stream if executeShouldUseStream() returns true', async () => { + const streamTransport = manager.initStreamTransport(); + sinon.stub(streamTransport, 'streamIsReady').get(() => true); + sinon.stub(streamTransport, 'isPendingClose').get(() => false); + sinon.stub(streamTransport, 'hasActiveSubscriptions').get(() => true); + sinon.stub(streamTransport, 'isUnableToConnect').get(() => false); + + const restSpy = sinon.stub(manager.restTransport, 'invokeMutation'); + const streamSpy = sinon + .stub(streamTransport, 'invokeMutation') + .resolves(testResponse); + + await manager.invokeMutation(mutationName1, variables1); + + expect(streamSpy).to.have.been.calledOnceWith( + mutationName1, + variables1 + ); + expect(restSpy).to.have.not.been.called; + }); + + it('invokeMutation should throw an error if stream transport throws an error and executeShouldUseStream remains true', async () => { + const streamTransport = manager.initStreamTransport(); + sinon.stub(streamTransport, 'streamIsReady').get(() => true); + sinon.stub(streamTransport, 'isPendingClose').get(() => false); + sinon.stub(streamTransport, 'hasActiveSubscriptions').get(() => true); + sinon.stub(streamTransport, 'isUnableToConnect').get(() => false); + + const streamStub = sinon + .stub(streamTransport, 'invokeMutation') + .rejects(expectedError); + const restStub = sinon + .stub(manager.restTransport, 'invokeMutation') + .resolves(testResponse); + + await expect( + manager.invokeMutation(mutationName1, variables1) + ).to.be.rejectedWith(expectedError); + + expect(streamStub).to.have.been.calledOnceWith( + mutationName1, + variables1 + ); + expect(restStub).to.not.have.been.called; + }); + + it('invokeMutation should fallback to REST if stream transport throws an error and then executeShouldUseStream becomes false', async () => { + const streamTransport = manager.initStreamTransport(); + sinon.stub(streamTransport, 'streamIsReady').get(() => true); + sinon.stub(streamTransport, 'isPendingClose').get(() => false); + sinon.stub(streamTransport, 'hasActiveSubscriptions').get(() => true); + sinon.stub(streamTransport, 'isUnableToConnect').get(() => false); + + const streamStub = sinon + .stub(streamTransport, 'invokeMutation') + .callsFake(async () => { + sinon.stub(streamTransport, 'isUnableToConnect').get(() => true); + throw expectedError; + }); + const restStub = sinon + .stub(manager.restTransport, 'invokeMutation') + .resolves(testResponse); + + await manager.invokeMutation(mutationName1, variables1); + + expect(streamStub).to.have.been.calledOnceWith( + mutationName1, + variables1 + ); + expect(restStub).to.have.been.calledOnceWith(mutationName1, variables1); + }); + + it('invokeMutation should fallback to REST for all in-flight mutations if stream fails', async () => { + const streamTransport = manager.initStreamTransport(); + sinon.stub(streamTransport, 'streamIsReady').get(() => true); + sinon.stub(streamTransport, 'isPendingClose').get(() => false); + sinon.stub(streamTransport, 'hasActiveSubscriptions').get(() => true); + sinon.stub(streamTransport, 'isUnableToConnect').get(() => false); + + let rejectStream!: (reason: unknown) => void; + const streamPromise = new Promise((_, reject) => { + rejectStream = reject; + }); + + const streamStub = sinon + .stub(streamTransport, 'invokeMutation') + .returns( + streamPromise as unknown as Promise> + ); + + const restStub = sinon + .stub(manager.restTransport, 'invokeMutation') + .resolves(testResponse); + + const p1 = manager.invokeMutation(mutationName1, variables1); + const p2 = manager.invokeMutation('mutation2', { key: 'two' }); + + // Verify both called stream transport and are pending + expect(streamStub).to.have.been.calledTwice; + expect(restStub).to.not.have.been.called; + + // Mark stream as failed BEFORE resolving/rejecting to trigger fallback + sinon.stub(streamTransport, 'isUnableToConnect').get(() => true); + + // Fail the stream + rejectStream(expectedError); + + await Promise.all([p1, p2]); + + expect(restStub).to.have.been.calledTwice; + }); + }); + + describe('invokeSubscribe dynamic routing', () => { + it('invokeSubscribe should throw an error if isUnableToConnect is true', () => { + const observer: SubscribeObserver = { + onData: () => {}, + onDisconnect: () => {}, + onError: () => {} + }; + const streamTransport = manager.initStreamTransport(); + sinon.stub(streamTransport, 'isUnableToConnect').get(() => true); + + const streamStub = sinon + .stub(streamTransport, 'invokeSubscribe') + .rejects(expectedError); + const restStub = sinon + .stub(manager.restTransport, 'invokeSubscribe') + .resolves(testResponse); + + expect(() => + manager.invokeSubscribe(observer, queryName1, variables1) + ).to.throw('Subscriptions are unavailable'); + + expect(streamStub).to.not.have.been.called; + expect(restStub).to.not.have.been.called; + }); + }); + }); + + describe('disconnects', () => { + it('subscriber onDisconnect should be called when stream fails during active subscription', async () => { + const observer: SubscribeObserver = { + onData: sinon.stub(), + onDisconnect: sinon.stub(), + onError: sinon.stub() + }; + const streamTransport = manager.initStreamTransport(); + sinon.stub(streamTransport, 'streamIsReady').get(() => true); + sinon.stub(streamTransport, 'isPendingClose').get(() => false); + sinon.stub(streamTransport, 'hasActiveSubscriptions').get(() => true); + sinon.stub(streamTransport, 'isUnableToConnect').get(() => false); + + // Add observer directly to tracking map to verify onDisconnect propagation + const transportWithInternals = streamTransport as unknown as { + subscribeObservers: Map>; + }; + transportWithInternals.subscribeObservers = new Map([['1', observer]]); + + ( + streamTransport as unknown as StreamTransportWithInternals + ).onStreamClose(1006, 'Abnormal Closure'); + + expect(observer.onDisconnect).to.have.been.calledOnceWith( + Code.OTHER, + 'Stream disconnected with code 1006: Abnormal Closure' + ); + }); + + describe('idle timeout', () => { + let clock: sinon.SinonFakeTimers; + let streamTransport: WebSocketTransport; + let restInvokeQuerySpy: sinon.SinonStub; + + beforeEach(() => { + clock = sinon.useFakeTimers(); + streamTransport = manager.initStreamTransport() as WebSocketTransport; + const streamTransportPublic = streamTransport as unknown as { + openConnection(): Promise; + sendMessage(payload: unknown): Promise; + }; + sinon.stub(streamTransportPublic, 'openConnection').resolves(); + sinon.stub(streamTransportPublic, 'sendMessage').resolves(); + sinon.stub(streamTransport, 'streamIsReady').get(() => true); + restInvokeQuerySpy = sinon + .stub(manager.restTransport, 'invokeQuery') + .resolves(testResponse); + }); + + afterEach(() => { + clock.restore(); + }); + + it('should route to REST during idle timeout and disconnect after 60s', async () => { + const observer: SubscribeObserver = { + onData: () => {}, + onDisconnect: () => {}, + onError: () => {} + }; + + manager.invokeSubscribe(observer, queryName1, variables1); + expect(manager.executeShouldUseStream()).to.be.true; + + manager.invokeUnsubscribe(queryName1, variables1); + expect(manager.executeShouldUseStream()).to.be.false; + + // without active streams, should route to REST + restInvokeQuerySpy.resetHistory(); + await manager.invokeQuery(queryName1, variables1); + expect(restInvokeQuerySpy).to.have.been.calledOnce; + + await clock.tickAsync(59000); + expect(manager.streamTransport).to.exist; + + await manager.invokeQuery(queryName1, variables1); + expect(restInvokeQuerySpy).to.have.been.calledTwice; + + await clock.tickAsync(1000); + expect(manager.streamTransport).to.be.undefined; + }); + + it('should route to REST after stream automatically closes', async () => { + const observer: SubscribeObserver = { + onData: () => {}, + onDisconnect: () => {}, + onError: () => {} + }; + + manager.invokeSubscribe(observer, queryName1, variables1); + manager.invokeUnsubscribe(queryName1, variables1); + + await clock.tickAsync(60000); + expect(manager.streamTransport).to.be.undefined; + + restInvokeQuerySpy.resetHistory(); + await manager.invokeQuery(queryName1, variables1); + expect(restInvokeQuerySpy).to.have.been.calledOnce; + }); + + it('should route back to stream after reconnect', async () => { + const observer: SubscribeObserver = { + onData: () => {}, + onDisconnect: () => {}, + onError: () => {} + }; + + manager.invokeSubscribe(observer, queryName1, variables1); + manager.invokeUnsubscribe(queryName1, variables1); + + await clock.tickAsync(60000); + expect(manager.streamTransport).to.be.undefined; + + manager.invokeSubscribe(observer, queryName1, variables1); + const newStreamTransport = manager.streamTransport!; + const newStreamTransportPublic = newStreamTransport as unknown as { + openConnection(): Promise; + sendMessage(payload: unknown): Promise; + }; + sinon.stub(newStreamTransportPublic, 'openConnection').resolves(); + sinon.stub(newStreamTransportPublic, 'sendMessage').resolves(); + sinon.stub(newStreamTransport, 'streamIsReady').get(() => true); + const streamExecuteQueryStub = sinon + .stub(newStreamTransport, 'invokeQuery') + .resolves(testResponse); + await manager.invokeQuery(queryName1, variables1); + expect(streamExecuteQueryStub).to.have.been.calledOnce; + expect(restInvokeQuerySpy).to.have.not.been.called; + }); + }); + }); +}); diff --git a/packages/data-connect/test/unit/userAgent.test.ts b/packages/data-connect/test/unit/userAgent.test.ts index 2b39967276..c8aaad0952 100644 --- a/packages/data-connect/test/unit/userAgent.test.ts +++ b/packages/data-connect/test/unit/userAgent.test.ts @@ -22,7 +22,7 @@ import sinonChai from 'sinon-chai'; import { DataConnect, executeQuery, getDataConnect, queryRef } from '../../src'; import { SDK_VERSION } from '../../src/core/version'; -import { initializeFetch } from '../../src/network/fetch'; +import { initializeFetch } from '../../src/network/rest'; use(sinonChai); const json = { diff --git a/packages/data-connect/test/unit/websocketTransport.test.ts b/packages/data-connect/test/unit/websocketTransport.test.ts new file mode 100644 index 0000000000..0793b203e1 --- /dev/null +++ b/packages/data-connect/test/unit/websocketTransport.test.ts @@ -0,0 +1,374 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai'; +import * as chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import * as sinon from 'sinon'; +import sinonChai from 'sinon-chai'; + +import { DataConnectOptions } from '../../src/api/DataConnect'; +import { Code } from '../../src/core/error'; +import * as logger from '../../src/logger'; +import { + WEBSOCKET_CLOSE_CODE, + WebSocketTransport, + initializeWebSocket +} from '../../src/network/stream/websocket'; +import { DataConnectStreamRequest } from '../../src/network/stream/wire'; +import { DataConnectResponse } from '../../src/network/transport'; + +import { expectIsNotSettled, MockWebSocket } from './testUtils'; + +chai.use(sinonChai); +chai.use(chaiAsPromised); + +/** Interface that exposes some private fields and methods of WebSocketTransport for testing purposes. */ +interface TransportWithInternals { + openConnection(): Promise; + closeConnection(): Promise; + sendMessage(req: DataConnectStreamRequest): Promise; + connection: MockWebSocket | undefined; + streamIsReady: boolean; + handleResponse( + requestId: string, + response: DataConnectResponse + ): Promise; + rejectAllActiveRequests(code: Code, reason: string): void; +} + +describe('WebSocketTransport', () => { + const dcOptions: DataConnectOptions = { + projectId: 'p', + location: 'l', + service: 's', + connector: 'c' + }; + + let transport: TransportWithInternals; + + beforeEach(() => { + initializeWebSocket(MockWebSocket as unknown as typeof WebSocket); + transport = new WebSocketTransport( + dcOptions + ) as unknown as TransportWithInternals; + }); + + afterEach(() => { + initializeWebSocket(WebSocket); + sinon.restore(); + }); + + const connectionError = new Error('Test connection error'); + + describe('openConnection', () => { + it('should resolve when onopen fires', async () => { + const openPromise = transport.openConnection(); + await expectIsNotSettled(openPromise); + await transport.connection!.simulateOpen(); + await expect(openPromise).to.be.fulfilled; + }); + + it('should reject when onerror fires', async () => { + const openPromise = transport.openConnection(); + await expectIsNotSettled(openPromise); + await transport.connection!.simulateError(connectionError); + await expect(openPromise).to.be.rejectedWith(/Failed to open connection/); + }); + + it('should de-duplicate calls when already connected', async () => { + const openPromise1 = transport.openConnection(); + const onOpenSpy = sinon.spy(transport.connection!, 'onopen'); + await transport.connection!.simulateOpen(); + await openPromise1; + const previousConnection = transport.connection; + const openPromise2 = transport.openConnection(); + await openPromise2; + expect(transport.connection).to.equal(previousConnection); + expect(onOpenSpy).to.have.been.calledOnce; + }); + + it('should de-duplicate calls when open connection is pending', async () => { + const openPromise1 = transport.openConnection(); + const onOpenSpy = sinon.spy(transport.connection!, 'onopen'); + await expectIsNotSettled(openPromise1); + const openPromise2 = transport.openConnection(); + await expectIsNotSettled(openPromise2); + await transport.connection!.simulateOpen(); + await expect(openPromise1).to.be.fulfilled; + await expect(openPromise2).to.be.fulfilled; + expect(onOpenSpy).to.have.been.calledOnce; + }); + }); + + describe('streamIsReady', () => { + it('should be false initially', () => { + expect(transport.streamIsReady).to.be.false; + }); + + it('should be false while connecting', async () => { + const openPromise = transport.openConnection(); + await expectIsNotSettled(openPromise); + expect(transport.streamIsReady).to.be.false; + }); + + it('should be true when connected', async () => { + const openPromise = transport.openConnection(); + await transport.connection!.simulateOpen(); + await openPromise; + expect(transport.streamIsReady).to.be.true; + }); + + it('should be false after disconnected', async () => { + const openPromise = transport.openConnection(); + await transport.connection!.simulateOpen(); + await openPromise; + await transport.connection!.simulateClose(); + expect(transport.streamIsReady).to.be.false; + }); + }); + + describe('closeConnection', () => { + it('should close the underlying websocket and reset connection states', async () => { + const openPromise = transport.openConnection(); + await transport.connection!.simulateOpen(); + await openPromise; + const mockWs = transport.connection!; + await transport.closeConnection(); + expect(mockWs.close).to.have.been.calledOnce; + expect(transport.connection).to.be.undefined; + }); + + it('should be idempotent if connection is already closed', async () => { + await expect(transport.closeConnection()).to.be.fulfilled; + }); + + it('should return rejected promise and clean up if ws.close() throws', async () => { + const openPromise = transport.openConnection(); + await transport.connection!.simulateOpen(); + await openPromise; + const mockWs = transport.connection!; + mockWs.close = sinon.stub().throws(connectionError); + await expect(transport.closeConnection()).to.be.rejectedWith( + connectionError + ); + expect(transport.connection).to.be.undefined; + }); + }); + + describe('onclose handler (handleWebsocketDisconnect)', () => { + it('should reset connection state when websocket is closed externally', async () => { + const openPromise = transport.openConnection(); + await transport.connection!.simulateOpen(); + await openPromise; + expect(transport.connection).to.not.be.undefined; + // simulate server drop / unexpected closure + await transport.connection!.simulateClose(); + expect(transport.connection).to.be.undefined; + }); + + it('should call rejectAllActiveRequests and clean up when closed externally', async () => { + const openPromise = transport.openConnection(); + await transport.connection!.simulateOpen(); + await openPromise; + + const rejectSpy = sinon.spy(transport, 'rejectAllActiveRequests'); + + await transport.connection!.simulateClose(); + + expect(rejectSpy).to.have.been.calledOnce; + expect(rejectSpy.firstCall.args[0]).to.equal(Code.OTHER); + expect(rejectSpy.firstCall.args[1]).to.equal( + `Stream disconnected with code ${WEBSOCKET_CLOSE_CODE}: Normal Closure` + ); + }); + }); + + describe('sendMessage', () => { + const payload: DataConnectStreamRequest = { + requestId: '1', + execute: { operationName: 'testQuery' } + }; + + it('should not send until connection is open', async () => { + const sendPromise = transport.sendMessage(payload); + await expectIsNotSettled(sendPromise); + await transport.connection!.simulateOpen(); + await sendPromise; + expect(transport.connection!.send).to.have.been.calledOnce; + }); + + it('should send stringified json payload', async () => { + const sendPromise = transport.sendMessage(payload); + await transport.connection!.simulateOpen(); + await sendPromise; + expect(transport.connection!.send).to.have.been.calledOnceWith( + JSON.stringify(payload) + ); + }); + }); + + describe('handleWebSocketMessage', () => { + let logErrorStub: sinon.SinonStub; + beforeEach(() => { + logErrorStub = sinon.stub(logger, 'logError'); + }); + + const messageWithExtensions = { + result: { + requestId: '1', + data: { foo: 'bar' }, + errors: [], + extensions: { dataConnect: [{ entityIds: ['id1'] }] } + } + }; + + const messageWithoutExtensions = { + result: { + requestId: '2', + data: { abc: 'xyz' }, + errors: [] + } + }; + + it('should correctly parse incoming JSON and handle response', async () => { + const handleResponseStub = sinon + .stub(transport, 'handleResponse') + .resolves(); + + const openPromise = transport.openConnection(); + await transport.connection!.simulateOpen(); + await openPromise; + + await transport.connection!.simulateMessage( + JSON.stringify(messageWithExtensions) + ); + + expect(handleResponseStub).to.have.been.calledOnce; + const [calledRequestId, calledResponse] = + handleResponseStub.firstCall.args; + expect(calledRequestId).to.equal(messageWithExtensions.result.requestId); + expect(calledResponse.data).to.deep.equal( + messageWithExtensions.result.data + ); + expect(calledResponse.errors).to.deep.equal( + messageWithExtensions.result.errors + ); + expect(calledResponse.extensions).to.deep.equal( + messageWithExtensions.result.extensions + ); + }); + + it('should map extensions to empty array if not strictly provided', async () => { + const handleResponseStub = sinon + .stub(transport, 'handleResponse') + .resolves(); + + const openPromise = transport.openConnection(); + await transport.connection!.simulateOpen(); + await openPromise; + + await transport.connection!.simulateMessage( + JSON.stringify(messageWithoutExtensions) + ); + + expect(handleResponseStub).to.have.been.calledOnce; + const calledResponse = handleResponseStub.firstCall.args[1]; + expect(calledResponse.extensions).to.deep.equal({ dataConnect: [] }); + }); + + it('should close connection with error if message is not an object', async () => { + const openPromise = transport.openConnection(); + const mockWs = transport.connection!; + await mockWs.simulateOpen(); + await openPromise; + + await mockWs.simulateMessage( + JSON.stringify('this is a string, not an object') + ); + + expect(mockWs.close).to.have.been.calledOnceWith( + WEBSOCKET_CLOSE_CODE, + 'WebSocket message is not an object' + ); + expect(logErrorStub).to.have.been.calledOnce; + expect(logErrorStub).to.have.been.calledWithMatch( + 'DataConnect WebSocket error, closing stream' + ); + }); + + it('should close connection with error if result is missing', async () => { + const openPromise = transport.openConnection(); + const mockWs = transport.connection!; + await mockWs.simulateOpen(); + await openPromise; + + const invalidData = { foo: 'bar' }; // no result object + + await mockWs.simulateMessage(JSON.stringify(invalidData)); + + expect(mockWs.close).to.have.been.calledOnceWith( + WEBSOCKET_CLOSE_CODE, + 'WebSocket message from emulator did not include result' + ); + expect(logErrorStub).to.have.been.calledOnce; + expect(logErrorStub).to.have.been.calledWithMatch( + 'DataConnect WebSocket error, closing stream' + ); + }); + + it('should close connection with error if result is not an object', async () => { + const openPromise = transport.openConnection(); + const mockWs = transport.connection!; + await mockWs.simulateOpen(); + await openPromise; + + const invalidData = { result: 'string result' }; + + await mockWs.simulateMessage(JSON.stringify(invalidData)); + + expect(mockWs.close).to.have.been.calledOnceWith( + WEBSOCKET_CLOSE_CODE, + 'WebSocket message result is not an object' + ); + expect(logErrorStub).to.have.been.calledOnce; + expect(logErrorStub).to.have.been.calledWithMatch( + 'DataConnect WebSocket error, closing stream' + ); + }); + + it('should close connection with error if requestId is missing', async () => { + const openPromise = transport.openConnection(); + const mockWs = transport.connection!; + await mockWs.simulateOpen(); + await openPromise; + + const invalidData = { result: { foo: 'bar' } }; // no requestId + + await mockWs.simulateMessage(JSON.stringify(invalidData)); + + expect(mockWs.close).to.have.been.calledOnceWith( + WEBSOCKET_CLOSE_CODE, + 'WebSocket message did not include requestId' + ); + expect(logErrorStub).to.have.been.calledOnce; + expect(logErrorStub).to.have.been.calledWithMatch( + 'DataConnect WebSocket error, closing stream' + ); + }); + }); +}); From 34c63bf1eb353110d61d135a65e083d46e9a6007 Mon Sep 17 00:00:00 2001 From: Stephen Rosa <84193009+stephenarosaj@users.noreply.github.com> Date: Thu, 9 Apr 2026 10:17:05 -0700 Subject: [PATCH 133/174] fix(data-connect): Fix auth and app check token names on stream wire (#9822) --- .changeset/empty-tools-greet.md | 6 + .../src/network/stream/streamTransport.ts | 14 ++- .../data-connect/src/network/stream/wire.ts | 8 +- .../test/unit/streamTransport.test.ts | 108 +++++++++++++----- 4 files changed, 98 insertions(+), 38 deletions(-) create mode 100644 .changeset/empty-tools-greet.md diff --git a/.changeset/empty-tools-greet.md b/.changeset/empty-tools-greet.md new file mode 100644 index 0000000000..1d99fbd6a8 --- /dev/null +++ b/.changeset/empty-tools-greet.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/data-connect': minor +--- + +Fix header names for auth and app check tokens over streaming diff --git a/packages/data-connect/src/network/stream/streamTransport.ts b/packages/data-connect/src/network/stream/streamTransport.ts index 2028bf44b2..47063fac82 100644 --- a/packages/data-connect/src/network/stream/streamTransport.ts +++ b/packages/data-connect/src/network/stream/streamTransport.ts @@ -171,6 +171,8 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon private closeTimeoutFinished = false; /** current auth uid. used to detect if a different user logs in */ private authUid: string | null | undefined; + /** Flag to ensure we wait for the initial auth state once per connection attempt. */ + private hasWaitedForInitialAuth = false; /** * Tracks a query execution request, storing the request body and creating and storing a promise that @@ -329,6 +331,7 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon protected onConnectionReady(): void { this.isFirstStreamMessage = true; this.lastSentAuthToken = null; + this.hasWaitedForInitialAuth = false; } /** @@ -426,12 +429,12 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon this._callerSdkType ); if (this.shouldIncludeAuth && this._authToken) { - headers.authToken = this._authToken; + headers['X-Firebase-Auth-Token'] = this._authToken; this.lastSentAuthToken = this._authToken; } if (this.isFirstStreamMessage) { if (this._appCheckToken) { - headers.appCheckToken = this._appCheckToken; + headers['X-Firebase-App-Check'] = this._appCheckToken; } preparedRequestBody.name = this._connectorResourcePath; } @@ -440,14 +443,19 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon return preparedRequestBody; } + // TODO(stephenarosaj): just make this async /** * Sends a request message to the server via the concrete implementation. * Ensures the connection is ready and prepares the message before sending. * @returns A promise that resolves when the request message has been sent. */ - private sendRequestMessage( + private async sendRequestMessage( requestBody: DataConnectStreamRequest ): Promise { + if (!this.hasWaitedForInitialAuth && this.authProvider) { + await this.getWithAuth(); + this.hasWaitedForInitialAuth = true; + } if (this.streamIsReady) { const prepared = this.prepareMessage(requestBody); return this.sendMessage(prepared); diff --git a/packages/data-connect/src/network/stream/wire.ts b/packages/data-connect/src/network/stream/wire.ts index a214d46c1f..bc2a880b31 100644 --- a/packages/data-connect/src/network/stream/wire.ts +++ b/packages/data-connect/src/network/stream/wire.ts @@ -50,10 +50,10 @@ export interface StreamRequest { * @internal */ export interface StreamRequestHeaders { - /** used to initially authenticate or re-authenticate */ - authToken?: string; - /** used to initially authenticate or re-authenticate */ - appCheckToken?: string; + /** used to initially authenticate or re-authenticate user */ + 'X-Firebase-Auth-Token'?: string; + /** used to initially attest app */ + 'X-Firebase-App-Check'?: string; /** SDK telemetry header */ 'X-Goog-Api-Client'?: string; /** firebase appid */ diff --git a/packages/data-connect/test/unit/streamTransport.test.ts b/packages/data-connect/test/unit/streamTransport.test.ts index fc8b613583..f0106e380f 100644 --- a/packages/data-connect/test/unit/streamTransport.test.ts +++ b/packages/data-connect/test/unit/streamTransport.test.ts @@ -84,8 +84,10 @@ class TestStreamTransport extends AbstractDataConnectStreamTransport { } authProvider = { - getAuth: () => ({ getUid: () => this._authToken }) - } as AuthTokenProvider; + getAuth: () => ({ getUid: () => this._authToken }), + getToken: (forceToken?: boolean) => + Promise.resolve({ accessToken: this._authToken || 'token' }) + } as unknown as AuthTokenProvider; /** Manually set app check token for testing purposes. */ setAppCheckToken(token: string | null): void { @@ -116,6 +118,11 @@ interface TransportWithInternals { triggerOnConnectionReady(): void; closeConnection(): Promise; cancelClose(): void; + sendRequestMessage( + requestBody: DataConnectStreamRequest + ): Promise; + getWithAuth(forceToken?: boolean): Promise; + hasWaitedForInitialAuth: boolean; prepareMessage< Variables, StreamBody extends DataConnectStreamRequest @@ -209,12 +216,40 @@ describe('AbstractDataConnectStreamTransport', () => { transport.setAuthToken(initialAuthToken); transport.setAppCheckToken(initialAppCheckToken); transport.appId = initialAppId; + transport.hasWaitedForInitialAuth = true; }); afterEach(() => { sinon.restore(); }); + describe('sendRequestMessage', () => { + it('should wait until auth token and app check token have been initialized before sending the message', async () => { + transport.hasWaitedForInitialAuth = false; + + let resolveAuth!: () => void; + const authPromise = new Promise(resolve => { + resolveAuth = () => resolve('token'); + }); + + const getWithAuthStub = sinon + .stub(transport, 'getWithAuth') + .returns(authPromise); + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + + const promise = transport.sendRequestMessage(unpreparedMessage); + + expect(getWithAuthStub).to.have.been.calledOnce; + expect(sendMessageSpy).to.not.have.been.called; + + resolveAuth(); + await promise; + + expect(sendMessageSpy).to.have.been.calledOnce; + expect(sendMessageSpy).to.have.been.calledAfter(getWithAuthStub); + }); + }); + describe('prepareMessage', () => { it('should not change data fields', () => { const preparedMessage = transport.prepareMessage( @@ -235,7 +270,9 @@ describe('AbstractDataConnectStreamTransport', () => { unpreparedMessage ) as DataConnectStreamRequest; expect(preparedMessage.headers).to.exist; - expect(preparedMessage.headers?.authToken).to.equal(initialAuthToken); + expect(preparedMessage.headers?.['X-Firebase-Auth-Token']).to.equal( + initialAuthToken + ); }); it('should NOT add the same auth token to subsequent messages', () => { @@ -243,7 +280,8 @@ describe('AbstractDataConnectStreamTransport', () => { const secondPreparedMessage = transport.prepareMessage( unpreparedMessage ) as DataConnectStreamRequest; - expect(secondPreparedMessage.headers?.authToken).to.be.undefined; + expect(secondPreparedMessage.headers?.['X-Firebase-Auth-Token']).to.be + .undefined; }); it('should include auth token when it changes', () => { @@ -251,14 +289,15 @@ describe('AbstractDataConnectStreamTransport', () => { const secondPreparedMessage = transport.prepareMessage( unpreparedMessage ) as DataConnectStreamRequest; - expect(secondPreparedMessage.headers?.authToken).to.be.undefined; + expect(secondPreparedMessage.headers?.['X-Firebase-Auth-Token']).to.be + .undefined; transport.setAuthToken(newAuthToken); const thirdPreparedMessage = transport.prepareMessage( unpreparedMessage ) as DataConnectStreamRequest; - expect(thirdPreparedMessage.headers?.authToken).to.equal( - newAuthToken - ); + expect( + thirdPreparedMessage.headers?.['X-Firebase-Auth-Token'] + ).to.equal(newAuthToken); }); }); @@ -268,9 +307,9 @@ describe('AbstractDataConnectStreamTransport', () => { unpreparedMessage ) as DataConnectStreamRequest; expect(firstPreparedMessage.headers).to.exist; - expect(firstPreparedMessage.headers?.appCheckToken).to.equal( - initialAppCheckToken - ); + expect( + firstPreparedMessage.headers?.['X-Firebase-App-Check'] + ).to.equal(initialAppCheckToken); }); it('should NOT add the same app check token to subsequent messages', () => { @@ -278,7 +317,8 @@ describe('AbstractDataConnectStreamTransport', () => { const secondPreparedMessage = transport.prepareMessage( unpreparedMessage ) as DataConnectStreamRequest; - expect(secondPreparedMessage.headers?.appCheckToken).to.be.undefined; + expect(secondPreparedMessage.headers?.['X-Firebase-App-Check']).to.be + .undefined; }); it('should NOT include app check token when it changes', () => { @@ -286,12 +326,14 @@ describe('AbstractDataConnectStreamTransport', () => { const secondPreparedMessage = transport.prepareMessage( unpreparedMessage ) as DataConnectStreamRequest; - expect(secondPreparedMessage.headers?.appCheckToken).to.be.undefined; + expect(secondPreparedMessage.headers?.['X-Firebase-App-Check']).to.be + .undefined; transport.setAppCheckToken(newAppCheckToken); const thirdPreparedMessage = transport.prepareMessage( unpreparedMessage ) as DataConnectStreamRequest; - expect(thirdPreparedMessage.headers?.appCheckToken).to.be.undefined; + expect(thirdPreparedMessage.headers?.['X-Firebase-App-Check']).to.be + .undefined; }); }); @@ -374,8 +416,8 @@ describe('AbstractDataConnectStreamTransport', () => { unpreparedMessage ) as DataConnectStreamRequest; expect(secondMessage.name).to.be.undefined; - expect(secondMessage.headers?.appCheckToken).to.be.undefined; - expect(secondMessage.headers?.authToken).to.be.undefined; + expect(secondMessage.headers?.['X-Firebase-App-Check']).to.be.undefined; + expect(secondMessage.headers?.['X-Firebase-Auth-Token']).to.be.undefined; // Trigger the physical connection reset transport.triggerOnConnectionReady(); @@ -385,10 +427,12 @@ describe('AbstractDataConnectStreamTransport', () => { unpreparedMessage ) as DataConnectStreamRequest; expect(thirdMessage.name).to.equal(expectedName); - expect(thirdMessage.headers?.appCheckToken).to.equal( + expect(thirdMessage.headers?.['X-Firebase-App-Check']).to.equal( initialAppCheckToken ); - expect(thirdMessage.headers?.authToken).to.equal(initialAuthToken); + expect(thirdMessage.headers?.['X-Firebase-Auth-Token']).to.equal( + initialAuthToken + ); }); }); @@ -592,6 +636,11 @@ describe('AbstractDataConnectStreamTransport', () => { onDisconnect: sinon.spy(), onError: sinon.spy() }; + + const sendMessageStub = sinon.stub(transport, 'sendMessage'); + sendMessageStub.onFirstCall().resolves(); + sendMessageStub.onSecondCall().rejects(expectedError); + transport.invokeSubscribe(observer, queryName1, variables1); const expectedKey = transport.getMapKey(queryName1, variables1); @@ -599,14 +648,11 @@ describe('AbstractDataConnectStreamTransport', () => { transport.activeSubscribeRequests.get(expectedKey); const subscribeRequestId = subscribeRequest?.requestId!; - const sendMessageStub = sinon - .stub(transport, 'sendMessage') - .rejects(expectedError); transport.invokeUnsubscribe(queryName1, variables1); // invokeUnsubscribe's sendMessage is fire and forget await sleep(500); - expect(sendMessageStub).to.have.been.calledOnce; + expect(sendMessageStub).to.have.been.calledTwice; expect(logErrorStub).to.have.been.calledOnce; expect(logErrorStub).to.have.been.calledWithMatch( 'Stream Transport failed to send unsubscribe message' @@ -1025,10 +1071,10 @@ describe('AbstractDataConnectStreamTransport', () => { await transport.invokeSubscribe(observer, queryName1, variables1); await transport.invokeUnsubscribe(queryName1, variables1); - clock.tick(1000 * 59); + await clock.tickAsync(1000 * 59); expect(closeSpy).to.not.have.been.called; - clock.tick(1000 * 2); + await clock.tickAsync(1000 * 2); expect(closeSpy).to.have.been.calledOnce; }); @@ -1044,12 +1090,12 @@ describe('AbstractDataConnectStreamTransport', () => { await transport.invokeSubscribe(observer, queryName1, variables1); await transport.invokeUnsubscribe(queryName1, variables1); - clock.tick(1000 * 30); + await clock.tickAsync(1000 * 30); expect(closeSpy).to.not.have.been.called; await transport.invokeSubscribe(observer, queryName2, variables2); - clock.tick(1000 * 65); + await clock.tickAsync(1000 * 65); expect(closeSpy).to.not.have.been.called; }); @@ -1066,16 +1112,16 @@ describe('AbstractDataConnectStreamTransport', () => { await transport.invokeSubscribe(observer, queryName1, variables1); await transport.invokeUnsubscribe(queryName1, variables1); - clock.tick(1000 * 30); + await clock.tickAsync(1000 * 30); expect(closeSpy).to.not.have.been.called; sendMessageStub.rejects(); await transport.invokeSubscribe(observer, queryName2, variables2); - clock.tick(1000 * 30); + await clock.tickAsync(1000 * 30); expect(closeSpy).to.not.have.been.called; - clock.tick(1000 * 35); + await clock.tickAsync(1000 * 35); expect(closeSpy).to.have.been.calledOnce; }); @@ -1093,7 +1139,7 @@ describe('AbstractDataConnectStreamTransport', () => { void transport.invokeQuery(queryName2, variables2); - clock.tick(1000 * 65); + await clock.tickAsync(1000 * 65); expect(closeSpy).to.not.have.been.called; }); @@ -1111,7 +1157,7 @@ describe('AbstractDataConnectStreamTransport', () => { const queryPromise = transport.invokeQuery(queryName2, variables2); - clock.tick(1000 * 65); + await clock.tickAsync(1000 * 65); expect(closeSpy).to.not.have.been.called; const expectedKey = transport.getMapKey(queryName2, variables2); From 78fc282d7cf7feefd65b7e337852b8a02461048a Mon Sep 17 00:00:00 2001 From: Google Open Source Bot Date: Thu, 9 Apr 2026 11:50:04 -0700 Subject: [PATCH 134/174] Version Packages (#9821) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/angry-ears-grow.md | 6 --- .changeset/cold-moles-compare.md | 6 --- .changeset/cool-dragons-compete.md | 6 --- .changeset/eighty-cameras-smoke.md | 5 --- .changeset/empty-tools-greet.md | 6 --- .changeset/funky-teeth-pick.md | 6 --- .changeset/gold-chefs-jam.md | 6 --- .changeset/happy-bugs-attack.md | 6 --- .changeset/orange-schools-bake.md | 6 --- .changeset/orange-worms-juggle.md | 6 --- .changeset/rotten-tigers-bake.md | 6 --- .changeset/shiny-papayas-begin.md | 5 --- .changeset/slimy-carpets-flow.md | 6 --- .changeset/smooth-apes-lick.md | 6 --- .changeset/sour-peaches-attend.md | 5 --- .changeset/stupid-turtles-grow.md | 5 --- .changeset/ten-pugs-tie.md | 6 --- .changeset/thick-roses-lick.md | 6 --- .changeset/thin-seas-accept.md | 6 --- integration/compat-interop/package.json | 8 ++-- integration/firestore/package.json | 4 +- integration/messaging/package.json | 2 +- packages/ai/CHANGELOG.md | 16 ++++++++ packages/ai/package.json | 4 +- packages/analytics-compat/package.json | 2 +- packages/analytics/package.json | 2 +- packages/app-check-compat/package.json | 2 +- packages/app-check/package.json | 2 +- packages/app-compat/CHANGELOG.md | 7 ++++ packages/app-compat/package.json | 4 +- packages/app-types/CHANGELOG.md | 6 +++ packages/app-types/package.json | 2 +- packages/app/CHANGELOG.md | 6 +++ packages/app/package.json | 2 +- packages/auth-compat/CHANGELOG.md | 7 ++++ packages/auth-compat/package.json | 6 +-- packages/auth/CHANGELOG.md | 6 +++ packages/auth/package.json | 4 +- packages/data-connect/CHANGELOG.md | 8 ++++ packages/data-connect/package.json | 4 +- packages/database-compat/CHANGELOG.md | 7 ++++ packages/database-compat/package.json | 6 +-- packages/database-types/CHANGELOG.md | 7 ++++ packages/database-types/package.json | 4 +- packages/database/package.json | 2 +- packages/firebase/CHANGELOG.md | 48 ++++++++++++++++++++++ packages/firebase/package.json | 22 +++++----- packages/firestore-compat/CHANGELOG.md | 7 ++++ packages/firestore-compat/package.json | 6 +-- packages/firestore/CHANGELOG.md | 26 ++++++++++++ packages/firestore/package.json | 8 ++-- packages/functions-compat/package.json | 2 +- packages/functions/package.json | 2 +- packages/installations-compat/package.json | 2 +- packages/installations/package.json | 2 +- packages/messaging-compat/package.json | 2 +- packages/messaging/package.json | 2 +- packages/performance-compat/package.json | 2 +- packages/performance/package.json | 2 +- packages/remote-config-compat/package.json | 2 +- packages/remote-config/package.json | 2 +- packages/storage-compat/package.json | 4 +- packages/storage/package.json | 4 +- packages/template/package.json | 2 +- repo-scripts/size-analysis/package.json | 2 +- 65 files changed, 215 insertions(+), 174 deletions(-) delete mode 100644 .changeset/angry-ears-grow.md delete mode 100644 .changeset/cold-moles-compare.md delete mode 100644 .changeset/cool-dragons-compete.md delete mode 100644 .changeset/eighty-cameras-smoke.md delete mode 100644 .changeset/empty-tools-greet.md delete mode 100644 .changeset/funky-teeth-pick.md delete mode 100644 .changeset/gold-chefs-jam.md delete mode 100644 .changeset/happy-bugs-attack.md delete mode 100644 .changeset/orange-schools-bake.md delete mode 100644 .changeset/orange-worms-juggle.md delete mode 100644 .changeset/rotten-tigers-bake.md delete mode 100644 .changeset/shiny-papayas-begin.md delete mode 100644 .changeset/slimy-carpets-flow.md delete mode 100644 .changeset/smooth-apes-lick.md delete mode 100644 .changeset/sour-peaches-attend.md delete mode 100644 .changeset/stupid-turtles-grow.md delete mode 100644 .changeset/ten-pugs-tie.md delete mode 100644 .changeset/thick-roses-lick.md delete mode 100644 .changeset/thin-seas-accept.md diff --git a/.changeset/angry-ears-grow.md b/.changeset/angry-ears-grow.md deleted file mode 100644 index 0aba2d0288..0000000000 --- a/.changeset/angry-ears-grow.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -[deprecated] All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). diff --git a/.changeset/cold-moles-compare.md b/.changeset/cold-moles-compare.md deleted file mode 100644 index 7c2e278a36..0000000000 --- a/.changeset/cold-moles-compare.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/firestore': minor -'firebase': minor ---- - -Add support for the parent expression diff --git a/.changeset/cool-dragons-compete.md b/.changeset/cool-dragons-compete.md deleted file mode 100644 index b8405e7758..0000000000 --- a/.changeset/cool-dragons-compete.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/firestore': minor ---- - -Add support for timestamp_trunc, timestamp_diff and timestamp_extract expressions diff --git a/.changeset/eighty-cameras-smoke.md b/.changeset/eighty-cameras-smoke.md deleted file mode 100644 index ecb3a6e188..0000000000 --- a/.changeset/eighty-cameras-smoke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/app-types': patch ---- - -Fix typo in package.json (dependency => dependencies) diff --git a/.changeset/empty-tools-greet.md b/.changeset/empty-tools-greet.md deleted file mode 100644 index 1d99fbd6a8..0000000000 --- a/.changeset/empty-tools-greet.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/data-connect': minor ---- - -Fix header names for auth and app check tokens over streaming diff --git a/.changeset/funky-teeth-pick.md b/.changeset/funky-teeth-pick.md deleted file mode 100644 index 89e43a08fd..0000000000 --- a/.changeset/funky-teeth-pick.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/auth': minor ---- - -Updated the peer dependency range for @react-native-async-storage/async-storage to support both v2 and v3 diff --git a/.changeset/gold-chefs-jam.md b/.changeset/gold-chefs-jam.md deleted file mode 100644 index c7d57e9f46..0000000000 --- a/.changeset/gold-chefs-jam.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -Deprecate `topK` and `temperature` properties for hybrid inference mode. diff --git a/.changeset/happy-bugs-attack.md b/.changeset/happy-bugs-attack.md deleted file mode 100644 index 82e6d18ae5..0000000000 --- a/.changeset/happy-bugs-attack.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"firebase": minor -"@firebase/firestore": minor ---- - -Added public preview support for full-text and geo search in Pipelines. diff --git a/.changeset/orange-schools-bake.md b/.changeset/orange-schools-bake.md deleted file mode 100644 index 6976b8301e..0000000000 --- a/.changeset/orange-schools-bake.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': patch -'@firebase/firestore': patch ---- - -Refactor the parameters for timestamp expressions and change all timegranularity value to lowercase diff --git a/.changeset/orange-worms-juggle.md b/.changeset/orange-worms-juggle.md deleted file mode 100644 index 8cdd22ce70..0000000000 --- a/.changeset/orange-worms-juggle.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/firestore': minor ---- - -Add support for logical expressions `nor` and `switchOn`. diff --git a/.changeset/rotten-tigers-bake.md b/.changeset/rotten-tigers-bake.md deleted file mode 100644 index 0f0c544146..0000000000 --- a/.changeset/rotten-tigers-bake.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/firestore': minor ---- - -Add support for pipeline expressions `ifNull` and `coalesce`. diff --git a/.changeset/shiny-papayas-begin.md b/.changeset/shiny-papayas-begin.md deleted file mode 100644 index 27fd6a9a9a..0000000000 --- a/.changeset/shiny-papayas-begin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/ai': patch ---- - -Fixed a bug that causes the model to error if the user specifies `responseSchema` or `responseJsonSchema`. diff --git a/.changeset/slimy-carpets-flow.md b/.changeset/slimy-carpets-flow.md deleted file mode 100644 index 83c246a138..0000000000 --- a/.changeset/slimy-carpets-flow.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -Add `startChat()` for `TemplateGenerativeModel`. diff --git a/.changeset/smooth-apes-lick.md b/.changeset/smooth-apes-lick.md deleted file mode 100644 index 1d5c162db9..0000000000 --- a/.changeset/smooth-apes-lick.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -Add automatic function calling and chat history for server prompt templates. diff --git a/.changeset/sour-peaches-attend.md b/.changeset/sour-peaches-attend.md deleted file mode 100644 index a0be554f67..0000000000 --- a/.changeset/sour-peaches-attend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/firestore': patch ---- - -Read user data when using internal pipeline proto serialization. diff --git a/.changeset/stupid-turtles-grow.md b/.changeset/stupid-turtles-grow.md deleted file mode 100644 index 5f4204fcda..0000000000 --- a/.changeset/stupid-turtles-grow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/firestore': patch ---- - -Read user data from pipeline in union stage. Fixes [GitHub Issue #9764](https://github.com/firebase/firebase-js-sdk/issues/9764) diff --git a/.changeset/ten-pugs-tie.md b/.changeset/ten-pugs-tie.md deleted file mode 100644 index 9eefb840c7..0000000000 --- a/.changeset/ten-pugs-tie.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/firestore': minor ---- - -Add subquery support to Pipelines. diff --git a/.changeset/thick-roses-lick.md b/.changeset/thick-roses-lick.md deleted file mode 100644 index 37735e6a02..0000000000 --- a/.changeset/thick-roses-lick.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/data-connect': minor ---- - -Add streaming support for Firebase Data Connect. diff --git a/.changeset/thin-seas-accept.md b/.changeset/thin-seas-accept.md deleted file mode 100644 index 82b82d5743..0000000000 --- a/.changeset/thin-seas-accept.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': minor -'@firebase/firestore': minor ---- - -**Beta API Breaking Change**: Change `Type` string union to be a raw string. diff --git a/integration/compat-interop/package.json b/integration/compat-interop/package.json index ea55aaf2c9..31316d9b6c 100644 --- a/integration/compat-interop/package.json +++ b/integration/compat-interop/package.json @@ -8,12 +8,12 @@ "test:debug": "karma start --browsers Chrome --auto-watch" }, "dependencies": { - "@firebase/app": "0.14.10", - "@firebase/app-compat": "0.5.10", + "@firebase/app": "0.14.11", + "@firebase/app-compat": "0.5.11", "@firebase/analytics": "0.10.21", "@firebase/analytics-compat": "0.2.27", - "@firebase/auth": "1.12.2", - "@firebase/auth-compat": "0.6.4", + "@firebase/auth": "1.13.0", + "@firebase/auth-compat": "0.6.5", "@firebase/functions": "0.13.3", "@firebase/functions-compat": "0.4.3", "@firebase/messaging": "0.12.25", diff --git a/integration/firestore/package.json b/integration/firestore/package.json index e97286e55c..60251ecce8 100644 --- a/integration/firestore/package.json +++ b/integration/firestore/package.json @@ -15,8 +15,8 @@ "test:memory:debug": "yarn build:memory; karma start --auto-watch --browsers Chrome" }, "dependencies": { - "@firebase/app": "0.14.10", - "@firebase/firestore": "4.13.0" + "@firebase/app": "0.14.11", + "@firebase/firestore": "4.14.0" }, "devDependencies": { "@types/mocha": "9.1.1", diff --git a/integration/messaging/package.json b/integration/messaging/package.json index df15118987..90432df4d7 100644 --- a/integration/messaging/package.json +++ b/integration/messaging/package.json @@ -9,7 +9,7 @@ "test:manual": "mocha --exit" }, "devDependencies": { - "firebase": "12.11.0", + "firebase": "12.12.0", "chai": "4.5.0", "chromedriver": "119.0.1", "express": "4.21.2", diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 670d2fe498..d55c70057a 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,5 +1,21 @@ # @firebase/ai +## 2.11.0 + +### Minor Changes + +- [`cccb6d0`](https://github.com/firebase/firebase-js-sdk/commit/cccb6d058cc2dac5495b797740697902ddfd4a93) [#9771](https://github.com/firebase/firebase-js-sdk/pull/9771) - [deprecated] All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). + +- [`6cbe865`](https://github.com/firebase/firebase-js-sdk/commit/6cbe86569cc49ed12e9e53173bb66e8624bc8d6e) [#9816](https://github.com/firebase/firebase-js-sdk/pull/9816) - Deprecate `topK` and `temperature` properties for hybrid inference mode. + +- [`9c8e864`](https://github.com/firebase/firebase-js-sdk/commit/9c8e8640e5ba91f2a3b1aa9229059dc35d0c427e) [#9763](https://github.com/firebase/firebase-js-sdk/pull/9763) - Add `startChat()` for `TemplateGenerativeModel`. + +- [`9c8e864`](https://github.com/firebase/firebase-js-sdk/commit/9c8e8640e5ba91f2a3b1aa9229059dc35d0c427e) [#9763](https://github.com/firebase/firebase-js-sdk/pull/9763) - Add automatic function calling and chat history for server prompt templates. + +### Patch Changes + +- [`f87c15e`](https://github.com/firebase/firebase-js-sdk/commit/f87c15e97af9913182ebaa1afb94a3fe802e04f4) [#9791](https://github.com/firebase/firebase-js-sdk/pull/9791) (fixes [#9792](https://github.com/firebase/firebase-js-sdk/issues/9792)) - Fixed a bug that causes the model to error if the user specifies `responseSchema` or `responseJsonSchema`. + ## 2.10.0 ### Minor Changes diff --git a/packages/ai/package.json b/packages/ai/package.json index 4c0b0ba525..57ecf62ed5 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/ai", - "version": "2.10.0", + "version": "2.11.0", "description": "The Firebase AI SDK", "author": "Firebase (https://firebase.google.com/)", "engines": { @@ -60,7 +60,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/analytics-compat/package.json b/packages/analytics-compat/package.json index 3c6bc734ff..22683f75d3 100644 --- a/packages/analytics-compat/package.json +++ b/packages/analytics-compat/package.json @@ -22,7 +22,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.10", + "@firebase/app-compat": "0.5.11", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/analytics/package.json b/packages/analytics/package.json index 4cce969cd4..c6b9eb35ad 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -47,7 +47,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "@rollup/plugin-commonjs": "21.1.0", diff --git a/packages/app-check-compat/package.json b/packages/app-check-compat/package.json index 1d8a31a447..aee72f1914 100644 --- a/packages/app-check-compat/package.json +++ b/packages/app-check-compat/package.json @@ -43,7 +43,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.10", + "@firebase/app-compat": "0.5.11", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-check/package.json b/packages/app-check/package.json index 504f003ad3..7ed374f48a 100644 --- a/packages/app-check/package.json +++ b/packages/app-check/package.json @@ -44,7 +44,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-compat/CHANGELOG.md b/packages/app-compat/CHANGELOG.md index a6adc07872..7ca05cc021 100644 --- a/packages/app-compat/CHANGELOG.md +++ b/packages/app-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/app-compat +## 0.5.11 + +### Patch Changes + +- Updated dependencies []: + - @firebase/app@0.14.11 + ## 0.5.10 ### Patch Changes diff --git a/packages/app-compat/package.json b/packages/app-compat/package.json index 116343627e..c281a6fc90 100644 --- a/packages/app-compat/package.json +++ b/packages/app-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-compat", - "version": "0.5.10", + "version": "0.5.11", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,7 +37,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "@firebase/util": "1.15.0", "@firebase/logger": "0.5.0", "@firebase/component": "0.7.2", diff --git a/packages/app-types/CHANGELOG.md b/packages/app-types/CHANGELOG.md index 35adae68b2..34faf4fca2 100644 --- a/packages/app-types/CHANGELOG.md +++ b/packages/app-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/app-types +## 0.9.4 + +### Patch Changes + +- [`b2c4646`](https://github.com/firebase/firebase-js-sdk/commit/b2c464643548e068f56d9f57a09b105b1b898ff1) [#9813](https://github.com/firebase/firebase-js-sdk/pull/9813) (fixes [#9787](https://github.com/firebase/firebase-js-sdk/issues/9787)) - Fix typo in package.json (dependency => dependencies) + ## 0.9.3 ### Patch Changes diff --git a/packages/app-types/package.json b/packages/app-types/package.json index 6c7fcee136..82ec52477d 100644 --- a/packages/app-types/package.json +++ b/packages/app-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-types", - "version": "0.9.3", + "version": "0.9.4", "description": "@firebase/app Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 9293be09ee..4e86935681 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/app +## 0.14.11 + +### Patch Changes + +- Update SDK_VERSION. + ## 0.14.10 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 264677f2db..b5c33c970c 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app", - "version": "0.14.10", + "version": "0.14.11", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", diff --git a/packages/auth-compat/CHANGELOG.md b/packages/auth-compat/CHANGELOG.md index b3a505c481..6226cfad25 100644 --- a/packages/auth-compat/CHANGELOG.md +++ b/packages/auth-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/auth-compat +## 0.6.5 + +### Patch Changes + +- Updated dependencies [[`715c042`](https://github.com/firebase/firebase-js-sdk/commit/715c0424d656b1be2d423c31f12e9ffbaeea2dd5)]: + - @firebase/auth@1.13.0 + ## 0.6.4 ### Patch Changes diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index 2ced0e34b8..e31b7a4db4 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth-compat", - "version": "0.6.4", + "version": "0.6.5", "description": "FirebaseAuth compatibility package that uses API style compatible with Firebase@8 and prior versions", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -49,7 +49,7 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/auth": "1.12.2", + "@firebase/auth": "1.13.0", "@firebase/auth-types": "0.13.0", "@firebase/component": "0.7.2", "@firebase/util": "1.15.0", @@ -57,7 +57,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.10", + "@firebase/app-compat": "0.5.11", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/auth/CHANGELOG.md b/packages/auth/CHANGELOG.md index 3301b964b2..86db43f7a5 100644 --- a/packages/auth/CHANGELOG.md +++ b/packages/auth/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/auth +## 1.13.0 + +### Minor Changes + +- [`715c042`](https://github.com/firebase/firebase-js-sdk/commit/715c0424d656b1be2d423c31f12e9ffbaeea2dd5) [#9740](https://github.com/firebase/firebase-js-sdk/pull/9740) (fixes [#9739](https://github.com/firebase/firebase-js-sdk/issues/9739)) - Updated the peer dependency range for @react-native-async-storage/async-storage to support both v2 and v3 + ## 1.12.2 ### Patch Changes diff --git a/packages/auth/package.json b/packages/auth/package.json index 60b0e5fa7b..66dc2265ad 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth", - "version": "1.12.2", + "version": "1.13.0", "description": "The Firebase Authenticaton component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/node/index.js", @@ -131,7 +131,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-strip": "3.0.4", "@types/express": "4.17.21", diff --git a/packages/data-connect/CHANGELOG.md b/packages/data-connect/CHANGELOG.md index 3d144028a6..b6cc55d062 100644 --- a/packages/data-connect/CHANGELOG.md +++ b/packages/data-connect/CHANGELOG.md @@ -1,5 +1,13 @@ ## Unreleased +## 0.6.0 + +### Minor Changes + +- [`34c63bf`](https://github.com/firebase/firebase-js-sdk/commit/34c63bf1eb353110d61d135a65e083d46e9a6007) [#9822](https://github.com/firebase/firebase-js-sdk/pull/9822) - Fix header names for auth and app check tokens over streaming + +- [`87d5cc1`](https://github.com/firebase/firebase-js-sdk/commit/87d5cc1ba0107cb9a7a07bc6033dcec360f78d28) [#9809](https://github.com/firebase/firebase-js-sdk/pull/9809) - Add streaming support for Firebase Data Connect. + ## 0.5.0 ### Minor Changes diff --git a/packages/data-connect/package.json b/packages/data-connect/package.json index 402dafdba9..93903d9621 100644 --- a/packages/data-connect/package.json +++ b/packages/data-connect/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/data-connect", - "version": "0.5.0", + "version": "0.6.0", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -55,7 +55,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/database-compat/CHANGELOG.md b/packages/database-compat/CHANGELOG.md index b72097f612..30bee1068f 100644 --- a/packages/database-compat/CHANGELOG.md +++ b/packages/database-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/database-compat +## 2.1.3 + +### Patch Changes + +- Updated dependencies []: + - @firebase/database-types@1.0.19 + ## 2.1.2 ### Patch Changes diff --git a/packages/database-compat/package.json b/packages/database-compat/package.json index ef63bc25e6..9c0868b5aa 100644 --- a/packages/database-compat/package.json +++ b/packages/database-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database-compat", - "version": "2.1.2", + "version": "2.1.3", "description": "The Realtime Database component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.js", @@ -50,14 +50,14 @@ }, "dependencies": { "@firebase/database": "1.1.2", - "@firebase/database-types": "1.0.18", + "@firebase/database-types": "1.0.19", "@firebase/logger": "0.5.0", "@firebase/util": "1.15.0", "@firebase/component": "0.7.2", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.10", + "@firebase/app-compat": "0.5.11", "typescript": "5.5.4" }, "repository": { diff --git a/packages/database-types/CHANGELOG.md b/packages/database-types/CHANGELOG.md index 4a22c0f0e5..9a0ce22106 100644 --- a/packages/database-types/CHANGELOG.md +++ b/packages/database-types/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/database-types +## 1.0.19 + +### Patch Changes + +- Updated dependencies [[`b2c4646`](https://github.com/firebase/firebase-js-sdk/commit/b2c464643548e068f56d9f57a09b105b1b898ff1)]: + - @firebase/app-types@0.9.4 + ## 1.0.18 ### Patch Changes diff --git a/packages/database-types/package.json b/packages/database-types/package.json index 4e0bc17b05..572b300e24 100644 --- a/packages/database-types/package.json +++ b/packages/database-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database-types", - "version": "1.0.18", + "version": "1.0.19", "description": "@firebase/database Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -12,7 +12,7 @@ "index.d.ts" ], "dependencies": { - "@firebase/app-types": "0.9.3", + "@firebase/app-types": "0.9.4", "@firebase/util": "1.15.0" }, "repository": { diff --git a/packages/database/package.json b/packages/database/package.json index 0cb83dbe84..3190989e7e 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -57,7 +57,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/packages/firebase/CHANGELOG.md b/packages/firebase/CHANGELOG.md index b55fed5117..6373e171f8 100644 --- a/packages/firebase/CHANGELOG.md +++ b/packages/firebase/CHANGELOG.md @@ -1,5 +1,53 @@ # firebase +## 12.12.0 + +### Minor Changes + +- [`cccb6d0`](https://github.com/firebase/firebase-js-sdk/commit/cccb6d058cc2dac5495b797740697902ddfd4a93) [#9771](https://github.com/firebase/firebase-js-sdk/pull/9771) - [deprecated] All Imagen models are deprecated and will shut down as early as June 2026. As a replacement, you can [migrate your apps to use Gemini Image models (the "Nano Banana" models)](https://firebase.google.com/docs/ai-logic/imagen-models-migration). + +- [`44c234c`](https://github.com/firebase/firebase-js-sdk/commit/44c234c2ba5f8ba18a2f2c99fe63df7692010bf3) [#9773](https://github.com/firebase/firebase-js-sdk/pull/9773) - Add support for the parent expression + +- [`5cd6509`](https://github.com/firebase/firebase-js-sdk/commit/5cd6509bdb1eedc9a37ed6ce7677450f574a7e9d) [#9728](https://github.com/firebase/firebase-js-sdk/pull/9728) - Add support for timestamp_trunc, timestamp_diff and timestamp_extract expressions + +- [`34c63bf`](https://github.com/firebase/firebase-js-sdk/commit/34c63bf1eb353110d61d135a65e083d46e9a6007) [#9822](https://github.com/firebase/firebase-js-sdk/pull/9822) - Fix header names for auth and app check tokens over streaming + +- [`715c042`](https://github.com/firebase/firebase-js-sdk/commit/715c0424d656b1be2d423c31f12e9ffbaeea2dd5) [#9740](https://github.com/firebase/firebase-js-sdk/pull/9740) (fixes [#9739](https://github.com/firebase/firebase-js-sdk/issues/9739)) - Updated the peer dependency range for @react-native-async-storage/async-storage to support both v2 and v3 + +- [`6cbe865`](https://github.com/firebase/firebase-js-sdk/commit/6cbe86569cc49ed12e9e53173bb66e8624bc8d6e) [#9816](https://github.com/firebase/firebase-js-sdk/pull/9816) - Deprecate `topK` and `temperature` properties for hybrid inference mode. + +- [`31bddcd`](https://github.com/firebase/firebase-js-sdk/commit/31bddcdd6200642f836c1eca7c9068470ca840bd) [#9734](https://github.com/firebase/firebase-js-sdk/pull/9734) - Added public preview support for full-text and geo search in Pipelines. + +- [`44ad4cc`](https://github.com/firebase/firebase-js-sdk/commit/44ad4cc2e54c6720d34fff4c2773f8887473b935) [#9702](https://github.com/firebase/firebase-js-sdk/pull/9702) - Add support for logical expressions `nor` and `switchOn`. + +- [`e8f14eb`](https://github.com/firebase/firebase-js-sdk/commit/e8f14eb499f10246b96759f58479905ab8f02e4c) [#9753](https://github.com/firebase/firebase-js-sdk/pull/9753) - Add support for pipeline expressions `ifNull` and `coalesce`. + +- [`9c8e864`](https://github.com/firebase/firebase-js-sdk/commit/9c8e8640e5ba91f2a3b1aa9229059dc35d0c427e) [#9763](https://github.com/firebase/firebase-js-sdk/pull/9763) - Add `startChat()` for `TemplateGenerativeModel`. + +- [`9c8e864`](https://github.com/firebase/firebase-js-sdk/commit/9c8e8640e5ba91f2a3b1aa9229059dc35d0c427e) [#9763](https://github.com/firebase/firebase-js-sdk/pull/9763) - Add automatic function calling and chat history for server prompt templates. + +- [`cecd028`](https://github.com/firebase/firebase-js-sdk/commit/cecd028de503302319a389a3331c5b94452daf95) [#9720](https://github.com/firebase/firebase-js-sdk/pull/9720) - Add subquery support to Pipelines. + +- [`87d5cc1`](https://github.com/firebase/firebase-js-sdk/commit/87d5cc1ba0107cb9a7a07bc6033dcec360f78d28) [#9809](https://github.com/firebase/firebase-js-sdk/pull/9809) - Add streaming support for Firebase Data Connect. + +- [`0e343c8`](https://github.com/firebase/firebase-js-sdk/commit/0e343c8706d2c1683fd802cadff8fa87f826698d) [#9725](https://github.com/firebase/firebase-js-sdk/pull/9725) - **Beta API Breaking Change**: Change `Type` string union to be a raw string. + +### Patch Changes + +- [`dd10ed7`](https://github.com/firebase/firebase-js-sdk/commit/dd10ed777b7bb4790c89225aa0a5be0a9d59e9a6) [#9750](https://github.com/firebase/firebase-js-sdk/pull/9750) - Refactor the parameters for timestamp expressions and change all timegranularity value to lowercase + +- Updated dependencies [[`cccb6d0`](https://github.com/firebase/firebase-js-sdk/commit/cccb6d058cc2dac5495b797740697902ddfd4a93), [`44c234c`](https://github.com/firebase/firebase-js-sdk/commit/44c234c2ba5f8ba18a2f2c99fe63df7692010bf3), [`5cd6509`](https://github.com/firebase/firebase-js-sdk/commit/5cd6509bdb1eedc9a37ed6ce7677450f574a7e9d), [`b2c4646`](https://github.com/firebase/firebase-js-sdk/commit/b2c464643548e068f56d9f57a09b105b1b898ff1), [`34c63bf`](https://github.com/firebase/firebase-js-sdk/commit/34c63bf1eb353110d61d135a65e083d46e9a6007), [`715c042`](https://github.com/firebase/firebase-js-sdk/commit/715c0424d656b1be2d423c31f12e9ffbaeea2dd5), [`6cbe865`](https://github.com/firebase/firebase-js-sdk/commit/6cbe86569cc49ed12e9e53173bb66e8624bc8d6e), [`31bddcd`](https://github.com/firebase/firebase-js-sdk/commit/31bddcdd6200642f836c1eca7c9068470ca840bd), [`dd10ed7`](https://github.com/firebase/firebase-js-sdk/commit/dd10ed777b7bb4790c89225aa0a5be0a9d59e9a6), [`44ad4cc`](https://github.com/firebase/firebase-js-sdk/commit/44ad4cc2e54c6720d34fff4c2773f8887473b935), [`e8f14eb`](https://github.com/firebase/firebase-js-sdk/commit/e8f14eb499f10246b96759f58479905ab8f02e4c), [`f87c15e`](https://github.com/firebase/firebase-js-sdk/commit/f87c15e97af9913182ebaa1afb94a3fe802e04f4), [`9c8e864`](https://github.com/firebase/firebase-js-sdk/commit/9c8e8640e5ba91f2a3b1aa9229059dc35d0c427e), [`9c8e864`](https://github.com/firebase/firebase-js-sdk/commit/9c8e8640e5ba91f2a3b1aa9229059dc35d0c427e), [`4e99d4b`](https://github.com/firebase/firebase-js-sdk/commit/4e99d4ba66a9a28558cd504826ae04fd07251c1b), [`334b266`](https://github.com/firebase/firebase-js-sdk/commit/334b266fec0fe63466dbb59bebe4d092bc3a924e), [`cecd028`](https://github.com/firebase/firebase-js-sdk/commit/cecd028de503302319a389a3331c5b94452daf95), [`87d5cc1`](https://github.com/firebase/firebase-js-sdk/commit/87d5cc1ba0107cb9a7a07bc6033dcec360f78d28), [`0e343c8`](https://github.com/firebase/firebase-js-sdk/commit/0e343c8706d2c1683fd802cadff8fa87f826698d)]: + - @firebase/ai@2.11.0 + - @firebase/app@0.14.11 + - @firebase/firestore@4.14.0 + - @firebase/app-types@0.9.4 + - @firebase/data-connect@0.6.0 + - @firebase/auth@1.13.0 + - @firebase/app-compat@0.5.11 + - @firebase/firestore-compat@0.4.8 + - @firebase/auth-compat@0.6.5 + - @firebase/database-compat@2.1.3 + ## 12.11.0 ### Minor Changes diff --git a/packages/firebase/package.json b/packages/firebase/package.json index f8be1a2bd9..a7177d9ed6 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -1,6 +1,6 @@ { "name": "firebase", - "version": "12.11.0", + "version": "12.12.0", "description": "Firebase JavaScript library for web and Node.js", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -423,17 +423,17 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/ai": "2.10.0", - "@firebase/app": "0.14.10", - "@firebase/app-compat": "0.5.10", - "@firebase/app-types": "0.9.3", - "@firebase/auth": "1.12.2", - "@firebase/auth-compat": "0.6.4", - "@firebase/data-connect": "0.5.0", + "@firebase/ai": "2.11.0", + "@firebase/app": "0.14.11", + "@firebase/app-compat": "0.5.11", + "@firebase/app-types": "0.9.4", + "@firebase/auth": "1.13.0", + "@firebase/auth-compat": "0.6.5", + "@firebase/data-connect": "0.6.0", "@firebase/database": "1.1.2", - "@firebase/database-compat": "2.1.2", - "@firebase/firestore": "4.13.0", - "@firebase/firestore-compat": "0.4.7", + "@firebase/database-compat": "2.1.3", + "@firebase/firestore": "4.14.0", + "@firebase/firestore-compat": "0.4.8", "@firebase/functions": "0.13.3", "@firebase/functions-compat": "0.4.3", "@firebase/installations": "0.6.21", diff --git a/packages/firestore-compat/CHANGELOG.md b/packages/firestore-compat/CHANGELOG.md index d65b76cdd9..e088416329 100644 --- a/packages/firestore-compat/CHANGELOG.md +++ b/packages/firestore-compat/CHANGELOG.md @@ -1,5 +1,12 @@ # @firebase/firestore-compat +## 0.4.8 + +### Patch Changes + +- Updated dependencies [[`44c234c`](https://github.com/firebase/firebase-js-sdk/commit/44c234c2ba5f8ba18a2f2c99fe63df7692010bf3), [`5cd6509`](https://github.com/firebase/firebase-js-sdk/commit/5cd6509bdb1eedc9a37ed6ce7677450f574a7e9d), [`31bddcd`](https://github.com/firebase/firebase-js-sdk/commit/31bddcdd6200642f836c1eca7c9068470ca840bd), [`dd10ed7`](https://github.com/firebase/firebase-js-sdk/commit/dd10ed777b7bb4790c89225aa0a5be0a9d59e9a6), [`44ad4cc`](https://github.com/firebase/firebase-js-sdk/commit/44ad4cc2e54c6720d34fff4c2773f8887473b935), [`e8f14eb`](https://github.com/firebase/firebase-js-sdk/commit/e8f14eb499f10246b96759f58479905ab8f02e4c), [`4e99d4b`](https://github.com/firebase/firebase-js-sdk/commit/4e99d4ba66a9a28558cd504826ae04fd07251c1b), [`334b266`](https://github.com/firebase/firebase-js-sdk/commit/334b266fec0fe63466dbb59bebe4d092bc3a924e), [`cecd028`](https://github.com/firebase/firebase-js-sdk/commit/cecd028de503302319a389a3331c5b94452daf95), [`0e343c8`](https://github.com/firebase/firebase-js-sdk/commit/0e343c8706d2c1683fd802cadff8fa87f826698d)]: + - @firebase/firestore@4.14.0 + ## 0.4.7 ### Patch Changes diff --git a/packages/firestore-compat/package.json b/packages/firestore-compat/package.json index 8866dea9ee..60c80ef212 100644 --- a/packages/firestore-compat/package.json +++ b/packages/firestore-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore-compat", - "version": "0.4.7", + "version": "0.4.8", "description": "The Cloud Firestore component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -47,13 +47,13 @@ }, "dependencies": { "@firebase/component": "0.7.2", - "@firebase/firestore": "4.13.0", + "@firebase/firestore": "4.14.0", "@firebase/util": "1.15.0", "@firebase/firestore-types": "3.0.3", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.10", + "@firebase/app-compat": "0.5.11", "@types/eslint": "7.29.0", "rollup": "2.79.2", "rollup-plugin-sourcemaps": "0.6.3", diff --git a/packages/firestore/CHANGELOG.md b/packages/firestore/CHANGELOG.md index c2bbbeae06..11be81ddc3 100644 --- a/packages/firestore/CHANGELOG.md +++ b/packages/firestore/CHANGELOG.md @@ -1,5 +1,31 @@ # @firebase/firestore +## 4.14.0 + +### Minor Changes + +- [`44c234c`](https://github.com/firebase/firebase-js-sdk/commit/44c234c2ba5f8ba18a2f2c99fe63df7692010bf3) [#9773](https://github.com/firebase/firebase-js-sdk/pull/9773) - Add support for the parent expression + +- [`5cd6509`](https://github.com/firebase/firebase-js-sdk/commit/5cd6509bdb1eedc9a37ed6ce7677450f574a7e9d) [#9728](https://github.com/firebase/firebase-js-sdk/pull/9728) - Add support for timestamp_trunc, timestamp_diff and timestamp_extract expressions + +- [`31bddcd`](https://github.com/firebase/firebase-js-sdk/commit/31bddcdd6200642f836c1eca7c9068470ca840bd) [#9734](https://github.com/firebase/firebase-js-sdk/pull/9734) - Added public preview support for full-text and geo search in Pipelines. + +- [`44ad4cc`](https://github.com/firebase/firebase-js-sdk/commit/44ad4cc2e54c6720d34fff4c2773f8887473b935) [#9702](https://github.com/firebase/firebase-js-sdk/pull/9702) - Add support for logical expressions `nor` and `switchOn`. + +- [`e8f14eb`](https://github.com/firebase/firebase-js-sdk/commit/e8f14eb499f10246b96759f58479905ab8f02e4c) [#9753](https://github.com/firebase/firebase-js-sdk/pull/9753) - Add support for pipeline expressions `ifNull` and `coalesce`. + +- [`cecd028`](https://github.com/firebase/firebase-js-sdk/commit/cecd028de503302319a389a3331c5b94452daf95) [#9720](https://github.com/firebase/firebase-js-sdk/pull/9720) - Add subquery support to Pipelines. + +- [`0e343c8`](https://github.com/firebase/firebase-js-sdk/commit/0e343c8706d2c1683fd802cadff8fa87f826698d) [#9725](https://github.com/firebase/firebase-js-sdk/pull/9725) - **Beta API Breaking Change**: Change `Type` string union to be a raw string. + +### Patch Changes + +- [`dd10ed7`](https://github.com/firebase/firebase-js-sdk/commit/dd10ed777b7bb4790c89225aa0a5be0a9d59e9a6) [#9750](https://github.com/firebase/firebase-js-sdk/pull/9750) - Refactor the parameters for timestamp expressions and change all timegranularity value to lowercase + +- [`4e99d4b`](https://github.com/firebase/firebase-js-sdk/commit/4e99d4ba66a9a28558cd504826ae04fd07251c1b) [#9752](https://github.com/firebase/firebase-js-sdk/pull/9752) - Read user data when using internal pipeline proto serialization. + +- [`334b266`](https://github.com/firebase/firebase-js-sdk/commit/334b266fec0fe63466dbb59bebe4d092bc3a924e) [#9765](https://github.com/firebase/firebase-js-sdk/pull/9765) - Read user data from pipeline in union stage. Fixes [GitHub Issue #9764](https://github.com/firebase/firebase-js-sdk/issues/9764) + ## 4.13.0 ### Minor Changes diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 39f638db04..4e9d4d1369 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore", - "version": "4.13.0", + "version": "4.14.0", "engines": { "node": ">=20.0.0" }, @@ -145,9 +145,9 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.10", - "@firebase/app-compat": "0.5.10", - "@firebase/auth": "1.12.2", + "@firebase/app": "0.14.11", + "@firebase/app-compat": "0.5.11", + "@firebase/auth": "1.13.0", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", "@types/eslint": "7.29.0", diff --git a/packages/functions-compat/package.json b/packages/functions-compat/package.json index ae7b07b3f0..41b0407eba 100644 --- a/packages/functions-compat/package.json +++ b/packages/functions-compat/package.json @@ -29,7 +29,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.10", + "@firebase/app-compat": "0.5.11", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/functions/package.json b/packages/functions/package.json index 144f9e901b..46d506eb08 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -49,7 +49,7 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/installations-compat/package.json b/packages/installations-compat/package.json index 1691e4b915..61f2ca699d 100644 --- a/packages/installations-compat/package.json +++ b/packages/installations-compat/package.json @@ -44,7 +44,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app-compat": "0.5.10", + "@firebase/app-compat": "0.5.11", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/installations/package.json b/packages/installations/package.json index 75a37e6b99..ab128fb773 100644 --- a/packages/installations/package.json +++ b/packages/installations/package.json @@ -49,7 +49,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/messaging-compat/package.json b/packages/messaging-compat/package.json index 553d72d493..42ca7f159e 100644 --- a/packages/messaging-compat/package.json +++ b/packages/messaging-compat/package.json @@ -44,7 +44,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.10", + "@firebase/app-compat": "0.5.11", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", "ts-essentials": "9.4.2", diff --git a/packages/messaging/package.json b/packages/messaging/package.json index 444067db84..7527654c39 100644 --- a/packages/messaging/package.json +++ b/packages/messaging/package.json @@ -60,7 +60,7 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/performance-compat/package.json b/packages/performance-compat/package.json index af5b6fde6b..4115734915 100644 --- a/packages/performance-compat/package.json +++ b/packages/performance-compat/package.json @@ -51,7 +51,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.10" + "@firebase/app-compat": "0.5.11" }, "repository": { "directory": "packages/performance-compat", diff --git a/packages/performance/package.json b/packages/performance/package.json index e07b7f645b..f2834a9978 100644 --- a/packages/performance/package.json +++ b/packages/performance/package.json @@ -47,7 +47,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/remote-config-compat/package.json b/packages/remote-config-compat/package.json index 4d526e1098..c302dac56e 100644 --- a/packages/remote-config-compat/package.json +++ b/packages/remote-config-compat/package.json @@ -50,7 +50,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.10" + "@firebase/app-compat": "0.5.11" }, "repository": { "directory": "packages/remote-config-compat", diff --git a/packages/remote-config/package.json b/packages/remote-config/package.json index 6fb62ed71e..fc9ce1379f 100644 --- a/packages/remote-config/package.json +++ b/packages/remote-config/package.json @@ -48,7 +48,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/storage-compat/package.json b/packages/storage-compat/package.json index 60ce914b8c..297cbaa47b 100644 --- a/packages/storage-compat/package.json +++ b/packages/storage-compat/package.json @@ -44,8 +44,8 @@ "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.10", - "@firebase/auth-compat": "0.6.4", + "@firebase/app-compat": "0.5.11", + "@firebase/auth-compat": "0.6.5", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.36.0", diff --git a/packages/storage/package.json b/packages/storage/package.json index 0631f0e860..3f0a04b29c 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -54,8 +54,8 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.10", - "@firebase/auth": "1.12.2", + "@firebase/app": "0.14.11", + "@firebase/auth": "1.13.0", "rollup": "2.79.2", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", diff --git a/packages/template/package.json b/packages/template/package.json index f0512848fa..d60f1f8351 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -48,7 +48,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.36.0", "typescript": "5.5.4" diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index 8b3af13d01..4c2437860d 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -40,7 +40,7 @@ "yargs": "17.7.2" }, "devDependencies": { - "@firebase/app": "0.14.10", + "@firebase/app": "0.14.11", "@firebase/logger": "0.5.0", "@types/webpack": "5.28.5" }, From fea8d1f5e418938fff19672aaad628d616eabd73 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Fri, 17 Apr 2026 11:59:26 -0400 Subject: [PATCH 135/174] test(firestore): Enable `forceIndex` tests (#9838) Enables the `forceIndex` tests. They set the `forceIndex` option to `"primary"` and simply assert that the snapshot contains an expected number of documents, and that the stage option has the `forceIndex` set as expected. Question: Is there a better way to validate that the request correctly used the index specified by `forceIndex`? --- .../test/integration/api/pipeline.test.ts | 22 ++++++++++++------- packages/firestore/test/lite/pipeline.test.ts | 22 ++++++++++++------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 5f222ac24a..8aff0a73b9 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -6011,27 +6011,33 @@ apiDescribe.skipClassic('Pipelines', persistence => { describe('stage options', () => { describe('forceIndex', () => { - // SKIP: requires pre-existing index - // eslint-disable-next-line no-restricted-properties - it.skip('Collection Stage', async () => { + it('Collection Stage', async () => { const snapshot = await execute( firestore.pipeline().collection({ collection: randomCol, - forceIndex: 'unknown' + forceIndex: 'primary' }) ); + expect( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (snapshot as any)._pipeline.stages[0].optionsProto.force_index + .stringValue + ).equal('primary'); expect(snapshot.results.length).to.equal(10); }); - // SKIP: requires pre-existing index - // eslint-disable-next-line no-restricted-properties - it.skip('CollectionGroup Stage', async () => { + it('CollectionGroup Stage', async () => { const snapshot = await execute( firestore.pipeline().collectionGroup({ collectionId: randomCol.id, - forceIndex: 'unknown' + forceIndex: 'primary' }) ); + expect( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (snapshot as any)._pipeline.stages[0].optionsProto.force_index + .stringValue + ).equal('primary'); expect(snapshot.results.length).to.equal(10); }); }); diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index f268750e47..7c5363aa41 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -5883,27 +5883,33 @@ describe.skipClassic('Firestore Pipelines', () => { describe('stage options', () => { describe('forceIndex', () => { - // SKIP: requires pre-existing index - // eslint-disable-next-line no-restricted-properties - it.skip('Collection Stage', async () => { + it('Collection Stage', async () => { const snapshot = await execute( firestore.pipeline().collection({ collection: randomCol, - forceIndex: 'unknown' + forceIndex: 'primary' }) ); + expect( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (snapshot as any)._pipeline.stages[0].optionsProto.force_index + .stringValue + ).equal('primary'); expect(snapshot.results.length).to.equal(10); }); - // SKIP: requires pre-existing index - // eslint-disable-next-line no-restricted-properties - it.skip('CollectionGroup Stage', async () => { + it('CollectionGroup Stage', async () => { const snapshot = await execute( firestore.pipeline().collectionGroup({ collectionId: randomCol.id, - forceIndex: 'unknown' + forceIndex: 'primary' }) ); + expect( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (snapshot as any)._pipeline.stages[0].optionsProto.force_index + .stringValue + ).equal('primary'); expect(snapshot.results.length).to.equal(10); }); }); From 6db5af46649382ee3ed73ab4e8f69abc5f9a33aa Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Fri, 17 Apr 2026 11:50:31 -0700 Subject: [PATCH 136/174] fix(ai): Fix TemplateChatSession type (#9840) --- .changeset/silly-hounds-lay.md | 5 ++ common/api-review/ai.api.md | 18 ++--- docs-devsite/_toc.yaml | 2 - docs-devsite/ai.md | 3 +- docs-devsite/ai.templatechatsession.md | 57 ++++++-------- .../ai.templategeneratecontentrequest.md | 75 ------------------- docs-devsite/ai.templategenerativemodel.md | 6 +- packages/ai/src/api.ts | 2 +- .../src/methods/template-chat-session.test.ts | 18 ++--- .../ai/src/methods/template-chat-session.ts | 14 ++-- .../src/models/template-generative-model.ts | 7 +- packages/ai/src/public-types.ts | 44 +++++++++++ packages/ai/src/types/requests.ts | 2 +- 13 files changed, 106 insertions(+), 147 deletions(-) create mode 100644 .changeset/silly-hounds-lay.md delete mode 100644 docs-devsite/ai.templategeneratecontentrequest.md diff --git a/.changeset/silly-hounds-lay.md b/.changeset/silly-hounds-lay.md new file mode 100644 index 0000000000..d447ca76db --- /dev/null +++ b/.changeset/silly-hounds-lay.md @@ -0,0 +1,5 @@ +--- +'@firebase/ai': patch +--- + +Fix `TemplateChatSession` type so it does not error on TypeScript build. See Github issue #9832. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 47121f9346..929185bf11 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -1389,21 +1389,13 @@ export class StringSchema extends Schema { toJSON(): SchemaRequest; } -// Warning: (ae-incompatible-release-tags) The symbol "TemplateChatSession" is marked as @beta, but its signature references "TemplateRequestInternal" which is marked as @internal -// // @beta -export class TemplateChatSession extends ChatSessionBase { - constructor(apiSettings: ApiSettings, params: StartTemplateChatParams, requestOptions?: RequestOptions | undefined); - // @internal - _callGenerateContent(formattedRequest: TemplateRequestInternal, singleRequestOptions?: RequestOptions): Promise; - // @internal - _callGenerateContentStream(formattedRequest: TemplateRequestInternal, singleRequestOptions?: RequestOptions): Promise; - // @internal - _formatRequest(incomingContent: Content, tempHistory: Content[]): TemplateRequestInternal; +export interface TemplateChatSession { + getHistory(): Promise; // (undocumented) params: StartTemplateChatParams; // (undocumented) - requestOptions?: RequestOptions | undefined; + requestOptions?: RequestOptions; sendMessage(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; sendMessageStream(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; } @@ -1436,7 +1428,9 @@ export interface TemplateFunctionDeclarationsToolInternal { templateFunctions?: TemplateFunctionDeclarationInternal[]; } -// @beta +// Warning: (ae-internal-missing-underscore) The name "TemplateGenerateContentRequest" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal export interface TemplateGenerateContentRequest { // (undocumented) [key: string]: unknown; diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index 669c4763d7..a17095729e 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -212,8 +212,6 @@ toc: path: /docs/reference/js/ai.templatefunctiondeclaration.md - title: TemplateFunctionDeclarationsTool path: /docs/reference/js/ai.templatefunctiondeclarationstool.md - - title: TemplateGenerateContentRequest - path: /docs/reference/js/ai.templategeneratecontentrequest.md - title: TemplateGenerativeModel path: /docs/reference/js/ai.templategenerativemodel.md - title: TemplateImagenModel diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index 783a307535..d9f39696ff 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -50,7 +50,6 @@ The Firebase AI Web SDK. | [ObjectSchema](./ai.objectschema.md#objectschema_class) | Schema class for "object" types. The properties param must be a map of Schema objects. | | [Schema](./ai.schema.md#schema_class) | Parent class encompassing all Schema types, with static methods that allow building specific Schema types. This class can be converted with JSON.stringify() into a JSON string accepted by Vertex AI REST endpoints. (This string conversion is automatically done when calling SDK methods.) | | [StringSchema](./ai.stringschema.md#stringschema_class) | Schema class for "string" types. Can be used with or without enum values. | -| [TemplateChatSession](./ai.templatechatsession.md#templatechatsession_class) | (Public Preview) ChatSession class for use with server prompt templates that enables sending chat messages and stores history of sent and received messages so far. | | [TemplateGenerativeModel](./ai.templategenerativemodel.md#templategenerativemodel_class) | (Public Preview) [GenerativeModel](./ai.generativemodel.md#generativemodel_class) APIs that execute on a server-side template.This class should only be instantiated with [getTemplateGenerativeModel()](./ai.md#gettemplategenerativemodel_9476bbc). | | [TemplateImagenModel](./ai.templateimagenmodel.md#templateimagenmodel_class) | Class for Imagen model APIs that execute on a server-side template.This class should only be instantiated with [getTemplateImagenModel()](./ai.md#gettemplateimagenmodel_9476bbc). | | [VertexAIBackend](./ai.vertexaibackend.md#vertexaibackend_class) | Configuration class for the Vertex AI Gemini API.Use this with [AIOptions](./ai.aioptions.md#aioptions_interface) when initializing the AI service via [getAI()](./ai.md#getai_a94a413) to specify the Vertex AI Gemini API as the backend. | @@ -141,9 +140,9 @@ The Firebase AI Web SDK. | [StartAudioConversationOptions](./ai.startaudioconversationoptions.md#startaudioconversationoptions_interface) | (Public Preview) Options for [startAudioConversation()](./ai.md#startaudioconversation_01c8e7f). | | [StartChatParams](./ai.startchatparams.md#startchatparams_interface) | Params for [GenerativeModel.startChat()](./ai.generativemodel.md#generativemodelstartchat). | | [StartTemplateChatParams](./ai.starttemplatechatparams.md#starttemplatechatparams_interface) | (Public Preview) Params for [TemplateGenerativeModel.startChat()](./ai.templategenerativemodel.md#templategenerativemodelstartchat). | +| [TemplateChatSession](./ai.templatechatsession.md#templatechatsession_interface) | (Public Preview) Interface representing a ChatSession class for use with server prompt templates that enables sending chat messages and stores history of sent and received messages so far. | | [TemplateFunctionDeclaration](./ai.templatefunctiondeclaration.md#templatefunctiondeclaration_interface) | (Public Preview) Structured representation of a template function declaration. Included in this declaration are the function name and parameters. This TemplateFunctionDeclaration is a representation of a block of code that can be used as a Tool by the model and executed by the client. Note: Template function declarations do not support description fields. | | [TemplateFunctionDeclarationsTool](./ai.templatefunctiondeclarationstool.md#templatefunctiondeclarationstool_interface) | (Public Preview) A piece of code that enables the system to interact with external systems. | -| [TemplateGenerateContentRequest](./ai.templategeneratecontentrequest.md#templategeneratecontentrequest_interface) | (Public Preview) Request sent through [TemplateGenerativeModel.generateContent()](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontent) | | [TextPart](./ai.textpart.md#textpart_interface) | Content part interface if the part represents a text string. | | [ThinkingConfig](./ai.thinkingconfig.md#thinkingconfig_interface) | Configuration for "thinking" behavior of compatible Gemini models.Certain models utilize a thinking process before generating a response. This allows them to reason through complex problems and plan a more coherent and accurate answer. | | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. | diff --git a/docs-devsite/ai.templatechatsession.md b/docs-devsite/ai.templatechatsession.md index 2cee825089..b8c1909243 100644 --- a/docs-devsite/ai.templatechatsession.md +++ b/docs-devsite/ai.templatechatsession.md @@ -9,61 +9,45 @@ overwritten. Changes should be made in the source code at https://github.com/firebase/firebase-js-sdk {% endcomment %} -# TemplateChatSession class +# TemplateChatSession interface > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -`ChatSession` class for use with server prompt templates that enables sending chat messages and stores history of sent and received messages so far. +Interface representing a `ChatSession` class for use with server prompt templates that enables sending chat messages and stores history of sent and received messages so far. Signature: ```typescript -export declare class TemplateChatSession extends ChatSessionBase +export interface TemplateChatSession ``` -Extends: [ChatSessionBase](./ai.chatsessionbase.md#chatsessionbase_class)<[StartTemplateChatParams](./ai.starttemplatechatparams.md#starttemplatechatparams_interface), TemplateRequestInternal, [TemplateFunctionDeclarationsTool](./ai.templatefunctiondeclarationstool.md#templatefunctiondeclarationstool_interface)> - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(apiSettings, params, requestOptions)](./ai.templatechatsession.md#templatechatsessionconstructor) | | (Public Preview) Constructs a new instance of the TemplateChatSession class | ## Properties -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [params](./ai.templatechatsession.md#templatechatsessionparams) | | [StartTemplateChatParams](./ai.starttemplatechatparams.md#starttemplatechatparams_interface) | (Public Preview) | -| [requestOptions](./ai.templatechatsession.md#templatechatsessionrequestoptions) | | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) \| undefined | (Public Preview) | +| Property | Type | Description | +| --- | --- | --- | +| [params](./ai.templatechatsession.md#templatechatsessionparams) | [StartTemplateChatParams](./ai.starttemplatechatparams.md#starttemplatechatparams_interface) | (Public Preview) | +| [requestOptions](./ai.templatechatsession.md#templatechatsessionrequestoptions) | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) | (Public Preview) | ## Methods -| Method | Modifiers | Description | -| --- | --- | --- | -| [sendMessage(request, singleRequestOptions)](./ai.templatechatsession.md#templatechatsessionsendmessage) | | (Public Preview) Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface) | -| [sendMessageStream(request, singleRequestOptions)](./ai.templatechatsession.md#templatechatsessionsendmessagestream) | | (Public Preview) Sends a chat message and receives the response as a [GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. | +| Method | Description | +| --- | --- | +| [getHistory()](./ai.templatechatsession.md#templatechatsessiongethistory) | (Public Preview) Gets the chat history so far. Blocked prompts are not added to history. Neither blocked candidates nor the prompts that generated them are added to history. | +| [sendMessage(request, singleRequestOptions)](./ai.templatechatsession.md#templatechatsessionsendmessage) | (Public Preview) Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface) | +| [sendMessageStream(request, singleRequestOptions)](./ai.templatechatsession.md#templatechatsessionsendmessagestream) | (Public Preview) Sends a chat message and receives the response as a [GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. | -## TemplateChatSession.(constructor) +## TemplateChatSession.params > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Constructs a new instance of the `TemplateChatSession` class - Signature: ```typescript -constructor(apiSettings: ApiSettings, params: StartTemplateChatParams, requestOptions?: RequestOptions | undefined); +params: StartTemplateChatParams; ``` -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| apiSettings | ApiSettings | | -| params | [StartTemplateChatParams](./ai.starttemplatechatparams.md#starttemplatechatparams_interface) | | -| requestOptions | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) \| undefined | | - -## TemplateChatSession.params +## TemplateChatSession.requestOptions > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > @@ -71,19 +55,24 @@ constructor(apiSettings: ApiSettings, params: StartTemplateChatParams, requestOp Signature: ```typescript -params: StartTemplateChatParams; +requestOptions?: RequestOptions; ``` -## TemplateChatSession.requestOptions +## TemplateChatSession.getHistory() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > +Gets the chat history so far. Blocked prompts are not added to history. Neither blocked candidates nor the prompts that generated them are added to history. + Signature: ```typescript -requestOptions?: RequestOptions | undefined; +getHistory(): Promise; ``` +Returns: + +Promise<[Content](./ai.content.md#content_interface)\[\]> ## TemplateChatSession.sendMessage() diff --git a/docs-devsite/ai.templategeneratecontentrequest.md b/docs-devsite/ai.templategeneratecontentrequest.md deleted file mode 100644 index c912d50a84..0000000000 --- a/docs-devsite/ai.templategeneratecontentrequest.md +++ /dev/null @@ -1,75 +0,0 @@ -Project: /docs/reference/js/_project.yaml -Book: /docs/reference/_book.yaml -page_type: reference - -{% comment %} -DO NOT EDIT THIS FILE! -This is generated by the JS SDK team, and any local changes will be -overwritten. Changes should be made in the source code at -https://github.com/firebase/firebase-js-sdk -{% endcomment %} - -# TemplateGenerateContentRequest interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Request sent through [TemplateGenerativeModel.generateContent()](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontent) - -Signature: - -```typescript -export interface TemplateGenerateContentRequest -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [history](./ai.templategeneratecontentrequest.md#templategeneratecontentrequesthistory) | [Content](./ai.content.md#content_interface)\[\] | (Public Preview) | -| [inputs](./ai.templategeneratecontentrequest.md#templategeneratecontentrequestinputs) | Record<string, unknown> | (Public Preview) | -| [toolConfig](./ai.templategeneratecontentrequest.md#templategeneratecontentrequesttoolconfig) | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | (Public Preview) | -| [tools](./ai.templategeneratecontentrequest.md#templategeneratecontentrequesttools) | [TemplateFunctionDeclarationsTool](./ai.templatefunctiondeclarationstool.md#templatefunctiondeclarationstool_interface)\[\] | (Public Preview) | - -## TemplateGenerateContentRequest.history - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Signature: - -```typescript -history?: Content[]; -``` - -## TemplateGenerateContentRequest.inputs - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Signature: - -```typescript -inputs?: Record; -``` - -## TemplateGenerateContentRequest.toolConfig - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Signature: - -```typescript -toolConfig?: ToolConfig; -``` - -## TemplateGenerateContentRequest.tools - -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Signature: - -```typescript -tools?: TemplateFunctionDeclarationsTool[]; -``` diff --git a/docs-devsite/ai.templategenerativemodel.md b/docs-devsite/ai.templategenerativemodel.md index 9b7d7349a8..ced5ad9722 100644 --- a/docs-devsite/ai.templategenerativemodel.md +++ b/docs-devsite/ai.templategenerativemodel.md @@ -41,7 +41,7 @@ export declare class TemplateGenerativeModel | --- | --- | --- | | [generateContent(templateId, templateVariables, singleRequestOptions)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontent) | | (Public Preview) Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | | [generateContentStream(templateId, templateVariables, singleRequestOptions)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontentstream) | | (Public Preview) Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. | -| [startChat(params)](./ai.templategenerativemodel.md#templategenerativemodelstartchat) | | (Public Preview) Starts a [TemplateChatSession](./ai.templatechatsession.md#templatechatsession_class) that will use this template to respond to messages. | +| [startChat(params)](./ai.templategenerativemodel.md#templategenerativemodelstartchat) | | (Public Preview) Starts a [TemplateChatSession](./ai.templatechatsession.md#templatechatsession_interface) that will use this template to respond to messages. | ## TemplateGenerativeModel.(constructor) @@ -131,7 +131,7 @@ Promise<[GenerateContentStreamResult](./ai.generatecontentstreamresult.md#gen > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Starts a [TemplateChatSession](./ai.templatechatsession.md#templatechatsession_class) that will use this template to respond to messages. +Starts a [TemplateChatSession](./ai.templatechatsession.md#templatechatsession_interface) that will use this template to respond to messages. Signature: @@ -147,5 +147,5 @@ startChat(params: StartTemplateChatParams): TemplateChatSession; Returns: -[TemplateChatSession](./ai.templatechatsession.md#templatechatsession_class) +[TemplateChatSession](./ai.templatechatsession.md#templatechatsession_interface) diff --git a/packages/ai/src/api.ts b/packages/ai/src/api.ts index e7c631498e..2c3f125a03 100644 --- a/packages/ai/src/api.ts +++ b/packages/ai/src/api.ts @@ -43,10 +43,10 @@ import { TemplateGenerativeModel } from './models/template-generative-model'; import { TemplateImagenModel } from './models/template-imagen-model'; import { logger } from './logger'; +export { TemplateChatSession } from './public-types'; export { ChatSession } from './methods/chat-session'; export { ChatSessionBase } from './methods/chat-session-base'; export { LiveSession } from './methods/live-session'; -export { TemplateChatSession } from './methods/template-chat-session'; export * from './requests/schema-builder'; export { ImagenImageFormat } from './requests/imagen-image-format'; export { diff --git a/packages/ai/src/methods/template-chat-session.test.ts b/packages/ai/src/methods/template-chat-session.test.ts index f1807373bd..c738a0d864 100644 --- a/packages/ai/src/methods/template-chat-session.test.ts +++ b/packages/ai/src/methods/template-chat-session.test.ts @@ -21,7 +21,7 @@ import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; import * as generateContentMethods from './generate-content'; import { Content, TemplateFunctionDeclaration } from '../types'; -import { TemplateChatSession } from './template-chat-session'; +import { TemplateChatSessionImpl } from './template-chat-session'; import { ApiSettings } from '../types/internal'; import { VertexAIBackend } from '../backend'; import { logger } from '../logger'; @@ -61,7 +61,7 @@ describe('TemplateChatSession', () => { 'should rename functionDeclarations to templateFunctions' + ' and parameters to inputSchema', () => { - const chatSession = new TemplateChatSession(fakeApiSettings, { + const chatSession = new TemplateChatSessionImpl(fakeApiSettings, { templateId: TEMPLATE_ID, tools: [ { @@ -92,7 +92,7 @@ describe('TemplateChatSession', () => { } ); it('should not include any properties not provided in params', () => { - const chatSession = new TemplateChatSession(fakeApiSettings, { + const chatSession = new TemplateChatSessionImpl(fakeApiSettings, { templateId: TEMPLATE_ID }); const formattedRequest = chatSession._formatRequest( @@ -112,7 +112,7 @@ describe('TemplateChatSession', () => { generateContentMethods, 'templateGenerateContent' ).rejects(new Error('templateGenerateContent failed')); - const chatSession = new TemplateChatSession(fakeApiSettings, { + const chatSession = new TemplateChatSessionImpl(fakeApiSettings, { templateId: TEMPLATE_ID }); await expect(chatSession.sendMessage('hello')).to.be.rejected; @@ -143,7 +143,7 @@ describe('TemplateChatSession', () => { // @ts-ignore response: fakeResponse }); - const chatSession = new TemplateChatSession(fakeApiSettings, { + const chatSession = new TemplateChatSessionImpl(fakeApiSettings, { templateId: TEMPLATE_ID }); const result = await chatSession.sendMessage('hello'); @@ -255,7 +255,7 @@ describe('TemplateChatSession', () => { }; } }); - const chatSession = new TemplateChatSession(fakeApiSettings, { + const chatSession = new TemplateChatSessionImpl(fakeApiSettings, { templateId: TEMPLATE_ID, tools: [ { @@ -317,7 +317,7 @@ describe('TemplateChatSession', () => { }; } }); - const chatSession = new TemplateChatSession(fakeApiSettings, { + const chatSession = new TemplateChatSessionImpl(fakeApiSettings, { templateId: TEMPLATE_ID, tools: [ { @@ -383,7 +383,7 @@ describe('TemplateChatSession', () => { }; } }); - const chatSession = new TemplateChatSession( + const chatSession = new TemplateChatSessionImpl( fakeApiSettings, { templateId: TEMPLATE_ID, @@ -439,7 +439,7 @@ describe('TemplateChatSession', () => { }; } }); - const chatSession = new TemplateChatSession(fakeApiSettings, { + const chatSession = new TemplateChatSessionImpl(fakeApiSettings, { templateId: TEMPLATE_ID, tools: [ { diff --git a/packages/ai/src/methods/template-chat-session.ts b/packages/ai/src/methods/template-chat-session.ts index e8e17fdbf0..e0e8247037 100644 --- a/packages/ai/src/methods/template-chat-session.ts +++ b/packages/ai/src/methods/template-chat-session.ts @@ -35,6 +35,7 @@ import { } from './generate-content'; import { ApiSettings } from '../types/internal'; import { ChatSessionBase } from './chat-session-base'; +import { TemplateChatSession } from '../public-types'; /** * `ChatSession` class for use with server prompt templates that @@ -43,11 +44,14 @@ import { ChatSessionBase } from './chat-session-base'; * * @beta */ -export class TemplateChatSession extends ChatSessionBase< - StartTemplateChatParams, - TemplateRequestInternal, - TemplateFunctionDeclarationsTool -> { +export class TemplateChatSessionImpl + extends ChatSessionBase< + StartTemplateChatParams, + TemplateRequestInternal, + TemplateFunctionDeclarationsTool + > + implements TemplateChatSession +{ constructor( apiSettings: ApiSettings, public params: StartTemplateChatParams, diff --git a/packages/ai/src/models/template-generative-model.ts b/packages/ai/src/models/template-generative-model.ts index 0ab1383e87..666c5ff842 100644 --- a/packages/ai/src/models/template-generative-model.ts +++ b/packages/ai/src/models/template-generative-model.ts @@ -24,11 +24,12 @@ import { AI, GenerateContentStreamResult, SingleRequestOptions, - StartTemplateChatParams + StartTemplateChatParams, + TemplateChatSession } from '../public-types'; import { ApiSettings } from '../types/internal'; import { initApiSettings } from './utils'; -import { TemplateChatSession } from '../methods/template-chat-session'; +import { TemplateChatSessionImpl } from '../methods/template-chat-session'; /** * {@link GenerativeModel} APIs that execute on a server-side template. @@ -120,7 +121,7 @@ export class TemplateGenerativeModel { * @beta */ startChat(params: StartTemplateChatParams): TemplateChatSession { - return new TemplateChatSession( + return new TemplateChatSessionImpl( this._apiSettings, params, this.requestOptions diff --git a/packages/ai/src/public-types.ts b/packages/ai/src/public-types.ts index fff41251a0..9238465f92 100644 --- a/packages/ai/src/public-types.ts +++ b/packages/ai/src/public-types.ts @@ -17,6 +17,15 @@ import { FirebaseApp } from '@firebase/app'; import { Backend } from './backend'; +import { + Content, + GenerateContentResult, + GenerateContentStreamResult, + Part, + RequestOptions, + SingleRequestOptions, + StartTemplateChatParams +} from './types'; export * from './types'; @@ -102,3 +111,38 @@ export interface AIOptions { */ useLimitedUseAppCheckTokens?: boolean; } + +/** + * Interface representing a `ChatSession` class for use with server + * prompt templates that enables sending chat messages and stores + * history of sent and received messages so far. + * + * @beta + */ +export interface TemplateChatSession { + params: StartTemplateChatParams; + requestOptions?: RequestOptions; + /** + * Sends a chat message and receives a non-streaming + * {@link GenerateContentResult} + */ + sendMessage( + request: string | Array, + singleRequestOptions?: SingleRequestOptions + ): Promise; + /** + * Sends a chat message and receives the response as a + * {@link GenerateContentStreamResult} containing an iterable stream + * and a response promise. + */ + sendMessageStream( + request: string | Array, + singleRequestOptions?: SingleRequestOptions + ): Promise; + /** + * Gets the chat history so far. Blocked prompts are not added to history. + * Neither blocked candidates nor the prompts that generated them are added + * to history. + */ + getHistory(): Promise; +} diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index 0866371f48..6180323191 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -76,7 +76,7 @@ export interface GenerateContentRequest extends BaseParams { /** * Request sent through {@link TemplateGenerativeModel.generateContent} - * @beta + * @internal */ export interface TemplateGenerateContentRequest { inputs?: Record; From 23ab5b9dadb0451e855740a48f4cb12d29091a70 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Fri, 17 Apr 2026 12:13:25 -0700 Subject: [PATCH 137/174] fix(ai): Update code execution and URL context doc comments to reflect they are public now (#9817) --- .changeset/silent-trains-bake.md | 5 +++++ common/api-review/ai.api.md | 9 +++------ docs-devsite/ai.codeexecutiontool.md | 10 ++-------- docs-devsite/ai.md | 6 +++--- docs-devsite/ai.urlcontext.md | 3 --- docs-devsite/ai.urlcontexttool.md | 8 +------- packages/ai/src/types/requests.ts | 7 +++---- 7 files changed, 17 insertions(+), 31 deletions(-) create mode 100644 .changeset/silent-trains-bake.md diff --git a/.changeset/silent-trains-bake.md b/.changeset/silent-trains-bake.md new file mode 100644 index 0000000000..b5efc3d468 --- /dev/null +++ b/.changeset/silent-trains-bake.md @@ -0,0 +1,5 @@ +--- +'@firebase/ai': patch +--- + +Update code execution and URL context features to reflect that they are generally available and no longer public preview. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 929185bf11..aee764ee7e 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -251,7 +251,7 @@ export interface CodeExecutionResultPart { thoughtSignature?: never; } -// @beta +// @public export interface CodeExecutionTool { codeExecution: {}; } @@ -1514,9 +1514,6 @@ export const ThinkingLevel: { // @public export type ThinkingLevel = (typeof ThinkingLevel)[keyof typeof ThinkingLevel]; -// Warning: (ae-incompatible-release-tags) The symbol "Tool" is marked as @public, but its signature references "CodeExecutionTool" which is marked as @beta -// Warning: (ae-incompatible-release-tags) The symbol "Tool" is marked as @public, but its signature references "URLContextTool" which is marked as @beta -// // @public export type Tool = FunctionDeclarationsTool | GoogleSearchTool | CodeExecutionTool | URLContextTool; @@ -1534,7 +1531,7 @@ export interface Transcription { // @public export type TypedSchema = IntegerSchema | NumberSchema | StringSchema | BooleanSchema | ObjectSchema | ArraySchema | AnyOfSchema; -// @beta +// @public export interface URLContext { } @@ -1543,7 +1540,7 @@ export interface URLContextMetadata { urlMetadata: URLMetadata[]; } -// @beta +// @public export interface URLContextTool { urlContext: URLContext; } diff --git a/docs-devsite/ai.codeexecutiontool.md b/docs-devsite/ai.codeexecutiontool.md index 68a1e133d7..bcfafa41bb 100644 --- a/docs-devsite/ai.codeexecutiontool.md +++ b/docs-devsite/ai.codeexecutiontool.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # CodeExecutionTool interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - A tool that enables the model to use code execution. Signature: @@ -25,14 +22,11 @@ export interface CodeExecutionTool | Property | Type | Description | | --- | --- | --- | -| [codeExecution](./ai.codeexecutiontool.md#codeexecutiontoolcodeexecution) | {} | (Public Preview) Specifies the Google Search configuration. Currently, this is an empty object, but it's reserved for future configuration options. | +| [codeExecution](./ai.codeexecutiontool.md#codeexecutiontoolcodeexecution) | {} | Currently, this is an empty object, but it's reserved for future configuration options. | ## CodeExecutionTool.codeExecution -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - -Specifies the Google Search configuration. Currently, this is an empty object, but it's reserved for future configuration options. +Currently, this is an empty object, but it's reserved for future configuration options. Signature: diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index d9f39696ff..be98207f35 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -68,7 +68,7 @@ The Firebase AI Web SDK. | [CitationMetadata](./ai.citationmetadata.md#citationmetadata_interface) | Citation metadata that may be found on a [GenerateContentCandidate](./ai.generatecontentcandidate.md#generatecontentcandidate_interface). | | [CodeExecutionResult](./ai.codeexecutionresult.md#codeexecutionresult_interface) | The results of code execution run by the model. | | [CodeExecutionResultPart](./ai.codeexecutionresultpart.md#codeexecutionresultpart_interface) | Represents the code execution result from the model. | -| [CodeExecutionTool](./ai.codeexecutiontool.md#codeexecutiontool_interface) | (Public Preview) A tool that enables the model to use code execution. | +| [CodeExecutionTool](./ai.codeexecutiontool.md#codeexecutiontool_interface) | A tool that enables the model to use code execution. | | [Content](./ai.content.md#content_interface) | Content type for both prompts and response candidates. | | [CountTokensRequest](./ai.counttokensrequest.md#counttokensrequest_interface) | Params for calling [GenerativeModel.countTokens()](./ai.generativemodel.md#generativemodelcounttokens) | | [CountTokensResponse](./ai.counttokensresponse.md#counttokensresponse_interface) | Response from calling [GenerativeModel.countTokens()](./ai.generativemodel.md#generativemodelcounttokens). | @@ -147,9 +147,9 @@ The Firebase AI Web SDK. | [ThinkingConfig](./ai.thinkingconfig.md#thinkingconfig_interface) | Configuration for "thinking" behavior of compatible Gemini models.Certain models utilize a thinking process before generating a response. This allows them to reason through complex problems and plan a more coherent and accurate answer. | | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. | | [Transcription](./ai.transcription.md#transcription_interface) | (Public Preview) Transcription of audio. This can be returned from a [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) if transcription is enabled with the inputAudioTranscription or outputAudioTranscription properties on the [LiveGenerationConfig](./ai.livegenerationconfig.md#livegenerationconfig_interface). | -| [URLContext](./ai.urlcontext.md#urlcontext_interface) | (Public Preview) Specifies the URL Context configuration. | +| [URLContext](./ai.urlcontext.md#urlcontext_interface) | Specifies the URL Context configuration. | | [URLContextMetadata](./ai.urlcontextmetadata.md#urlcontextmetadata_interface) | Metadata related to [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface). | -| [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface) | (Public Preview) A tool that allows you to provide additional context to the models in the form of public web URLs. By including URLs in your request, the Gemini model will access the content from those pages to inform and enhance its response. | +| [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface) | A tool that allows you to provide additional context to the models in the form of public web URLs. By including URLs in your request, the Gemini model will access the content from those pages to inform and enhance its response. | | [URLMetadata](./ai.urlmetadata.md#urlmetadata_interface) | Metadata for a single URL retrieved by the [URLContextTool](./ai.urlcontexttool.md#urlcontexttool_interface) tool. | | [UsageMetadata](./ai.usagemetadata.md#usagemetadata_interface) | Usage metadata about a [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | | [VideoMetadata](./ai.videometadata.md#videometadata_interface) | Describes the input video content. | diff --git a/docs-devsite/ai.urlcontext.md b/docs-devsite/ai.urlcontext.md index 435d278e4d..7fec0481e6 100644 --- a/docs-devsite/ai.urlcontext.md +++ b/docs-devsite/ai.urlcontext.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # URLContext interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Specifies the URL Context configuration. Signature: diff --git a/docs-devsite/ai.urlcontexttool.md b/docs-devsite/ai.urlcontexttool.md index 6ecc2a323c..cbe94d45b7 100644 --- a/docs-devsite/ai.urlcontexttool.md +++ b/docs-devsite/ai.urlcontexttool.md @@ -10,9 +10,6 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # URLContextTool interface -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - A tool that allows you to provide additional context to the models in the form of public web URLs. By including URLs in your request, the Gemini model will access the content from those pages to inform and enhance its response. Signature: @@ -25,13 +22,10 @@ export interface URLContextTool | Property | Type | Description | | --- | --- | --- | -| [urlContext](./ai.urlcontexttool.md#urlcontexttoolurlcontext) | [URLContext](./ai.urlcontext.md#urlcontext_interface) | (Public Preview) Specifies the URL Context configuration. | +| [urlContext](./ai.urlcontexttool.md#urlcontexttoolurlcontext) | [URLContext](./ai.urlcontext.md#urlcontext_interface) | Specifies the URL Context configuration. | ## URLContextTool.urlContext -> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. -> - Specifies the URL Context configuration. Signature: diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index 6180323191..3b10836bb8 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -422,11 +422,10 @@ export interface GoogleSearchTool { /** * A tool that enables the model to use code execution. * - * @beta + * @public */ export interface CodeExecutionTool { /** - * Specifies the Google Search configuration. * Currently, this is an empty object, but it's reserved for future configuration options. */ codeExecution: {}; @@ -446,7 +445,7 @@ export interface GoogleSearch {} * URLs. By including URLs in your request, the Gemini model will access the content from those * pages to inform and enhance its response. * - * @beta + * @public */ export interface URLContextTool { /** @@ -458,7 +457,7 @@ export interface URLContextTool { /** * Specifies the URL Context configuration. * - * @beta + * @public */ export interface URLContext {} From eb45714084b174dc109fd4d7a99f285f22079ad2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 12:18:02 -0700 Subject: [PATCH 138/174] build(deps): bump handlebars from 4.7.8 to 4.7.9 (#9778) Bumps [handlebars](https://github.com/handlebars-lang/handlebars.js) from 4.7.8 to 4.7.9. - [Release notes](https://github.com/handlebars-lang/handlebars.js/releases) - [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/v4.7.9/release-notes.md) - [Commits](https://github.com/handlebars-lang/handlebars.js/compare/v4.7.8...v4.7.9) --- updated-dependencies: - dependency-name: handlebars dependency-version: 4.7.9 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 09f5a4389e..4609749883 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8804,9 +8804,9 @@ gzip-size@6.0.0: duplexer "^0.1.2" handlebars@^4.7.2, handlebars@^4.7.7: - version "4.7.8" - resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" - integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== + version "4.7.9" + resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz#6f139082ab58dc4e5a0e51efe7db5ae890d56a0f" + integrity sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ== dependencies: minimist "^1.2.5" neo-async "^2.6.2" From 7bb8c35d729bc9d70e007bc8867800a13602fcd5 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 20 Apr 2026 10:27:40 -0700 Subject: [PATCH 139/174] chore: Add combine PRs workflow (#9856) --- .github/workflows/combine-prs.yml | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/combine-prs.yml diff --git a/.github/workflows/combine-prs.yml b/.github/workflows/combine-prs.yml new file mode 100644 index 0000000000..36f73c3e03 --- /dev/null +++ b/.github/workflows/combine-prs.yml @@ -0,0 +1,37 @@ +# Copyright 2026 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. + +name: Combine PRs + +on: + workflow_dispatch: # allows you to manually trigger the workflow + +# The minimum permissions required to run this Action +permissions: + contents: write + pull-requests: write + checks: read + +jobs: + combine-prs: + runs-on: ubuntu-latest + + steps: + - name: combine-prs + id: combine-prs + # This action defaults to combining branches that begin with + # "dependabot" but can be configured. + uses: github/combine-prs@v5.2.0 + with: + labels: combined-pr # Optional: add a label to the combined PR \ No newline at end of file From c4a02d4916783b12f3135298d3894c1b0fe8be26 Mon Sep 17 00:00:00 2001 From: Google Open Source Bot Date: Mon, 20 Apr 2026 15:26:31 -0700 Subject: [PATCH 140/174] Version Packages (#9865) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/silent-trains-bake.md | 5 ----- .changeset/silly-hounds-lay.md | 5 ----- integration/messaging/package.json | 2 +- packages/ai/CHANGELOG.md | 8 ++++++++ packages/ai/package.json | 2 +- packages/firebase/CHANGELOG.md | 7 +++++++ packages/firebase/package.json | 4 ++-- 7 files changed, 19 insertions(+), 14 deletions(-) delete mode 100644 .changeset/silent-trains-bake.md delete mode 100644 .changeset/silly-hounds-lay.md diff --git a/.changeset/silent-trains-bake.md b/.changeset/silent-trains-bake.md deleted file mode 100644 index b5efc3d468..0000000000 --- a/.changeset/silent-trains-bake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/ai': patch ---- - -Update code execution and URL context features to reflect that they are generally available and no longer public preview. diff --git a/.changeset/silly-hounds-lay.md b/.changeset/silly-hounds-lay.md deleted file mode 100644 index d447ca76db..0000000000 --- a/.changeset/silly-hounds-lay.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/ai': patch ---- - -Fix `TemplateChatSession` type so it does not error on TypeScript build. See Github issue #9832. diff --git a/integration/messaging/package.json b/integration/messaging/package.json index 90432df4d7..ca616d257e 100644 --- a/integration/messaging/package.json +++ b/integration/messaging/package.json @@ -9,7 +9,7 @@ "test:manual": "mocha --exit" }, "devDependencies": { - "firebase": "12.12.0", + "firebase": "12.12.1", "chai": "4.5.0", "chromedriver": "119.0.1", "express": "4.21.2", diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index d55c70057a..7de78db5af 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,5 +1,13 @@ # @firebase/ai +## 2.11.1 + +### Patch Changes + +- [`23ab5b9`](https://github.com/firebase/firebase-js-sdk/commit/23ab5b9dadb0451e855740a48f4cb12d29091a70) [#9817](https://github.com/firebase/firebase-js-sdk/pull/9817) - Update code execution and URL context features to reflect that they are generally available and no longer public preview. + +- [`6db5af4`](https://github.com/firebase/firebase-js-sdk/commit/6db5af46649382ee3ed73ab4e8f69abc5f9a33aa) [#9840](https://github.com/firebase/firebase-js-sdk/pull/9840) (fixes [#9832](https://github.com/firebase/firebase-js-sdk/issues/9832)) - Fix `TemplateChatSession` type so it does not error on TypeScript build. See Github issue #9832. + ## 2.11.0 ### Minor Changes diff --git a/packages/ai/package.json b/packages/ai/package.json index 57ecf62ed5..d9139a3369 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/ai", - "version": "2.11.0", + "version": "2.11.1", "description": "The Firebase AI SDK", "author": "Firebase (https://firebase.google.com/)", "engines": { diff --git a/packages/firebase/CHANGELOG.md b/packages/firebase/CHANGELOG.md index 6373e171f8..3921d478c0 100644 --- a/packages/firebase/CHANGELOG.md +++ b/packages/firebase/CHANGELOG.md @@ -1,5 +1,12 @@ # firebase +## 12.12.1 + +### Patch Changes + +- Updated dependencies [[`23ab5b9`](https://github.com/firebase/firebase-js-sdk/commit/23ab5b9dadb0451e855740a48f4cb12d29091a70), [`6db5af4`](https://github.com/firebase/firebase-js-sdk/commit/6db5af46649382ee3ed73ab4e8f69abc5f9a33aa)]: + - @firebase/ai@2.11.1 + ## 12.12.0 ### Minor Changes diff --git a/packages/firebase/package.json b/packages/firebase/package.json index a7177d9ed6..6e0bc7ee03 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -1,6 +1,6 @@ { "name": "firebase", - "version": "12.12.0", + "version": "12.12.1", "description": "Firebase JavaScript library for web and Node.js", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -423,7 +423,7 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/ai": "2.11.0", + "@firebase/ai": "2.11.1", "@firebase/app": "0.14.11", "@firebase/app-compat": "0.5.11", "@firebase/app-types": "0.9.4", From c9f45fa39ffb775c9f05d7f9b40e1af6fa3b9a73 Mon Sep 17 00:00:00 2001 From: wu-hui <53845758+wu-hui@users.noreply.github.com> Date: Tue, 21 Apr 2026 10:53:50 -0400 Subject: [PATCH 141/174] chore(firestore): rename nameddb tests to enterprise (#9863) --- .github/workflows/test-changed-firestore.yml | 6 +++--- packages/firestore/package.json | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test-changed-firestore.yml b/.github/workflows/test-changed-firestore.yml index feb5eb0f67..e1c47e7984 100644 --- a/.github/workflows/test-changed-firestore.yml +++ b/.github/workflows/test-changed-firestore.yml @@ -107,7 +107,7 @@ jobs: name: Test Firestore strategy: matrix: - test-name: ["test:browser", "test:travis", "test:lite:browser", "test:browser:prod:nameddb", "test:lite:browser:nameddb"] + test-name: ["test:browser", "test:travis", "test:lite:browser", "test:browser:prod:enterprise", "test:lite:browser:enterprise"] runs-on: ubuntu-latest needs: build if: ${{ needs.build.outputs.changed == 'true'}} @@ -196,7 +196,7 @@ jobs: name: Test Firestore on Firefox strategy: matrix: - test-name: ["test:browser", "test:travis", "test:lite:browser", "test:browser:prod:nameddb", "test:lite:browser:nameddb"] + test-name: ["test:browser", "test:travis", "test:lite:browser", "test:browser:prod:enterprise", "test:lite:browser:enterprise"] runs-on: ubuntu-latest needs: build if: ${{ needs.build.outputs.changed == 'true'}} @@ -253,7 +253,7 @@ jobs: # TODO (dlarocque): Add test:travis once the browser tests are isolated # Exclude test:travis for now, since it includes node tests, which are failing for # some reason. - test-name: ["test:browser", "test:lite:browser", "test:browser:prod:nameddb", "test:lite:browser:nameddb"] + test-name: ["test:browser", "test:lite:browser", "test:browser:prod:enterprise", "test:lite:browser:enterprise"] runs-on: macos-latest needs: build if: ${{ needs.build.outputs.changed == 'true'}} diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 4e9d4d1369..2f9b02fc0b 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -24,14 +24,14 @@ "prettier": "prettier --write '*.js' '@(lite|src|test|scripts)/**/*.ts' 'test/unit/remote/bloom_filter_golden_test_data/*.json'", "test:lite": "ts-node ./scripts/run-tests.ts --emulator --platform node_lite --main=lite/index.ts 'test/lite/**/*.test.ts'", "test:lite:prod": "ts-node ./scripts/run-tests.ts --platform node_lite --main=lite/index.ts 'test/lite/**/*.test.ts'", - "test:lite:prod:nameddb": "ts-node ./scripts/run-tests.ts --platform node_lite --databaseId=enterprise --main=lite/index.ts --firestoreEdition=enterprise 'test/lite/**/*.test.ts'", + "test:lite:prod:enterprise": "ts-node ./scripts/run-tests.ts --platform node_lite --databaseId=enterprise --main=lite/index.ts --firestoreEdition=enterprise 'test/lite/**/*.test.ts'", "test:lite:browser": "karma start --lite", - "test:lite:browser:nameddb": "karma start --lite --databaseId=enterprise --firestoreEdition=enterprise", + "test:lite:browser:enterprise": "karma start --lite --databaseId=enterprise --firestoreEdition=enterprise", "test:lite:browser:debug": "karma start --browsers=Chrome --lite --auto-watch", "test": "run-s --npm-path npm lint assertion-id:check test:all", "test:ci": "node ../../scripts/run_tests_in_ci.js -s test:all:ci", - "test:all:ci": "run-s --npm-path npm test:browser test:travis test:lite:browser test:browser:prod:nameddb test:lite:browser:nameddb", - "test:all": "run-p --npm-path npm test:browser test:lite:browser test:travis test:minified test:browser:prod:nameddb test:lite:browser:nameddb", + "test:all:ci": "run-s --npm-path npm test:browser test:travis test:lite:browser test:browser:prod:enterprise test:lite:browser:enterprise", + "test:all": "run-p --npm-path npm test:browser test:lite:browser test:travis test:minified test:browser:prod:enterprise test:lite:browser:enterprise", "test:browser": "karma start", "test:browser:emulator:debug": "karma start --browsers=Chrome --targetBackend=emulator", "test:browser:emulator": "karma start --targetBackend=emulator", @@ -39,12 +39,12 @@ "test:browser:prod": "karma start --targetBackend=prod", "test:webkit:prod": "BROWSERS=WebkitHeadless karma start --targetBackend=prod", "test:webkit:unit": "BROWSERS=WebkitHeadless karma start --unit --targetBackend=prod", - "test:browser:prod:nameddb": "karma start --targetBackend=prod --databaseId=enterprise --firestoreEdition=enterprise", + "test:browser:prod:enterprise": "karma start --targetBackend=prod --databaseId=enterprise --firestoreEdition=enterprise", "test:browser:unit": "karma start --unit", "test:browser:debug": "karma start --browsers=Chrome --auto-watch", "test:node": "ts-node ./scripts/run-tests.ts --main=test/register.ts --emulator 'test/{,!(browser|lite)/**/}*.test.ts'", "test:node:prod": "ts-node ./scripts/run-tests.ts --main=test/register.ts 'test/{,!(browser|lite)/**/}*.test.ts'", - "test:node:prod:nameddb": "ts-node ./scripts/run-tests.ts --main=test/register.ts --databaseId=enterprise --firestoreEdition=enterprise 'test/{,!(browser|lite)/**/}*.test.ts'", + "test:node:prod:enterprise": "ts-node ./scripts/run-tests.ts --main=test/register.ts --databaseId=enterprise --firestoreEdition=enterprise 'test/{,!(browser|lite)/**/}*.test.ts'", "test:node:persistence": "ts-node ./scripts/run-tests.ts --main=test/register.ts --persistence --emulator 'test/{,!(browser|lite)/**/}*.test.ts'", "test:node:persistence:prod": "ts-node ./scripts/run-tests.ts --main=test/register.ts --persistence 'test/{,!(browser|lite)/**/}*.test.ts'", "test:travis": "ts-node --compiler-options='{\"module\":\"commonjs\"}' ../../scripts/emulator-testing/firestore-test-runner.ts", From e24b336f20590541b56aaee1b6a374b36c9c4cc0 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 21 Apr 2026 12:41:54 -0400 Subject: [PATCH 142/174] test(firestore): remove nightly conditional `get_field` tests (#9868) --- .../test/integration/api/pipeline.test.ts | 71 ++----------------- packages/firestore/test/lite/pipeline.test.ts | 71 ++----------------- 2 files changed, 8 insertions(+), 134 deletions(-) diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 8aff0a73b9..4b06ceb273 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -24,7 +24,6 @@ import { FirebaseError } from '@firebase/util'; import { expect, use } from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import { logWarn } from '../../../src/util/log'; import { addEqualityMatcher } from '../../util/equality_matcher'; import { Deferred } from '../../util/promise'; import { @@ -6573,39 +6572,8 @@ apiDescribe.skipClassic('Pipelines', persistence => { .addFields(reviewsSub.toArrayExpression().as('reviews')) .select('title', 'reviews'); - // TODO(dlarocque): Remove these target backend conditionals once the 'get_field' rename has rolled out to prod. - const host = firestore._getSettings().host; - const isProd = host === 'firestore.googleapis.com'; - const isNightly = host === 'test-firestore.sandbox.googleapis.com'; - - if (isProd) { - // The execution of this pipeline is expected to result in a network error - // from the backend until the breaking change to rename the 'field' expression to - // 'get_field' has rolled out to prod. - try { - const results = await execute(ppl); - - // If this is reached, the execution of the pipeline didn't throw an error, so the - // breaking change must have rolled out to prod. We can assert the newly expected behaviour. - logWarn( - "The 'get_field' expression rename has rolled out to the prod backend. Remove the target backend conditionals in this test." - ); - expectResults(results, { title: '1984', reviews: ['Alice'] }); - } catch (err: unknown) { - const error: Error = err as Error; - expect(error.message).to.equals( - "The function 'get_field' does not exist, did you mean 'field'?" - ); - } - } else if (isNightly) { - const results = await execute(ppl); - expectResults(results, { title: '1984', reviews: ['Alice'] }); - } else { - expect(false).to.equal( - true, - `This test is only expected to run against firestore.googleapis.com or test-firestore.sandbox.googleapis.com, but it instead ran against ${host}` - ); - } + const results = await execute(ppl); + expectResults(results, { title: '1984', reviews: ['Alice'] }); }); }); @@ -6687,39 +6655,8 @@ apiDescribe.skipClassic('Pipelines', persistence => { .addFields(reviewsSub.toArrayExpression().as('reviews')) .select('title', 'reviews'); - // TODO(dlarocque): Remove these target backend conditionals once the 'get_field' rename has rolled out to prod. - const host = firestore._getSettings().host; - const isProd = host === 'firestore.googleapis.com'; - const isNightly = host === 'test-firestore.sandbox.googleapis.com'; - - if (isProd) { - // The execution of this pipeline is expected to result in a network error - // from the backend until the breaking change to rename the 'field' expression to - // 'get_field' has rolled out to prod. - try { - const results = await execute(ppl); - - // If this is reached, the execution of the pipeline didn't throw an error, so the - // breaking change must have rolled out to prod. We can assert the newly expected behaviour. - logWarn( - "The 'get_field' expression rename has rolled out to the prod backend. Remove the target backend conditionals in this test." - ); - expectResults(results, { title: '1984', reviews: [] }); - } catch (err: unknown) { - const error: Error = err as Error; - expect(error.message).to.equals( - "The function 'get_field' does not exist, did you mean 'field'?" - ); - } - } else if (isNightly) { - const results = await execute(ppl); - expectResults(results, { title: '1984', reviews: [] }); - } else { - expect(false).to.equal( - true, - `This test is only expected to run against firestore.googleapis.com or test-firestore.sandbox.googleapis.com, but it instead ran against ${host}` - ); - } + const results = await execute(ppl); + expectResults(results, { title: '1984', reviews: [] }); }); }); diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 7c5363aa41..64bcf7b2c0 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -53,7 +53,6 @@ import { FindNearestStageOptions } from '../../src/lite-api/stage_options'; import { Timestamp } from '../../src/lite-api/timestamp'; import { writeBatch } from '../../src/lite-api/write_batch'; import { Code, FirestoreError } from '../../src/util/error'; -import { logWarn } from '../../src/util/log'; import { getRunEnterpriseTests, getTargetBackend, @@ -6445,39 +6444,8 @@ describe.skipClassic('Firestore Pipelines', () => { .addFields(reviewsSub.toArrayExpression().as('reviews')) .select('title', 'reviews'); - // TODO(dlarocque): Remove these target backend conditionals once the 'get_field' rename has rolled out to prod. - const host = firestore._getSettings().host; - const isProd = host === 'firestore.googleapis.com'; - const isNightly = host === 'test-firestore.sandbox.googleapis.com'; - - if (isProd) { - // The execution of this pipeline is expected to result in a network error - // from the backend until the breaking change to rename the 'field' expression to - // 'get_field' has rolled out to prod. - try { - const results = await execute(ppl); - - // If this is reached, the execution of the pipeline didn't throw an error, so the - // breaking change must have rolled out to prod. We can assert the newly expected behaviour. - logWarn( - "The 'get_field' expression rename has rolled out to the prod backend. Remove the target backend conditionals in this test." - ); - expectResults(results, { title: '1984', reviews: ['Alice'] }); - } catch (err: unknown) { - const error: Error = err as Error; - expect(error.message).to.equals( - "Request failed with error: The function 'get_field' does not exist, did you mean 'field'?" - ); - } - } else if (isNightly) { - const results = await execute(ppl); - expectResults(results, { title: '1984', reviews: ['Alice'] }); - } else { - expect(false).to.equal( - true, - `This test is only expected to run against firestore.googleapis.com or test-firestore.sandbox.googleapis.com, but it instead ran against ${host}` - ); - } + const results = await execute(ppl); + expectResults(results, { title: '1984', reviews: ['Alice'] }); }); }); @@ -6560,39 +6528,8 @@ describe.skipClassic('Firestore Pipelines', () => { .addFields(reviewsSub.toArrayExpression().as('reviews')) .select('title', 'reviews'); - // TODO(dlarocque): Remove these target backend conditionals once the 'get_field' rename has rolled out to prod. - const host = firestore._getSettings().host; - const isProd = host === 'firestore.googleapis.com'; - const isNightly = host === 'test-firestore.sandbox.googleapis.com'; - - if (isProd) { - // The execution of this pipeline is expected to result in a network error - // from the backend until the breaking change to rename the 'field' expression to - // 'get_field' has rolled out to prod. - try { - const results = await execute(ppl); - - // If this is reached, the execution of the pipeline didn't throw an error, so the - // breaking change must have rolled out to prod. We can assert the newly expected behaviour. - logWarn( - "The 'get_field' expression rename has rolled out to the prod backend. Remove the target backend conditionals in this test." - ); - expectResults(results, { title: '1984', reviews: [] }); - } catch (err: unknown) { - const error: Error = err as Error; - expect(error.message).to.equals( - "Request failed with error: The function 'get_field' does not exist, did you mean 'field'?" - ); - } - } else if (isNightly) { - const results = await execute(ppl); - expectResults(results, { title: '1984', reviews: [] }); - } else { - expect(false).to.equal( - true, - `This test is only expected to run against firestore.googleapis.com or test-firestore.sandbox.googleapis.com, but it instead ran against ${host}` - ); - } + const results = await execute(ppl); + expectResults(results, { title: '1984', reviews: [] }); }); }); From 8daacbff8d986684ed9195aefe9b8eb4cacc9aa9 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 21 Apr 2026 12:44:16 -0400 Subject: [PATCH 143/174] build(firestore): generate lib for Firestore Studio (#9858) --- packages/firestore/package.json | 2 +- .../scripts/build-console-ui-types.ts | 476 ++ packages/firestore/src/protos/compile.sh | 28 +- .../src/protos/google/api/annotations.proto | 2 +- .../src/protos/google/api/client.proto | 541 +- .../protos/google/api/field_behavior.proto | 18 +- .../src/protos/google/api/http.proto | 63 +- .../src/protos/google/api/launch_stage.proto | 72 + .../src/protos/google/api/resource.proto | 242 + .../src/protos/google/api/routing.proto | 465 ++ .../firestore/v1/aggregation_result.proto | 7 +- .../google/firestore/v1/bloom_filter.proto | 24 +- .../protos/google/firestore/v1/common.proto | 23 +- .../protos/google/firestore/v1/document.proto | 84 +- .../google/firestore/v1/explain_stats.proto | 41 + .../google/firestore/v1/firestore.proto | 361 +- .../protos/google/firestore/v1/pipeline.proto | 54 +- .../protos/google/firestore/v1/query.proto | 300 +- .../google/firestore/v1/query_profile.proto | 2 +- .../protos/google/firestore/v1/write.proto | 66 +- .../src/protos/google/protobuf/any.proto | 157 +- .../protos/google/protobuf/descriptor.proto | 762 +- .../src/protos/google/protobuf/empty.proto | 5 +- .../src/protos/google/protobuf/struct.proto | 67 +- .../protos/google/protobuf/timestamp.proto | 44 +- .../src/protos/google/protobuf/wrappers.proto | 48 +- .../src/protos/google/rpc/status.proto | 9 +- .../src/protos/google/type/latlng.proto | 9 +- packages/firestore/src/protos/protos.json | 6868 ++++++++++------- packages/firestore/src/protos/update.sh | 53 +- packages/firestore/src/protos/verify.patch | 15 + 31 files changed, 7472 insertions(+), 3436 deletions(-) create mode 100644 packages/firestore/scripts/build-console-ui-types.ts create mode 100644 packages/firestore/src/protos/google/api/launch_stage.proto create mode 100644 packages/firestore/src/protos/google/api/resource.proto create mode 100644 packages/firestore/src/protos/google/api/routing.proto create mode 100644 packages/firestore/src/protos/google/firestore/v1/explain_stats.proto create mode 100644 packages/firestore/src/protos/verify.patch diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 2f9b02fc0b..e37e032494 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -51,7 +51,7 @@ "test:minified": "(cd ../../integration/firestore ; yarn test)", "trusted-type-check": "tsec -p tsconfig.json --noEmit", "api-report:main": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore --packageRoot . --typescriptDts ./dist/firestore/src/index.d.ts --rollupDts ./dist/private.d.ts --untrimmedRollupDts ./dist/internal.d.ts --publicDts ./dist/index.d.ts", - "api-report:pipelines": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-pipelines --packageRoot . --typescriptDts ./dist/firestore/pipelines/pipelines.d.ts --rollupDts ./dist/private.pipelines.d.ts --untrimmedRollupDts ./dist/internal.pipelines.d.ts --publicDts ./dist/pipelines.d.ts --otherExportsPublicDtsFiles ./dist/index.d.ts --excludeForgottenExportWarning", + "api-report:pipelines": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-pipelines --packageRoot . --typescriptDts ./dist/firestore/pipelines/pipelines.d.ts --rollupDts ./dist/private.pipelines.d.ts --untrimmedRollupDts ./dist/internal.pipelines.d.ts --publicDts ./dist/pipelines.d.ts --otherExportsPublicDtsFiles ./dist/index.d.ts --excludeForgottenExportWarning && TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node scripts/build-console-ui-types.ts --input ./dist/pipelines.d.ts --output ./dist/pipelines_extra_lib.txt", "api-report:lite": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-lite --packageRoot . --typescriptDts ./dist/firestore/lite/index.d.ts --rollupDts ./dist/lite/private.d.ts --untrimmedRollupDts ./dist/lite/internal.d.ts --publicDts ./dist/lite/index.d.ts", "api-report:lite:pipelines": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node ../../repo-scripts/prune-dts/extract-public-api.ts --package firestore-lite-pipelines --packageRoot . --typescriptDts ./dist/firestore/lite/pipelines/pipelines.d.ts --rollupDts ./dist/lite/private.pipelines.d.ts --untrimmedRollupDts ./dist/lite/internal.pipelines.d.ts --publicDts ./dist/lite/pipelines.d.ts --otherExportsPublicDtsFiles ./dist/lite/index.d.ts --excludeForgottenExportWarning", "api-report:api-json": "rm -rf temp && api-extractor run --local --verbose", diff --git a/packages/firestore/scripts/build-console-ui-types.ts b/packages/firestore/scripts/build-console-ui-types.ts new file mode 100644 index 0000000000..8240a4e8aa --- /dev/null +++ b/packages/firestore/scripts/build-console-ui-types.ts @@ -0,0 +1,476 @@ +/* eslint-disable no-console */ +/** + * @license + * Copyright 2026 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. + */ + +/** + * @fileoverview Generates and verifies the pipelines_extra_lib.txt file for the Firestore Query Editor. + * + * 1. Reads the pruned pipelines.d.ts. + * 2. Uses regex to strip module syntax (import/export). + * 3. Appends required hardcoded UI types. + * 4. Runs an in-memory TypeScript compilation to verify the generated code is valid. + * 5. Writes the result to the output file. + */ + +import * as fs from 'fs'; +import * as path from 'path'; + +import * as ts from 'typescript'; + +// Parse arguments +const args: string[] = process.argv.slice(2); +let sourceDtsPath: string = ''; +let destTxtPath: string = ''; + +for (let i = 0; i < args.length; i++) { + if (args[i] === '--input' && args[i + 1]) { + sourceDtsPath = path.resolve(process.cwd(), args[i + 1]); + i++; + } else if (args[i] === '--output' && args[i + 1]) { + destTxtPath = path.resolve(process.cwd(), args[i + 1]); + i++; + } +} + +if (!sourceDtsPath || !destTxtPath) { + console.error('❌ Error: Missing required arguments.'); + console.error( + 'Usage: ts-node build-console-ui-types.ts --input --output ' + ); + process.exit(1); +} + +if (!fs.existsSync(sourceDtsPath)) { + console.error(`❌ Error: Source file not found: ${sourceDtsPath}`); + process.exit(1); +} + +// Hard-coded UI types +const HEADER: string = `// AUTO-GENERATED BY https://github.com/firebase/firebase-js-sdk/blob/main/packages/firestore/scripts/build-console-ui-types.ts +// DO NOT EDIT MANUALLY +// +// +// Purpose: +// This file provides TypeScript declarations (.d.ts) for the Firestore Pipelines +// API, tailored for use within the Firebase Console's Firestore UI code in Google3. +// It enables type checking, autocompletion, and a clear API contract for the UI +// components interacting with Firestore Pipelines. +// +// Structure: +// 1. Manual Definitions: The initial section of this file contains hand-crafted +// type definitions. These include: +// - A base \`Firestore\` interface exposing the \`pipeline()\` method. +// - Common Firestore data types (e.g., Timestamp, GeoPoint, VectorValue). +// - Stubs for types like \`Query\` and \`DocumentReference\` set to \`never\` +// to discourage their use in this context. +// +// 2. Auto-populated Pipelines Types: The section below the marker +// "// BEGIN PIPELINE TYPES" is automatically populated from the +// Firebase JavaScript SDK build. + +interface Firestore { + pipeline(): PipelineSource; +} + +/** + * @type {Firestore} +*/ +declare var db: Firestore; + +/** + * Not supported in the query editor. + */ +type Query = never; + +/** + * Not supported in the query editor. + */ +type DocumentReference = never; + +/** + * A \`FieldPath\` refers to a field in a document. The path may consist of a + * single field name (referring to a top-level field in the document), or a + * list of field names (referring to a nested field in the document). + * + * Create a \`FieldPath\` by providing field names. If more than one field + * name is provided, the path will point to a nested field in a document. + */ +declare class FieldPath { + /** + * Creates a \`FieldPath\` from the provided field names. If more than one field + * name is provided, the path will point to a nested field in a document. + * + * @param fieldNames - A list of field names. + */ + constructor(...fieldNames: string[]); + /** + * Returns true if this \`FieldPath\` is equal to the provided one. + * + * @param other - The \`FieldPath\` to compare against. + * @returns true if this \`FieldPath\` is equal to the provided one. + */ + isEqual(other: FieldPath): boolean; +} + +/** + * Creates a new \`VectorValue\` constructed with a copy of the given array of numbers. + * + * @param values - Create a \`VectorValue\` instance with a copy of this array of numbers. + * + * @returns A new \`VectorValue\` constructed with a copy of the given array of numbers. + */ +declare function vector(values?: number[]): VectorValue; + +/** + * Represents a vector type in Firestore documents. + * Create an instance with {@link vector}. + * + * @class VectorValue + */ +declare class VectorValue { + /** + * Returns a copy of the raw number array form of the vector. + */ + toArray(): number[]; + /** + * Returns \`true\` if the two \`VectorValue\` values have the same raw number arrays, returns \`false\` otherwise. + */ + isEqual(other: VectorValue): boolean; + /** + * Returns a JSON-serializable representation of this \`VectorValue\` instance. + * + * @returns a JSON representation of this object. + */ + toJSON(): object; + /** + * Builds a \`VectorValue\` instance from a JSON object created by {@link VectorValue.toJSON}. + * + * @param json a JSON object represention of a \`VectorValue\` instance. + * @returns an instance of {@link VectorValue} if the JSON object could be parsed. Throws a + * {@link FirestoreError} if an error occurs. + */ + static fromJSON(json: object): VectorValue; +} + +/** + * An immutable object representing an array of bytes. + */ +declare class Bytes { + private constructor(); + /** + * Creates a new \`Bytes\` object from the given Base64 string, converting it to + * bytes. + * + * @param base64 - The Base64 string used to create the \`Bytes\` object. + */ + static fromBase64String(base64: string): Bytes; + /** + * Creates a new \`Bytes\` object from the given Uint8Array. + * + * @param array - The Uint8Array used to create the \`Bytes\` object. + */ + static fromUint8Array(array: Uint8Array): Bytes; + /** + * Returns the underlying bytes as a Base64-encoded string. + * + * @returns The Base64-encoded string created from the \`Bytes\` object. + */ + toBase64(): string; + /** + * Returns the underlying bytes in a new \`Uint8Array\`. + * + * @returns The Uint8Array created from the \`Bytes\` object. + */ + toUint8Array(): Uint8Array; + /** + * Returns a string representation of the \`Bytes\` object. + * + * @returns A string representation of the \`Bytes\` object. + */ + toString(): string; + /** + * Returns true if this \`Bytes\` object is equal to the provided one. + * + * @param other - The \`Bytes\` object to compare against. + * @returns true if this \`Bytes\` object is equal to the provided one. + */ + isEqual(other: Bytes): boolean; + /** + * Returns a JSON-serializable representation of this \`Bytes\` instance. + * + * @returns a JSON representation of this object. + */ + toJSON(): object; + /** + * Builds a \`Bytes\` instance from a JSON object created by {@link Bytes.toJSON}. + * + * @param json a JSON object represention of a \`Bytes\` instance + * @returns an instance of {@link Bytes} if the JSON object could be parsed. Throws a + * {@link FirestoreError} if an error occurs. + */ + static fromJSON(json: object): Bytes; +} + +/** + * A \`Timestamp\` represents a point in time independent of any time zone or + * calendar, represented as seconds and fractions of seconds at nanosecond + * resolution in UTC Epoch time. + * + * It is encoded using the Proleptic Gregorian Calendar which extends the + * Gregorian calendar backwards to year one. It is encoded assuming all minutes + * are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second + * table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59.999999999Z. + * + * For examples and further specifications, refer to the + * {@link https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto | Timestamp definition}. + */ +declare class Timestamp { + /** + * The number of seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. + */ + readonly seconds: number; + /** + * The fractions of a second at nanosecond resolution.* + */ + readonly nanoseconds: number; + /** + * Creates a new timestamp with the current date, with millisecond precision. + * + * @returns a new timestamp representing the current date. + */ + static now(): Timestamp; + /** + * Creates a new timestamp from the given date. + * + * @param date - The date to initialize the \`Timestamp\` from. + * @returns A new \`Timestamp\` representing the same point in time as the given + * date. + */ + static fromDate(date: Date): Timestamp; + /** + * Creates a new timestamp from the given number of milliseconds. + * + * @param milliseconds - Number of milliseconds since Unix epoch + * 1970-01-01T00:00:00Z. + * @returns A new \`Timestamp\` representing the same point in time as the given + * number of milliseconds. + */ + static fromMillis(milliseconds: number): Timestamp; + /** + * Creates a new timestamp. + * + * @param seconds - The number of seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + * @param nanoseconds - The non-negative fractions of a second at nanosecond + * resolution. Negative second values with fractions must still have + * non-negative nanoseconds values that count forward in time. Must be + * from 0 to 999,999,999 inclusive. + */ + constructor( + /** + * The number of seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. + */ + seconds: number, + /** + * The fractions of a second at nanosecond resolution.* + */ + nanoseconds: number); + /** + * Converts a \`Timestamp\` to a JavaScript \`Date\` object. This conversion + * causes a loss of precision since \`Date\` objects only support millisecond + * precision. + * + * @returns JavaScript \`Date\` object representing the same point in time as + * this \`Timestamp\`, with millisecond precision. + */ + toDate(): Date; + /** + * Converts a \`Timestamp\` to a numeric timestamp (in milliseconds since + * epoch). This operation causes a loss of precision. + * + * @returns The point in time corresponding to this timestamp, represented as + * the number of milliseconds since Unix epoch 1970-01-01T00:00:00Z. + */ + toMillis(): number; + /** + * Returns true if this \`Timestamp\` is equal to the provided one. + * + * @param other - The \`Timestamp\` to compare against. + * @returns true if this \`Timestamp\` is equal to the provided one. + */ + isEqual(other: Timestamp): boolean; + /** Returns a textual representation of this \`Timestamp\`. */ + toString(): string; + /** + * Returns a JSON-serializable representation of this \`Timestamp\`. + */ + toJSON(): { + seconds: number; + nanoseconds: number; + type: string; + }; + /** + * Builds a \`Timestamp\` instance from a JSON object created by {@link Timestamp.toJSON}. + */ + static fromJSON(json: object): Timestamp; + /** + * Converts this object to a primitive string, which allows \`Timestamp\` objects + * to be compared using the \`>\`, \`<=\`, \`>=\` and \`>\` operators. + */ + valueOf(): string; +} + +/** + * An immutable object representing a geographic location in Firestore. The + * location is represented as latitude/longitude pair. + * + * Latitude values are in the range of [-90, 90]. + * Longitude values are in the range of [-180, 180]. + */ +declare class GeoPoint { + /** + * Creates a new immutable \`GeoPoint\` object with the provided latitude and + * longitude values. + * @param latitude - The latitude as number between -90 and 90. + * @param longitude - The longitude as number between -180 and 180. + */ + constructor(latitude: number, longitude: number); + /** + * The latitude of this \`GeoPoint\` instance. + */ + get latitude(): number; + /** + * The longitude of this \`GeoPoint\` instance. + */ + get longitude(): number; + /** + * Returns true if this \`GeoPoint\` is equal to the provided one. + * + * @param other - The \`GeoPoint\` to compare against. + * @returns true if this \`GeoPoint\` is equal to the provided one. + */ + isEqual(other: GeoPoint): boolean; + /** + * Returns a JSON-serializable representation of this \`GeoPoint\` instance. + * + * @returns a JSON representation of this object. + */ + toJSON(): { + latitude: number; + longitude: number; + type: string; + }; + /** + * Builds a \`GeoPoint\` instance from a JSON object created by {@link GeoPoint.toJSON}. + * + * @param json a JSON object represention of a \`GeoPoint\` instance + * @returns an instance of {@link GeoPoint} if the JSON object could be parsed. Throws a + * {@link FirestoreError} if an error occurs. + */ + static fromJSON(json: object): GeoPoint; +} + +type DocumentData = { [field: string]: any }; + +// ============================================================================ +// BEGIN PIPELINE TYPES (Pruned from source) +// ============================================================================ +`; +// Regex processing to remove ES module syntax (import/export statements) +let dtsContent: string = fs.readFileSync(sourceDtsPath, 'utf8'); + +// Strip multi-line and single-line imports +dtsContent = dtsContent.replace(/^import\s+[\s\S]*?from\s+['"][^'"]+['"];?\s*$/gm, ''); +dtsContent = dtsContent.replace(/^import\s+['"][^'"]+['"];?\s*$/gm, ''); + +// Strip bulk exports: export { Foo, Bar }; +dtsContent = dtsContent.replace(/^export\s+\{[\s\S]*?\};?\s*$/gm, ''); + +// Strip 'export ' modifiers from the beginning of lines. +// This converts 'export declare class' -> 'declare class', which is standard +// for ambient global declaration files. +dtsContent = dtsContent.replace(/^\s*export\s+/gm, ''); + +const finalContent: string = HEADER + '\n' + dtsContent; + +// Verify the final content is valid TypeScript +const outputDir: string = path.dirname(destTxtPath); +const tempDtsPath: string = path.join(outputDir, 'temp_ui_types.d.ts'); +const tempTestPath: string = path.join(outputDir, 'temp_ui_test.ts'); + +fs.writeFileSync(tempDtsPath, finalContent); +fs.writeFileSync( + tempTestPath, + ` + /// + + // Test 1: Verify the UI 'db' entry point and pipeline chaining works + const p = db.pipeline() + .collection("books") + .where(equal("title", "1984")) + .select("author"); + + // Test 2: Verify hardcoded types exist and align with pipeline expectations + const ts: Timestamp = Timestamp.now(); + const pt: GeoPoint = new GeoPoint(1, 2); + const vec: VectorValue = vector([1.0, 2.0]); + const b: Bytes = Bytes.fromBase64String("abc"); + const path: FieldPath = new FieldPath("field"); +` +); + +// Run the TS Compiler +const program: ts.Program = ts.createProgram([tempTestPath], { + noEmit: true, + strict: true, + skipLibCheck: true // Skip internal .d.ts formatting quirks, just verify the API contract works. +}); + +const diagnostics: readonly ts.Diagnostic[] = ts.getPreEmitDiagnostics(program); + +// Cleanup temp files immediately +try { + fs.unlinkSync(tempDtsPath); + fs.unlinkSync(tempTestPath); +} catch (e) { + // Ignore errors if temp files couldn't be deleted +} + +if (diagnostics.length > 0) { + console.error('ERROR: Type verification failed for Console UI pipeline types!'); + console.error( + 'This usually means the hardcoded types in build-console-ui-types.ts drifted from the SDK, or the regex stripped too much.' + ); + + diagnostics.forEach((diag) => { + if (diag.file) { + const { line, character } = ts.getLineAndCharacterOfPosition(diag.file, diag.start!); + const message = ts.flattenDiagnosticMessageText(diag.messageText, '\n'); + console.error(`${diag.file.fileName} (${line + 1},${character + 1}): ${message}`); + } else { + console.error(ts.flattenDiagnosticMessageText(diag.messageText, '\n')); + } + }); + + process.exit(1); // Fail the build +} + +// Write output +fs.writeFileSync(destTxtPath, finalContent); +console.log(`✅ Successfully generated and verified console UI types at ${destTxtPath}`); diff --git a/packages/firestore/src/protos/compile.sh b/packages/firestore/src/protos/compile.sh index 9f9fb4b321..e26b612636 100755 --- a/packages/firestore/src/protos/compile.sh +++ b/packages/firestore/src/protos/compile.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright 2017 Google Inc. +# Copyright 2026 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,19 +16,19 @@ set -euo pipefail -# Variables -PROTOS_DIR="." -PBJS="../../node_modules/.bin/pbjs" -PBTS="../../node_modules/.bin/pbts" +# Verify dependencies +for cmd in npx find; do + if ! command -v "$cmd" &> /dev/null; then + echo "Error: $cmd is required but not installed." >&2 + exit 1 + fi +done -"${PBJS}" --path=. --target=json -o protos.json \ - -r firestore/v1 "${PROTOS_DIR}/google/firestore/v1/*.proto" \ - "${PROTOS_DIR}/google/protobuf/*.proto" "${PROTOS_DIR}/google/type/*.proto" \ - "${PROTOS_DIR}/google/rpc/*.proto" "${PROTOS_DIR}/google/api/*.proto" +PROTOS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PROTO_FILES=$(find "${PROTOS_DIR}/google" -name "*.proto") -"${PBJS}" --path="${PROTOS_DIR}" --target=static -o temp.js \ - -r firestore/v1 "${PROTOS_DIR}/google/firestore/v1/*.proto" \ - "${PROTOS_DIR}/google/protobuf/*.proto" "${PROTOS_DIR}/google/type/*.proto" \ - "${PROTOS_DIR}/google/rpc/*.proto" "${PROTOS_DIR}/google/api/*.proto" +# Generate JSON representation +npx pbjs --path="${PROTOS_DIR}" --target=json -o "${PROTOS_DIR}/protos.json" \ + -r firestore/v1 $PROTO_FILES -"${PBTS}" -o temp.d.ts --no-comments temp.js +rm -f "${PROTOS_DIR}/temp.d.ts" diff --git a/packages/firestore/src/protos/google/api/annotations.proto b/packages/firestore/src/protos/google/api/annotations.proto index efdab3db6c..417edd8fa1 100644 --- a/packages/firestore/src/protos/google/api/annotations.proto +++ b/packages/firestore/src/protos/google/api/annotations.proto @@ -1,4 +1,4 @@ -// Copyright 2015 Google LLC +// 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. diff --git a/packages/firestore/src/protos/google/api/client.proto b/packages/firestore/src/protos/google/api/client.proto index 3b3fd0c401..332e0d086d 100644 --- a/packages/firestore/src/protos/google/api/client.proto +++ b/packages/firestore/src/protos/google/api/client.proto @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,7 +16,9 @@ syntax = "proto3"; package google.api; +import "google/api/launch_stage.proto"; import "google/protobuf/descriptor.proto"; +import "google/protobuf/duration.proto"; option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; option java_multiple_files = true; @@ -39,15 +41,15 @@ extend google.protobuf.MethodOptions { // // For example, the proto RPC and annotation: // - // rpc CreateSubscription(CreateSubscriptionRequest) - // returns (Subscription) { - // option (google.api.method_signature) = "name,topic"; - // } + // rpc CreateSubscription(CreateSubscriptionRequest) + // returns (Subscription) { + // option (google.api.method_signature) = "name,topic"; + // } // // Would add the following Java overload (in addition to the method accepting // the request object): // - // public final Subscription createSubscription(String name, String topic) + // public final Subscription createSubscription(String name, String topic) // // The following backwards-compatibility guidelines apply: // @@ -69,31 +71,528 @@ extend google.protobuf.ServiceOptions { // // Example: // - // service Foo { - // option (google.api.default_host) = "foo.googleapi.com"; - // ... - // } + // service Foo { + // option (google.api.default_host) = "foo.googleapi.com"; + // ... + // } string default_host = 1049; // OAuth scopes needed for the client. // // Example: // - // service Foo { - // option (google.api.oauth_scopes) = \ - // "https://www.googleapis.com/auth/cloud-platform"; - // ... - // } + // service Foo { + // option (google.api.oauth_scopes) = \ + // "https://www.googleapis.com/auth/cloud-platform"; + // ... + // } // // If there is more than one scope, use a comma-separated string: // // Example: // - // service Foo { - // option (google.api.oauth_scopes) = \ - // "https://www.googleapis.com/auth/cloud-platform," - // "https://www.googleapis.com/auth/monitoring"; - // ... - // } + // service Foo { + // option (google.api.oauth_scopes) = \ + // "https://www.googleapis.com/auth/cloud-platform," + // "https://www.googleapis.com/auth/monitoring"; + // ... + // } string oauth_scopes = 1050; + + // The API version of this service, which should be sent by version-aware + // clients to the service. This allows services to abide by the schema and + // behavior of the service at the time this API version was deployed. + // The format of the API version must be treated as opaque by clients. + // Services may use a format with an apparent structure, but clients must + // not rely on this to determine components within an API version, or attempt + // to construct other valid API versions. Note that this is for upcoming + // functionality and may not be implemented for all services. + // + // Example: + // + // service Foo { + // option (google.api.api_version) = "v1_20230821_preview"; + // } + string api_version = 525000001; +} + +// Required information for every language. +message CommonLanguageSettings { + // Link to automatically generated reference documentation. Example: + // https://cloud.google.com/nodejs/docs/reference/asset/latest + string reference_docs_uri = 1 [deprecated = true]; + + // The destination where API teams want this client library to be published. + repeated ClientLibraryDestination destinations = 2; + + // Configuration for which RPCs should be generated in the GAPIC client. + // + // Note: This field should not be used in most cases. + SelectiveGapicGeneration selective_gapic_generation = 3; +} + +// Details about how and where to publish client libraries. +message ClientLibrarySettings { + // Version of the API to apply these settings to. This is the full protobuf + // package for the API, ending in the version element. + // Examples: "google.cloud.speech.v1" and "google.spanner.admin.database.v1". + string version = 1; + + // Launch stage of this version of the API. + LaunchStage launch_stage = 2; + + // When using transport=rest, the client request will encode enums as + // numbers rather than strings. + bool rest_numeric_enums = 3; + + // Settings for legacy Java features, supported in the Service YAML. + JavaSettings java_settings = 21; + + // Settings for C++ client libraries. + CppSettings cpp_settings = 22; + + // Settings for PHP client libraries. + PhpSettings php_settings = 23; + + // Settings for Python client libraries. + PythonSettings python_settings = 24; + + // Settings for Node client libraries. + NodeSettings node_settings = 25; + + // Settings for .NET client libraries. + DotnetSettings dotnet_settings = 26; + + // Settings for Ruby client libraries. + RubySettings ruby_settings = 27; + + // Settings for Go client libraries. + GoSettings go_settings = 28; +} + +// This message configures the settings for publishing [Google Cloud Client +// libraries](https://cloud.google.com/apis/docs/cloud-client-libraries) +// generated from the service config. +message Publishing { + // A list of API method settings, e.g. the behavior for methods that use the + // long-running operation pattern. + repeated MethodSettings method_settings = 2; + + // Link to a *public* URI where users can report issues. Example: + // https://issuetracker.google.com/issues/new?component=190865&template=1161103 + string new_issue_uri = 101; + + // Link to product home page. Example: + // https://cloud.google.com/asset-inventory/docs/overview + string documentation_uri = 102; + + // Used as a tracking tag when collecting data about the APIs developer + // relations artifacts like docs, packages delivered to package managers, + // etc. Example: "speech". + string api_short_name = 103; + + // GitHub label to apply to issues and pull requests opened for this API. + string github_label = 104; + + // GitHub teams to be added to CODEOWNERS in the directory in GitHub + // containing source code for the client libraries for this API. + repeated string codeowner_github_teams = 105; + + // A prefix used in sample code when demarking regions to be included in + // documentation. + string doc_tag_prefix = 106; + + // For whom the client library is being published. + ClientLibraryOrganization organization = 107; + + // Client library settings. If the same version string appears multiple + // times in this list, then the last one wins. Settings from earlier + // settings with the same version string are discarded. + repeated ClientLibrarySettings library_settings = 109; + + // Optional link to proto reference documentation. Example: + // https://cloud.google.com/pubsub/lite/docs/reference/rpc + string proto_reference_documentation_uri = 110; + + // Optional link to REST reference documentation. Example: + // https://cloud.google.com/pubsub/lite/docs/reference/rest + string rest_reference_documentation_uri = 111; +} + +// Settings for Java client libraries. +message JavaSettings { + // The package name to use in Java. Clobbers the java_package option + // set in the protobuf. This should be used **only** by APIs + // who have already set the language_settings.java.package_name" field + // in gapic.yaml. API teams should use the protobuf java_package option + // where possible. + // + // Example of a YAML configuration:: + // + // publishing: + // library_settings: + // java_settings: + // library_package: com.google.cloud.pubsub.v1 + string library_package = 1; + + // Configure the Java class name to use instead of the service's for its + // corresponding generated GAPIC client. Keys are fully-qualified + // service names as they appear in the protobuf (including the full + // the language_settings.java.interface_names" field in gapic.yaml. API + // teams should otherwise use the service name as it appears in the + // protobuf. + // + // Example of a YAML configuration:: + // + // publishing: + // java_settings: + // service_class_names: + // - google.pubsub.v1.Publisher: TopicAdmin + // - google.pubsub.v1.Subscriber: SubscriptionAdmin + map service_class_names = 2; + + // Some settings. + CommonLanguageSettings common = 3; +} + +// Settings for C++ client libraries. +message CppSettings { + // Some settings. + CommonLanguageSettings common = 1; +} + +// Settings for Php client libraries. +message PhpSettings { + // Some settings. + CommonLanguageSettings common = 1; + + // The package name to use in Php. Clobbers the php_namespace option + // set in the protobuf. This should be used **only** by APIs + // who have already set the language_settings.php.package_name" field + // in gapic.yaml. API teams should use the protobuf php_namespace option + // where possible. + // + // Example of a YAML configuration:: + // + // publishing: + // library_settings: + // php_settings: + // library_package: Google\Cloud\PubSub\V1 + string library_package = 2; +} + +// Settings for Python client libraries. +message PythonSettings { + // Experimental features to be included during client library generation. + // These fields will be deprecated once the feature graduates and is enabled + // by default. + message ExperimentalFeatures { + // Enables generation of asynchronous REST clients if `rest` transport is + // enabled. By default, asynchronous REST clients will not be generated. + // This feature will be enabled by default 1 month after launching the + // feature in preview packages. + bool rest_async_io_enabled = 1; + + // Enables generation of protobuf code using new types that are more + // Pythonic which are included in `protobuf>=5.29.x`. This feature will be + // enabled by default 1 month after launching the feature in preview + // packages. + bool protobuf_pythonic_types_enabled = 2; + + // Disables generation of an unversioned Python package for this client + // library. This means that the module names will need to be versioned in + // import statements. For example `import google.cloud.library_v2` instead + // of `import google.cloud.library`. + bool unversioned_package_disabled = 3; + } + + // Some settings. + CommonLanguageSettings common = 1; + + // Experimental features to be included during client library generation. + ExperimentalFeatures experimental_features = 2; +} + +// Settings for Node client libraries. +message NodeSettings { + // Some settings. + CommonLanguageSettings common = 1; +} + +// Settings for Dotnet client libraries. +message DotnetSettings { + // Some settings. + CommonLanguageSettings common = 1; + + // Map from original service names to renamed versions. + // This is used when the default generated types + // would cause a naming conflict. (Neither name is + // fully-qualified.) + // Example: Subscriber to SubscriberServiceApi. + map renamed_services = 2; + + // Map from full resource types to the effective short name + // for the resource. This is used when otherwise resource + // named from different services would cause naming collisions. + // Example entry: + // "datalabeling.googleapis.com/Dataset": "DataLabelingDataset" + map renamed_resources = 3; + + // List of full resource types to ignore during generation. + // This is typically used for API-specific Location resources, + // which should be handled by the generator as if they were actually + // the common Location resources. + // Example entry: "documentai.googleapis.com/Location" + repeated string ignored_resources = 4; + + // Namespaces which must be aliased in snippets due to + // a known (but non-generator-predictable) naming collision + repeated string forced_namespace_aliases = 5; + + // Method signatures (in the form "service.method(signature)") + // which are provided separately, so shouldn't be generated. + // Snippets *calling* these methods are still generated, however. + repeated string handwritten_signatures = 6; +} + +// Settings for Ruby client libraries. +message RubySettings { + // Some settings. + CommonLanguageSettings common = 1; +} + +// Settings for Go client libraries. +message GoSettings { + // Some settings. + CommonLanguageSettings common = 1; + + // Map of service names to renamed services. Keys are the package relative + // service names and values are the name to be used for the service client + // and call options. + // + // Example: + // + // publishing: + // go_settings: + // renamed_services: + // Publisher: TopicAdmin + map renamed_services = 2; +} + +// Describes the generator configuration for a method. +message MethodSettings { + // Describes settings to use when generating API methods that use the + // long-running operation pattern. + // All default values below are from those used in the client library + // generators (e.g. + // [Java](https://github.com/googleapis/gapic-generator-java/blob/04c2faa191a9b5a10b92392fe8482279c4404803/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java)). + message LongRunning { + // Initial delay after which the first poll request will be made. + // Default value: 5 seconds. + google.protobuf.Duration initial_poll_delay = 1; + + // Multiplier to gradually increase delay between subsequent polls until it + // reaches max_poll_delay. + // Default value: 1.5. + float poll_delay_multiplier = 2; + + // Maximum time between two subsequent poll requests. + // Default value: 45 seconds. + google.protobuf.Duration max_poll_delay = 3; + + // Total polling timeout. + // Default value: 5 minutes. + google.protobuf.Duration total_poll_timeout = 4; + } + + // The fully qualified name of the method, for which the options below apply. + // This is used to find the method to apply the options. + // + // Example: + // + // publishing: + // method_settings: + // - selector: google.storage.control.v2.StorageControl.CreateFolder + // # method settings for CreateFolder... + string selector = 1; + + // Describes settings to use for long-running operations when generating + // API methods for RPCs. Complements RPCs that use the annotations in + // google/longrunning/operations.proto. + // + // Example of a YAML configuration:: + // + // publishing: + // method_settings: + // - selector: google.cloud.speech.v2.Speech.BatchRecognize + // long_running: + // initial_poll_delay: 60s # 1 minute + // poll_delay_multiplier: 1.5 + // max_poll_delay: 360s # 6 minutes + // total_poll_timeout: 54000s # 90 minutes + LongRunning long_running = 2; + + // List of top-level fields of the request message, that should be + // automatically populated by the client libraries based on their + // (google.api.field_info).format. Currently supported format: UUID4. + // + // Example of a YAML configuration: + // + // publishing: + // method_settings: + // - selector: google.example.v1.ExampleService.CreateExample + // auto_populated_fields: + // - request_id + repeated string auto_populated_fields = 3; + + // Batching configuration for an API method in client libraries. + // + // Example of a YAML configuration: + // + // publishing: + // method_settings: + // - selector: google.example.v1.ExampleService.BatchCreateExample + // batching: + // element_count_threshold: 1000 + // request_byte_threshold: 100000000 + // delay_threshold_millis: 10 + BatchingConfigProto batching = 4; +} + +// The organization for which the client libraries are being published. +// Affects the url where generated docs are published, etc. +enum ClientLibraryOrganization { + // Not useful. + CLIENT_LIBRARY_ORGANIZATION_UNSPECIFIED = 0; + + // Google Cloud Platform Org. + CLOUD = 1; + + // Ads (Advertising) Org. + ADS = 2; + + // Photos Org. + PHOTOS = 3; + + // Street View Org. + STREET_VIEW = 4; + + // Shopping Org. + SHOPPING = 5; + + // Geo Org. + GEO = 6; + + // Generative AI - https://developers.generativeai.google + GENERATIVE_AI = 7; +} + +// To where should client libraries be published? +enum ClientLibraryDestination { + // Client libraries will neither be generated nor published to package + // managers. + CLIENT_LIBRARY_DESTINATION_UNSPECIFIED = 0; + + // Generate the client library in a repo under github.com/googleapis, + // but don't publish it to package managers. + GITHUB = 10; + + // Publish the library to package managers like nuget.org and npmjs.com. + PACKAGE_MANAGER = 20; +} + +// This message is used to configure the generation of a subset of the RPCs in +// a service for client libraries. +// +// Note: This feature should not be used in most cases. +message SelectiveGapicGeneration { + // An allowlist of the fully qualified names of RPCs that should be included + // on public client surfaces. + repeated string methods = 1; + + // Setting this to true indicates to the client generators that methods + // that would be excluded from the generation should instead be generated + // in a way that indicates these methods should not be consumed by + // end users. How this is expressed is up to individual language + // implementations to decide. Some examples may be: added annotations, + // obfuscated identifiers, or other language idiomatic patterns. + bool generate_omitted_as_internal = 2; +} + +// `BatchingConfigProto` defines the batching configuration for an API method. +message BatchingConfigProto { + // The thresholds which trigger a batched request to be sent. + BatchingSettingsProto thresholds = 1; + + // The request and response fields used in batching. + BatchingDescriptorProto batch_descriptor = 2; +} + +// `BatchingSettingsProto` specifies a set of batching thresholds, each of +// which acts as a trigger to send a batch of messages as a request. At least +// one threshold must be positive nonzero. +message BatchingSettingsProto { + // The number of elements of a field collected into a batch which, if + // exceeded, causes the batch to be sent. + int32 element_count_threshold = 1; + + // The aggregated size of the batched field which, if exceeded, causes the + // batch to be sent. This size is computed by aggregating the sizes of the + // request field to be batched, not of the entire request message. + int64 request_byte_threshold = 2; + + // The duration after which a batch should be sent, starting from the addition + // of the first message to that batch. + google.protobuf.Duration delay_threshold = 3; + + // The maximum number of elements collected in a batch that could be accepted + // by server. + int32 element_count_limit = 4; + + // The maximum size of the request that could be accepted by server. + int32 request_byte_limit = 5; + + // The maximum number of elements allowed by flow control. + int32 flow_control_element_limit = 6; + + // The maximum size of data allowed by flow control. + int32 flow_control_byte_limit = 7; + + // The behavior to take when the flow control limit is exceeded. + FlowControlLimitExceededBehaviorProto flow_control_limit_exceeded_behavior = + 8; +} + +// The behavior to take when the flow control limit is exceeded. +enum FlowControlLimitExceededBehaviorProto { + // Default behavior, system-defined. + UNSET_BEHAVIOR = 0; + + // Stop operation, raise error. + THROW_EXCEPTION = 1; + + // Pause operation until limit clears. + BLOCK = 2; + + // Continue operation, disregard limit. + IGNORE = 3; +} + +// `BatchingDescriptorProto` specifies the fields of the request message to be +// used for batching, and, optionally, the fields of the response message to be +// used for demultiplexing. +message BatchingDescriptorProto { + // The repeated field in the request message to be aggregated by batching. + string batched_field = 1; + + // A list of the fields in the request message. Two requests will be batched + // together only if the values of every field specified in + // `request_discriminator_fields` is equal between the two requests. + repeated string discriminator_fields = 2; + + // Optional. When present, indicates the field in the response message to be + // used to demultiplex the response into multiple response messages, in + // correspondence with the multiple request messages originally batched + // together. + string subresponse_field = 3; } diff --git a/packages/firestore/src/protos/google/api/field_behavior.proto b/packages/firestore/src/protos/google/api/field_behavior.proto index c4abe3b670..861f8254fb 100644 --- a/packages/firestore/src/protos/google/api/field_behavior.proto +++ b/packages/firestore/src/protos/google/api/field_behavior.proto @@ -1,4 +1,4 @@ -// Copyright 2018 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -37,7 +37,7 @@ extend google.protobuf.FieldOptions { // google.protobuf.Timestamp expire_time = 1 // [(google.api.field_behavior) = OUTPUT_ONLY, // (google.api.field_behavior) = IMMUTABLE]; - repeated google.api.FieldBehavior field_behavior = 1052; + repeated google.api.FieldBehavior field_behavior = 1052 [packed = false]; } // An indicator of the behavior of a given field (for example, that a field @@ -87,4 +87,18 @@ enum FieldBehavior { // a non-empty value will be returned. The user will not be aware of what // non-empty value to expect. NON_EMPTY_DEFAULT = 7; + + // Denotes that the field in a resource (a message annotated with + // google.api.resource) is used in the resource name to uniquely identify the + // resource. For AIP-compliant APIs, this should only be applied to the + // `name` field on the resource. + // + // This behavior should not be applied to references to other resources within + // the message. + // + // The identifier field of resources often have different field behavior + // depending on the request it is embedded in (e.g. for Create methods name + // is optional and unused, while for Update methods it is required). Instead + // of method-specific annotations, only `IDENTIFIER` is required. + IDENTIFIER = 8; } diff --git a/packages/firestore/src/protos/google/api/http.proto b/packages/firestore/src/protos/google/api/http.proto index 113fa936a0..bb3af8e56a 100644 --- a/packages/firestore/src/protos/google/api/http.proto +++ b/packages/firestore/src/protos/google/api/http.proto @@ -1,4 +1,4 @@ -// Copyright 2015 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ syntax = "proto3"; package google.api; -option cc_enable_arenas = true; option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; option java_multiple_files = true; option java_outer_classname = "HttpProto"; @@ -41,7 +40,7 @@ message Http { bool fully_decode_reserved_expansion = 2; } -// # gRPC Transcoding +// gRPC Transcoding // // gRPC Transcoding is a feature for mapping between a gRPC method and one or // more HTTP REST endpoints. It allows developers to build a single API service @@ -82,9 +81,8 @@ message Http { // // This enables an HTTP REST to gRPC mapping as below: // -// HTTP | gRPC -// -----|----- -// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` +// - HTTP: `GET /v1/messages/123456` +// - gRPC: `GetMessage(name: "messages/123456")` // // Any fields in the request message which are not bound by the path template // automatically become HTTP query parameters if there is no HTTP request body. @@ -108,11 +106,9 @@ message Http { // // This enables a HTTP JSON to RPC mapping as below: // -// HTTP | gRPC -// -----|----- -// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | -// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: -// "foo"))` +// - HTTP: `GET /v1/messages/123456?revision=2&sub.subfield=foo` +// - gRPC: `GetMessage(message_id: "123456" revision: 2 sub: +// SubMessage(subfield: "foo"))` // // Note that fields which are mapped to URL query parameters must have a // primitive type or a repeated primitive type or a non-repeated message type. @@ -142,10 +138,8 @@ message Http { // representation of the JSON in the request body is determined by // protos JSON encoding: // -// HTTP | gRPC -// -----|----- -// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: -// "123456" message { text: "Hi!" })` +// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` +// - gRPC: `UpdateMessage(message_id: "123456" message { text: "Hi!" })` // // The special name `*` can be used in the body mapping to define that // every field not bound by the path template should be mapped to the @@ -168,10 +162,8 @@ message Http { // // The following HTTP JSON to RPC mapping is enabled: // -// HTTP | gRPC -// -----|----- -// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: -// "123456" text: "Hi!")` +// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` +// - gRPC: `UpdateMessage(message_id: "123456" text: "Hi!")` // // Note that when using `*` in the body mapping, it is not possible to // have HTTP parameters, as all fields not bound by the path end in @@ -199,29 +191,32 @@ message Http { // // This enables the following two alternative HTTP JSON to RPC mappings: // -// HTTP | gRPC -// -----|----- -// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` -// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: -// "123456")` +// - HTTP: `GET /v1/messages/123456` +// - gRPC: `GetMessage(message_id: "123456")` // -// ## Rules for HTTP mapping +// - HTTP: `GET /v1/users/me/messages/123456` +// - gRPC: `GetMessage(user_id: "me" message_id: "123456")` +// +// Rules for HTTP mapping // // 1. Leaf request fields (recursive expansion nested messages in the request // message) are classified into three categories: // - Fields referred by the path template. They are passed via the URL path. -// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They are passed via the HTTP +// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They +// are passed via the HTTP // request body. // - All other fields are passed via the URL query parameters, and the // parameter name is the field path in the request message. A repeated // field can be represented as multiple query parameters under the same // name. -// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL query parameter, all fields +// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL +// query parameter, all fields // are passed via URL path and HTTP request body. -// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP request body, all +// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP +// request body, all // fields are passed via URL path and URL query parameters. // -// ### Path template syntax +// Path template syntax // // Template = "/" Segments [ Verb ] ; // Segments = Segment { "/" Segment } ; @@ -260,7 +255,7 @@ message Http { // Document](https://developers.google.com/discovery/v1/reference/apis) as // `{+var}`. // -// ## Using gRPC API Service Configuration +// Using gRPC API Service Configuration // // gRPC API Service Configuration (service config) is a configuration language // for configuring a gRPC service to become a user-facing product. The @@ -275,15 +270,14 @@ message Http { // specified in the service config will override any matching transcoding // configuration in the proto. // -// Example: +// The following example selects a gRPC method and applies an `HttpRule` to it: // // http: // rules: -// # Selects a gRPC method and applies HttpRule to it. // - selector: example.v1.Messaging.GetMessage // get: /v1/messages/{message_id}/{sub.subfield} // -// ## Special notes +// Special notes // // When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the // proto to JSON conversion must follow the [proto3 @@ -313,7 +307,8 @@ message Http { message HttpRule { // Selects a method to which this rule applies. // - // Refer to [selector][google.api.DocumentationRule.selector] for syntax details. + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. string selector = 1; // Determines the URL pattern is matched by this rules. This pattern can be diff --git a/packages/firestore/src/protos/google/api/launch_stage.proto b/packages/firestore/src/protos/google/api/launch_stage.proto new file mode 100644 index 0000000000..0fff247bd8 --- /dev/null +++ b/packages/firestore/src/protos/google/api/launch_stage.proto @@ -0,0 +1,72 @@ +// Copyright 2026 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. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api;api"; +option java_multiple_files = true; +option java_outer_classname = "LaunchStageProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// The launch stage as defined by [Google Cloud Platform +// Launch Stages](https://cloud.google.com/terms/launch-stages). +enum LaunchStage { + // Do not use this default value. + LAUNCH_STAGE_UNSPECIFIED = 0; + + // The feature is not yet implemented. Users can not use it. + UNIMPLEMENTED = 6; + + // Prelaunch features are hidden from users and are only visible internally. + PRELAUNCH = 7; + + // Early Access features are limited to a closed group of testers. To use + // these features, you must sign up in advance and sign a Trusted Tester + // agreement (which includes confidentiality provisions). These features may + // be unstable, changed in backward-incompatible ways, and are not + // guaranteed to be released. + EARLY_ACCESS = 1; + + // Alpha is a limited availability test for releases before they are cleared + // for widespread use. By Alpha, all significant design issues are resolved + // and we are in the process of verifying functionality. Alpha customers + // need to apply for access, agree to applicable terms, and have their + // projects allowlisted. Alpha releases don't have to be feature complete, + // no SLAs are provided, and there are no technical support obligations, but + // they will be far enough along that customers can actually use them in + // test environments or for limited-use tests -- just like they would in + // normal production cases. + ALPHA = 2; + + // Beta is the point at which we are ready to open a release for any + // customer to use. There are no SLA or technical support obligations in a + // Beta release. Products will be complete from a feature perspective, but + // may have some open outstanding issues. Beta releases are suitable for + // limited production use cases. + BETA = 3; + + // GA features are open to all developers and are considered stable and + // fully qualified for production use. + GA = 4; + + // Deprecated features are scheduled to be shut down and removed. For more + // information, see the "Deprecation Policy" section of our [Terms of + // Service](https://cloud.google.com/terms/) + // and the [Google Cloud Platform Subject to the Deprecation + // Policy](https://cloud.google.com/terms/deprecation) documentation. + DEPRECATED = 5; +} diff --git a/packages/firestore/src/protos/google/api/resource.proto b/packages/firestore/src/protos/google/api/resource.proto new file mode 100644 index 0000000000..2a5213bb08 --- /dev/null +++ b/packages/firestore/src/protos/google/api/resource.proto @@ -0,0 +1,242 @@ +// Copyright 2026 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. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "ResourceProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.FieldOptions { + // An annotation that describes a resource reference, see + // [ResourceReference][]. + google.api.ResourceReference resource_reference = 1055; +} + +extend google.protobuf.FileOptions { + // An annotation that describes a resource definition without a corresponding + // message; see [ResourceDescriptor][]. + repeated google.api.ResourceDescriptor resource_definition = 1053; +} + +extend google.protobuf.MessageOptions { + // An annotation that describes a resource definition, see + // [ResourceDescriptor][]. + google.api.ResourceDescriptor resource = 1053; +} + +// A simple descriptor of a resource type. +// +// ResourceDescriptor annotates a resource message (either by means of a +// protobuf annotation or use in the service config), and associates the +// resource's schema, the resource type, and the pattern of the resource name. +// +// Example: +// +// message Topic { +// // Indicates this message defines a resource schema. +// // Declares the resource type in the format of {service}/{kind}. +// // For Kubernetes resources, the format is {api group}/{kind}. +// option (google.api.resource) = { +// type: "pubsub.googleapis.com/Topic" +// pattern: "projects/{project}/topics/{topic}" +// }; +// } +// +// The ResourceDescriptor Yaml config will look like: +// +// resources: +// - type: "pubsub.googleapis.com/Topic" +// pattern: "projects/{project}/topics/{topic}" +// +// Sometimes, resources have multiple patterns, typically because they can +// live under multiple parents. +// +// Example: +// +// message LogEntry { +// option (google.api.resource) = { +// type: "logging.googleapis.com/LogEntry" +// pattern: "projects/{project}/logs/{log}" +// pattern: "folders/{folder}/logs/{log}" +// pattern: "organizations/{organization}/logs/{log}" +// pattern: "billingAccounts/{billing_account}/logs/{log}" +// }; +// } +// +// The ResourceDescriptor Yaml config will look like: +// +// resources: +// - type: 'logging.googleapis.com/LogEntry' +// pattern: "projects/{project}/logs/{log}" +// pattern: "folders/{folder}/logs/{log}" +// pattern: "organizations/{organization}/logs/{log}" +// pattern: "billingAccounts/{billing_account}/logs/{log}" +message ResourceDescriptor { + // A description of the historical or future-looking state of the + // resource pattern. + enum History { + // The "unset" value. + HISTORY_UNSPECIFIED = 0; + + // The resource originally had one pattern and launched as such, and + // additional patterns were added later. + ORIGINALLY_SINGLE_PATTERN = 1; + + // The resource has one pattern, but the API owner expects to add more + // later. (This is the inverse of ORIGINALLY_SINGLE_PATTERN, and prevents + // that from being necessary once there are multiple patterns.) + FUTURE_MULTI_PATTERN = 2; + } + + // A flag representing a specific style that a resource claims to conform to. + enum Style { + // The unspecified value. Do not use. + STYLE_UNSPECIFIED = 0; + + // This resource is intended to be "declarative-friendly". + // + // Declarative-friendly resources must be more strictly consistent, and + // setting this to true communicates to tools that this resource should + // adhere to declarative-friendly expectations. + // + // Note: This is used by the API linter (linter.aip.dev) to enable + // additional checks. + DECLARATIVE_FRIENDLY = 1; + } + + // The resource type. It must be in the format of + // {service_name}/{resource_type_kind}. The `resource_type_kind` must be + // singular and must not include version numbers. + // + // Example: `storage.googleapis.com/Bucket` + // + // The value of the resource_type_kind must follow the regular expression + // /[A-Za-z][a-zA-Z0-9]+/. It should start with an upper case character and + // should use PascalCase (UpperCamelCase). The maximum number of + // characters allowed for the `resource_type_kind` is 100. + string type = 1; + + // Optional. The relative resource name pattern associated with this resource + // type. The DNS prefix of the full resource name shouldn't be specified here. + // + // The path pattern must follow the syntax, which aligns with HTTP binding + // syntax: + // + // Template = Segment { "/" Segment } ; + // Segment = LITERAL | Variable ; + // Variable = "{" LITERAL "}" ; + // + // Examples: + // + // - "projects/{project}/topics/{topic}" + // - "projects/{project}/knowledgeBases/{knowledge_base}" + // + // The components in braces correspond to the IDs for each resource in the + // hierarchy. It is expected that, if multiple patterns are provided, + // the same component name (e.g. "project") refers to IDs of the same + // type of resource. + repeated string pattern = 2; + + // Optional. The field on the resource that designates the resource name + // field. If omitted, this is assumed to be "name". + string name_field = 3; + + // Optional. The historical or future-looking state of the resource pattern. + // + // Example: + // + // // The InspectTemplate message originally only supported resource + // // names with organization, and project was added later. + // message InspectTemplate { + // option (google.api.resource) = { + // type: "dlp.googleapis.com/InspectTemplate" + // pattern: + // "organizations/{organization}/inspectTemplates/{inspect_template}" + // pattern: "projects/{project}/inspectTemplates/{inspect_template}" + // history: ORIGINALLY_SINGLE_PATTERN + // }; + // } + History history = 4; + + // The plural name used in the resource name and permission names, such as + // 'projects' for the resource name of 'projects/{project}' and the permission + // name of 'cloudresourcemanager.googleapis.com/projects.get'. One exception + // to this is for Nested Collections that have stuttering names, as defined + // in [AIP-122](https://google.aip.dev/122#nested-collections), where the + // collection ID in the resource name pattern does not necessarily directly + // match the `plural` value. + // + // It is the same concept of the `plural` field in k8s CRD spec + // https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ + // + // Note: The plural form is required even for singleton resources. See + // https://aip.dev/156 + string plural = 5; + + // The same concept of the `singular` field in k8s CRD spec + // https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ + // Such as "project" for the `resourcemanager.googleapis.com/Project` type. + string singular = 6; + + // Style flag(s) for this resource. + // These indicate that a resource is expected to conform to a given + // style. See the specific style flags for additional information. + repeated Style style = 10; +} + +// Defines a proto annotation that describes a string field that refers to +// an API resource. +message ResourceReference { + // The resource type that the annotated field references. + // + // Example: + // + // message Subscription { + // string topic = 2 [(google.api.resource_reference) = { + // type: "pubsub.googleapis.com/Topic" + // }]; + // } + // + // Occasionally, a field may reference an arbitrary resource. In this case, + // APIs use the special value * in their resource reference. + // + // Example: + // + // message GetIamPolicyRequest { + // string resource = 2 [(google.api.resource_reference) = { + // type: "*" + // }]; + // } + string type = 1; + + // The resource type of a child collection that the annotated field + // references. This is useful for annotating the `parent` field that + // doesn't have a fixed resource type. + // + // Example: + // + // message ListLogEntriesRequest { + // string parent = 1 [(google.api.resource_reference) = { + // child_type: "logging.googleapis.com/LogEntry" + // }; + // } + string child_type = 2; +} diff --git a/packages/firestore/src/protos/google/api/routing.proto b/packages/firestore/src/protos/google/api/routing.proto new file mode 100644 index 0000000000..020d32f7b7 --- /dev/null +++ b/packages/firestore/src/protos/google/api/routing.proto @@ -0,0 +1,465 @@ +// Copyright 2026 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. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "RoutingProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.MethodOptions { + // See RoutingRule. + google.api.RoutingRule routing = 72295729; +} + +// Specifies the routing information that should be sent along with the request +// in the form of routing header. +// **NOTE:** All service configuration rules follow the "last one wins" order. +// +// The examples below will apply to an RPC which has the following request type: +// +// Message Definition: +// +// message Request { +// // The name of the Table +// // Values can be of the following formats: +// // - `projects//tables/` +// // - `projects//instances//tables/
    ` +// // - `region//zones//tables/
    ` +// string table_name = 1; +// +// // This value specifies routing for replication. +// // It can be in the following formats: +// // - `profiles/` +// // - a legacy `profile_id` that can be any string +// string app_profile_id = 2; +// } +// +// Example message: +// +// { +// table_name: projects/proj_foo/instances/instance_bar/table/table_baz, +// app_profile_id: profiles/prof_qux +// } +// +// The routing header consists of one or multiple key-value pairs. The order of +// the key-value pairs is undefined, the order of the `routing_parameters` in +// the `RoutingRule` only matters for the evaluation order of the path +// templates when `field` is the same. See the examples below for more details. +// +// Every key and value in the routing header must be percent-encoded, +// and joined together in the following format: `key1=value1&key2=value2`. +// The examples below skip the percent-encoding for readability. +// +// Example 1 +// +// Extracting a field from the request to put into the routing header +// unchanged, with the key equal to the field name. +// +// annotation: +// +// option (google.api.routing) = { +// // Take the `app_profile_id`. +// routing_parameters { +// field: "app_profile_id" +// } +// }; +// +// result: +// +// x-goog-request-params: app_profile_id=profiles/prof_qux +// +// Example 2 +// +// Extracting a field from the request to put into the routing header +// unchanged, with the key different from the field name. +// +// annotation: +// +// option (google.api.routing) = { +// // Take the `app_profile_id`, but name it `routing_id` in the header. +// routing_parameters { +// field: "app_profile_id" +// path_template: "{routing_id=**}" +// } +// }; +// +// result: +// +// x-goog-request-params: routing_id=profiles/prof_qux +// +// Example 3 +// +// Extracting a field from the request to put into the routing +// header, while matching a path template syntax on the field's value. +// +// NB: it is more useful to send nothing than to send garbage for the purpose +// of dynamic routing, since garbage pollutes cache. Thus the matching. +// +// Sub-example 3a +// +// The field matches the template. +// +// annotation: +// +// option (google.api.routing) = { +// // Take the `table_name`, if it's well-formed (with project-based +// // syntax). +// routing_parameters { +// field: "table_name" +// path_template: "{table_name=projects/*/instances/*/**}" +// } +// }; +// +// result: +// +// x-goog-request-params: +// table_name=projects/proj_foo/instances/instance_bar/table/table_baz +// +// Sub-example 3b +// +// The field does not match the template. +// +// annotation: +// +// option (google.api.routing) = { +// // Take the `table_name`, if it's well-formed (with region-based +// // syntax). +// routing_parameters { +// field: "table_name" +// path_template: "{table_name=regions/*/zones/*/**}" +// } +// }; +// +// result: +// +// +// +// Sub-example 3c +// +// Multiple alternative conflictingly named path templates are +// specified. The one that matches is used to construct the header. +// +// annotation: +// +// option (google.api.routing) = { +// // Take the `table_name`, if it's well-formed, whether +// // using the region- or projects-based syntax. +// +// routing_parameters { +// field: "table_name" +// path_template: "{table_name=regions/*/zones/*/**}" +// } +// routing_parameters { +// field: "table_name" +// path_template: "{table_name=projects/*/instances/*/**}" +// } +// }; +// +// result: +// +// x-goog-request-params: +// table_name=projects/proj_foo/instances/instance_bar/table/table_baz +// +// Example 4 +// +// Extracting a single routing header key-value pair by matching a +// template syntax on (a part of) a single request field. +// +// annotation: +// +// option (google.api.routing) = { +// // Take just the project id from the `table_name` field. +// routing_parameters { +// field: "table_name" +// path_template: "{routing_id=projects/*}/**" +// } +// }; +// +// result: +// +// x-goog-request-params: routing_id=projects/proj_foo +// +// Example 5 +// +// Extracting a single routing header key-value pair by matching +// several conflictingly named path templates on (parts of) a single request +// field. The last template to match "wins" the conflict. +// +// annotation: +// +// option (google.api.routing) = { +// // If the `table_name` does not have instances information, +// // take just the project id for routing. +// // Otherwise take project + instance. +// +// routing_parameters { +// field: "table_name" +// path_template: "{routing_id=projects/*}/**" +// } +// routing_parameters { +// field: "table_name" +// path_template: "{routing_id=projects/*/instances/*}/**" +// } +// }; +// +// result: +// +// x-goog-request-params: +// routing_id=projects/proj_foo/instances/instance_bar +// +// Example 6 +// +// Extracting multiple routing header key-value pairs by matching +// several non-conflicting path templates on (parts of) a single request field. +// +// Sub-example 6a +// +// Make the templates strict, so that if the `table_name` does not +// have an instance information, nothing is sent. +// +// annotation: +// +// option (google.api.routing) = { +// // The routing code needs two keys instead of one composite +// // but works only for the tables with the "project-instance" name +// // syntax. +// +// routing_parameters { +// field: "table_name" +// path_template: "{project_id=projects/*}/instances/*/**" +// } +// routing_parameters { +// field: "table_name" +// path_template: "projects/*/{instance_id=instances/*}/**" +// } +// }; +// +// result: +// +// x-goog-request-params: +// project_id=projects/proj_foo&instance_id=instances/instance_bar +// +// Sub-example 6b +// +// Make the templates loose, so that if the `table_name` does not +// have an instance information, just the project id part is sent. +// +// annotation: +// +// option (google.api.routing) = { +// // The routing code wants two keys instead of one composite +// // but will work with just the `project_id` for tables without +// // an instance in the `table_name`. +// +// routing_parameters { +// field: "table_name" +// path_template: "{project_id=projects/*}/**" +// } +// routing_parameters { +// field: "table_name" +// path_template: "projects/*/{instance_id=instances/*}/**" +// } +// }; +// +// result (is the same as 6a for our example message because it has the instance +// information): +// +// x-goog-request-params: +// project_id=projects/proj_foo&instance_id=instances/instance_bar +// +// Example 7 +// +// Extracting multiple routing header key-value pairs by matching +// several path templates on multiple request fields. +// +// NB: note that here there is no way to specify sending nothing if one of the +// fields does not match its template. E.g. if the `table_name` is in the wrong +// format, the `project_id` will not be sent, but the `routing_id` will be. +// The backend routing code has to be aware of that and be prepared to not +// receive a full complement of keys if it expects multiple. +// +// annotation: +// +// option (google.api.routing) = { +// // The routing needs both `project_id` and `routing_id` +// // (from the `app_profile_id` field) for routing. +// +// routing_parameters { +// field: "table_name" +// path_template: "{project_id=projects/*}/**" +// } +// routing_parameters { +// field: "app_profile_id" +// path_template: "{routing_id=**}" +// } +// }; +// +// result: +// +// x-goog-request-params: +// project_id=projects/proj_foo&routing_id=profiles/prof_qux +// +// Example 8 +// +// Extracting a single routing header key-value pair by matching +// several conflictingly named path templates on several request fields. The +// last template to match "wins" the conflict. +// +// annotation: +// +// option (google.api.routing) = { +// // The `routing_id` can be a project id or a region id depending on +// // the table name format, but only if the `app_profile_id` is not set. +// // If `app_profile_id` is set it should be used instead. +// +// routing_parameters { +// field: "table_name" +// path_template: "{routing_id=projects/*}/**" +// } +// routing_parameters { +// field: "table_name" +// path_template: "{routing_id=regions/*}/**" +// } +// routing_parameters { +// field: "app_profile_id" +// path_template: "{routing_id=**}" +// } +// }; +// +// result: +// +// x-goog-request-params: routing_id=profiles/prof_qux +// +// Example 9 +// +// Bringing it all together. +// +// annotation: +// +// option (google.api.routing) = { +// // For routing both `table_location` and a `routing_id` are needed. +// // +// // table_location can be either an instance id or a region+zone id. +// // +// // For `routing_id`, take the value of `app_profile_id` +// // - If it's in the format `profiles/`, send +// // just the `` part. +// // - If it's any other literal, send it as is. +// // If the `app_profile_id` is empty, and the `table_name` starts with +// // the project_id, send that instead. +// +// routing_parameters { +// field: "table_name" +// path_template: "projects/*/{table_location=instances/*}/tables/*" +// } +// routing_parameters { +// field: "table_name" +// path_template: "{table_location=regions/*/zones/*}/tables/*" +// } +// routing_parameters { +// field: "table_name" +// path_template: "{routing_id=projects/*}/**" +// } +// routing_parameters { +// field: "app_profile_id" +// path_template: "{routing_id=**}" +// } +// routing_parameters { +// field: "app_profile_id" +// path_template: "profiles/{routing_id=*}" +// } +// }; +// +// result: +// +// x-goog-request-params: +// table_location=instances/instance_bar&routing_id=prof_qux +message RoutingRule { + // A collection of Routing Parameter specifications. + // **NOTE:** If multiple Routing Parameters describe the same key + // (via the `path_template` field or via the `field` field when + // `path_template` is not provided), "last one wins" rule + // determines which Parameter gets used. + // See the examples for more details. + repeated RoutingParameter routing_parameters = 2; +} + +// A projection from an input message to the GRPC or REST header. +message RoutingParameter { + // A request field to extract the header key-value pair from. + string field = 1; + + // A pattern matching the key-value field. Optional. + // If not specified, the whole field specified in the `field` field will be + // taken as value, and its name used as key. If specified, it MUST contain + // exactly one named segment (along with any number of unnamed segments) The + // pattern will be matched over the field specified in the `field` field, then + // if the match is successful: + // - the name of the single named segment will be used as a header name, + // - the match value of the segment will be used as a header value; + // if the match is NOT successful, nothing will be sent. + // + // Example: + // + // -- This is a field in the request message + // | that the header value will be extracted from. + // | + // | -- This is the key name in the + // | | routing header. + // V | + // field: "table_name" v + // path_template: "projects/*/{table_location=instances/*}/tables/*" + // ^ ^ + // | | + // In the {} brackets is the pattern that -- | + // specifies what to extract from the | + // field as a value to be sent. | + // | + // The string in the field must match the whole pattern -- + // before brackets, inside brackets, after brackets. + // + // When looking at this specific example, we can see that: + // - A key-value pair with the key `table_location` + // and the value matching `instances/*` should be added + // to the x-goog-request-params routing header. + // - The value is extracted from the request message's `table_name` field + // if it matches the full pattern specified: + // `projects/*/instances/*/tables/*`. + // + // **NB:** If the `path_template` field is not provided, the key name is + // equal to the field name, and the whole field should be sent as a value. + // This makes the pattern for the field and the value functionally equivalent + // to `**`, and the configuration + // + // { + // field: "table_name" + // } + // + // is a functionally equivalent shorthand to: + // + // { + // field: "table_name" + // path_template: "{table_name=**}" + // } + // + // See Example 1 for more details. + string path_template = 2; +} diff --git a/packages/firestore/src/protos/google/firestore/v1/aggregation_result.proto b/packages/firestore/src/protos/google/firestore/v1/aggregation_result.proto index 538e3fef5e..4eee2ddc8a 100644 --- a/packages/firestore/src/protos/google/firestore/v1/aggregation_result.proto +++ b/packages/firestore/src/protos/google/firestore/v1/aggregation_result.proto @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,7 +19,7 @@ package google.firestore.v1; import "google/firestore/v1/document.proto"; option csharp_namespace = "Google.Cloud.Firestore.V1"; -option go_package = "google.golang.org/genproto/googleapis/firestore/v1;firestore"; +option go_package = "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb"; option java_multiple_files = true; option java_outer_classname = "AggregationResultProto"; option java_package = "com.google.firestore.v1"; @@ -35,7 +35,8 @@ option ruby_package = "Google::Cloud::Firestore::V1"; message AggregationResult { // The result of the aggregation functions, ex: `COUNT(*) AS total_docs`. // - // The key is the [alias][google.firestore.v1.StructuredAggregationQuery.Aggregation.alias] + // The key is the + // [alias][google.firestore.v1.StructuredAggregationQuery.Aggregation.alias] // assigned to the aggregation function on input and the size of this map // equals the number of aggregation functions in the query. map aggregate_fields = 2; diff --git a/packages/firestore/src/protos/google/firestore/v1/bloom_filter.proto b/packages/firestore/src/protos/google/firestore/v1/bloom_filter.proto index 6f3b70d465..f9bbdbf08d 100644 --- a/packages/firestore/src/protos/google/firestore/v1/bloom_filter.proto +++ b/packages/firestore/src/protos/google/firestore/v1/bloom_filter.proto @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ syntax = "proto3"; package google.firestore.v1; option csharp_namespace = "Google.Cloud.Firestore.V1"; -option go_package = "google.golang.org/genproto/googleapis/firestore/v1;firestore"; +option go_package = "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb"; option java_multiple_files = true; option java_outer_classname = "BloomFilterProto"; option java_package = "com.google.firestore.v1"; @@ -32,21 +32,21 @@ option ruby_package = "Google::Cloud::Firestore::V1"; // defines the number of bits of the last byte to be ignored as "padding". The // values of these "padding" bits are unspecified and must be ignored. // -// To retrieve the first bit, bit 0, calculate: (bitmap[0] & 0x01) != 0. -// To retrieve the second bit, bit 1, calculate: (bitmap[0] & 0x02) != 0. -// To retrieve the third bit, bit 2, calculate: (bitmap[0] & 0x04) != 0. -// To retrieve the fourth bit, bit 3, calculate: (bitmap[0] & 0x08) != 0. -// To retrieve bit n, calculate: (bitmap[n / 8] & (0x01 << (n % 8))) != 0. +// To retrieve the first bit, bit 0, calculate: `(bitmap[0] & 0x01) != 0`. +// To retrieve the second bit, bit 1, calculate: `(bitmap[0] & 0x02) != 0`. +// To retrieve the third bit, bit 2, calculate: `(bitmap[0] & 0x04) != 0`. +// To retrieve the fourth bit, bit 3, calculate: `(bitmap[0] & 0x08) != 0`. +// To retrieve bit n, calculate: `(bitmap[n / 8] & (0x01 << (n % 8))) != 0`. // // The "size" of a `BitSequence` (the number of bits it contains) is calculated -// by this formula: (bitmap.length * 8) - padding. +// by this formula: `(bitmap.length * 8) - padding`. message BitSequence { // The bytes that encode the bit sequence. // May have a length of zero. bytes bitmap = 1; // The number of bits of the last byte in `bitmap` to ignore as "padding". - // If the length of `bitmap` is zero, then this value must be 0. + // If the length of `bitmap` is zero, then this value must be `0`. // Otherwise, this value must be between 0 and 7, inclusive. int32 padding = 2; } @@ -57,10 +57,10 @@ message BitSequence { // hash as 2 distinct 64-bit hash values, interpreted as unsigned integers // using 2's complement encoding. // -// These two hash values, named h1 and h2, are then used to compute the -// `hash_count` hash values using the formula, starting at i=0: +// These two hash values, named `h1` and `h2`, are then used to compute the +// `hash_count` hash values using the formula, starting at `i=0`: // -// h(i) = h1 + (i * h2) +// h(i) = h1 + (i * h2) // // These resulting values are then taken modulo the number of bits in the bloom // filter to get the bits of the bloom filter to test for the given entry. diff --git a/packages/firestore/src/protos/google/firestore/v1/common.proto b/packages/firestore/src/protos/google/firestore/v1/common.proto index 3bc978ca9a..799fd011c2 100644 --- a/packages/firestore/src/protos/google/firestore/v1/common.proto +++ b/packages/firestore/src/protos/google/firestore/v1/common.proto @@ -1,4 +1,4 @@ -// Copyright 2021 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,10 +17,9 @@ syntax = "proto3"; package google.firestore.v1; import "google/protobuf/timestamp.proto"; -import "google/api/annotations.proto"; option csharp_namespace = "Google.Cloud.Firestore.V1"; -option go_package = "google.golang.org/genproto/googleapis/firestore/v1;firestore"; +option go_package = "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb"; option java_multiple_files = true; option java_outer_classname = "CommonProto"; option java_package = "com.google.firestore.v1"; @@ -32,10 +31,12 @@ option ruby_package = "Google::Cloud::Firestore::V1"; // Used to restrict a get or update operation on a document to a subset of its // fields. // This is different from standard field masks, as this is always scoped to a -// [Document][google.firestore.v1.Document], and takes in account the dynamic nature of [Value][google.firestore.v1.Value]. +// [Document][google.firestore.v1.Document], and takes in account the dynamic +// nature of [Value][google.firestore.v1.Value]. message DocumentMask { - // The list of field paths in the mask. See [Document.fields][google.firestore.v1.Document.fields] for a field - // path syntax reference. + // The list of field paths in the mask. See + // [Document.fields][google.firestore.v1.Document.fields] for a field path + // syntax reference. repeated string field_paths = 1; } @@ -48,7 +49,7 @@ message Precondition { bool exists = 1; // When set, the target document must exist and have been last updated at - // that time. + // that time. Timestamp must be microsecond aligned. google.protobuf.Timestamp update_time = 2; } } @@ -56,6 +57,9 @@ message Precondition { // Options for creating a new transaction. message TransactionOptions { // Options for a transaction that can be used to read and write documents. + // + // Firestore does not allow 3rd party auth requests to create read-write. + // transactions. message ReadWrite { // An optional transaction to retry. bytes retry_transaction = 1; @@ -67,7 +71,10 @@ message TransactionOptions { // consistency. oneof consistency_selector { // Reads documents at the given time. - // This may not be older than 60 seconds. + // + // This must be a microsecond precision timestamp within the past one + // hour, or if Point-in-Time Recovery is enabled, can additionally be a + // whole minute timestamp within the past 7 days. google.protobuf.Timestamp read_time = 2; } } diff --git a/packages/firestore/src/protos/google/firestore/v1/document.proto b/packages/firestore/src/protos/google/firestore/v1/document.proto index e186dd96d7..a77dbd9971 100644 --- a/packages/firestore/src/protos/google/firestore/v1/document.proto +++ b/packages/firestore/src/protos/google/firestore/v1/document.proto @@ -1,4 +1,4 @@ -// Copyright 2021 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,13 +16,13 @@ syntax = "proto3"; package google.firestore.v1; +import "google/api/field_behavior.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; import "google/type/latlng.proto"; -import "google/api/annotations.proto"; option csharp_namespace = "Google.Cloud.Firestore.V1"; -option go_package = "google.golang.org/genproto/googleapis/firestore/v1;firestore"; +option go_package = "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb"; option java_multiple_files = true; option java_outer_classname = "DocumentProto"; option java_package = "com.google.firestore.v1"; @@ -42,23 +42,23 @@ message Document { // // The map keys represent field names. // - // A simple field name contains only characters `a` to `z`, `A` to `Z`, - // `0` to `9`, or `_`, and must not start with `0` to `9`. For example, - // `foo_bar_17`. - // // Field names matching the regular expression `__.*__` are reserved. Reserved - // field names are forbidden except in certain documented contexts. The map - // keys, represented as UTF-8, must not exceed 1,500 bytes and cannot be + // field names are forbidden except in certain documented contexts. The field + // names, represented as UTF-8, must not exceed 1,500 bytes and cannot be // empty. // // Field paths may be used in other contexts to refer to structured fields - // defined here. For `map_value`, the field path is represented by the simple - // or quoted field names of the containing fields, delimited by `.`. For - // example, the structured field - // `"foo" : { map_value: { "x&y" : { string_value: "hello" }}}` would be - // represented by the field path `foo.x&y`. + // defined here. For `map_value`, the field path is represented by a + // dot-delimited (`.`) string of segments. Each segment is either a simple + // field name (defined below) or a quoted field name. For example, the + // structured field `"foo" : { map_value: { "x&y" : { string_value: "hello" + // }}}` would be represented by the field path `` foo.`x&y` ``. + // + // A simple field name contains only characters `a` to `z`, `A` to `Z`, + // `0` to `9`, or `_`, and must not start with `0` to `9`. For example, + // `foo_bar_17`. // - // Within a field path, a quoted field name starts and ends with `` ` `` and + // A quoted field name starts and ends with `` ` `` and // may contain any character. Some characters, including `` ` ``, must be // escaped using a `\`. For example, `` `x&y` `` represents `x&y` and // `` `bak\`tik` `` represents `` bak`tik ``. @@ -123,12 +123,13 @@ message Value { // An array value. // - // Cannot directly contain another array value, though can contain an + // Cannot directly contain another array value, though can contain a // map which contains another array. ArrayValue array_value = 9; // A map value. MapValue map_value = 6; + // Value which references a field. // // This is considered relative (vs absolute) since it only refers to a field @@ -139,9 +140,6 @@ message Value { // * Must follow [field reference][FieldReference.field_path] limitations. // // * Not allowed to be used when writing documents. - // - // (-- NOTE(batchik): long term, there is no reason this type should not be - // allowed to be used on the write path. --) string field_reference_value = 19; // Pointer to a variable defined elsewhere in a pipeline. @@ -156,13 +154,6 @@ message Value { // **Requires:** // // * Not allowed to be used when writing documents. - // - // (-- NOTE(batchik): similar to above, there is no reason to not allow - // storing expressions into the database, just no plan to support in - // the near term. - // - // This would actually be an interesting way to represent user-defined - // functions or more expressive rules-based systems. --) Function function_value = 20; // A value that represents an unevaluated pipeline. @@ -170,13 +161,6 @@ message Value { // **Requires:** // // * Not allowed to be used when writing documents. - // - // (-- NOTE(batchik): similar to above, there is no reason to not allow - // storing expressions into the database, just no plan to support in - // the near term. - // - // This would actually be an interesting way to represent user-defined - // functions or more expressive rules-based systems. --) Pipeline pipeline_value = 21; } } @@ -198,7 +182,6 @@ message MapValue { map fields = 1; } - // Represents an unevaluated scalar expression. // // For example, the expression `like(user_name, "%alice%")` is represented as: @@ -208,23 +191,19 @@ message MapValue { // args { field_reference: "user_name" } // args { string_value: "%alice%" } // ``` -// -// (-- api-linter: core::0123::resource-annotation=disabled -// aip.dev/not-precedent: this is not a One Platform API resource. --) message Function { - // The name of the function to evaluate. + // Required. The name of the function to evaluate. // // **Requires:** // // * must be in snake case (lower case with underscore separator). - // - string name = 1; + string name = 1 [(google.api.field_behavior) = REQUIRED]; - // Ordered list of arguments the given function expects. - repeated Value args = 2; + // Optional. Ordered list of arguments the given function expects. + repeated Value args = 2 [(google.api.field_behavior) = OPTIONAL]; - // Optional named arguments that certain functions may support. - map options = 3; + // Optional. Optional named arguments that certain functions may support. + map options = 3 [(google.api.field_behavior) = OPTIONAL]; } // A Firestore query represented as an ordered list of operations / stages. @@ -249,21 +228,20 @@ message Pipeline { // // See public documentation for the full list. message Stage { - // The name of the stage to evaluate. + // Required. The name of the stage to evaluate. // // **Requires:** // // * must be in snake case (lower case with underscore separator). - // - string name = 1; + string name = 1 [(google.api.field_behavior) = REQUIRED]; - // Ordered list of arguments the given stage expects. - repeated Value args = 2; + // Optional. Ordered list of arguments the given stage expects. + repeated Value args = 2 [(google.api.field_behavior) = OPTIONAL]; - // Optional named arguments that certain functions may support. - map options = 3; + // Optional. Optional named arguments that certain functions may support. + map options = 3 [(google.api.field_behavior) = OPTIONAL]; } - // Ordered list of stages to evaluate. - repeated Stage stages = 1; + // Required. Ordered list of stages to evaluate. + repeated Stage stages = 1 [(google.api.field_behavior) = REQUIRED]; } diff --git a/packages/firestore/src/protos/google/firestore/v1/explain_stats.proto b/packages/firestore/src/protos/google/firestore/v1/explain_stats.proto new file mode 100644 index 0000000000..a05d530133 --- /dev/null +++ b/packages/firestore/src/protos/google/firestore/v1/explain_stats.proto @@ -0,0 +1,41 @@ +// Copyright 2026 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. + +syntax = "proto3"; + +package google.firestore.v1; + +import "google/protobuf/any.proto"; + +option csharp_namespace = "Google.Cloud.Firestore.V1"; +option go_package = "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb"; +option java_multiple_files = true; +option java_outer_classname = "ExplainStatsProto"; +option java_package = "com.google.firestore.v1"; +option php_namespace = "Google\\Cloud\\Firestore\\V1"; +option ruby_package = "Google::Cloud::Firestore::V1"; + +// Specification of Firestore Explain Stats fields. + +// Pipeline explain stats. +// +// Depending on the explain options in the original request, this can contain +// the optimized plan and / or execution stats. +message ExplainStats { + // The format depends on the `output_format` options in the request. + // + // Currently there are two supported options: `TEXT` and `JSON`. + // Both supply a `google.protobuf.StringValue`. + google.protobuf.Any data = 1; +} diff --git a/packages/firestore/src/protos/google/firestore/v1/firestore.proto b/packages/firestore/src/protos/google/firestore/v1/firestore.proto index 3e7b62e060..f65646a4af 100644 --- a/packages/firestore/src/protos/google/firestore/v1/firestore.proto +++ b/packages/firestore/src/protos/google/firestore/v1/firestore.proto @@ -1,4 +1,4 @@ -// Copyright 2021 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,11 +19,14 @@ package google.firestore.v1; import "google/api/annotations.proto"; import "google/api/client.proto"; import "google/api/field_behavior.proto"; +import "google/api/routing.proto"; import "google/firestore/v1/aggregation_result.proto"; import "google/firestore/v1/common.proto"; import "google/firestore/v1/document.proto"; +import "google/firestore/v1/explain_stats.proto"; import "google/firestore/v1/pipeline.proto"; import "google/firestore/v1/query.proto"; +import "google/firestore/v1/query_profile.proto"; import "google/firestore/v1/write.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/timestamp.proto"; @@ -31,11 +34,10 @@ import "google/protobuf/wrappers.proto"; import "google/rpc/status.proto"; option csharp_namespace = "Google.Cloud.Firestore.V1"; -option go_package = "google.golang.org/genproto/googleapis/firestore/v1;firestore"; +option go_package = "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb"; option java_multiple_files = true; option java_outer_classname = "FirestoreProto"; option java_package = "com.google.firestore.v1"; -option objc_class_prefix = "GCFS"; option php_namespace = "Google\\Cloud\\Firestore\\V1"; option ruby_package = "Google::Cloud::Firestore::V1"; @@ -47,8 +49,8 @@ option ruby_package = "Google::Cloud::Firestore::V1"; // document database that simplifies storing, syncing, and querying data for // your mobile, web, and IoT apps at global scale. Its client libraries provide // live synchronization and offline support, while its security features and -// integrations with Firebase and Google Cloud Platform (GCP) accelerate -// building truly serverless apps. +// integrations with Firebase and Google Cloud Platform accelerate building +// truly serverless apps. service Firestore { option (google.api.default_host) = "firestore.googleapis.com"; option (google.api.oauth_scopes) = @@ -66,6 +68,9 @@ service Firestore { rpc ListDocuments(ListDocumentsRequest) returns (ListDocumentsResponse) { option (google.api.http) = { get: "/v1/{parent=projects/*/databases/*/documents/*/**}/{collection_id}" + additional_bindings { + get: "/v1/{parent=projects/*/databases/*/documents}/{collection_id}" + } }; } @@ -90,7 +95,8 @@ service Firestore { // // Documents returned by this method are not guaranteed to be returned in the // same order that they were requested. - rpc BatchGetDocuments(BatchGetDocumentsRequest) returns (stream BatchGetDocumentsResponse) { + rpc BatchGetDocuments(BatchGetDocumentsRequest) + returns (stream BatchGetDocumentsResponse) { option (google.api.http) = { post: "/v1/{database=projects/*/databases/*}/documents:batchGet" body: "*" @@ -98,7 +104,8 @@ service Firestore { } // Starts a new transaction. - rpc BeginTransaction(BeginTransactionRequest) returns (BeginTransactionResponse) { + rpc BeginTransaction(BeginTransactionRequest) + returns (BeginTransactionResponse) { option (google.api.http) = { post: "/v1/{database=projects/*/databases/*}/documents:beginTransaction" body: "*" @@ -143,12 +150,23 @@ service Firestore { post: "/v1/{database=projects/*/databases/*}/documents:executePipeline" body: "*" }; + option (google.api.routing) = { + routing_parameters { + field: "database" + path_template: "projects/{project_id=*}/**" + } + routing_parameters { + field: "database" + path_template: "projects/*/databases/{database_id=*}/**" + } + }; } // Runs an aggregation query. // - // Rather than producing [Document][google.firestore.v1.Document] results like [Firestore.RunQuery][google.firestore.v1.Firestore.RunQuery], - // this API allows running an aggregation to produce a series of + // Rather than producing [Document][google.firestore.v1.Document] results like + // [Firestore.RunQuery][google.firestore.v1.Firestore.RunQuery], this API + // allows running an aggregation to produce a series of // [AggregationResult][google.firestore.v1.AggregationResult] server-side. // // High-Level Example: @@ -157,7 +175,8 @@ service Firestore { // -- Return the number of documents in table given a filter. // SELECT COUNT(*) FROM ( SELECT * FROM k where a = true ); // ``` - rpc RunAggregationQuery(RunAggregationQueryRequest) returns (stream RunAggregationQueryResponse) { + rpc RunAggregationQuery(RunAggregationQueryRequest) + returns (stream RunAggregationQueryResponse) { option (google.api.http) = { post: "/v1/{parent=projects/*/databases/*/documents}:runAggregationQuery" body: "*" @@ -182,7 +201,8 @@ service Firestore { }; } - // Streams batches of document updates and deletes, in order. + // Streams batches of document updates and deletes, in order. This method is + // only available via gRPC or WebChannel (not REST). rpc Write(stream WriteRequest) returns (stream WriteResponse) { option (google.api.http) = { post: "/v1/{database=projects/*/databases/*}/documents:write" @@ -190,7 +210,8 @@ service Firestore { }; } - // Listens to changes. + // Listens to changes. This method is only available via gRPC or WebChannel + // (not REST). rpc Listen(stream ListenRequest) returns (stream ListenResponse) { option (google.api.http) = { post: "/v1/{database=projects/*/databases/*}/documents:listen" @@ -199,7 +220,8 @@ service Firestore { } // Lists all the collection IDs underneath a document. - rpc ListCollectionIds(ListCollectionIdsRequest) returns (ListCollectionIdsResponse) { + rpc ListCollectionIds(ListCollectionIdsRequest) + returns (ListCollectionIdsResponse) { option (google.api.http) = { post: "/v1/{parent=projects/*/databases/*/documents}:listCollectionIds" body: "*" @@ -216,7 +238,8 @@ service Firestore { // The BatchWrite method does not apply the write operations atomically // and can apply them out of order. Method does not allow more than one write // per document. Each write succeeds or fails independently. See the - // [BatchWriteResponse][google.firestore.v1.BatchWriteResponse] for the success status of each write. + // [BatchWriteResponse][google.firestore.v1.BatchWriteResponse] for the + // success status of each write. // // If you require an atomically applied set of writes, use // [Commit][google.firestore.v1.Firestore.Commit] instead. @@ -236,7 +259,8 @@ service Firestore { } } -// The request for [Firestore.GetDocument][google.firestore.v1.Firestore.GetDocument]. +// The request for +// [Firestore.GetDocument][google.firestore.v1.Firestore.GetDocument]. message GetDocumentRequest { // Required. The resource name of the Document to get. In the format: // `projects/{project_id}/databases/{database_id}/documents/{document_path}`. @@ -255,78 +279,109 @@ message GetDocumentRequest { bytes transaction = 3; // Reads the version of the document at the given time. - // This may not be older than 270 seconds. + // + // This must be a microsecond precision timestamp within the past one hour, + // or if Point-in-Time Recovery is enabled, can additionally be a whole + // minute timestamp within the past 7 days. google.protobuf.Timestamp read_time = 5; } } -// The request for [Firestore.ListDocuments][google.firestore.v1.Firestore.ListDocuments]. +// The request for +// [Firestore.ListDocuments][google.firestore.v1.Firestore.ListDocuments]. message ListDocumentsRequest { // Required. The parent resource name. In the format: // `projects/{project_id}/databases/{database_id}/documents` or // `projects/{project_id}/databases/{database_id}/documents/{document_path}`. + // // For example: // `projects/my-project/databases/my-database/documents` or // `projects/my-project/databases/my-database/documents/chatrooms/my-chatroom` string parent = 1 [(google.api.field_behavior) = REQUIRED]; - // Required. The collection ID, relative to `parent`, to list. For example: `chatrooms` - // or `messages`. - string collection_id = 2 [(google.api.field_behavior) = REQUIRED]; + // Optional. The collection ID, relative to `parent`, to list. + // + // For example: `chatrooms` or `messages`. + // + // This is optional, and when not provided, Firestore will list documents + // from all collections under the provided `parent`. + string collection_id = 2 [(google.api.field_behavior) = OPTIONAL]; - // The maximum number of documents to return. - int32 page_size = 3; + // Optional. The maximum number of documents to return in a single response. + // + // Firestore may return fewer than this value. + int32 page_size = 3 [(google.api.field_behavior) = OPTIONAL]; - // The `next_page_token` value returned from a previous List request, if any. - string page_token = 4; + // Optional. A page token, received from a previous `ListDocuments` response. + // + // Provide this to retrieve the subsequent page. When paginating, all other + // parameters (with the exception of `page_size`) must match the values set + // in the request that generated the page token. + string page_token = 4 [(google.api.field_behavior) = OPTIONAL]; - // The order to sort results by. For example: `priority desc, name`. - string order_by = 6; + // Optional. The optional ordering of the documents to return. + // + // For example: `priority desc, __name__ desc`. + // + // This mirrors the [`ORDER BY`][google.firestore.v1.StructuredQuery.order_by] + // used in Firestore queries but in a string representation. When absent, + // documents are ordered based on `__name__ ASC`. + string order_by = 6 [(google.api.field_behavior) = OPTIONAL]; - // The fields to return. If not set, returns all fields. + // Optional. The fields to return. If not set, returns all fields. // // If a document has a field that is not present in this mask, that field // will not be returned in the response. - DocumentMask mask = 7; + DocumentMask mask = 7 [(google.api.field_behavior) = OPTIONAL]; // The consistency mode for this transaction. // If not set, defaults to strong consistency. oneof consistency_selector { - // Reads documents in a transaction. + // Perform the read as part of an already active transaction. bytes transaction = 8; - // Reads documents as they were at the given time. - // This may not be older than 270 seconds. + // Perform the read at the provided time. + // + // This must be a microsecond precision timestamp within the past one hour, + // or if Point-in-Time Recovery is enabled, can additionally be a whole + // minute timestamp within the past 7 days. google.protobuf.Timestamp read_time = 10; } - // If the list should show missing documents. A missing document is a - // document that does not exist but has sub-documents. These documents will - // be returned with a key but will not have fields, [Document.create_time][google.firestore.v1.Document.create_time], - // or [Document.update_time][google.firestore.v1.Document.update_time] set. + // If the list should show missing documents. // - // Requests with `show_missing` may not specify `where` or - // `order_by`. + // A document is missing if it does not exist, but there are sub-documents + // nested underneath it. When true, such missing documents will be returned + // with a key but will not have fields, + // [`create_time`][google.firestore.v1.Document.create_time], or + // [`update_time`][google.firestore.v1.Document.update_time] set. + // + // Requests with `show_missing` may not specify `where` or `order_by`. bool show_missing = 12; } -// The response for [Firestore.ListDocuments][google.firestore.v1.Firestore.ListDocuments]. +// The response for +// [Firestore.ListDocuments][google.firestore.v1.Firestore.ListDocuments]. message ListDocumentsResponse { // The Documents found. repeated Document documents = 1; - // The next page token. + // A token to retrieve the next page of documents. + // + // If this field is omitted, there are no subsequent pages. string next_page_token = 2; } -// The request for [Firestore.CreateDocument][google.firestore.v1.Firestore.CreateDocument]. +// The request for +// [Firestore.CreateDocument][google.firestore.v1.Firestore.CreateDocument]. message CreateDocumentRequest { // Required. The parent resource. For example: // `projects/{project_id}/databases/{database_id}/documents` or // `projects/{project_id}/databases/{database_id}/documents/chatrooms/{chatroom_id}` string parent = 1 [(google.api.field_behavior) = REQUIRED]; - // Required. The collection ID, relative to `parent`, to list. For example: `chatrooms`. + // Required. The collection ID, relative to `parent`, to list. For example: + // `chatrooms`. string collection_id = 2 [(google.api.field_behavior) = REQUIRED]; // The client-assigned document ID to use for this document. @@ -344,7 +399,8 @@ message CreateDocumentRequest { DocumentMask mask = 5; } -// The request for [Firestore.UpdateDocument][google.firestore.v1.Firestore.UpdateDocument]. +// The request for +// [Firestore.UpdateDocument][google.firestore.v1.Firestore.UpdateDocument]. message UpdateDocumentRequest { // Required. The updated document. // Creates the document if it does not already exist. @@ -370,7 +426,8 @@ message UpdateDocumentRequest { Precondition current_document = 4; } -// The request for [Firestore.DeleteDocument][google.firestore.v1.Firestore.DeleteDocument]. +// The request for +// [Firestore.DeleteDocument][google.firestore.v1.Firestore.DeleteDocument]. message DeleteDocumentRequest { // Required. The resource name of the Document to delete. In the format: // `projects/{project_id}/databases/{database_id}/documents/{document_path}`. @@ -381,7 +438,8 @@ message DeleteDocumentRequest { Precondition current_document = 2; } -// The request for [Firestore.BatchGetDocuments][google.firestore.v1.Firestore.BatchGetDocuments]. +// The request for +// [Firestore.BatchGetDocuments][google.firestore.v1.Firestore.BatchGetDocuments]. message BatchGetDocumentsRequest { // Required. The database name. In the format: // `projects/{project_id}/databases/{database_id}`. @@ -412,12 +470,16 @@ message BatchGetDocumentsRequest { TransactionOptions new_transaction = 5; // Reads documents as they were at the given time. - // This may not be older than 270 seconds. + // + // This must be a microsecond precision timestamp within the past one hour, + // or if Point-in-Time Recovery is enabled, can additionally be a whole + // minute timestamp within the past 7 days. google.protobuf.Timestamp read_time = 7; } } -// The streamed response for [Firestore.BatchGetDocuments][google.firestore.v1.Firestore.BatchGetDocuments]. +// The streamed response for +// [Firestore.BatchGetDocuments][google.firestore.v1.Firestore.BatchGetDocuments]. message BatchGetDocumentsResponse { // A single result. // This can be empty if the server is just returning a transaction. @@ -432,17 +494,19 @@ message BatchGetDocumentsResponse { // The transaction that was started as part of this request. // Will only be set in the first response, and only if - // [BatchGetDocumentsRequest.new_transaction][google.firestore.v1.BatchGetDocumentsRequest.new_transaction] was set in the request. + // [BatchGetDocumentsRequest.new_transaction][google.firestore.v1.BatchGetDocumentsRequest.new_transaction] + // was set in the request. bytes transaction = 3; // The time at which the document was read. - // This may be monotonically increasing, in this case the previous documents in + // This may be monotically increasing, in this case the previous documents in // the result stream are guaranteed not to have changed between their // read_time and this one. google.protobuf.Timestamp read_time = 4; } -// The request for [Firestore.BeginTransaction][google.firestore.v1.Firestore.BeginTransaction]. +// The request for +// [Firestore.BeginTransaction][google.firestore.v1.Firestore.BeginTransaction]. message BeginTransactionRequest { // Required. The database name. In the format: // `projects/{project_id}/databases/{database_id}`. @@ -453,7 +517,8 @@ message BeginTransactionRequest { TransactionOptions options = 2; } -// The response for [Firestore.BeginTransaction][google.firestore.v1.Firestore.BeginTransaction]. +// The response for +// [Firestore.BeginTransaction][google.firestore.v1.Firestore.BeginTransaction]. message BeginTransactionResponse { // The transaction that was started. bytes transaction = 1; @@ -516,7 +581,9 @@ message RunQueryRequest { // The consistency mode for this transaction. // If not set, defaults to strong consistency. oneof consistency_selector { - // Reads documents in a transaction. + // Run the query within an already active transaction. + // + // The value here is the opaque transaction ID to execute the query in. bytes transaction = 5; // Starts a new transaction and reads the documents. @@ -526,21 +593,29 @@ message RunQueryRequest { TransactionOptions new_transaction = 6; // Reads documents as they were at the given time. - // This may not be older than 270 seconds. + // + // This must be a microsecond precision timestamp within the past one hour, + // or if Point-in-Time Recovery is enabled, can additionally be a whole + // minute timestamp within the past 7 days. google.protobuf.Timestamp read_time = 7; } + + // Optional. Explain options for the query. If set, additional query + // statistics will be returned. If not, only query results will be returned. + ExplainOptions explain_options = 10 [(google.api.field_behavior) = OPTIONAL]; } -// The response for [Firestore.RunQuery][google.firestore.v1.Firestore.RunQuery]. +// The response for +// [Firestore.RunQuery][google.firestore.v1.Firestore.RunQuery]. message RunQueryResponse { // The transaction that was started as part of this request. // Can only be set in the first response, and only if - // [RunQueryRequest.new_transaction][google.firestore.v1.RunQueryRequest.new_transaction] was set in the request. - // If set, no other fields will be set in this response. + // [RunQueryRequest.new_transaction][google.firestore.v1.RunQueryRequest.new_transaction] + // was set in the request. If set, no other fields will be set in this + // response. bytes transaction = 2; - // A query result. - // Not set when reporting partial progress. + // A query result, not set when reporting partial progress. Document document = 1; // The time at which the document was read. This may be monotonically @@ -555,14 +630,28 @@ message RunQueryResponse { // The number of results that have been skipped due to an offset between // the last response and the current response. int32 skipped_results = 4; + + // The continuation mode for the query. If present, it indicates the current + // query response stream has finished. This can be set with or without a + // `document` present, but when set, no more results are returned. + oneof continuation_selector { + // If present, Firestore has completely finished the request and no more + // documents will be returned. + bool done = 6; + } + + // Query explain metrics. This is only present when the + // [RunQueryRequest.explain_options][google.firestore.v1.RunQueryRequest.explain_options] + // is provided, and it is sent only once with the last response in the stream. + ExplainMetrics explain_metrics = 11; } -// The request for [Firestore.ExecutePipeline][]. +// The request for +// [Firestore.ExecutePipeline][google.firestore.v1.Firestore.ExecutePipeline]. message ExecutePipelineRequest { - // Database identifier, in the form `projects/{project}/databases/{database}`. - string database = 1 [ - (google.api.field_behavior) = REQUIRED - ]; + // Required. Database identifier, in the form + // `projects/{project}/databases/{database}`. + string database = 1 [(google.api.field_behavior) = REQUIRED]; oneof pipeline_type { // A pipelined operation. @@ -589,17 +678,15 @@ message ExecutePipelineRequest { // minute timestamp within the past 7 days. google.protobuf.Timestamp read_time = 7; } - - // Explain / analyze options for the pipeline. - // ExplainOptions explain_options = 8 [(google.api.field_behavior) = OPTIONAL]; } // The response for [Firestore.Execute][]. message ExecutePipelineResponse { // Newly created transaction identifier. // - // This field is only specified on the first response from the server when - // the request specified [ExecuteRequest.new_transaction][]. + // This field is only specified as part of the first response from the server, + // alongside the `results` field when the original request specified + // [ExecuteRequest.new_transaction][]. bytes transaction = 1; // An ordered batch of results returned executing a pipeline. @@ -608,32 +695,38 @@ message ExecutePipelineResponse { // progress message is returned. // // The fields present in the returned documents are only those that were - // explicitly requested in the pipeline, this include those like - // [`__name__`][Document.name] & [`__update_time__`][Document.update_time]. - // This is explicitly a divergence from `Firestore.RunQuery` / - // `Firestore.GetDocument` RPCs which always return such fields even when they - // are not specified in the [`mask`][DocumentMask]. + // explicitly requested in the pipeline, this includes those like + // [`__name__`][google.firestore.v1.Document.name] and + // [`__update_time__`][google.firestore.v1.Document.update_time]. This is + // explicitly a divergence from `Firestore.RunQuery` / `Firestore.GetDocument` + // RPCs which always return such fields even when they are not specified in + // the [`mask`][google.firestore.v1.DocumentMask]. repeated Document results = 2; - // The time at which the document(s) were read. + // The time at which the results are valid. // - // This may be monotonically increasing; in this case, the previous documents - // in the result stream are guaranteed not to have changed between their - // `execution_time` and this one. + // This is a (not strictly) monotonically increasing value across multiple + // responses in the same stream. The API guarantees that all previously + // returned results are still valid at the latest `execution_time`. This + // allows the API consumer to treat the query if it ran at the latest + // `execution_time` returned. // // If the query returns no results, a response with `execution_time` and no // `results` will be sent, and this represents the time at which the operation // was run. google.protobuf.Timestamp execution_time = 3; - // Query explain metrics. + // Query explain stats. // - // Set on the last response when [ExecutePipelineRequest.explain_options][] - // was specified on the request. - // ExplainMetrics explain_metrics = 4; + // This is present on the **last** response if the request configured explain + // to run in 'analyze' or 'explain' mode in the pipeline options. If the query + // does not return any results, a response with `explain_stats` and no + // `results` will still be sent. + ExplainStats explain_stats = 4; } -// The request for [Firestore.RunAggregationQuery][google.firestore.v1.Firestore.RunAggregationQuery]. +// The request for +// [Firestore.RunAggregationQuery][google.firestore.v1.Firestore.RunAggregationQuery]. message RunAggregationQueryRequest { // Required. The parent resource name. In the format: // `projects/{project_id}/databases/{database_id}/documents` or @@ -664,19 +757,23 @@ message RunAggregationQueryRequest { // Executes the query at the given timestamp. // - // Requires: - // - // * Cannot be more than 270 seconds in the past. + // This must be a microsecond precision timestamp within the past one hour, + // or if Point-in-Time Recovery is enabled, can additionally be a whole + // minute timestamp within the past 7 days. google.protobuf.Timestamp read_time = 6; } + + // Optional. Explain options for the query. If set, additional query + // statistics will be returned. If not, only query results will be returned. + ExplainOptions explain_options = 8 [(google.api.field_behavior) = OPTIONAL]; } -// The response for [Firestore.RunAggregationQuery][google.firestore.v1.Firestore.RunAggregationQuery]. +// The response for +// [Firestore.RunAggregationQuery][google.firestore.v1.Firestore.RunAggregationQuery]. message RunAggregationQueryResponse { // A single aggregation result. // - // Not present when reporting partial progress or when the query produced - // zero results. + // Not present when reporting partial progress. AggregationResult result = 1; // The transaction that was started as part of this request. @@ -685,11 +782,24 @@ message RunAggregationQueryResponse { // a new transaction. bytes transaction = 2; - // The time at which the aggregate value is valid for. + // The time at which the aggregate result was computed. This is always + // monotonically increasing; in this case, the previous AggregationResult in + // the result stream are guaranteed not to have changed between their + // `read_time` and this one. + // + // If the query returns no results, a response with `read_time` and no + // `result` will be sent, and this represents the time at which the query + // was run. google.protobuf.Timestamp read_time = 3; + + // Query explain metrics. This is only present when the + // [RunAggregationQueryRequest.explain_options][google.firestore.v1.RunAggregationQueryRequest.explain_options] + // is provided, and it is sent only once with the last response in the stream. + ExplainMetrics explain_metrics = 10; } -// The request for [Firestore.PartitionQuery][google.firestore.v1.Firestore.PartitionQuery]. +// The request for +// [Firestore.PartitionQuery][google.firestore.v1.Firestore.PartitionQuery]. message PartitionQueryRequest { // Required. The parent resource name. In the format: // `projects/{project_id}/databases/{database_id}/documents`. @@ -739,9 +849,21 @@ message PartitionQueryRequest { // if more results exist. A second call to PartitionQuery will return up to // 2 partitions, to complete the total of 10 specified in `partition_count`. int32 page_size = 5; + + // The consistency mode for this request. + // If not set, defaults to strong consistency. + oneof consistency_selector { + // Reads documents as they were at the given time. + // + // This must be a microsecond precision timestamp within the past one hour, + // or if Point-in-Time Recovery is enabled, can additionally be a whole + // minute timestamp within the past 7 days. + google.protobuf.Timestamp read_time = 6; + } } -// The response for [Firestore.PartitionQuery][google.firestore.v1.Firestore.PartitionQuery]. +// The response for +// [Firestore.PartitionQuery][google.firestore.v1.Firestore.PartitionQuery]. message PartitionQueryResponse { // Partition results. // Each partition is a split point that can be used by RunQuery as a starting @@ -759,7 +881,7 @@ message PartitionQueryResponse { // * query, start_at B // // An empty result may indicate that the query has too few results to be - // partitioned. + // partitioned, or that the query is not yet supported for partitioning. repeated Cursor partitions = 1; // A page token that may be used to request an additional set of results, up @@ -800,9 +922,9 @@ message WriteRequest { // A stream token that was previously sent by the server. // // The client should set this field to the token from the most recent - // [WriteResponse][google.firestore.v1.WriteResponse] it has received. This acknowledges that the client has - // received responses up to this token. After sending this token, earlier - // tokens may not be used anymore. + // [WriteResponse][google.firestore.v1.WriteResponse] it has received. This + // acknowledges that the client has received responses up to this token. After + // sending this token, earlier tokens may not be used anymore. // // The server may close the stream if there are too many unacknowledged // responses. @@ -872,8 +994,8 @@ message ListenResponse { // A [Document][google.firestore.v1.Document] has been deleted. DocumentDelete document_delete = 4; - // A [Document][google.firestore.v1.Document] has been removed from a target (because it is no longer - // relevant to that target). + // A [Document][google.firestore.v1.Document] has been removed from a target + // (because it is no longer relevant to that target). DocumentRemove document_remove = 6; // A filter to apply to the set of documents previously returned for the @@ -924,10 +1046,12 @@ message Target { // When to start listening. // - // If not specified, all matching Documents are returned before any - // subsequent changes. + // If specified, only the matching Documents that have been updated AFTER the + // `resume_token` or `read_time` will be returned. Otherwise, all matching + // Documents are returned before any subsequent changes. oneof resume_type { - // A resume token from a prior [TargetChange][google.firestore.v1.TargetChange] for an identical target. + // A resume token from a prior + // [TargetChange][google.firestore.v1.TargetChange] for an identical target. // // Using a resume token with a different target is unsupported and may fail. bytes resume_token = 4; @@ -940,6 +1064,21 @@ message Target { // The target ID that identifies the target on the stream. Must be a positive // number and non-zero. + // + // If `target_id` is 0 (or unspecified), the server will assign an ID for this + // target and return that in a `TargetChange::ADD` event. Once a target with + // `target_id=0` is added, all subsequent targets must also have + // `target_id=0`. If an `AddTarget` request with `target_id != 0` is + // sent to the server after a target with `target_id=0` is added, the server + // will immediately send a response with a `TargetChange::Remove` event. + // + // Note that if the client sends multiple `AddTarget` requests + // without an ID, the order of IDs returned in `TargetChange.target_ids` are + // undefined. Therefore, clients should provide a target ID instead of relying + // on the server to assign one. + // + // If `target_id` is non-zero, there must not be an existing active target on + // this stream with the same ID. int32 target_id = 5; // If the target should be removed once it is current and consistent. @@ -951,7 +1090,6 @@ message Target { // This value is only relevant when a `resume_type` is provided. This value // being present and greater than zero signals that the client wants // `ExistenceFilter.unchanged_names` to be included in the response. - // google.protobuf.Int32Value expected_count = 12; } @@ -1018,7 +1156,8 @@ message TargetChange { google.protobuf.Timestamp read_time = 6; } -// The request for [Firestore.ListCollectionIds][google.firestore.v1.Firestore.ListCollectionIds]. +// The request for +// [Firestore.ListCollectionIds][google.firestore.v1.Firestore.ListCollectionIds]. message ListCollectionIdsRequest { // Required. The parent document. In the format: // `projects/{project_id}/databases/{database_id}/documents/{document_path}`. @@ -1032,9 +1171,21 @@ message ListCollectionIdsRequest { // A page token. Must be a value from // [ListCollectionIdsResponse][google.firestore.v1.ListCollectionIdsResponse]. string page_token = 3; + + // The consistency mode for this request. + // If not set, defaults to strong consistency. + oneof consistency_selector { + // Reads documents as they were at the given time. + // + // This must be a microsecond precision timestamp within the past one hour, + // or if Point-in-Time Recovery is enabled, can additionally be a whole + // minute timestamp within the past 7 days. + google.protobuf.Timestamp read_time = 4; + } } -// The response from [Firestore.ListCollectionIds][google.firestore.v1.Firestore.ListCollectionIds]. +// The response from +// [Firestore.ListCollectionIds][google.firestore.v1.Firestore.ListCollectionIds]. message ListCollectionIdsResponse { // The collection ids. repeated string collection_ids = 1; @@ -1043,7 +1194,8 @@ message ListCollectionIdsResponse { string next_page_token = 2; } -// The request for [Firestore.BatchWrite][google.firestore.v1.Firestore.BatchWrite]. +// The request for +// [Firestore.BatchWrite][google.firestore.v1.Firestore.BatchWrite]. message BatchWriteRequest { // Required. The database name. In the format: // `projects/{project_id}/databases/{database_id}`. @@ -1060,7 +1212,8 @@ message BatchWriteRequest { map labels = 3; } -// The response from [Firestore.BatchWrite][google.firestore.v1.Firestore.BatchWrite]. +// The response from +// [Firestore.BatchWrite][google.firestore.v1.Firestore.BatchWrite]. message BatchWriteResponse { // The result of applying the writes. // diff --git a/packages/firestore/src/protos/google/firestore/v1/pipeline.proto b/packages/firestore/src/protos/google/firestore/v1/pipeline.proto index ea5b230933..509ecd2730 100644 --- a/packages/firestore/src/protos/google/firestore/v1/pipeline.proto +++ b/packages/firestore/src/protos/google/firestore/v1/pipeline.proto @@ -1,41 +1,43 @@ -/*! - * 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. - */ +// Copyright 2026 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. syntax = "proto3"; + package google.firestore.v1; + +import "google/api/field_behavior.proto"; import "google/firestore/v1/document.proto"; + option csharp_namespace = "Google.Cloud.Firestore.V1"; -option php_namespace = "Google\\Cloud\\Firestore\\V1"; -option ruby_package = "Google::Cloud::Firestore::V1"; +option go_package = "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb"; option java_multiple_files = true; -option java_package = "com.google.firestore.v1"; option java_outer_classname = "PipelineProto"; +option java_package = "com.google.firestore.v1"; option objc_class_prefix = "GCFS"; +option php_namespace = "Google\\Cloud\\Firestore\\V1"; +option ruby_package = "Google::Cloud::Firestore::V1"; + // A Firestore query represented as an ordered list of operations / stages. // -// This is considered the top-level function which plans & executes a query. +// This is considered the top-level function which plans and executes a query. // It is logically equivalent to `query(stages, options)`, but prevents the // client from having to build a function wrapper. message StructuredPipeline { - // The pipeline query to execute. - Pipeline pipeline = 1; - // Optional query-level arguments. - // - // (-- Think query statement hints. --) + // Required. The pipeline query to execute. + Pipeline pipeline = 1 [(google.api.field_behavior) = REQUIRED]; + + // Optional. Optional query-level arguments. // - // (-- TODO(batchik): define the api contract of using an unsupported hint --) - map options = 2; + map options = 2 [(google.api.field_behavior) = OPTIONAL]; } diff --git a/packages/firestore/src/protos/google/firestore/v1/query.proto b/packages/firestore/src/protos/google/firestore/v1/query.proto index 9ce102e690..0144ffe5cd 100644 --- a/packages/firestore/src/protos/google/firestore/v1/query.proto +++ b/packages/firestore/src/protos/google/firestore/v1/query.proto @@ -1,4 +1,4 @@ -// Copyright 2021 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,12 +16,12 @@ syntax = "proto3"; package google.firestore.v1; +import "google/api/field_behavior.proto"; import "google/firestore/v1/document.proto"; import "google/protobuf/wrappers.proto"; -import "google/api/annotations.proto"; option csharp_namespace = "Google.Cloud.Firestore.V1"; -option go_package = "google.golang.org/genproto/googleapis/firestore/v1;firestore"; +option go_package = "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb"; option java_multiple_files = true; option java_outer_classname = "QueryProto"; option java_package = "com.google.firestore.v1"; @@ -30,6 +30,15 @@ option php_namespace = "Google\\Cloud\\Firestore\\V1"; option ruby_package = "Google::Cloud::Firestore::V1"; // A Firestore query. +// +// The query stages are executed in the following order: +// 1. from +// 2. where +// 3. select +// 4. order_by + start_at + end_at +// 5. offset +// 6. limit +// 7. find_nearest message StructuredQuery { // A selection of a collection, such as `messages as m1`. message CollectionSelector { @@ -76,7 +85,10 @@ message StructuredQuery { Operator op = 1; // The list of filters to combine. - // Must contain at least one filter. + // + // Requires: + // + // * At least one filter is present. repeated Filter filters = 2; } @@ -133,8 +145,9 @@ message StructuredQuery { // // Requires: // - // * That `value` is a non-empty `ArrayValue` with at most 10 values. - // * No other `IN` or `ARRAY_CONTAINS_ANY` or `NOT_IN`. + // * That `value` is a non-empty `ArrayValue`, subject to disjunction + // limits. + // * No `NOT_IN` filters in the same query. IN = 8; // The given `field` is an array that contains any of the values in the @@ -142,8 +155,10 @@ message StructuredQuery { // // Requires: // - // * That `value` is a non-empty `ArrayValue` with at most 10 values. - // * No other `IN` or `ARRAY_CONTAINS_ANY` or `NOT_IN`. + // * That `value` is a non-empty `ArrayValue`, subject to disjunction + // limits. + // * No other `ARRAY_CONTAINS_ANY` filters within the same disjunction. + // * No `NOT_IN` filters in the same query. ARRAY_CONTAINS_ANY = 9; // The value of the `field` is not in the given array. @@ -151,7 +166,7 @@ message StructuredQuery { // Requires: // // * That `value` is a non-empty `ArrayValue` with at most 10 values. - // * No other `IN`, `ARRAY_CONTAINS_ANY`, `NOT_IN`, `NOT_EQUAL`, + // * No other `OR`, `IN`, `ARRAY_CONTAINS_ANY`, `NOT_IN`, `NOT_EQUAL`, // `IS_NOT_NULL`, or `IS_NOT_NAN`. // * That `field` comes first in the `order_by`. NOT_IN = 10; @@ -216,8 +231,27 @@ message StructuredQuery { Direction direction = 2; } - // A reference to a field, such as `max(messages.time) as max_time`. + // A sort direction. + enum Direction { + // Unspecified. + DIRECTION_UNSPECIFIED = 0; + + // Ascending. + ASCENDING = 1; + + // Descending. + DESCENDING = 2; + } + + // A reference to a field in a document, ex: `stats.operations`. message FieldReference { + // A reference to a field in a document. + // + // Requires: + // + // * MUST be a dot-delimited (`.`) string of segments, where each segment + // conforms to [document field name][google.firestore.v1.Document.fields] + // limitations. string field_path = 2; } @@ -230,19 +264,78 @@ message StructuredQuery { repeated FieldReference fields = 2; } - // A sort direction. - enum Direction { - // Unspecified. - DIRECTION_UNSPECIFIED = 0; - - // Ascending. - ASCENDING = 1; + // Nearest Neighbors search config. The ordering provided by FindNearest + // supersedes the order_by stage. If multiple documents have the same vector + // distance, the returned document order is not guaranteed to be stable + // between queries. + message FindNearest { + // The distance measure to use when comparing vectors. + enum DistanceMeasure { + // Should not be set. + DISTANCE_MEASURE_UNSPECIFIED = 0; + + // Measures the EUCLIDEAN distance between the vectors. See + // [Euclidean](https://en.wikipedia.org/wiki/Euclidean_distance) to learn + // more. The resulting distance decreases the more similar two vectors + // are. + EUCLIDEAN = 1; + + // COSINE distance compares vectors based on the angle between them, which + // allows you to measure similarity that isn't based on the vectors + // magnitude. We recommend using DOT_PRODUCT with unit normalized vectors + // instead of COSINE distance, which is mathematically equivalent with + // better performance. See [Cosine + // Similarity](https://en.wikipedia.org/wiki/Cosine_similarity) to learn + // more about COSINE similarity and COSINE distance. The resulting + // COSINE distance decreases the more similar two vectors are. + COSINE = 2; + + // Similar to cosine but is affected by the magnitude of the vectors. See + // [Dot Product](https://en.wikipedia.org/wiki/Dot_product) to learn more. + // The resulting distance increases the more similar two vectors are. + DOT_PRODUCT = 3; + } - // Descending. - DESCENDING = 2; + // Required. An indexed vector field to search upon. Only documents which + // contain vectors whose dimensionality match the query_vector can be + // returned. + FieldReference vector_field = 1 [(google.api.field_behavior) = REQUIRED]; + + // Required. The query vector that we are searching on. Must be a vector of + // no more than 2048 dimensions. + Value query_vector = 2 [(google.api.field_behavior) = REQUIRED]; + + // Required. The distance measure to use, required. + DistanceMeasure distance_measure = 3 + [(google.api.field_behavior) = REQUIRED]; + + // Required. The number of nearest neighbors to return. Must be a positive + // integer of no more than 1000. + google.protobuf.Int32Value limit = 4 + [(google.api.field_behavior) = REQUIRED]; + + // Optional. Optional name of the field to output the result of the vector + // distance calculation. Must conform to [document field + // name][google.firestore.v1.Document.fields] limitations. + string distance_result_field = 5 [(google.api.field_behavior) = OPTIONAL]; + + // Optional. Option to specify a threshold for which no less similar + // documents will be returned. The behavior of the specified + // `distance_measure` will affect the meaning of the distance threshold. + // Since DOT_PRODUCT distances increase when the vectors are more similar, + // the comparison is inverted. + // + // * For EUCLIDEAN, COSINE: `WHERE distance <= distance_threshold` + // * For DOT_PRODUCT: `WHERE distance >= distance_threshold` + google.protobuf.DoubleValue distance_threshold = 6 + [(google.api.field_behavior) = OPTIONAL]; } - // The projection to return. + // Optional sub-set of the fields to return. + // + // This acts as a [DocumentMask][google.firestore.v1.DocumentMask] over the + // documents returned from a query. When not set, assumes that the caller + // wants all fields returned. Projection select = 1; // The collections to query. @@ -253,66 +346,126 @@ message StructuredQuery { // The order to apply to the query results. // - // Firestore guarantees a stable ordering through the following rules: + // Firestore allows callers to provide a full ordering, a partial ordering, or + // no ordering at all. In all cases, Firestore guarantees a stable ordering + // through the following rules: // - // * Any field required to appear in `order_by`, that is not already - // specified in `order_by`, is appended to the order in field name order - // by default. + // * The `order_by` is required to reference all fields used with an + // inequality filter. + // * All fields that are required to be in the `order_by` but are not already + // present are appended in lexicographical ordering of the field name. // * If an order on `__name__` is not specified, it is appended by default. // // Fields are appended with the same sort direction as the last order // specified, or 'ASCENDING' if no order was specified. For example: // - // * `SELECT * FROM Foo ORDER BY A` becomes - // `SELECT * FROM Foo ORDER BY A, __name__` - // * `SELECT * FROM Foo ORDER BY A DESC` becomes - // `SELECT * FROM Foo ORDER BY A DESC, __name__ DESC` - // * `SELECT * FROM Foo WHERE A > 1` becomes - // `SELECT * FROM Foo WHERE A > 1 ORDER BY A, __name__` + // * `ORDER BY a` becomes `ORDER BY a ASC, __name__ ASC` + // * `ORDER BY a DESC` becomes `ORDER BY a DESC, __name__ DESC` + // * `WHERE a > 1` becomes `WHERE a > 1 ORDER BY a ASC, __name__ ASC` + // * `WHERE __name__ > ... AND a > 1` becomes + // `WHERE __name__ > ... AND a > 1 ORDER BY a ASC, __name__ ASC` repeated Order order_by = 4; - // A starting point for the query results. + // A potential prefix of a position in the result set to start the query at. + // + // The ordering of the result set is based on the `ORDER BY` clause of the + // original query. + // + // ``` + // SELECT * FROM k WHERE a = 1 AND b > 2 ORDER BY b ASC, __name__ ASC; + // ``` + // + // This query's results are ordered by `(b ASC, __name__ ASC)`. + // + // Cursors can reference either the full ordering or a prefix of the location, + // though it cannot reference more fields than what are in the provided + // `ORDER BY`. + // + // Continuing off the example above, attaching the following start cursors + // will have varying impact: + // + // - `START BEFORE (2, /k/123)`: start the query right before `a = 1 AND + // b > 2 AND __name__ > /k/123`. + // - `START AFTER (10)`: start the query right after `a = 1 AND b > 10`. + // + // Unlike `OFFSET` which requires scanning over the first N results to skip, + // a start cursor allows the query to begin at a logical position. This + // position is not required to match an actual result, it will scan forward + // from this position to find the next document. + // + // Requires: + // + // * The number of values cannot be greater than the number of fields + // specified in the `ORDER BY` clause. Cursor start_at = 7; - // A end point for the query results. + // A potential prefix of a position in the result set to end the query at. + // + // This is similar to `START_AT` but with it controlling the end position + // rather than the start position. + // + // Requires: + // + // * The number of values cannot be greater than the number of fields + // specified in the `ORDER BY` clause. Cursor end_at = 8; - // The number of results to skip. + // The number of documents to skip before returning the first result. // - // Applies before limit, but after all other constraints. Must be >= 0 if - // specified. + // This applies after the constraints specified by the `WHERE`, `START AT`, & + // `END AT` but before the `LIMIT` clause. + // + // Requires: + // + // * The value must be greater than or equal to zero if specified. int32 offset = 6; // The maximum number of results to return. // // Applies after all other constraints. - // Must be >= 0 if specified. + // + // Requires: + // + // * The value must be greater than or equal to zero if specified. google.protobuf.Int32Value limit = 5; + + // Optional. A potential nearest neighbors search. + // + // Applies after all other filters and ordering. + // + // Finds the closest vector embeddings to the given query vector. + FindNearest find_nearest = 9 [(google.api.field_behavior) = OPTIONAL]; } +// Firestore query for running an aggregation over a +// [StructuredQuery][google.firestore.v1.StructuredQuery]. message StructuredAggregationQuery { - // Defines a aggregation that produces a single result. + // Defines an aggregation that produces a single result. message Aggregation { // Count of documents that match the query. // // The `COUNT(*)` aggregation function operates on the entire document // so it does not require a field reference. message Count { - // Optional. Optional constraint on the maximum number of documents to count. + // Optional. Optional constraint on the maximum number of documents to + // count. // // This provides a way to set an upper bound on the number of documents - // to scan, limiting latency and cost. + // to scan, limiting latency, and cost. + // + // Unspecified is interpreted as no bound. // // High-Level Example: // // ``` - // SELECT COUNT_UP_TO(1000) FROM ( SELECT * FROM k ); + // AGGREGATE COUNT_UP_TO(1000) OVER ( SELECT * FROM k ); // ``` // // Requires: // // * Must be greater than zero when present. - google.protobuf.Int64Value up_to = 1; + google.protobuf.Int64Value up_to = 1 + [(google.api.field_behavior) = OPTIONAL]; } // Sum of the values of the requested field. @@ -320,12 +473,22 @@ message StructuredAggregationQuery { // * Only numeric values will be aggregated. All non-numeric values // including `NULL` are skipped. // - // * If the aggregated values contain `NaN`, returns `NaN`. + // * If the aggregated values contain `NaN`, returns `NaN`. Infinity math + // follows IEEE-754 standards. // // * If the aggregated value set is empty, returns 0. // - // * Returns a 64-bit integer if the sum result is an integer value and does - // not overflow or underflow. Otherwise, the result is returned as a double. + // * Returns a 64-bit integer if all aggregated numbers are integers and the + // sum result does not overflow. Otherwise, the result is returned as a + // double. Note that even if all the aggregated values are integers, the + // result is returned as a double if it cannot fit within a 64-bit signed + // integer. When this occurs, the returned value will lose precision. + // + // * When underflow occurs, floating-point aggregation is non-deterministic. + // This means that running the same query repeatedly without any changes to + // the underlying values could produce slightly different results each + // time. In those cases, values should be stored as integers over + // floating-point numbers. message Sum { // The field to aggregate on. StructuredQuery.FieldReference field = 1; @@ -336,7 +499,8 @@ message StructuredAggregationQuery { // * Only numeric values will be aggregated. All non-numeric values // including `NULL` are skipped. // - // * If the aggregated values contain `NaN`, returns `NaN`. + // * If the aggregated values contain `NaN`, returns `NaN`. Infinity math + // follows IEEE-754 standards. // // * If the aggregated value set is empty, returns `NULL`. // @@ -358,14 +522,42 @@ message StructuredAggregationQuery { Avg avg = 3; } - // Required. The name of the field to store the result of the aggregation into. + // Optional. Optional name of the field to store the result of the + // aggregation into. + // + // If not provided, Firestore will pick a default name following the format + // `field_`. For example: + // + // ``` + // AGGREGATE + // COUNT_UP_TO(1) AS count_up_to_1, + // COUNT_UP_TO(2), + // COUNT_UP_TO(3) AS count_up_to_3, + // COUNT(*) + // OVER ( + // ... + // ); + // ``` + // + // becomes: + // + // ``` + // AGGREGATE + // COUNT_UP_TO(1) AS count_up_to_1, + // COUNT_UP_TO(2) AS field_1, + // COUNT_UP_TO(3) AS count_up_to_3, + // COUNT(*) AS field_2 + // OVER ( + // ... + // ); + // ``` // // Requires: // - // * Must be present. // * Must be unique across all aggregation aliases. - // * Conform to existing [document field name][google.firestore.v1.Document.fields] limitations. - string alias = 7; + // * Conform to [document field name][google.firestore.v1.Document.fields] + // limitations. + string alias = 7 [(google.api.field_behavior) = OPTIONAL]; } // The base query to aggregate over. @@ -374,8 +566,14 @@ message StructuredAggregationQuery { StructuredQuery structured_query = 1; } - // Optional. Series of aggregations to apply on top of the `structured_query`. - repeated Aggregation aggregations = 3; + // Optional. Series of aggregations to apply over the results of the + // `structured_query`. + // + // Requires: + // + // * A minimum of one and maximum of five aggregations per query. + repeated Aggregation aggregations = 3 + [(google.api.field_behavior) = OPTIONAL]; } // A position in a query result set. diff --git a/packages/firestore/src/protos/google/firestore/v1/query_profile.proto b/packages/firestore/src/protos/google/firestore/v1/query_profile.proto index de27144a03..a5f9e95c51 100644 --- a/packages/firestore/src/protos/google/firestore/v1/query_profile.proto +++ b/packages/firestore/src/protos/google/firestore/v1/query_profile.proto @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/packages/firestore/src/protos/google/firestore/v1/write.proto b/packages/firestore/src/protos/google/firestore/v1/write.proto index d8465955b6..8b569a5e0c 100644 --- a/packages/firestore/src/protos/google/firestore/v1/write.proto +++ b/packages/firestore/src/protos/google/firestore/v1/write.proto @@ -1,4 +1,4 @@ -// Copyright 2021 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,10 +20,9 @@ import "google/firestore/v1/bloom_filter.proto"; import "google/firestore/v1/common.proto"; import "google/firestore/v1/document.proto"; import "google/protobuf/timestamp.proto"; -import "google/api/annotations.proto"; option csharp_namespace = "Google.Cloud.Firestore.V1"; -option go_package = "google.golang.org/genproto/googleapis/firestore/v1;firestore"; +option go_package = "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb"; option java_multiple_files = true; option java_outer_classname = "WriteProto"; option java_package = "com.google.firestore.v1"; @@ -91,8 +90,9 @@ message DocumentTransform { REQUEST_TIME = 1; } - // The path of the field. See [Document.fields][google.firestore.v1.Document.fields] for the field path syntax - // reference. + // The path of the field. See + // [Document.fields][google.firestore.v1.Document.fields] for the field path + // syntax reference. string field_path = 1; // The transformation to apply on the field. @@ -186,18 +186,20 @@ message WriteResult { // previous update_time. google.protobuf.Timestamp update_time = 1; - // The results of applying each [DocumentTransform.FieldTransform][google.firestore.v1.DocumentTransform.FieldTransform], in the - // same order. + // The results of applying each + // [DocumentTransform.FieldTransform][google.firestore.v1.DocumentTransform.FieldTransform], + // in the same order. repeated Value transform_results = 2; } // A [Document][google.firestore.v1.Document] has changed. // -// May be the result of multiple [writes][google.firestore.v1.Write], including deletes, that -// ultimately resulted in a new value for the [Document][google.firestore.v1.Document]. +// May be the result of multiple [writes][google.firestore.v1.Write], including +// deletes, that ultimately resulted in a new value for the +// [Document][google.firestore.v1.Document]. // -// Multiple [DocumentChange][google.firestore.v1.DocumentChange] messages may be returned for the same logical -// change, if multiple targets are affected. +// Multiple [DocumentChange][google.firestore.v1.DocumentChange] messages may be +// returned for the same logical change, if multiple targets are affected. message DocumentChange { // The new state of the [Document][google.firestore.v1.Document]. // @@ -213,13 +215,15 @@ message DocumentChange { // A [Document][google.firestore.v1.Document] has been deleted. // -// May be the result of multiple [writes][google.firestore.v1.Write], including updates, the -// last of which deleted the [Document][google.firestore.v1.Document]. +// May be the result of multiple [writes][google.firestore.v1.Write], including +// updates, the last of which deleted the +// [Document][google.firestore.v1.Document]. // -// Multiple [DocumentDelete][google.firestore.v1.DocumentDelete] messages may be returned for the same logical -// delete, if multiple targets are affected. +// Multiple [DocumentDelete][google.firestore.v1.DocumentDelete] messages may be +// returned for the same logical delete, if multiple targets are affected. message DocumentDelete { - // The resource name of the [Document][google.firestore.v1.Document] that was deleted. + // The resource name of the [Document][google.firestore.v1.Document] that was + // deleted. string document = 1; // A set of target IDs for targets that previously matched this entity. @@ -231,16 +235,19 @@ message DocumentDelete { google.protobuf.Timestamp read_time = 4; } -// A [Document][google.firestore.v1.Document] has been removed from the view of the targets. +// A [Document][google.firestore.v1.Document] has been removed from the view of +// the targets. // // Sent if the document is no longer relevant to a target and is out of view. // Can be sent instead of a DocumentDelete or a DocumentChange if the server -// cannot send the new value of the document. +// can not send the new value of the document. // -// Multiple [DocumentRemove][google.firestore.v1.DocumentRemove] messages may be returned for the same logical -// write or delete, if multiple targets are affected. +// Multiple [DocumentRemove][google.firestore.v1.DocumentRemove] messages may be +// returned for the same logical write or delete, if multiple targets are +// affected. message DocumentRemove { - // The resource name of the [Document][google.firestore.v1.Document] that has gone out of view. + // The resource name of the [Document][google.firestore.v1.Document] that has + // gone out of view. string document = 1; // A set of target IDs for targets that previously matched this document. @@ -257,17 +264,22 @@ message ExistenceFilter { // The target ID to which this filter applies. int32 target_id = 1; - // The total count of documents that match [target_id][google.firestore.v1.ExistenceFilter.target_id]. + // The total count of documents that match + // [target_id][google.firestore.v1.ExistenceFilter.target_id]. // // If different from the count of documents in the client that match, the // client must manually determine which documents no longer match the target. + // + // The client can use the `unchanged_names` bloom filter to assist with + // this determination by testing ALL the document names against the filter; + // if the document name is NOT in the filter, it means the document no + // longer matches the target. int32 count = 2; - // A bloom filter that contains the UTF-8 byte encodings of the resource names - // of the documents that match [target_id][google.firestore.v1.ExistenceFilter.target_id], in the - // form `projects/{project_id}/databases/{database_id}/documents/{document_path}` - // that have NOT changed since the query results indicated by the resume token - // or timestamp given in `Target.resume_type`. + // A bloom filter that, despite its name, contains the UTF-8 byte encodings of + // the resource names of ALL the documents that match + // [target_id][google.firestore.v1.ExistenceFilter.target_id], in the form + // `projects/{project_id}/databases/{database_id}/documents/{document_path}`. // // This bloom filter may be omitted at the server's discretion, such as if it // is deemed that the client will not make use of it or if it is too diff --git a/packages/firestore/src/protos/google/protobuf/any.proto b/packages/firestore/src/protos/google/protobuf/any.proto index c9be854167..e95b5b49cf 100644 --- a/packages/firestore/src/protos/google/protobuf/any.proto +++ b/packages/firestore/src/protos/google/protobuf/any.proto @@ -32,124 +32,75 @@ syntax = "proto3"; package google.protobuf; -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option go_package = "github.com/golang/protobuf/ptypes/any"; +option go_package = "google.golang.org/protobuf/types/known/anypb"; option java_package = "com.google.protobuf"; option java_outer_classname = "AnyProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; // `Any` contains an arbitrary serialized protocol buffer message along with a // URL that describes the type of the serialized message. // -// Protobuf library provides support to pack/unpack Any values in the form -// of utility functions or additional generated methods of the Any type. -// -// Example 1: Pack and unpack a message in C++. -// -// Foo foo = ...; -// Any any; -// any.PackFrom(foo); -// ... -// if (any.UnpackTo(&foo)) { -// ... -// } -// -// Example 2: Pack and unpack a message in Java. -// -// Foo foo = ...; -// Any any = Any.pack(foo); -// ... -// if (any.is(Foo.class)) { -// foo = any.unpack(Foo.class); -// } -// -// Example 3: Pack and unpack a message in Python. -// -// foo = Foo(...) -// any = Any() -// any.Pack(foo) -// ... -// if any.Is(Foo.DESCRIPTOR): -// any.Unpack(foo) -// ... -// -// Example 4: Pack and unpack a message in Go -// -// foo := &pb.Foo{...} -// any, err := ptypes.MarshalAny(foo) -// ... -// foo := &pb.Foo{} -// if err := ptypes.UnmarshalAny(any, foo); err != nil { -// ... -// } -// -// The pack methods provided by protobuf library will by default use -// 'type.googleapis.com/full.type.name' as the type URL and the unpack -// methods only use the fully qualified type name after the last '/' -// in the type URL, for example "foo.bar.com/x/y.z" will yield type -// name "y.z". -// -// -// JSON -// ==== -// The JSON representation of an `Any` value uses the regular -// representation of the deserialized, embedded message, with an -// additional field `@type` which contains the type URL. Example: -// -// package google.profile; -// message Person { -// string first_name = 1; -// string last_name = 2; -// } -// -// { -// "@type": "type.googleapis.com/google.profile.Person", -// "firstName": , -// "lastName": -// } -// -// If the embedded message type is well-known and has a custom JSON -// representation, that representation will be embedded adding a field -// `value` which holds the custom JSON in addition to the `@type` -// field. Example (for message [google.protobuf.Duration][]): -// -// { -// "@type": "type.googleapis.com/google.protobuf.Duration", -// "value": "1.212s" -// } -// +// In its binary encoding, an `Any` is an ordinary message; but in other wire +// forms like JSON, it has a special encoding. The format of the type URL is +// described on the `type_url` field. +// +// Protobuf APIs provide utilities to interact with `Any` values: +// +// - A 'pack' operation accepts a message and constructs a generic `Any` wrapper +// around it. +// - An 'unpack' operation reads the content of an `Any` message, either into an +// existing message or a new one. Unpack operations must check the type of the +// value they unpack against the declared `type_url`. +// - An 'is' operation decides whether an `Any` contains a message of the given +// type, i.e. whether it can 'unpack' that type. +// +// The JSON format representation of an `Any` follows one of these cases: +// +// - For types without special-cased JSON encodings, the JSON format +// representation of the `Any` is the same as that of the message, with an +// additional `@type` field which contains the type URL. +// - For types with special-cased JSON encodings (typically called 'well-known' +// types, listed in https://protobuf.dev/programming-guides/json/#any), the +// JSON format representation has a key `@type` which contains the type URL +// and a key `value` which contains the JSON-serialized value. +// +// The text format representation of an `Any` is like a message with one field +// whose name is the type URL in brackets. For example, an `Any` containing a +// `foo.Bar` message may be written `[type.googleapis.com/foo.Bar] { a: 2 }`. message Any { - // A URL/resource name that uniquely identifies the type of the serialized - // protocol buffer message. This string must contain at least - // one "/" character. The last segment of the URL's path must represent - // the fully qualified name of the type (as in - // `path/google.protobuf.Duration`). The name should be in a canonical form - // (e.g., leading "." is not accepted). + // Identifies the type of the serialized Protobuf message with a URI reference + // consisting of a prefix ending in a slash and the fully-qualified type name. // - // In practice, teams usually precompile into the binary all types that they - // expect it to use in the context of Any. However, for URLs which use the - // scheme `http`, `https`, or no scheme, one can optionally set up a type - // server that maps type URLs to message definitions as follows: + // Example: type.googleapis.com/google.protobuf.StringValue // - // * If no scheme is provided, `https` is assumed. - // * An HTTP GET on the URL must yield a [google.protobuf.Type][] - // value in binary format, or produce an error. - // * Applications are allowed to cache lookup results based on the - // URL, or have them precompiled into a binary to avoid any - // lookup. Therefore, binary compatibility needs to be preserved - // on changes to types. (Use versioned type names to manage - // breaking changes.) + // This string must contain at least one `/` character, and the content after + // the last `/` must be the fully-qualified name of the type in canonical + // form, without a leading dot. Do not write a scheme on these URI references + // so that clients do not attempt to contact them. // - // Note: this functionality is not currently available in the official - // protobuf release, and it is not used for type URLs beginning with - // type.googleapis.com. + // The prefix is arbitrary and Protobuf implementations are expected to + // simply strip off everything up to and including the last `/` to identify + // the type. `type.googleapis.com/` is a common default prefix that some + // legacy implementations require. This prefix does not indicate the origin of + // the type, and URIs containing it are not expected to respond to any + // requests. // - // Schemes other than `http`, `https` (or the empty scheme) might be - // used with implementation specific semantics. + // All type URL strings must be legal URI references with the additional + // restriction (for the text format) that the content of the reference + // must consist only of alphanumeric characters, percent-encoded escapes, and + // characters in the following set (not including the outer backticks): + // `/-.~_!$&()*+,;=`. Despite our allowing percent encodings, implementations + // should not unescape them to prevent confusion with existing parsers. For + // example, `type.googleapis.com%2FFoo` should be rejected. // + // In the original design of `Any`, the possibility of launching a type + // resolution service at these type URLs was considered but Protobuf never + // implemented one and considers contacting these URLs to be problematic and + // a potential security issue. Do not attempt to contact type URLs. string type_url = 1; - // Must be a valid serialized protocol buffer of the above specified type. + // Holds a Protobuf serialization of the type described by type_url. bytes value = 2; } diff --git a/packages/firestore/src/protos/google/protobuf/descriptor.proto b/packages/firestore/src/protos/google/protobuf/descriptor.proto index d5d794f5a3..25dddc0999 100644 --- a/packages/firestore/src/protos/google/protobuf/descriptor.proto +++ b/packages/firestore/src/protos/google/protobuf/descriptor.proto @@ -1,32 +1,9 @@ // Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// Copyright 2008 Google LLC. All rights reserved. // -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by @@ -36,12 +13,11 @@ // A valid .proto file can be translated directly to a FileDescriptorProto // without any other information (e.g. without reading its imports). - syntax = "proto2"; package google.protobuf; -option go_package = "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor"; +option go_package = "google.golang.org/protobuf/types/descriptorpb"; option java_package = "com.google.protobuf"; option java_outer_classname = "DescriptorProtos"; option csharp_namespace = "Google.Protobuf.Reflection"; @@ -56,6 +32,53 @@ option optimize_for = SPEED; // files it parses. message FileDescriptorSet { repeated FileDescriptorProto file = 1; + + // Extensions for tooling. + extensions 536000000 [declaration = { + number: 536000000 + type: ".buf.descriptor.v1.FileDescriptorSetExtension" + full_name: ".buf.descriptor.v1.buf_file_descriptor_set_extension" + }]; +} + +// The full set of known editions. +enum Edition { + // A placeholder for an unknown edition value. + EDITION_UNKNOWN = 0; + + // A placeholder edition for specifying default behaviors *before* a feature + // was first introduced. This is effectively an "infinite past". + EDITION_LEGACY = 900; + + // Legacy syntax "editions". These pre-date editions, but behave much like + // distinct editions. These can't be used to specify the edition of proto + // files, but feature definitions must supply proto2/proto3 defaults for + // backwards compatibility. + EDITION_PROTO2 = 998; + EDITION_PROTO3 = 999; + + // Editions that have been released. The specific values are arbitrary and + // should not be depended on, but they will always be time-ordered for easy + // comparison. + EDITION_2023 = 1000; + EDITION_2024 = 1001; + EDITION_2026 = 1002; + + // A placeholder edition for developing and testing unscheduled features. + EDITION_UNSTABLE = 9999; + + // Placeholder editions for testing feature resolution. These should not be + // used or relied on outside of tests. + EDITION_1_TEST_ONLY = 1; + EDITION_2_TEST_ONLY = 2; + EDITION_99997_TEST_ONLY = 99997; + EDITION_99998_TEST_ONLY = 99998; + EDITION_99999_TEST_ONLY = 99999; + + // Placeholder for specifying unbounded edition support. This should only + // ever be used by plugins that can expect to never require any changes to + // support a new edition. + EDITION_MAX = 0x7FFFFFFF; } // Describes a complete .proto file. @@ -71,6 +94,10 @@ message FileDescriptorProto { // For Google-internal migration only. Do not use. repeated int32 weak_dependency = 11; + // Names of files imported by this file purely for the purpose of providing + // option extensions. These are excluded from the dependency list above. + repeated string option_dependency = 15; + // All top-level definitions in this file. repeated DescriptorProto message_type = 4; repeated EnumDescriptorProto enum_type = 5; @@ -86,8 +113,19 @@ message FileDescriptorProto { optional SourceCodeInfo source_code_info = 9; // The syntax of the proto file. - // The supported values are "proto2" and "proto3". + // The supported values are "proto2", "proto3", and "editions". + // + // If `edition` is present, this value must be "editions". + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. optional string syntax = 12; + + // The edition of the proto file. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional Edition edition = 14; } // Describes a message type. @@ -101,8 +139,8 @@ message DescriptorProto { repeated EnumDescriptorProto enum_type = 4; message ExtensionRange { - optional int32 start = 1; - optional int32 end = 2; + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. optional ExtensionRangeOptions options = 3; } @@ -123,12 +161,64 @@ message DescriptorProto { // Reserved field names, which may not be used by fields in the same message. // A given name may only be reserved once. repeated string reserved_name = 10; + + // Support for `export` and `local` keywords on enums. + optional SymbolVisibility visibility = 11; } message ExtensionRangeOptions { + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; + message Declaration { + // The extension number declared within the extension range. + optional int32 number = 1; + + // The fully-qualified name of the extension field. There must be a leading + // dot in front of the full name. + optional string full_name = 2; + + // The fully-qualified type name of the extension field. Unlike + // Metadata.type, Declaration.type must have a leading dot for messages + // and enums. + optional string type = 3; + + // If true, indicates that the number is reserved in the extension range, + // and any extension field with the number will fail to compile. Set this + // when a declared extension field is deleted. + optional bool reserved = 5; + + // If true, indicates that the extension must be defined as repeated. + // Otherwise the extension must be defined as optional. + optional bool repeated = 6; + + reserved 4; // removed is_repeated + } + + // For external users: DO NOT USE. We are in the process of open sourcing + // extension declaration and executing internal cleanups before it can be + // used externally. + repeated Declaration declaration = 2 [retention = RETENTION_SOURCE]; + + // Any features defined in the specific edition. + optional FeatureSet features = 50; + + // The verification state of the extension range. + enum VerificationState { + // All the extensions of the range must be declared. + DECLARATION = 0; + UNVERIFIED = 1; + } + + // The verification state of the range. + // TODO: flip the default to DECLARATION once all empty ranges + // are marked as UNVERIFIED. + optional VerificationState verification = 3 + [default = UNVERIFIED, retention = RETENTION_SOURCE]; + // Clients can define custom options in extensions of this message. See above. extensions 1000 to max; } @@ -152,9 +242,10 @@ message FieldDescriptorProto { TYPE_BOOL = 8; TYPE_STRING = 9; // Tag-delimited aggregate. - // Group type is deprecated and not supported in proto3. However, Proto3 + // Group type is deprecated and not supported after google.protobuf. However, Proto3 // implementations should still be able to parse the group wire format and - // treat group fields as unknown fields. + // treat group fields as unknown fields. In Editions, the group wire format + // can be enabled via the `message_encoding` feature. TYPE_GROUP = 10; TYPE_MESSAGE = 11; // Length-delimited aggregate. @@ -171,8 +262,11 @@ message FieldDescriptorProto { enum Label { // 0 is reserved for errors LABEL_OPTIONAL = 1; - LABEL_REQUIRED = 2; LABEL_REPEATED = 3; + // The required label is only allowed in google.protobuf. In proto3 and Editions + // it's explicitly prohibited. In Editions, the `field_presence` feature + // can be used to get this behavior. + LABEL_REQUIRED = 2; } optional string name = 1; @@ -198,7 +292,6 @@ message FieldDescriptorProto { // For booleans, "true" or "false". // For strings, contains the default text contents (not escaped in any way). // For bytes, contains the C escaped value. All bytes >= 128 are escaped. - // TODO(kenton): Base-64 encode? optional string default_value = 7; // If set, gives the index of a oneof in the containing type's oneof_decl @@ -212,6 +305,29 @@ message FieldDescriptorProto { optional string json_name = 10; optional FieldOptions options = 8; + + // If true, this is a proto3 "optional". When a proto3 field is optional, it + // tracks presence regardless of field type. + // + // When proto3_optional is true, this field must belong to a oneof to signal + // to old proto3 clients that presence is tracked for this field. This oneof + // is known as a "synthetic" oneof, and this field must be its sole member + // (each proto3 optional field gets its own synthetic oneof). Synthetic oneofs + // exist in the descriptor only, and do not generate any API. Synthetic oneofs + // must be ordered after all "real" oneofs. + // + // For message fields, proto3_optional doesn't create any semantic change, + // since non-repeated message fields always track presence. However it still + // indicates the semantic detail of whether the user wrote "optional" or not. + // This can be useful for round-tripping the .proto file. For consistency we + // give message fields a synthetic oneof also, even though it is not required + // to track presence. This is especially important because the parser can't + // tell if a field is a message or an enum, so it must always create a + // synthetic oneof. + // + // Proto2 optional fields do not set this flag, because they already indicate + // optional with `LABEL_OPTIONAL`. + optional bool proto3_optional = 17; } // Describes a oneof. @@ -247,6 +363,9 @@ message EnumDescriptorProto { // Reserved enum value names, which may not be reused. A given name may only // be reserved once. repeated string reserved_name = 5; + + // Support for `export` and `local` keywords on enums. + optional SymbolVisibility visibility = 6; } // Describes a value within an enum. @@ -263,6 +382,9 @@ message ServiceDescriptorProto { repeated MethodDescriptorProto method = 2; optional ServiceOptions options = 3; + + reserved 4; + reserved "stream"; } // Describes a method of a service. @@ -282,7 +404,6 @@ message MethodDescriptorProto { optional bool server_streaming = 6 [default = false]; } - // =================================================================== // Options @@ -323,34 +444,46 @@ message FileOptions { // domain names. optional string java_package = 1; - - // If set, all the classes from the .proto file are wrapped in a single - // outer class with the given name. This applies to both Proto1 - // (equivalent to the old "--one_java_file" option) and Proto2 (where - // a .proto always translates to a single class, but you may want to - // explicitly choose the class name). + // Controls the name of the wrapper Java class generated for the .proto file. + // That class will always contain the .proto file's getDescriptor() method as + // well as any top-level extensions defined in the .proto file. + // If java_multiple_files is disabled, then all the other classes from the + // .proto file will be nested inside the single wrapper outer class. optional string java_outer_classname = 8; - // If set true, then the Java code generator will generate a separate .java + // If enabled, then the Java code generator will generate a separate .java // file for each top-level message, enum, and service defined in the .proto - // file. Thus, these types will *not* be nested inside the outer class - // named by java_outer_classname. However, the outer class will still be + // file. Thus, these types will *not* be nested inside the wrapper class + // named by java_outer_classname. However, the wrapper class will still be // generated to contain the file's getDescriptor() method as well as any // top-level extensions defined in the file. - optional bool java_multiple_files = 10 [default = false]; + optional bool java_multiple_files = 10 [ + default = false, + feature_support = { + edition_introduced: EDITION_PROTO2 + edition_removed: EDITION_2024 + removal_error: "This behavior is enabled by default in editions 2024 and above. " + "To disable it, you can set `features.(pb.java).nest_in_file_class = YES` " + "on individual messages, enums, or services." + + } + ]; // This option does nothing. optional bool java_generate_equals_and_hash = 20 [deprecated=true]; - // If set true, then the Java2 code generator will generate code that - // throws an exception whenever an attempt is made to assign a non-UTF-8 - // byte sequence to a string field. - // Message reflection will do the same. - // However, an extension field still accepts non-UTF-8 byte sequences. - // This option has no effect on when used with the lite runtime. + // A proto2 file can set this to true to opt in to UTF-8 checking for Java, + // which will throw an exception if invalid UTF-8 is parsed from the wire or + // assigned to a string field. + // + // TODO: clarify exactly what kinds of field types this option + // applies to, and update these docs accordingly. + // + // Proto3 files already perform these checks. Setting the option explicitly to + // false has no effect: it cannot be used to opt proto3 files out of UTF-8 + // checks. optional bool java_string_check_utf8 = 27 [default = false]; - // Generated classes can be optimized for speed or code size. enum OptimizeMode { SPEED = 1; // Generate complete code for parsing, serialization, @@ -367,8 +500,6 @@ message FileOptions { // - Otherwise, the basename of the .proto file, without extension. optional string go_package = 11; - - // Should generic services be generated in each language? "Generic" services // are not specific to any particular RPC system. They are generated by the // main code generators in each language (without additional plugins). @@ -382,7 +513,8 @@ message FileOptions { optional bool cc_generic_services = 16 [default = false]; optional bool java_generic_services = 17 [default = false]; optional bool py_generic_services = 18 [default = false]; - optional bool php_generic_services = 42 [default = false]; + reserved 42; // removed php_generic_services + reserved "php_generic_services"; // Is this file deprecated? // Depending on the target platform, this can emit Deprecated annotations @@ -392,8 +524,7 @@ message FileOptions { // Enables the use of arenas for the proto messages in this file. This applies // only to generated classes for C++. - optional bool cc_enable_arenas = 31 [default = false]; - + optional bool cc_enable_arenas = 31 [default = true]; // Sets the objective c class prefix which is prepended to all objective c // generated classes from this .proto. There is no default. @@ -427,6 +558,20 @@ message FileOptions { // determining the ruby package. optional string ruby_package = 45; + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 50; + + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998 [declaration = { + number: 990, + full_name: ".pb.file.cpp", + type: ".pb.file.CppFileOptions" + }]; + // The parser stores options it doesn't recognize here. // See the documentation for the "Options" section above. repeated UninterpretedOption uninterpreted_option = 999; @@ -470,6 +615,8 @@ message MessageOptions { // this is a formalization for deprecating messages. optional bool deprecated = 3 [default = false]; + reserved 4, 5, 6; + // Whether the message is an automatically generated map entry type for the // maps field. // @@ -496,6 +643,28 @@ message MessageOptions { reserved 8; // javalite_serializable reserved 9; // javanano_as_lite + // Enable the legacy handling of JSON field name conflicts. This lowercases + // and strips underscored from the fields before comparison in proto3 only. + // The new behavior takes `json_name` into account and applies to proto2 as + // well. + // + // This should only be used as a temporary measure against broken builds due + // to the change in behavior for JSON field name conflicts. + // + // TODO This is legacy behavior we plan to remove once downstream + // teams have had time to migrate. + optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated = true]; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 12; + + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -504,15 +673,24 @@ message MessageOptions { } message FieldOptions { + // NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. // The ctype option instructs the C++ code generator to use a different // representation of the field than it normally would. See the specific - // options below. This option is not yet implemented in the open source - // release -- sorry, we'll try to include it in a future version! - optional CType ctype = 1 [default = STRING]; + // options below. This option is only implemented to support use of + // [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of + // type "bytes" in the open source release. + // TODO: make ctype actually deprecated. + optional CType ctype = 1 [/*deprecated = true,*/ default = STRING]; enum CType { // Default mode. STRING = 0; + // The option [ctype=CORD] may be applied to a non-repeated field of type + // "bytes". It indicates that in C++, the data should be stored in a Cord + // instead of a string. For very large strings, this may reduce memory + // fragmentation. It may also allow better performance when parsing from a + // Cord, or when parsing with aliasing enabled, as the parsed Cord may then + // alias the original buffer. CORD = 1; STRING_PIECE = 2; @@ -521,7 +699,9 @@ message FieldOptions { // a more efficient representation on the wire. Rather than repeatedly // writing the tag and type for each element, the entire array is encoded as // a single length-delimited blob. In proto3, only explicit setting it to - // false will avoid using packed encoding. + // false will avoid using packed encoding. This option is prohibited in + // Editions, but the `repeated_field_encoding` feature can be used to control + // the behavior. optional bool packed = 2; // The jstype option determines the JavaScript type used for values of the @@ -564,28 +744,100 @@ message FieldOptions { // call from multiple threads concurrently, while non-const methods continue // to require exclusive access. // - // - // Note that implementations may choose not to check required fields within - // a lazy sub-message. That is, calling IsInitialized() on the outer message - // may return true even if the inner message has missing required fields. - // This is necessary because otherwise the inner message would have to be - // parsed in order to perform the check, defeating the purpose of lazy - // parsing. An implementation which chooses not to check required fields - // must be consistent about it. That is, for any particular sub-message, the - // implementation must either *always* check its required fields, or *never* - // check its required fields, regardless of whether or not the message has - // been parsed. + // Note that lazy message fields are still eagerly verified to check + // ill-formed wireformat or missing required fields. Calling IsInitialized() + // on the outer message would fail if the inner message has missing required + // fields. Failed verification would result in parsing failure (except when + // uninitialized messages are acceptable). optional bool lazy = 5 [default = false]; + // unverified_lazy does no correctness checks on the byte stream. This should + // only be used where lazy with verification is prohibitive for performance + // reasons. + optional bool unverified_lazy = 15 [default = false]; + // Is this field deprecated? // Depending on the target platform, this can emit Deprecated annotations // for accessors, or it will be completely ignored; in the very least, this // is a formalization for deprecating fields. optional bool deprecated = 3 [default = false]; + // DEPRECATED. DO NOT USE! // For Google-internal migration only. Do not use. - optional bool weak = 10 [default = false]; + optional bool weak = 10 [default = false, deprecated = true]; + + // Indicate that the field value should not be printed out when using debug + // formats, e.g. when the field contains sensitive credentials. + optional bool debug_redact = 16 [default = false]; + + // If set to RETENTION_SOURCE, the option will be omitted from the binary. + enum OptionRetention { + RETENTION_UNKNOWN = 0; + RETENTION_RUNTIME = 1; + RETENTION_SOURCE = 2; + } + + optional OptionRetention retention = 17; + + // This indicates the types of entities that the field may apply to when used + // as an option. If it is unset, then the field may be freely used as an + // option on any kind of entity. + enum OptionTargetType { + TARGET_TYPE_UNKNOWN = 0; + TARGET_TYPE_FILE = 1; + TARGET_TYPE_EXTENSION_RANGE = 2; + TARGET_TYPE_MESSAGE = 3; + TARGET_TYPE_FIELD = 4; + TARGET_TYPE_ONEOF = 5; + TARGET_TYPE_ENUM = 6; + TARGET_TYPE_ENUM_ENTRY = 7; + TARGET_TYPE_SERVICE = 8; + TARGET_TYPE_METHOD = 9; + } + + repeated OptionTargetType targets = 19; + + message EditionDefault { + optional Edition edition = 3; + optional string value = 2; // Textproto value. + } + repeated EditionDefault edition_defaults = 20; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 21; + + // Information about the support window of a feature. + message FeatureSupport { + // The edition that this feature was first available in. In editions + // earlier than this one, the default assigned to EDITION_LEGACY will be + // used, and proto files will not be able to override it. + optional Edition edition_introduced = 1; + + // The edition this feature becomes deprecated in. Using this after this + // edition may trigger warnings. + optional Edition edition_deprecated = 2; + + // The deprecation warning text if this feature is used after the edition it + // was marked deprecated in. + optional string deprecation_warning = 3; + + // The edition this feature is no longer available in. In editions after + // this one, the last default assigned will be used, and proto files will + // not be able to override it. + optional Edition edition_removed = 4; + + // The removal error text if this feature is used after the edition it was + // removed in. + optional string removal_error = 5; + } + optional FeatureSupport feature_support = 22; + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -593,10 +845,21 @@ message FieldOptions { // Clients can define custom options in extensions of this message. See above. extensions 1000 to max; - reserved 4; // removed jtype + reserved 4; // removed jtype + reserved 18; // reserve target, target_obsolete_do_not_use } message OneofOptions { + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 1; + + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -618,6 +881,24 @@ message EnumOptions { reserved 5; // javanano_as_lite + // Enable the legacy handling of JSON field name conflicts. This lowercases + // and strips underscored from the fields before comparison in proto3 only. + // The new behavior takes `json_name` into account and applies to proto2 as + // well. + // TODO Remove this legacy behavior once downstream teams have + // had time to migrate. + optional bool deprecated_legacy_json_field_conflicts = 6 [deprecated = true]; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 7; + + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -632,6 +913,24 @@ message EnumValueOptions { // this is a formalization for deprecating enum values. optional bool deprecated = 1 [default = false]; + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 2; + + // Indicate that fields annotated with this enum value should not be printed + // out when using debug formats, e.g. when the field contains sensitive + // credentials. + optional bool debug_redact = 3 [default = false]; + + // Information about the support window of a feature value. + optional FieldOptions.FeatureSupport feature_support = 4; + + // Range reserved for first-class extension options defined by the Protobuf + // team. Custom options must use the 1000+ range instead. + extensions 990 to 998; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -641,6 +940,12 @@ message EnumValueOptions { message ServiceOptions { + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 34; + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC // framework. We apologize for hoarding these numbers to ourselves, but // we were already using them long before we decided to release Protocol @@ -652,6 +957,10 @@ message ServiceOptions { // this is a formalization for deprecating services. optional bool deprecated = 33 [default = false]; + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -683,6 +992,16 @@ message MethodOptions { optional IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 35; + + // Range reserved for first-class custom options defined by the Protobuf + // team. User custom options must use the 1000+ range instead. + extensions 990 to 998; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -690,7 +1009,6 @@ message MethodOptions { extensions 1000 to max; } - // A message representing a option the parser does not recognize. This only // appears in options protos created by the compiler::Parser class. // DescriptorPool resolves these when building Descriptor objects. Therefore, @@ -701,8 +1019,8 @@ message UninterpretedOption { // The name of the uninterpreted option. Each string represents a segment in // a dot-separated name. is_extension is true iff a segment represents an // extension (denoted with parentheses in options specs in .proto files). - // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents - // "foo.(bar.baz).qux". + // E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents + // "foo.(bar.baz).moo". message NamePart { required string name_part = 1; required bool is_extension = 2; @@ -719,6 +1037,248 @@ message UninterpretedOption { optional string aggregate_value = 8; } +// =================================================================== +// Features + +// TODO Enums in C++ gencode (and potentially other languages) are +// not well scoped. This means that each of the feature enums below can clash +// with each other. The short names we've chosen maximize call-site +// readability, but leave us very open to this scenario. A future feature will +// be designed and implemented to handle this, hopefully before we ever hit a +// conflict here. +message FeatureSet { + enum FieldPresence { + FIELD_PRESENCE_UNKNOWN = 0; + EXPLICIT = 1; + IMPLICIT = 2; + LEGACY_REQUIRED = 3; + } + optional FieldPresence field_presence = 1 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPLICIT" }, + edition_defaults = { edition: EDITION_PROTO3, value: "IMPLICIT" }, + edition_defaults = { edition: EDITION_2023, value: "EXPLICIT" } + ]; + + enum EnumType { + ENUM_TYPE_UNKNOWN = 0; + OPEN = 1; + CLOSED = 2; + } + optional EnumType enum_type = 2 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "CLOSED" }, + edition_defaults = { edition: EDITION_PROTO3, value: "OPEN" } + ]; + + enum RepeatedFieldEncoding { + REPEATED_FIELD_ENCODING_UNKNOWN = 0; + PACKED = 1; + EXPANDED = 2; + } + optional RepeatedFieldEncoding repeated_field_encoding = 3 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPANDED" }, + edition_defaults = { edition: EDITION_PROTO3, value: "PACKED" } + ]; + + enum Utf8Validation { + UTF8_VALIDATION_UNKNOWN = 0; + VERIFY = 2; + NONE = 3; + reserved 1; + } + optional Utf8Validation utf8_validation = 4 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "NONE" }, + edition_defaults = { edition: EDITION_PROTO3, value: "VERIFY" } + ]; + + enum MessageEncoding { + MESSAGE_ENCODING_UNKNOWN = 0; + LENGTH_PREFIXED = 1; + DELIMITED = 2; + } + optional MessageEncoding message_encoding = 5 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "LENGTH_PREFIXED" } + ]; + + enum JsonFormat { + JSON_FORMAT_UNKNOWN = 0; + ALLOW = 1; + LEGACY_BEST_EFFORT = 2; + } + optional JsonFormat json_format = 6 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "LEGACY_BEST_EFFORT" }, + edition_defaults = { edition: EDITION_PROTO3, value: "ALLOW" } + ]; + + enum EnforceNamingStyle { + ENFORCE_NAMING_STYLE_UNKNOWN = 0; + STYLE2024 = 1; + STYLE_LEGACY = 2; + STYLE2026 = 3; + } + optional EnforceNamingStyle enforce_naming_style = 7 [ + retention = RETENTION_SOURCE, + targets = TARGET_TYPE_FILE, + targets = TARGET_TYPE_EXTENSION_RANGE, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_ONEOF, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_ENUM_ENTRY, + targets = TARGET_TYPE_SERVICE, + targets = TARGET_TYPE_METHOD, + feature_support = { + edition_introduced: EDITION_2024, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "STYLE_LEGACY" }, + edition_defaults = { edition: EDITION_2024, value: "STYLE2024" }, + edition_defaults = { edition: EDITION_UNSTABLE, value: "STYLE2026" } + ]; + + message VisibilityFeature { + enum DefaultSymbolVisibility { + DEFAULT_SYMBOL_VISIBILITY_UNKNOWN = 0; + + // Default pre-EDITION_2024, all UNSET visibility are export. + EXPORT_ALL = 1; + + // All top-level symbols default to export, nested default to local. + EXPORT_TOP_LEVEL = 2; + + // All symbols default to local. + LOCAL_ALL = 3; + + // All symbols local by default. Nested types cannot be exported. + // With special case caveat for message { enum {} reserved 1 to max; } + // This is the recommended setting for new protos. + STRICT = 4; + } + reserved 1 to max; + } + optional VisibilityFeature.DefaultSymbolVisibility default_symbol_visibility = + 8 [ + retention = RETENTION_SOURCE, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2024, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPORT_ALL" }, + edition_defaults = { edition: EDITION_2024, value: "EXPORT_TOP_LEVEL" } + ]; + + reserved 999; + + extensions 1000 to 9994 [ + declaration = { + number: 1000, + full_name: ".pb.cpp", + type: ".pb.CppFeatures" + }, + declaration = { + number: 1001, + full_name: ".pb.java", + type: ".pb.JavaFeatures" + }, + declaration = { number: 1002, full_name: ".pb.go", type: ".pb.GoFeatures" }, + declaration = { + number: 1003, + full_name: ".pb.python", + type: ".pb.PythonFeatures" + }, + declaration = { + number: 1004, + full_name: ".pb.csharp", + type: ".pb.CSharpFeatures" + }, + declaration = { + number: 1100, + full_name: ".imp.impress_feature_set", + type: ".imp.ImpressFeatureSet" + }, + declaration = { + number: 9989, + full_name: ".pb.java_mutable", + type: ".pb.JavaMutableFeatures" + }, + declaration = { + number: 9990, + full_name: ".pb.proto1", + type: ".pb.Proto1Features" + } + ]; + + extensions 9995 to 9999; // For internal testing + extensions 10000; // for https://github.com/bufbuild/protobuf-es +} + +// A compiled specification for the defaults of a set of features. These +// messages are generated from FeatureSet extensions and can be used to seed +// feature resolution. The resolution with this object becomes a simple search +// for the closest matching edition, followed by proto merges. +message FeatureSetDefaults { + // A map from every known edition with a unique set of defaults to its + // defaults. Not all editions may be contained here. For a given edition, + // the defaults at the closest matching edition ordered at or before it should + // be used. This field must be in strict ascending order by edition. + message FeatureSetEditionDefault { + optional Edition edition = 3; + + // Defaults of features that can be overridden in this edition. + optional FeatureSet overridable_features = 4; + + // Defaults of features that can't be overridden in this edition. + optional FeatureSet fixed_features = 5; + + reserved 1, 2; + reserved "features"; + } + repeated FeatureSetEditionDefault defaults = 1; + + // The minimum supported edition (inclusive) when this was constructed. + // Editions before this will not have defaults. + optional Edition minimum_edition = 4; + + // The maximum known edition (inclusive) when this was constructed. Editions + // after this will not have reliable defaults. + optional Edition maximum_edition = 5; +} + // =================================================================== // Optional source code info @@ -774,8 +1334,8 @@ message SourceCodeInfo { // location. // // Each element is a field number or an index. They form a path from - // the root FileDescriptorProto to the place where the definition. For - // example, this path: + // the root FileDescriptorProto to the place where the definition appears. + // For example, this path: // [ 4, 3, 2, 7, 1 ] // refers to: // file.message_type(3) // 4, 3 @@ -829,13 +1389,13 @@ message SourceCodeInfo { // // Comment attached to baz. // // Another line attached to baz. // - // // Comment attached to qux. + // // Comment attached to moo. // // - // // Another line attached to qux. - // optional double qux = 4; + // // Another line attached to moo. + // optional double moo = 4; // // // Detached comment for corge. This is not leading or trailing comments - // // to qux or corge because there are blank lines separating it from + // // to moo or corge because there are blank lines separating it from // // both. // // // Detached comment for corge paragraph 2. @@ -853,6 +1413,13 @@ message SourceCodeInfo { optional string trailing_comments = 4; repeated string leading_detached_comments = 6; } + + // Extensions for tooling. + extensions 536000000 [declaration = { + number: 536000000 + type: ".buf.descriptor.v1.SourceCodeInfoExtension" + full_name: ".buf.descriptor.v1.buf_source_code_info_extension" + }]; } // Describes the relationship between generated code and its original source @@ -875,8 +1442,31 @@ message GeneratedCodeInfo { optional int32 begin = 3; // Identifies the ending offset in bytes in the generated code that - // relates to the identified offset. The end offset should be one past + // relates to the identified object. The end offset should be one past // the last relevant byte (so the length of the text = end - begin). optional int32 end = 4; + + // Represents the identified object's effect on the element in the original + // .proto file. + enum Semantic { + // There is no effect or the effect is indescribable. + NONE = 0; + // The element is set or otherwise mutated. + SET = 1; + // An alias to the element is returned. + ALIAS = 2; + } + optional Semantic semantic = 5; } } + +// Describes the 'visibility' of a symbol with respect to the proto import +// system. Symbols can only be imported when the visibility rules do not prevent +// it (ex: local symbols cannot be imported). Visibility modifiers can only set +// on `message` and `enum` as they are the only types available to be referenced +// from other files. +enum SymbolVisibility { + VISIBILITY_UNSET = 0; + VISIBILITY_LOCAL = 1; + VISIBILITY_EXPORT = 2; +} diff --git a/packages/firestore/src/protos/google/protobuf/empty.proto b/packages/firestore/src/protos/google/protobuf/empty.proto index 03cacd2330..b87c89dcfc 100644 --- a/packages/firestore/src/protos/google/protobuf/empty.proto +++ b/packages/firestore/src/protos/google/protobuf/empty.proto @@ -32,12 +32,12 @@ syntax = "proto3"; package google.protobuf; -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option go_package = "github.com/golang/protobuf/ptypes/empty"; +option go_package = "google.golang.org/protobuf/types/known/emptypb"; option java_package = "com.google.protobuf"; option java_outer_classname = "EmptyProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; // A generic empty message that you can re-use to avoid defining duplicated @@ -48,5 +48,4 @@ option cc_enable_arenas = true; // rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); // } // -// The JSON representation for `Empty` is empty JSON object `{}`. message Empty {} diff --git a/packages/firestore/src/protos/google/protobuf/struct.proto b/packages/firestore/src/protos/google/protobuf/struct.proto index 7d7808e7fb..a03667da4e 100644 --- a/packages/firestore/src/protos/google/protobuf/struct.proto +++ b/packages/firestore/src/protos/google/protobuf/struct.proto @@ -32,64 +32,79 @@ syntax = "proto3"; package google.protobuf; -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/struct;structpb"; +option go_package = "google.golang.org/protobuf/types/known/structpb"; option java_package = "com.google.protobuf"; option java_outer_classname = "StructProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; - -// `Struct` represents a structured data value, consisting of fields -// which map to dynamically typed values. In some languages, `Struct` -// might be supported by a native representation. For example, in -// scripting languages like JS a struct is represented as an -// object. The details of that representation are described together -// with the proto support for the language. +// Represents a JSON object. +// +// An unordered key-value map, intending to perfectly capture the semantics of a +// JSON object. This enables parsing any arbitrary JSON payload as a message +// field in ProtoJSON format. // -// The JSON representation for `Struct` is JSON object. +// This follows RFC 8259 guidelines for interoperable JSON: notably this type +// cannot represent large Int64 values or `NaN`/`Infinity` numbers, +// since the JSON format generally does not support those values in its number +// type. +// +// If you do not intend to parse arbitrary JSON into your message, a custom +// typed message should be preferred instead of using this type. message Struct { // Unordered map of dynamically typed values. map fields = 1; } +// Represents a JSON value. +// // `Value` represents a dynamically typed value which can be either // null, a number, a string, a boolean, a recursive struct value, or a -// list of values. A producer of value is expected to set one of that -// variants, absence of any variant indicates an error. -// -// The JSON representation for `Value` is JSON value. +// list of values. A producer of value is expected to set one of these +// variants. Absence of any variant is an invalid state. message Value { // The kind of value. oneof kind { - // Represents a null value. + // Represents a JSON `null`. NullValue null_value = 1; - // Represents a double value. + + // Represents a JSON number. Must not be `NaN`, `Infinity` or + // `-Infinity`, since those are not supported in JSON. This also cannot + // represent large Int64 values, since JSON format generally does not + // support them in its number type. double number_value = 2; - // Represents a string value. + + // Represents a JSON string. string string_value = 3; - // Represents a boolean value. + + // Represents a JSON boolean (`true` or `false` literal in JSON). bool bool_value = 4; - // Represents a structured value. + + // Represents a JSON object. Struct struct_value = 5; - // Represents a repeated `Value`. + + // Represents a JSON array. ListValue list_value = 6; } } -// `NullValue` is a singleton enumeration to represent the null value for the -// `Value` type union. +// Represents a JSON `null`. +// +// `NullValue` is a sentinel, using an enum with only one value to represent +// the null value for the `Value` type union. // -// The JSON representation for `NullValue` is JSON `null`. +// A field of type `NullValue` with any value other than `0` is considered +// invalid. Most ProtoJSON serializers will emit a Value with a `null_value` set +// as a JSON `null` regardless of the integer value, and so will round trip to +// a `0` value. enum NullValue { // Null value. NULL_VALUE = 0; } -// `ListValue` is a wrapper around a repeated field of values. -// -// The JSON representation for `ListValue` is JSON array. +// Represents a JSON array. message ListValue { // Repeated field of dynamically typed values. repeated Value values = 1; diff --git a/packages/firestore/src/protos/google/protobuf/timestamp.proto b/packages/firestore/src/protos/google/protobuf/timestamp.proto index 2b9e26a9b3..6bc1efc6d6 100644 --- a/packages/firestore/src/protos/google/protobuf/timestamp.proto +++ b/packages/firestore/src/protos/google/protobuf/timestamp.proto @@ -32,13 +32,13 @@ syntax = "proto3"; package google.protobuf; -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/timestamp"; +option go_package = "google.golang.org/protobuf/types/known/timestamppb"; option java_package = "com.google.protobuf"; option java_outer_classname = "TimestampProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; // A Timestamp represents a point in time independent of any time zone or local // calendar, encoded as a count of seconds and fractions of seconds at @@ -90,8 +90,15 @@ option objc_class_prefix = "GPB"; // Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) // .setNanos((int) ((millis % 1000) * 1000000)).build(); // +// Example 5: Compute Timestamp from Java `Instant.now()`. +// +// Instant now = Instant.now(); // -// Example 5: Compute Timestamp from current time in Python. +// Timestamp timestamp = +// Timestamp.newBuilder().setSeconds(now.getEpochSecond()) +// .setNanos(now.getNano()).build(); +// +// Example 6: Compute Timestamp from current time in Python. // // timestamp = Timestamp() // timestamp.GetCurrentTime() @@ -105,33 +112,34 @@ option objc_class_prefix = "GPB"; // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone -// is required. A proto3 JSON serializer should always use UTC (as indicated by -// "Z") when printing the Timestamp type and a proto3 JSON parser should be +// is required. A ProtoJSON serializer should always use UTC (as indicated by +// "Z") when printing the Timestamp type and a ProtoJSON parser should be // able to accept both UTC and other timezones (as indicated by an offset). // // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past // 01:30 UTC on January 15, 2017. // // In JavaScript, one can convert a Date object to this format using the -// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) +// standard +// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) // method. In Python, a standard `datetime.datetime` object can be converted -// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) -// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one -// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( -// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D +// to this format using +// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with +// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use +// the Joda Time's [`ISODateTimeFormat.dateTime()`]( +// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime() // ) to obtain a formatter capable of generating timestamps in this format. // -// message Timestamp { - - // Represents seconds of UTC time since Unix epoch - // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - // 9999-12-31T23:59:59Z inclusive. + // Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must + // be between -62135596800 and 253402300799 inclusive (which corresponds to + // 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z). int64 seconds = 1; - // Non-negative fractions of a second at nanosecond resolution. Negative - // second values with fractions must still have non-negative nanos values - // that count forward in time. Must be from 0 to 999,999,999 + // Non-negative fractions of a second at nanosecond resolution. This field is + // the nanosecond portion of the duration, not an alternative to seconds. + // Negative second values with fractions must still have non-negative nanos + // values that count forward in time. Must be between 0 and 999,999,999 // inclusive. int32 nanos = 2; } diff --git a/packages/firestore/src/protos/google/protobuf/wrappers.proto b/packages/firestore/src/protos/google/protobuf/wrappers.proto index 9ee41e384a..e583e7c40b 100644 --- a/packages/firestore/src/protos/google/protobuf/wrappers.proto +++ b/packages/firestore/src/protos/google/protobuf/wrappers.proto @@ -27,11 +27,18 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Wrappers for primitive (non-message) types. These types are useful -// for embedding primitives in the `google.protobuf.Any` type and for places -// where we need to distinguish between the absence of a primitive -// typed field and its default value. +// +// Wrappers for primitive (non-message) types. These types were needed +// for legacy reasons and are not recommended for use in new APIs. +// +// Historically these wrappers were useful to have presence on proto3 primitive +// fields, but proto3 syntax has been updated to support the `optional` keyword. +// Using that keyword is now the strongly preferred way to add presence to +// proto3 primitive fields. +// +// A secondary usecase was to embed primitives in the `google.protobuf.Any` +// type: it is now recommended that you embed your value in your own wrapper +// message which can be specifically documented. // // These wrappers have no meaningful use within repeated fields as they lack // the ability to detect presence on individual elements. @@ -42,17 +49,20 @@ syntax = "proto3"; package google.protobuf; -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/wrappers"; +option go_package = "google.golang.org/protobuf/types/known/wrapperspb"; option java_package = "com.google.protobuf"; option java_outer_classname = "WrappersProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; // Wrapper message for `double`. // // The JSON representation for `DoubleValue` is JSON number. +// +// Not recommended for use in new APIs, but still useful for legacy APIs and +// has no plan to be removed. message DoubleValue { // The double value. double value = 1; @@ -61,6 +71,9 @@ message DoubleValue { // Wrapper message for `float`. // // The JSON representation for `FloatValue` is JSON number. +// +// Not recommended for use in new APIs, but still useful for legacy APIs and +// has no plan to be removed. message FloatValue { // The float value. float value = 1; @@ -69,6 +82,9 @@ message FloatValue { // Wrapper message for `int64`. // // The JSON representation for `Int64Value` is JSON string. +// +// Not recommended for use in new APIs, but still useful for legacy APIs and +// has no plan to be removed. message Int64Value { // The int64 value. int64 value = 1; @@ -77,6 +93,9 @@ message Int64Value { // Wrapper message for `uint64`. // // The JSON representation for `UInt64Value` is JSON string. +// +// Not recommended for use in new APIs, but still useful for legacy APIs and +// has no plan to be removed. message UInt64Value { // The uint64 value. uint64 value = 1; @@ -85,6 +104,9 @@ message UInt64Value { // Wrapper message for `int32`. // // The JSON representation for `Int32Value` is JSON number. +// +// Not recommended for use in new APIs, but still useful for legacy APIs and +// has no plan to be removed. message Int32Value { // The int32 value. int32 value = 1; @@ -93,6 +115,9 @@ message Int32Value { // Wrapper message for `uint32`. // // The JSON representation for `UInt32Value` is JSON number. +// +// Not recommended for use in new APIs, but still useful for legacy APIs and +// has no plan to be removed. message UInt32Value { // The uint32 value. uint32 value = 1; @@ -101,6 +126,9 @@ message UInt32Value { // Wrapper message for `bool`. // // The JSON representation for `BoolValue` is JSON `true` and `false`. +// +// Not recommended for use in new APIs, but still useful for legacy APIs and +// has no plan to be removed. message BoolValue { // The bool value. bool value = 1; @@ -109,6 +137,9 @@ message BoolValue { // Wrapper message for `string`. // // The JSON representation for `StringValue` is JSON string. +// +// Not recommended for use in new APIs, but still useful for legacy APIs and +// has no plan to be removed. message StringValue { // The string value. string value = 1; @@ -117,6 +148,9 @@ message StringValue { // Wrapper message for `bytes`. // // The JSON representation for `BytesValue` is JSON string. +// +// Not recommended for use in new APIs, but still useful for legacy APIs and +// has no plan to be removed. message BytesValue { // The bytes value. bytes value = 1; diff --git a/packages/firestore/src/protos/google/rpc/status.proto b/packages/firestore/src/protos/google/rpc/status.proto index 3b1f7a932f..97f50b9d89 100644 --- a/packages/firestore/src/protos/google/rpc/status.proto +++ b/packages/firestore/src/protos/google/rpc/status.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ package google.rpc; import "google/protobuf/any.proto"; -option cc_enable_arenas = true; option go_package = "google.golang.org/genproto/googleapis/rpc/status;status"; option java_multiple_files = true; option java_outer_classname = "StatusProto"; @@ -33,12 +32,14 @@ option objc_class_prefix = "RPC"; // You can find out more about this error model and how to work with it in the // [API Design Guide](https://cloud.google.com/apis/design/errors). message Status { - // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. + // The status code, which should be an enum value of + // [google.rpc.Code][google.rpc.Code]. int32 code = 1; // A developer-facing error message, which should be in English. Any // user-facing error message should be localized and sent in the - // [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. + // [google.rpc.Status.details][google.rpc.Status.details] field, or localized + // by the client. string message = 2; // A list of messages that carry the error details. There is a common set of diff --git a/packages/firestore/src/protos/google/type/latlng.proto b/packages/firestore/src/protos/google/type/latlng.proto index 9231456e32..2866058ccf 100644 --- a/packages/firestore/src/protos/google/type/latlng.proto +++ b/packages/firestore/src/protos/google/type/latlng.proto @@ -1,4 +1,4 @@ -// Copyright 2021 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ syntax = "proto3"; package google.type; -option cc_enable_arenas = true; option go_package = "google.golang.org/genproto/googleapis/type/latlng;latlng"; option java_multiple_files = true; option java_outer_classname = "LatLngProto"; @@ -25,9 +24,9 @@ option objc_class_prefix = "GTP"; // An object that represents a latitude/longitude pair. This is expressed as a // pair of doubles to represent degrees latitude and degrees longitude. Unless -// specified otherwise, this must conform to the -// WGS84 -// standard. Values must be within normalized ranges. +// specified otherwise, this object must conform to the +// +// WGS84 standard. Values must be within normalized ranges. message LatLng { // The latitude in degrees. It must be in the range [-90.0, +90.0]. double latitude = 1; diff --git a/packages/firestore/src/protos/protos.json b/packages/firestore/src/protos/protos.json index ab3ddc50e8..d443ba4f19 100644 --- a/packages/firestore/src/protos/protos.json +++ b/packages/firestore/src/protos/protos.json @@ -1,3259 +1,4527 @@ { + "options": { + "syntax": "proto3" + }, "nested": { "google": { "nested": { - "protobuf": { - "options": { - "go_package": "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor", - "java_package": "com.google.protobuf", - "java_outer_classname": "DescriptorProtos", - "csharp_namespace": "Google.Protobuf.Reflection", - "objc_class_prefix": "GPB", - "cc_enable_arenas": true, - "optimize_for": "SPEED" - }, + "firestore": { "nested": { - "Struct": { - "fields": { - "fields": { - "keyType": "string", - "type": "Value", - "id": 1 - } - } - }, - "Value": { - "oneofs": { - "kind": { - "oneof": [ - "nullValue", - "numberValue", - "stringValue", - "boolValue", - "structValue", - "listValue" - ] - } - }, - "fields": { - "nullValue": { - "type": "NullValue", - "id": 1 - }, - "numberValue": { - "type": "double", - "id": 2 - }, - "stringValue": { - "type": "string", - "id": 3 - }, - "boolValue": { - "type": "bool", - "id": 4 - }, - "structValue": { - "type": "Struct", - "id": 5 - }, - "listValue": { - "type": "ListValue", - "id": 6 - } - } - }, - "NullValue": { - "values": { - "NULL_VALUE": 0 - } - }, - "ListValue": { - "fields": { - "values": { - "rule": "repeated", - "type": "Value", - "id": 1 - } - } - }, - "Timestamp": { - "fields": { - "seconds": { - "type": "int64", - "id": 1 - }, - "nanos": { - "type": "int32", - "id": 2 - } - } - }, - "FileDescriptorSet": { - "edition": "proto2", - "fields": { - "file": { - "rule": "repeated", - "type": "FileDescriptorProto", - "id": 1 - } - } - }, - "FileDescriptorProto": { - "edition": "proto2", - "fields": { - "name": { - "type": "string", - "id": 1 - }, - "package": { - "type": "string", - "id": 2 - }, - "dependency": { - "rule": "repeated", - "type": "string", - "id": 3 - }, - "publicDependency": { - "rule": "repeated", - "type": "int32", - "id": 10 - }, - "weakDependency": { - "rule": "repeated", - "type": "int32", - "id": 11 - }, - "messageType": { - "rule": "repeated", - "type": "DescriptorProto", - "id": 4 - }, - "enumType": { - "rule": "repeated", - "type": "EnumDescriptorProto", - "id": 5 - }, - "service": { - "rule": "repeated", - "type": "ServiceDescriptorProto", - "id": 6 - }, - "extension": { - "rule": "repeated", - "type": "FieldDescriptorProto", - "id": 7 - }, - "options": { - "type": "FileOptions", - "id": 8 - }, - "sourceCodeInfo": { - "type": "SourceCodeInfo", - "id": 9 - }, - "syntax": { - "type": "string", - "id": 12 - } - } - }, - "DescriptorProto": { - "edition": "proto2", - "fields": { - "name": { - "type": "string", - "id": 1 - }, - "field": { - "rule": "repeated", - "type": "FieldDescriptorProto", - "id": 2 - }, - "extension": { - "rule": "repeated", - "type": "FieldDescriptorProto", - "id": 6 - }, - "nestedType": { - "rule": "repeated", - "type": "DescriptorProto", - "id": 3 - }, - "enumType": { - "rule": "repeated", - "type": "EnumDescriptorProto", - "id": 4 - }, - "extensionRange": { - "rule": "repeated", - "type": "ExtensionRange", - "id": 5 - }, - "oneofDecl": { - "rule": "repeated", - "type": "OneofDescriptorProto", - "id": 8 - }, - "options": { - "type": "MessageOptions", - "id": 7 - }, - "reservedRange": { - "rule": "repeated", - "type": "ReservedRange", - "id": 9 - }, - "reservedName": { - "rule": "repeated", - "type": "string", - "id": 10 - } + "v1": { + "options": { + "csharp_namespace": "Google.Cloud.Firestore.V1", + "go_package": "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb", + "java_multiple_files": true, + "java_outer_classname": "QueryProto", + "java_package": "com.google.firestore.v1", + "objc_class_prefix": "GCFS", + "php_namespace": "Google\\Cloud\\Firestore\\V1", + "ruby_package": "Google::Cloud::Firestore::V1" }, "nested": { - "ExtensionRange": { + "AggregationResult": { "fields": { - "start": { - "type": "int32", - "id": 1 - }, - "end": { - "type": "int32", + "aggregateFields": { + "keyType": "string", + "type": "Value", "id": 2 - }, - "options": { - "type": "ExtensionRangeOptions", - "id": 3 } } }, - "ReservedRange": { + "Document": { "fields": { - "start": { - "type": "int32", + "name": { + "type": "string", "id": 1 }, - "end": { - "type": "int32", + "fields": { + "keyType": "string", + "type": "Value", "id": 2 + }, + "createTime": { + "type": "google.protobuf.Timestamp", + "id": 3 + }, + "updateTime": { + "type": "google.protobuf.Timestamp", + "id": 4 } } - } - } - }, - "ExtensionRangeOptions": { - "edition": "proto2", - "fields": { - "uninterpretedOption": { - "rule": "repeated", - "type": "UninterpretedOption", - "id": 999 - } - }, - "extensions": [ - [ - 1000, - 536870911 - ] - ] - }, - "FieldDescriptorProto": { - "edition": "proto2", - "fields": { - "name": { - "type": "string", - "id": 1 - }, - "number": { - "type": "int32", - "id": 3 - }, - "label": { - "type": "Label", - "id": 4 - }, - "type": { - "type": "Type", - "id": 5 - }, - "typeName": { - "type": "string", - "id": 6 - }, - "extendee": { - "type": "string", - "id": 2 - }, - "defaultValue": { - "type": "string", - "id": 7 - }, - "oneofIndex": { - "type": "int32", - "id": 9 - }, - "jsonName": { - "type": "string", - "id": 10 }, - "options": { - "type": "FieldOptions", - "id": 8 - } - }, - "nested": { - "Type": { - "values": { - "TYPE_DOUBLE": 1, - "TYPE_FLOAT": 2, - "TYPE_INT64": 3, - "TYPE_UINT64": 4, - "TYPE_INT32": 5, - "TYPE_FIXED64": 6, - "TYPE_FIXED32": 7, - "TYPE_BOOL": 8, - "TYPE_STRING": 9, - "TYPE_GROUP": 10, - "TYPE_MESSAGE": 11, - "TYPE_BYTES": 12, - "TYPE_UINT32": 13, - "TYPE_ENUM": 14, - "TYPE_SFIXED32": 15, - "TYPE_SFIXED64": 16, - "TYPE_SINT32": 17, - "TYPE_SINT64": 18 + "Value": { + "oneofs": { + "valueType": { + "oneof": [ + "nullValue", + "booleanValue", + "integerValue", + "doubleValue", + "timestampValue", + "stringValue", + "bytesValue", + "referenceValue", + "geoPointValue", + "arrayValue", + "mapValue", + "fieldReferenceValue", + "variableReferenceValue", + "functionValue", + "pipelineValue" + ] + } + }, + "fields": { + "nullValue": { + "type": "google.protobuf.NullValue", + "id": 11 + }, + "booleanValue": { + "type": "bool", + "id": 1 + }, + "integerValue": { + "type": "int64", + "id": 2 + }, + "doubleValue": { + "type": "double", + "id": 3 + }, + "timestampValue": { + "type": "google.protobuf.Timestamp", + "id": 10 + }, + "stringValue": { + "type": "string", + "id": 17 + }, + "bytesValue": { + "type": "bytes", + "id": 18 + }, + "referenceValue": { + "type": "string", + "id": 5 + }, + "geoPointValue": { + "type": "google.type.LatLng", + "id": 8 + }, + "arrayValue": { + "type": "ArrayValue", + "id": 9 + }, + "mapValue": { + "type": "MapValue", + "id": 6 + }, + "fieldReferenceValue": { + "type": "string", + "id": 19 + }, + "variableReferenceValue": { + "type": "string", + "id": 22 + }, + "functionValue": { + "type": "Function", + "id": 20 + }, + "pipelineValue": { + "type": "Pipeline", + "id": 21 + } } }, - "Label": { - "values": { - "LABEL_OPTIONAL": 1, - "LABEL_REQUIRED": 2, - "LABEL_REPEATED": 3 + "ArrayValue": { + "fields": { + "values": { + "rule": "repeated", + "type": "Value", + "id": 1 + } } - } - } - }, - "OneofDescriptorProto": { - "edition": "proto2", - "fields": { - "name": { - "type": "string", - "id": 1 - }, - "options": { - "type": "OneofOptions", - "id": 2 - } - } - }, - "EnumDescriptorProto": { - "edition": "proto2", - "fields": { - "name": { - "type": "string", - "id": 1 - }, - "value": { - "rule": "repeated", - "type": "EnumValueDescriptorProto", - "id": 2 - }, - "options": { - "type": "EnumOptions", - "id": 3 - }, - "reservedRange": { - "rule": "repeated", - "type": "EnumReservedRange", - "id": 4 }, - "reservedName": { - "rule": "repeated", - "type": "string", - "id": 5 - } - }, - "nested": { - "EnumReservedRange": { + "MapValue": { "fields": { - "start": { - "type": "int32", + "fields": { + "keyType": "string", + "type": "Value", "id": 1 - }, - "end": { - "type": "int32", - "id": 2 } } - } - } - }, - "EnumValueDescriptorProto": { - "edition": "proto2", - "fields": { - "name": { - "type": "string", - "id": 1 }, - "number": { - "type": "int32", - "id": 2 + "Function": { + "fields": { + "name": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "args": { + "rule": "repeated", + "type": "Value", + "id": 2, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + }, + "options": { + "keyType": "string", + "type": "Value", + "id": 3, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + } + } }, - "options": { - "type": "EnumValueOptions", - "id": 3 - } - } - }, - "ServiceDescriptorProto": { - "edition": "proto2", - "fields": { - "name": { - "type": "string", - "id": 1 - }, - "method": { - "rule": "repeated", - "type": "MethodDescriptorProto", - "id": 2 - }, - "options": { - "type": "ServiceOptions", - "id": 3 - } - } - }, - "MethodDescriptorProto": { - "edition": "proto2", - "fields": { - "name": { - "type": "string", - "id": 1 - }, - "inputType": { - "type": "string", - "id": 2 - }, - "outputType": { - "type": "string", - "id": 3 - }, - "options": { - "type": "MethodOptions", - "id": 4 - }, - "clientStreaming": { - "type": "bool", - "id": 5, - "options": { - "default": false + "Pipeline": { + "fields": { + "stages": { + "rule": "repeated", + "type": "Stage", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + } + }, + "nested": { + "Stage": { + "fields": { + "name": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "args": { + "rule": "repeated", + "type": "Value", + "id": 2, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + }, + "options": { + "keyType": "string", + "type": "Value", + "id": 3, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + } + } + } } }, - "serverStreaming": { - "type": "bool", - "id": 6, - "options": { - "default": false + "Write": { + "oneofs": { + "operation": { + "oneof": [ + "update", + "delete", + "verify", + "transform" + ] + } + }, + "fields": { + "update": { + "type": "Document", + "id": 1 + }, + "delete": { + "type": "string", + "id": 2 + }, + "verify": { + "type": "string", + "id": 5 + }, + "transform": { + "type": "DocumentTransform", + "id": 6 + }, + "updateMask": { + "type": "DocumentMask", + "id": 3 + }, + "updateTransforms": { + "rule": "repeated", + "type": "DocumentTransform.FieldTransform", + "id": 7 + }, + "currentDocument": { + "type": "Precondition", + "id": 4 + } } - } - } - }, - "FileOptions": { - "edition": "proto2", - "fields": { - "javaPackage": { - "type": "string", - "id": 1 }, - "javaOuterClassname": { - "type": "string", - "id": 8 + "DocumentTransform": { + "fields": { + "document": { + "type": "string", + "id": 1 + }, + "fieldTransforms": { + "rule": "repeated", + "type": "FieldTransform", + "id": 2 + } + }, + "nested": { + "FieldTransform": { + "oneofs": { + "transformType": { + "oneof": [ + "setToServerValue", + "increment", + "maximum", + "minimum", + "appendMissingElements", + "removeAllFromArray" + ] + } + }, + "fields": { + "fieldPath": { + "type": "string", + "id": 1 + }, + "setToServerValue": { + "type": "ServerValue", + "id": 2 + }, + "increment": { + "type": "Value", + "id": 3 + }, + "maximum": { + "type": "Value", + "id": 4 + }, + "minimum": { + "type": "Value", + "id": 5 + }, + "appendMissingElements": { + "type": "ArrayValue", + "id": 6 + }, + "removeAllFromArray": { + "type": "ArrayValue", + "id": 7 + } + }, + "nested": { + "ServerValue": { + "values": { + "SERVER_VALUE_UNSPECIFIED": 0, + "REQUEST_TIME": 1 + } + } + } + } + } }, - "javaMultipleFiles": { - "type": "bool", - "id": 10, - "options": { - "default": false + "WriteResult": { + "fields": { + "updateTime": { + "type": "google.protobuf.Timestamp", + "id": 1 + }, + "transformResults": { + "rule": "repeated", + "type": "Value", + "id": 2 + } } }, - "javaGenerateEqualsAndHash": { - "type": "bool", - "id": 20, - "options": { - "deprecated": true + "DocumentChange": { + "fields": { + "document": { + "type": "Document", + "id": 1 + }, + "targetIds": { + "rule": "repeated", + "type": "int32", + "id": 5 + }, + "removedTargetIds": { + "rule": "repeated", + "type": "int32", + "id": 6 + } } }, - "javaStringCheckUtf8": { - "type": "bool", - "id": 27, - "options": { - "default": false + "DocumentDelete": { + "fields": { + "document": { + "type": "string", + "id": 1 + }, + "removedTargetIds": { + "rule": "repeated", + "type": "int32", + "id": 6 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 4 + } } }, - "optimizeFor": { - "type": "OptimizeMode", - "id": 9, - "options": { - "default": "SPEED" + "DocumentRemove": { + "fields": { + "document": { + "type": "string", + "id": 1 + }, + "removedTargetIds": { + "rule": "repeated", + "type": "int32", + "id": 2 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 4 + } } }, - "goPackage": { - "type": "string", - "id": 11 - }, - "ccGenericServices": { - "type": "bool", - "id": 16, - "options": { - "default": false + "ExistenceFilter": { + "fields": { + "targetId": { + "type": "int32", + "id": 1 + }, + "count": { + "type": "int32", + "id": 2 + }, + "unchangedNames": { + "type": "BloomFilter", + "id": 3 + } } }, - "javaGenericServices": { - "type": "bool", - "id": 17, - "options": { - "default": false + "BitSequence": { + "fields": { + "bitmap": { + "type": "bytes", + "id": 1 + }, + "padding": { + "type": "int32", + "id": 2 + } } }, - "pyGenericServices": { - "type": "bool", - "id": 18, - "options": { - "default": false + "BloomFilter": { + "fields": { + "bits": { + "type": "BitSequence", + "id": 1 + }, + "hashCount": { + "type": "int32", + "id": 2 + } } }, - "phpGenericServices": { - "type": "bool", - "id": 42, - "options": { - "default": false + "DocumentMask": { + "fields": { + "fieldPaths": { + "rule": "repeated", + "type": "string", + "id": 1 + } } }, - "deprecated": { - "type": "bool", - "id": 23, - "options": { - "default": false + "Precondition": { + "oneofs": { + "conditionType": { + "oneof": [ + "exists", + "updateTime" + ] + } + }, + "fields": { + "exists": { + "type": "bool", + "id": 1 + }, + "updateTime": { + "type": "google.protobuf.Timestamp", + "id": 2 + } } }, - "ccEnableArenas": { - "type": "bool", - "id": 31, - "options": { - "default": false + "TransactionOptions": { + "oneofs": { + "mode": { + "oneof": [ + "readOnly", + "readWrite" + ] + } + }, + "fields": { + "readOnly": { + "type": "ReadOnly", + "id": 2 + }, + "readWrite": { + "type": "ReadWrite", + "id": 3 + } + }, + "nested": { + "ReadWrite": { + "fields": { + "retryTransaction": { + "type": "bytes", + "id": 1 + } + } + }, + "ReadOnly": { + "oneofs": { + "consistencySelector": { + "oneof": [ + "readTime" + ] + } + }, + "fields": { + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 2 + } + } + } } }, - "objcClassPrefix": { - "type": "string", - "id": 36 - }, - "csharpNamespace": { - "type": "string", - "id": 37 - }, - "swiftPrefix": { - "type": "string", - "id": 39 - }, - "phpClassPrefix": { - "type": "string", - "id": 40 - }, - "phpNamespace": { - "type": "string", - "id": 41 - }, - "phpMetadataNamespace": { - "type": "string", - "id": 44 - }, - "rubyPackage": { - "type": "string", - "id": 45 - }, - "uninterpretedOption": { - "rule": "repeated", - "type": "UninterpretedOption", - "id": 999 - } - }, - "extensions": [ - [ - 1000, - 536870911 - ] - ], - "reserved": [ - [ - 38, - 38 - ] - ], - "nested": { - "OptimizeMode": { - "values": { - "SPEED": 1, - "CODE_SIZE": 2, - "LITE_RUNTIME": 3 - } - } - } - }, - "MessageOptions": { - "edition": "proto2", - "fields": { - "messageSetWireFormat": { - "type": "bool", - "id": 1, - "options": { - "default": false + "ExplainStats": { + "fields": { + "data": { + "type": "google.protobuf.Any", + "id": 1 + } } }, - "noStandardDescriptorAccessor": { - "type": "bool", - "id": 2, - "options": { - "default": false + "ExplainOptions": { + "fields": { + "analyze": { + "type": "bool", + "id": 1, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + } } }, - "deprecated": { - "type": "bool", - "id": 3, - "options": { - "default": false + "ExplainMetrics": { + "fields": { + "planSummary": { + "type": "PlanSummary", + "id": 1 + }, + "executionStats": { + "type": "ExecutionStats", + "id": 2 + } } }, - "mapEntry": { - "type": "bool", - "id": 7 + "PlanSummary": { + "fields": { + "indexesUsed": { + "rule": "repeated", + "type": "google.protobuf.Struct", + "id": 1 + } + } }, - "uninterpretedOption": { - "rule": "repeated", - "type": "UninterpretedOption", - "id": 999 - } - }, - "extensions": [ - [ - 1000, - 536870911 - ] - ], - "reserved": [ - [ - 8, - 8 - ], - [ - 9, - 9 - ] - ] - }, - "FieldOptions": { - "edition": "proto2", - "fields": { - "ctype": { - "type": "CType", - "id": 1, + "ExecutionStats": { + "fields": { + "resultsReturned": { + "type": "int64", + "id": 1 + }, + "executionDuration": { + "type": "google.protobuf.Duration", + "id": 3 + }, + "readOperations": { + "type": "int64", + "id": 4 + }, + "debugStats": { + "type": "google.protobuf.Struct", + "id": 5 + } + } + }, + "Firestore": { "options": { - "default": "STRING" + "(google.api.default_host)": "firestore.googleapis.com", + "(google.api.oauth_scopes)": "https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/datastore" + }, + "methods": { + "GetDocument": { + "requestType": "GetDocumentRequest", + "responseType": "Document", + "options": { + "(google.api.http).get": "/v1/{name=projects/*/databases/*/documents/*/**}" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "get": "/v1/{name=projects/*/databases/*/documents/*/**}" + } + } + ] + }, + "ListDocuments": { + "requestType": "ListDocumentsRequest", + "responseType": "ListDocumentsResponse", + "options": { + "(google.api.http).get": "/v1/{parent=projects/*/databases/*/documents/*/**}/{collection_id}", + "(google.api.http).additional_bindings.get": "/v1/{parent=projects/*/databases/*/documents}/{collection_id}" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "get": "/v1/{parent=projects/*/databases/*/documents/*/**}/{collection_id}", + "additional_bindings": { + "get": "/v1/{parent=projects/*/databases/*/documents}/{collection_id}" + } + } + } + ] + }, + "UpdateDocument": { + "requestType": "UpdateDocumentRequest", + "responseType": "Document", + "options": { + "(google.api.http).patch": "/v1/{document.name=projects/*/databases/*/documents/*/**}", + "(google.api.http).body": "document", + "(google.api.method_signature)": "document,update_mask" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "patch": "/v1/{document.name=projects/*/databases/*/documents/*/**}", + "body": "document" + } + }, + { + "(google.api.method_signature)": "document,update_mask" + } + ] + }, + "DeleteDocument": { + "requestType": "DeleteDocumentRequest", + "responseType": "google.protobuf.Empty", + "options": { + "(google.api.http).delete": "/v1/{name=projects/*/databases/*/documents/*/**}", + "(google.api.method_signature)": "name" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "delete": "/v1/{name=projects/*/databases/*/documents/*/**}" + } + }, + { + "(google.api.method_signature)": "name" + } + ] + }, + "BatchGetDocuments": { + "requestType": "BatchGetDocumentsRequest", + "responseType": "BatchGetDocumentsResponse", + "responseStream": true, + "options": { + "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:batchGet", + "(google.api.http).body": "*" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{database=projects/*/databases/*}/documents:batchGet", + "body": "*" + } + } + ] + }, + "BeginTransaction": { + "requestType": "BeginTransactionRequest", + "responseType": "BeginTransactionResponse", + "options": { + "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:beginTransaction", + "(google.api.http).body": "*", + "(google.api.method_signature)": "database" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{database=projects/*/databases/*}/documents:beginTransaction", + "body": "*" + } + }, + { + "(google.api.method_signature)": "database" + } + ] + }, + "Commit": { + "requestType": "CommitRequest", + "responseType": "CommitResponse", + "options": { + "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:commit", + "(google.api.http).body": "*", + "(google.api.method_signature)": "database,writes" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{database=projects/*/databases/*}/documents:commit", + "body": "*" + } + }, + { + "(google.api.method_signature)": "database,writes" + } + ] + }, + "Rollback": { + "requestType": "RollbackRequest", + "responseType": "google.protobuf.Empty", + "options": { + "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:rollback", + "(google.api.http).body": "*", + "(google.api.method_signature)": "database,transaction" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{database=projects/*/databases/*}/documents:rollback", + "body": "*" + } + }, + { + "(google.api.method_signature)": "database,transaction" + } + ] + }, + "RunQuery": { + "requestType": "RunQueryRequest", + "responseType": "RunQueryResponse", + "responseStream": true, + "options": { + "(google.api.http).post": "/v1/{parent=projects/*/databases/*/documents}:runQuery", + "(google.api.http).body": "*", + "(google.api.http).additional_bindings.post": "/v1/{parent=projects/*/databases/*/documents/*/**}:runQuery", + "(google.api.http).additional_bindings.body": "*" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{parent=projects/*/databases/*/documents}:runQuery", + "body": "*", + "additional_bindings": { + "post": "/v1/{parent=projects/*/databases/*/documents/*/**}:runQuery", + "body": "*" + } + } + } + ] + }, + "ExecutePipeline": { + "requestType": "ExecutePipelineRequest", + "responseType": "ExecutePipelineResponse", + "responseStream": true, + "options": { + "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:executePipeline", + "(google.api.http).body": "*", + "(google.api.routing).routing_parameters.field": "database", + "(google.api.routing).routing_parameters.path_template": "projects/*/databases/{database_id=*}/**" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{database=projects/*/databases/*}/documents:executePipeline", + "body": "*" + } + }, + { + "(google.api.routing)": { + "routing_parameters": [ + { + "field": "database", + "path_template": "projects/{project_id=*}/**" + }, + { + "field": "database", + "path_template": "projects/*/databases/{database_id=*}/**" + } + ] + } + } + ] + }, + "RunAggregationQuery": { + "requestType": "RunAggregationQueryRequest", + "responseType": "RunAggregationQueryResponse", + "responseStream": true, + "options": { + "(google.api.http).post": "/v1/{parent=projects/*/databases/*/documents}:runAggregationQuery", + "(google.api.http).body": "*", + "(google.api.http).additional_bindings.post": "/v1/{parent=projects/*/databases/*/documents/*/**}:runAggregationQuery", + "(google.api.http).additional_bindings.body": "*" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{parent=projects/*/databases/*/documents}:runAggregationQuery", + "body": "*", + "additional_bindings": { + "post": "/v1/{parent=projects/*/databases/*/documents/*/**}:runAggregationQuery", + "body": "*" + } + } + } + ] + }, + "PartitionQuery": { + "requestType": "PartitionQueryRequest", + "responseType": "PartitionQueryResponse", + "options": { + "(google.api.http).post": "/v1/{parent=projects/*/databases/*/documents}:partitionQuery", + "(google.api.http).body": "*", + "(google.api.http).additional_bindings.post": "/v1/{parent=projects/*/databases/*/documents/*/**}:partitionQuery", + "(google.api.http).additional_bindings.body": "*" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{parent=projects/*/databases/*/documents}:partitionQuery", + "body": "*", + "additional_bindings": { + "post": "/v1/{parent=projects/*/databases/*/documents/*/**}:partitionQuery", + "body": "*" + } + } + } + ] + }, + "Write": { + "requestType": "WriteRequest", + "requestStream": true, + "responseType": "WriteResponse", + "responseStream": true, + "options": { + "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:write", + "(google.api.http).body": "*" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{database=projects/*/databases/*}/documents:write", + "body": "*" + } + } + ] + }, + "Listen": { + "requestType": "ListenRequest", + "requestStream": true, + "responseType": "ListenResponse", + "responseStream": true, + "options": { + "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:listen", + "(google.api.http).body": "*" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{database=projects/*/databases/*}/documents:listen", + "body": "*" + } + } + ] + }, + "ListCollectionIds": { + "requestType": "ListCollectionIdsRequest", + "responseType": "ListCollectionIdsResponse", + "options": { + "(google.api.http).post": "/v1/{parent=projects/*/databases/*/documents}:listCollectionIds", + "(google.api.http).body": "*", + "(google.api.http).additional_bindings.post": "/v1/{parent=projects/*/databases/*/documents/*/**}:listCollectionIds", + "(google.api.http).additional_bindings.body": "*", + "(google.api.method_signature)": "parent" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{parent=projects/*/databases/*/documents}:listCollectionIds", + "body": "*", + "additional_bindings": { + "post": "/v1/{parent=projects/*/databases/*/documents/*/**}:listCollectionIds", + "body": "*" + } + } + }, + { + "(google.api.method_signature)": "parent" + } + ] + }, + "BatchWrite": { + "requestType": "BatchWriteRequest", + "responseType": "BatchWriteResponse", + "options": { + "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:batchWrite", + "(google.api.http).body": "*" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{database=projects/*/databases/*}/documents:batchWrite", + "body": "*" + } + } + ] + }, + "CreateDocument": { + "requestType": "CreateDocumentRequest", + "responseType": "Document", + "options": { + "(google.api.http).post": "/v1/{parent=projects/*/databases/*/documents/**}/{collection_id}", + "(google.api.http).body": "document" + }, + "parsedOptions": [ + { + "(google.api.http)": { + "post": "/v1/{parent=projects/*/databases/*/documents/**}/{collection_id}", + "body": "document" + } + } + ] + } } }, - "packed": { - "type": "bool", - "id": 2 + "GetDocumentRequest": { + "oneofs": { + "consistencySelector": { + "oneof": [ + "transaction", + "readTime" + ] + } + }, + "fields": { + "name": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "mask": { + "type": "DocumentMask", + "id": 2 + }, + "transaction": { + "type": "bytes", + "id": 3 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 5 + } + } }, - "jstype": { - "type": "JSType", - "id": 6, - "options": { - "default": "JS_NORMAL" + "ListDocumentsRequest": { + "oneofs": { + "consistencySelector": { + "oneof": [ + "transaction", + "readTime" + ] + } + }, + "fields": { + "parent": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "collectionId": { + "type": "string", + "id": 2, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + }, + "pageSize": { + "type": "int32", + "id": 3, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + }, + "pageToken": { + "type": "string", + "id": 4, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + }, + "orderBy": { + "type": "string", + "id": 6, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + }, + "mask": { + "type": "DocumentMask", + "id": 7, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + }, + "transaction": { + "type": "bytes", + "id": 8 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 10 + }, + "showMissing": { + "type": "bool", + "id": 12 + } } }, - "lazy": { - "type": "bool", - "id": 5, - "options": { - "default": false + "ListDocumentsResponse": { + "fields": { + "documents": { + "rule": "repeated", + "type": "Document", + "id": 1 + }, + "nextPageToken": { + "type": "string", + "id": 2 + } + } + }, + "CreateDocumentRequest": { + "fields": { + "parent": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "collectionId": { + "type": "string", + "id": 2, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "documentId": { + "type": "string", + "id": 3 + }, + "document": { + "type": "Document", + "id": 4, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "mask": { + "type": "DocumentMask", + "id": 5 + } + } + }, + "UpdateDocumentRequest": { + "fields": { + "document": { + "type": "Document", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "updateMask": { + "type": "DocumentMask", + "id": 2 + }, + "mask": { + "type": "DocumentMask", + "id": 3 + }, + "currentDocument": { + "type": "Precondition", + "id": 4 + } + } + }, + "DeleteDocumentRequest": { + "fields": { + "name": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "currentDocument": { + "type": "Precondition", + "id": 2 + } + } + }, + "BatchGetDocumentsRequest": { + "oneofs": { + "consistencySelector": { + "oneof": [ + "transaction", + "newTransaction", + "readTime" + ] + } + }, + "fields": { + "database": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "documents": { + "rule": "repeated", + "type": "string", + "id": 2 + }, + "mask": { + "type": "DocumentMask", + "id": 3 + }, + "transaction": { + "type": "bytes", + "id": 4 + }, + "newTransaction": { + "type": "TransactionOptions", + "id": 5 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 7 + } } }, - "deprecated": { - "type": "bool", - "id": 3, - "options": { - "default": false + "BatchGetDocumentsResponse": { + "oneofs": { + "result": { + "oneof": [ + "found", + "missing" + ] + } + }, + "fields": { + "found": { + "type": "Document", + "id": 1 + }, + "missing": { + "type": "string", + "id": 2 + }, + "transaction": { + "type": "bytes", + "id": 3 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 4 + } } }, - "weak": { - "type": "bool", - "id": 10, - "options": { - "default": false + "BeginTransactionRequest": { + "fields": { + "database": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "options": { + "type": "TransactionOptions", + "id": 2 + } } }, - "uninterpretedOption": { - "rule": "repeated", - "type": "UninterpretedOption", - "id": 999 - } - }, - "extensions": [ - [ - 1000, - 536870911 - ] - ], - "reserved": [ - [ - 4, - 4 - ] - ], - "nested": { - "CType": { - "values": { - "STRING": 0, - "CORD": 1, - "STRING_PIECE": 2 + "BeginTransactionResponse": { + "fields": { + "transaction": { + "type": "bytes", + "id": 1 + } } }, - "JSType": { - "values": { - "JS_NORMAL": 0, - "JS_STRING": 1, - "JS_NUMBER": 2 + "CommitRequest": { + "fields": { + "database": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "writes": { + "rule": "repeated", + "type": "Write", + "id": 2 + }, + "transaction": { + "type": "bytes", + "id": 3 + } } - } - } - }, - "OneofOptions": { - "edition": "proto2", - "fields": { - "uninterpretedOption": { - "rule": "repeated", - "type": "UninterpretedOption", - "id": 999 - } - }, - "extensions": [ - [ - 1000, - 536870911 - ] - ] - }, - "EnumOptions": { - "edition": "proto2", - "fields": { - "allowAlias": { - "type": "bool", - "id": 2 }, - "deprecated": { - "type": "bool", - "id": 3, - "options": { - "default": false + "CommitResponse": { + "fields": { + "writeResults": { + "rule": "repeated", + "type": "WriteResult", + "id": 1 + }, + "commitTime": { + "type": "google.protobuf.Timestamp", + "id": 2 + } } }, - "uninterpretedOption": { - "rule": "repeated", - "type": "UninterpretedOption", - "id": 999 - } - }, - "extensions": [ - [ - 1000, - 536870911 - ] - ], - "reserved": [ - [ - 5, - 5 - ] - ] - }, - "EnumValueOptions": { - "edition": "proto2", - "fields": { - "deprecated": { - "type": "bool", - "id": 1, - "options": { - "default": false + "RollbackRequest": { + "fields": { + "database": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "transaction": { + "type": "bytes", + "id": 2, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + } } }, - "uninterpretedOption": { - "rule": "repeated", - "type": "UninterpretedOption", - "id": 999 - } - }, - "extensions": [ - [ - 1000, - 536870911 - ] - ] - }, - "ServiceOptions": { - "edition": "proto2", - "fields": { - "deprecated": { - "type": "bool", - "id": 33, - "options": { - "default": false + "RunQueryRequest": { + "oneofs": { + "queryType": { + "oneof": [ + "structuredQuery" + ] + }, + "consistencySelector": { + "oneof": [ + "transaction", + "newTransaction", + "readTime" + ] + } + }, + "fields": { + "parent": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "structuredQuery": { + "type": "StructuredQuery", + "id": 2 + }, + "transaction": { + "type": "bytes", + "id": 5 + }, + "newTransaction": { + "type": "TransactionOptions", + "id": 6 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 7 + }, + "explainOptions": { + "type": "ExplainOptions", + "id": 10, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + } } }, - "uninterpretedOption": { - "rule": "repeated", - "type": "UninterpretedOption", - "id": 999 - } - }, - "extensions": [ - [ - 1000, - 536870911 - ] - ] - }, - "MethodOptions": { - "edition": "proto2", - "fields": { - "deprecated": { - "type": "bool", - "id": 33, - "options": { - "default": false + "RunQueryResponse": { + "oneofs": { + "continuationSelector": { + "oneof": [ + "done" + ] + } + }, + "fields": { + "transaction": { + "type": "bytes", + "id": 2 + }, + "document": { + "type": "Document", + "id": 1 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 3 + }, + "skippedResults": { + "type": "int32", + "id": 4 + }, + "done": { + "type": "bool", + "id": 6 + }, + "explainMetrics": { + "type": "ExplainMetrics", + "id": 11 + } } }, - "idempotencyLevel": { - "type": "IdempotencyLevel", - "id": 34, - "options": { - "default": "IDEMPOTENCY_UNKNOWN" + "ExecutePipelineRequest": { + "oneofs": { + "pipelineType": { + "oneof": [ + "structuredPipeline" + ] + }, + "consistencySelector": { + "oneof": [ + "transaction", + "newTransaction", + "readTime" + ] + } + }, + "fields": { + "database": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "structuredPipeline": { + "type": "StructuredPipeline", + "id": 2 + }, + "transaction": { + "type": "bytes", + "id": 5 + }, + "newTransaction": { + "type": "TransactionOptions", + "id": 6 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 7 + } } }, - "uninterpretedOption": { - "rule": "repeated", - "type": "UninterpretedOption", - "id": 999 - } - }, - "extensions": [ - [ - 1000, - 536870911 - ] - ], - "nested": { - "IdempotencyLevel": { - "values": { - "IDEMPOTENCY_UNKNOWN": 0, - "NO_SIDE_EFFECTS": 1, - "IDEMPOTENT": 2 + "ExecutePipelineResponse": { + "fields": { + "transaction": { + "type": "bytes", + "id": 1 + }, + "results": { + "rule": "repeated", + "type": "Document", + "id": 2 + }, + "executionTime": { + "type": "google.protobuf.Timestamp", + "id": 3 + }, + "explainStats": { + "type": "ExplainStats", + "id": 4 + } } - } - } - }, - "UninterpretedOption": { - "edition": "proto2", - "fields": { - "name": { - "rule": "repeated", - "type": "NamePart", - "id": 2 - }, - "identifierValue": { - "type": "string", - "id": 3 - }, - "positiveIntValue": { - "type": "uint64", - "id": 4 - }, - "negativeIntValue": { - "type": "int64", - "id": 5 - }, - "doubleValue": { - "type": "double", - "id": 6 }, - "stringValue": { - "type": "bytes", - "id": 7 - }, - "aggregateValue": { - "type": "string", - "id": 8 - } - }, - "nested": { - "NamePart": { + "RunAggregationQueryRequest": { + "oneofs": { + "queryType": { + "oneof": [ + "structuredAggregationQuery" + ] + }, + "consistencySelector": { + "oneof": [ + "transaction", + "newTransaction", + "readTime" + ] + } + }, "fields": { - "namePart": { - "rule": "required", + "parent": { "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "structuredAggregationQuery": { + "type": "StructuredAggregationQuery", + "id": 2 + }, + "transaction": { + "type": "bytes", + "id": 4 + }, + "newTransaction": { + "type": "TransactionOptions", + "id": 5 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 6 + }, + "explainOptions": { + "type": "ExplainOptions", + "id": 8, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + } + } + }, + "RunAggregationQueryResponse": { + "fields": { + "result": { + "type": "AggregationResult", "id": 1 }, - "isExtension": { - "rule": "required", - "type": "bool", + "transaction": { + "type": "bytes", "id": 2 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 3 + }, + "explainMetrics": { + "type": "ExplainMetrics", + "id": 10 } } - } - } - }, - "SourceCodeInfo": { - "edition": "proto2", - "fields": { - "location": { - "rule": "repeated", - "type": "Location", - "id": 1 - } - }, - "nested": { - "Location": { + }, + "PartitionQueryRequest": { + "oneofs": { + "queryType": { + "oneof": [ + "structuredQuery" + ] + }, + "consistencySelector": { + "oneof": [ + "readTime" + ] + } + }, "fields": { - "path": { - "rule": "repeated", - "type": "int32", + "parent": { + "type": "string", "id": 1, "options": { - "packed": true + "(google.api.field_behavior)": "REQUIRED" } }, - "span": { - "rule": "repeated", - "type": "int32", - "id": 2, - "options": { - "packed": true - } + "structuredQuery": { + "type": "StructuredQuery", + "id": 2 }, - "leadingComments": { - "type": "string", + "partitionCount": { + "type": "int64", "id": 3 }, - "trailingComments": { + "pageToken": { "type": "string", "id": 4 }, - "leadingDetachedComments": { - "rule": "repeated", - "type": "string", + "pageSize": { + "type": "int32", + "id": 5 + }, + "readTime": { + "type": "google.protobuf.Timestamp", "id": 6 } } - } - } - }, - "GeneratedCodeInfo": { - "edition": "proto2", - "fields": { - "annotation": { - "rule": "repeated", - "type": "Annotation", - "id": 1 - } - }, - "nested": { - "Annotation": { + }, + "PartitionQueryResponse": { "fields": { - "path": { + "partitions": { "rule": "repeated", - "type": "int32", + "type": "Cursor", + "id": 1 + }, + "nextPageToken": { + "type": "string", + "id": 2 + } + } + }, + "WriteRequest": { + "fields": { + "database": { + "type": "string", "id": 1, "options": { - "packed": true + "(google.api.field_behavior)": "REQUIRED" } }, - "sourceFile": { + "streamId": { "type": "string", "id": 2 }, - "begin": { - "type": "int32", + "writes": { + "rule": "repeated", + "type": "Write", "id": 3 }, - "end": { - "type": "int32", + "streamToken": { + "type": "bytes", "id": 4 + }, + "labels": { + "keyType": "string", + "type": "string", + "id": 5 } } - } - } - }, - "DoubleValue": { - "fields": { - "value": { - "type": "double", - "id": 1 - } - } - }, - "FloatValue": { - "fields": { - "value": { - "type": "float", - "id": 1 - } - } - }, - "Int64Value": { - "fields": { - "value": { - "type": "int64", - "id": 1 - } - } - }, - "UInt64Value": { - "fields": { - "value": { - "type": "uint64", - "id": 1 - } - } - }, - "Int32Value": { - "fields": { - "value": { - "type": "int32", - "id": 1 - } - } - }, - "UInt32Value": { - "fields": { - "value": { - "type": "uint32", - "id": 1 - } - } - }, - "BoolValue": { - "fields": { - "value": { - "type": "bool", - "id": 1 - } - } - }, - "StringValue": { - "fields": { - "value": { - "type": "string", - "id": 1 - } - } - }, - "BytesValue": { - "fields": { - "value": { - "type": "bytes", - "id": 1 - } - } - }, - "Empty": { - "fields": {} - }, - "Any": { - "fields": { - "type_url": { - "type": "string", - "id": 1 - }, - "value": { - "type": "bytes", - "id": 2 - } - } - }, - "Duration": { - "fields": { - "seconds": { - "type": "int64", - "id": 1 }, - "nanos": { - "type": "int32", - "id": 2 - } - } - } - } - }, - "firestore": { - "nested": { - "v1": { - "options": { - "csharp_namespace": "Google.Cloud.Firestore.V1", - "go_package": "cloud.google.com/go/firestore/apiv1/firestorepb;firestorepb", - "java_multiple_files": true, - "java_outer_classname": "QueryProfileProto", - "java_package": "com.google.firestore.v1", - "objc_class_prefix": "GCFS", - "php_namespace": "Google\\Cloud\\Firestore\\V1", - "ruby_package": "Google::Cloud::Firestore::V1" - }, - "nested": { - "AggregationResult": { + "WriteResponse": { "fields": { - "aggregateFields": { - "keyType": "string", - "type": "Value", + "streamId": { + "type": "string", + "id": 1 + }, + "streamToken": { + "type": "bytes", "id": 2 + }, + "writeResults": { + "rule": "repeated", + "type": "WriteResult", + "id": 3 + }, + "commitTime": { + "type": "google.protobuf.Timestamp", + "id": 4 } } }, - "Document": { + "ListenRequest": { + "oneofs": { + "targetChange": { + "oneof": [ + "addTarget", + "removeTarget" + ] + } + }, "fields": { - "name": { + "database": { "type": "string", - "id": 1 + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } }, - "fields": { + "addTarget": { + "type": "Target", + "id": 2 + }, + "removeTarget": { + "type": "int32", + "id": 3 + }, + "labels": { "keyType": "string", - "type": "Value", + "type": "string", + "id": 4 + } + } + }, + "ListenResponse": { + "oneofs": { + "responseType": { + "oneof": [ + "targetChange", + "documentChange", + "documentDelete", + "documentRemove", + "filter" + ] + } + }, + "fields": { + "targetChange": { + "type": "TargetChange", "id": 2 }, - "createTime": { - "type": "google.protobuf.Timestamp", + "documentChange": { + "type": "DocumentChange", "id": 3 }, - "updateTime": { - "type": "google.protobuf.Timestamp", + "documentDelete": { + "type": "DocumentDelete", "id": 4 + }, + "documentRemove": { + "type": "DocumentRemove", + "id": 6 + }, + "filter": { + "type": "ExistenceFilter", + "id": 5 } } }, - "Value": { + "Target": { "oneofs": { - "valueType": { + "targetType": { "oneof": [ - "nullValue", - "booleanValue", - "integerValue", - "doubleValue", - "timestampValue", - "stringValue", - "bytesValue", - "referenceValue", - "geoPointValue", - "arrayValue", - "mapValue", - "fieldReferenceValue", - "variableReferenceValue", - "functionValue", - "pipelineValue" + "query", + "documents" + ] + }, + "resumeType": { + "oneof": [ + "resumeToken", + "readTime" ] } }, "fields": { - "nullValue": { - "type": "google.protobuf.NullValue", - "id": 11 - }, - "booleanValue": { - "type": "bool", - "id": 1 - }, - "integerValue": { - "type": "int64", + "query": { + "type": "QueryTarget", "id": 2 }, - "doubleValue": { - "type": "double", + "documents": { + "type": "DocumentsTarget", "id": 3 }, - "timestampValue": { - "type": "google.protobuf.Timestamp", - "id": 10 - }, - "stringValue": { - "type": "string", - "id": 17 - }, - "bytesValue": { + "resumeToken": { "type": "bytes", - "id": 18 - }, - "referenceValue": { - "type": "string", - "id": 5 + "id": 4 }, - "geoPointValue": { - "type": "google.type.LatLng", - "id": 8 + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 11 }, - "arrayValue": { - "type": "ArrayValue", - "id": 9 + "targetId": { + "type": "int32", + "id": 5 }, - "mapValue": { - "type": "MapValue", + "once": { + "type": "bool", "id": 6 }, - "fieldReferenceValue": { - "type": "string", - "id": 19 - }, - "variableReferenceValue": { - "type": "string", - "id": 22 - }, - "functionValue": { - "type": "Function", - "id": 20 - }, - "pipelineValue": { - "type": "Pipeline", - "id": 21 - } - } - }, - "ArrayValue": { - "fields": { - "values": { - "rule": "repeated", - "type": "Value", - "id": 1 + "expectedCount": { + "type": "google.protobuf.Int32Value", + "id": 12 } - } - }, - "MapValue": { - "fields": { - "fields": { - "keyType": "string", - "type": "Value", - "id": 1 + }, + "nested": { + "DocumentsTarget": { + "fields": { + "documents": { + "rule": "repeated", + "type": "string", + "id": 2 + } + } + }, + "QueryTarget": { + "oneofs": { + "queryType": { + "oneof": [ + "structuredQuery" + ] + } + }, + "fields": { + "parent": { + "type": "string", + "id": 1 + }, + "structuredQuery": { + "type": "StructuredQuery", + "id": 2 + } + } } } }, - "Function": { + "TargetChange": { "fields": { - "name": { - "type": "string", + "targetChangeType": { + "type": "TargetChangeType", "id": 1 }, - "args": { + "targetIds": { "rule": "repeated", - "type": "Value", + "type": "int32", "id": 2 }, - "options": { - "keyType": "string", - "type": "Value", + "cause": { + "type": "google.rpc.Status", "id": 3 - } - } - }, - "Pipeline": { - "fields": { - "stages": { - "rule": "repeated", - "type": "Stage", - "id": 1 + }, + "resumeToken": { + "type": "bytes", + "id": 4 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 6 } }, "nested": { - "Stage": { - "fields": { - "name": { - "type": "string", - "id": 1 - }, - "args": { - "rule": "repeated", - "type": "Value", - "id": 2 - }, - "options": { - "keyType": "string", - "type": "Value", - "id": 3 - } + "TargetChangeType": { + "values": { + "NO_CHANGE": 0, + "ADD": 1, + "REMOVE": 2, + "CURRENT": 3, + "RESET": 4 } } } }, - "BitSequence": { + "ListCollectionIdsRequest": { + "oneofs": { + "consistencySelector": { + "oneof": [ + "readTime" + ] + } + }, "fields": { - "bitmap": { - "type": "bytes", - "id": 1 + "parent": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } }, - "padding": { + "pageSize": { "type": "int32", "id": 2 + }, + "pageToken": { + "type": "string", + "id": 3 + }, + "readTime": { + "type": "google.protobuf.Timestamp", + "id": 4 } } }, - "BloomFilter": { + "ListCollectionIdsResponse": { "fields": { - "bits": { - "type": "BitSequence", + "collectionIds": { + "rule": "repeated", + "type": "string", "id": 1 }, - "hashCount": { - "type": "int32", + "nextPageToken": { + "type": "string", "id": 2 } } }, - "DocumentMask": { + "BatchWriteRequest": { "fields": { - "fieldPaths": { + "database": { + "type": "string", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "writes": { "rule": "repeated", + "type": "Write", + "id": 2 + }, + "labels": { + "keyType": "string", "type": "string", - "id": 1 + "id": 3 } } }, - "Precondition": { - "oneofs": { - "conditionType": { - "oneof": [ - "exists", - "updateTime" - ] - } - }, + "BatchWriteResponse": { "fields": { - "exists": { - "type": "bool", + "writeResults": { + "rule": "repeated", + "type": "WriteResult", "id": 1 }, - "updateTime": { - "type": "google.protobuf.Timestamp", + "status": { + "rule": "repeated", + "type": "google.rpc.Status", "id": 2 } } }, - "TransactionOptions": { - "oneofs": { - "mode": { - "oneof": [ - "readOnly", - "readWrite" - ] + "StructuredPipeline": { + "fields": { + "pipeline": { + "type": "Pipeline", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "options": { + "keyType": "string", + "type": "Value", + "id": 2, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } } - }, + } + }, + "StructuredQuery": { "fields": { - "readOnly": { - "type": "ReadOnly", + "select": { + "type": "Projection", + "id": 1 + }, + "from": { + "rule": "repeated", + "type": "CollectionSelector", "id": 2 }, - "readWrite": { - "type": "ReadWrite", + "where": { + "type": "Filter", "id": 3 + }, + "orderBy": { + "rule": "repeated", + "type": "Order", + "id": 4 + }, + "startAt": { + "type": "Cursor", + "id": 7 + }, + "endAt": { + "type": "Cursor", + "id": 8 + }, + "offset": { + "type": "int32", + "id": 6 + }, + "limit": { + "type": "google.protobuf.Int32Value", + "id": 5 + }, + "findNearest": { + "type": "FindNearest", + "id": 9, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } } }, "nested": { - "ReadWrite": { + "CollectionSelector": { "fields": { - "retryTransaction": { - "type": "bytes", - "id": 1 + "collectionId": { + "type": "string", + "id": 2 + }, + "allDescendants": { + "type": "bool", + "id": 3 } } }, - "ReadOnly": { + "Filter": { "oneofs": { - "consistencySelector": { + "filterType": { "oneof": [ - "readTime" + "compositeFilter", + "fieldFilter", + "unaryFilter" ] } }, "fields": { - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 2 - } - } - } - } - }, - "Firestore": { - "options": { - "(google.api.default_host)": "firestore.googleapis.com", - "(google.api.oauth_scopes)": "https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/datastore" - }, - "methods": { - "GetDocument": { - "requestType": "GetDocumentRequest", - "responseType": "Document", - "options": { - "(google.api.http).get": "/v1/{name=projects/*/databases/*/documents/*/**}" - }, - "parsedOptions": [ - { - "(google.api.http)": { - "get": "/v1/{name=projects/*/databases/*/documents/*/**}" - } - } - ] - }, - "ListDocuments": { - "requestType": "ListDocumentsRequest", - "responseType": "ListDocumentsResponse", - "options": { - "(google.api.http).get": "/v1/{parent=projects/*/databases/*/documents/*/**}/{collection_id}" - }, - "parsedOptions": [ - { - "(google.api.http)": { - "get": "/v1/{parent=projects/*/databases/*/documents/*/**}/{collection_id}" - } - } - ] - }, - "UpdateDocument": { - "requestType": "UpdateDocumentRequest", - "responseType": "Document", - "options": { - "(google.api.http).patch": "/v1/{document.name=projects/*/databases/*/documents/*/**}", - "(google.api.http).body": "document", - "(google.api.method_signature)": "document,update_mask" - }, - "parsedOptions": [ - { - "(google.api.http)": { - "patch": "/v1/{document.name=projects/*/databases/*/documents/*/**}", - "body": "document" - } - }, - { - "(google.api.method_signature)": "document,update_mask" - } - ] - }, - "DeleteDocument": { - "requestType": "DeleteDocumentRequest", - "responseType": "google.protobuf.Empty", - "options": { - "(google.api.http).delete": "/v1/{name=projects/*/databases/*/documents/*/**}", - "(google.api.method_signature)": "name" - }, - "parsedOptions": [ - { - "(google.api.http)": { - "delete": "/v1/{name=projects/*/databases/*/documents/*/**}" - } - }, - { - "(google.api.method_signature)": "name" - } - ] - }, - "BatchGetDocuments": { - "requestType": "BatchGetDocumentsRequest", - "responseType": "BatchGetDocumentsResponse", - "responseStream": true, - "options": { - "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:batchGet", - "(google.api.http).body": "*" - }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{database=projects/*/databases/*}/documents:batchGet", - "body": "*" - } - } - ] - }, - "BeginTransaction": { - "requestType": "BeginTransactionRequest", - "responseType": "BeginTransactionResponse", - "options": { - "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:beginTransaction", - "(google.api.http).body": "*", - "(google.api.method_signature)": "database" - }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{database=projects/*/databases/*}/documents:beginTransaction", - "body": "*" - } - }, - { - "(google.api.method_signature)": "database" - } - ] - }, - "Commit": { - "requestType": "CommitRequest", - "responseType": "CommitResponse", - "options": { - "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:commit", - "(google.api.http).body": "*", - "(google.api.method_signature)": "database,writes" - }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{database=projects/*/databases/*}/documents:commit", - "body": "*" - } + "compositeFilter": { + "type": "CompositeFilter", + "id": 1 }, - { - "(google.api.method_signature)": "database,writes" + "fieldFilter": { + "type": "FieldFilter", + "id": 2 + }, + "unaryFilter": { + "type": "UnaryFilter", + "id": 3 } - ] + } }, - "Rollback": { - "requestType": "RollbackRequest", - "responseType": "google.protobuf.Empty", - "options": { - "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:rollback", - "(google.api.http).body": "*", - "(google.api.method_signature)": "database,transaction" - }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{database=projects/*/databases/*}/documents:rollback", - "body": "*" - } + "CompositeFilter": { + "fields": { + "op": { + "type": "Operator", + "id": 1 }, - { - "(google.api.method_signature)": "database,transaction" + "filters": { + "rule": "repeated", + "type": "Filter", + "id": 2 } - ] - }, - "RunQuery": { - "requestType": "RunQueryRequest", - "responseType": "RunQueryResponse", - "responseStream": true, - "options": { - "(google.api.http).post": "/v1/{parent=projects/*/databases/*/documents}:runQuery", - "(google.api.http).body": "*", - "(google.api.http).additional_bindings.post": "/v1/{parent=projects/*/databases/*/documents/*/**}:runQuery", - "(google.api.http).additional_bindings.body": "*" }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{parent=projects/*/databases/*/documents}:runQuery", - "body": "*", - "additional_bindings": { - "post": "/v1/{parent=projects/*/databases/*/documents/*/**}:runQuery", - "body": "*" - } + "nested": { + "Operator": { + "values": { + "OPERATOR_UNSPECIFIED": 0, + "AND": 1, + "OR": 2 } } - ] + } }, - "ExecutePipeline": { - "requestType": "ExecutePipelineRequest", - "responseType": "ExecutePipelineResponse", - "responseStream": true, - "options": { - "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:executePipeline", - "(google.api.http).body": "*" + "FieldFilter": { + "fields": { + "field": { + "type": "FieldReference", + "id": 1 + }, + "op": { + "type": "Operator", + "id": 2 + }, + "value": { + "type": "Value", + "id": 3 + } }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{database=projects/*/databases/*}/documents:executePipeline", - "body": "*" + "nested": { + "Operator": { + "values": { + "OPERATOR_UNSPECIFIED": 0, + "LESS_THAN": 1, + "LESS_THAN_OR_EQUAL": 2, + "GREATER_THAN": 3, + "GREATER_THAN_OR_EQUAL": 4, + "EQUAL": 5, + "NOT_EQUAL": 6, + "ARRAY_CONTAINS": 7, + "IN": 8, + "ARRAY_CONTAINS_ANY": 9, + "NOT_IN": 10 } } - ] + } }, - "RunAggregationQuery": { - "requestType": "RunAggregationQueryRequest", - "responseType": "RunAggregationQueryResponse", - "responseStream": true, - "options": { - "(google.api.http).post": "/v1/{parent=projects/*/databases/*/documents}:runAggregationQuery", - "(google.api.http).body": "*", - "(google.api.http).additional_bindings.post": "/v1/{parent=projects/*/databases/*/documents/*/**}:runAggregationQuery", - "(google.api.http).additional_bindings.body": "*" + "UnaryFilter": { + "oneofs": { + "operandType": { + "oneof": [ + "field" + ] + } }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{parent=projects/*/databases/*/documents}:runAggregationQuery", - "body": "*", - "additional_bindings": { - "post": "/v1/{parent=projects/*/databases/*/documents/*/**}:runAggregationQuery", - "body": "*" - } - } + "fields": { + "op": { + "type": "Operator", + "id": 1 + }, + "field": { + "type": "FieldReference", + "id": 2 } - ] - }, - "PartitionQuery": { - "requestType": "PartitionQueryRequest", - "responseType": "PartitionQueryResponse", - "options": { - "(google.api.http).post": "/v1/{parent=projects/*/databases/*/documents}:partitionQuery", - "(google.api.http).body": "*", - "(google.api.http).additional_bindings.post": "/v1/{parent=projects/*/databases/*/documents/*/**}:partitionQuery", - "(google.api.http).additional_bindings.body": "*" }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{parent=projects/*/databases/*/documents}:partitionQuery", - "body": "*", - "additional_bindings": { - "post": "/v1/{parent=projects/*/databases/*/documents/*/**}:partitionQuery", - "body": "*" - } + "nested": { + "Operator": { + "values": { + "OPERATOR_UNSPECIFIED": 0, + "IS_NAN": 2, + "IS_NULL": 3, + "IS_NOT_NAN": 4, + "IS_NOT_NULL": 5 } } - ] + } }, - "Write": { - "requestType": "WriteRequest", - "requestStream": true, - "responseType": "WriteResponse", - "responseStream": true, - "options": { - "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:write", - "(google.api.http).body": "*" - }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{database=projects/*/databases/*}/documents:write", - "body": "*" - } + "Order": { + "fields": { + "field": { + "type": "FieldReference", + "id": 1 + }, + "direction": { + "type": "Direction", + "id": 2 } - ] + } }, - "Listen": { - "requestType": "ListenRequest", - "requestStream": true, - "responseType": "ListenResponse", - "responseStream": true, - "options": { - "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:listen", - "(google.api.http).body": "*" - }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{database=projects/*/databases/*}/documents:listen", - "body": "*" - } + "Direction": { + "values": { + "DIRECTION_UNSPECIFIED": 0, + "ASCENDING": 1, + "DESCENDING": 2 + } + }, + "FieldReference": { + "fields": { + "fieldPath": { + "type": "string", + "id": 2 } - ] + } }, - "ListCollectionIds": { - "requestType": "ListCollectionIdsRequest", - "responseType": "ListCollectionIdsResponse", - "options": { - "(google.api.http).post": "/v1/{parent=projects/*/databases/*/documents}:listCollectionIds", - "(google.api.http).body": "*", - "(google.api.http).additional_bindings.post": "/v1/{parent=projects/*/databases/*/documents/*/**}:listCollectionIds", - "(google.api.http).additional_bindings.body": "*", - "(google.api.method_signature)": "parent" - }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{parent=projects/*/databases/*/documents}:listCollectionIds", - "body": "*", - "additional_bindings": { - "post": "/v1/{parent=projects/*/databases/*/documents/*/**}:listCollectionIds", - "body": "*" - } + "Projection": { + "fields": { + "fields": { + "rule": "repeated", + "type": "FieldReference", + "id": 2 + } + } + }, + "FindNearest": { + "fields": { + "vectorField": { + "type": "FieldReference", + "id": 1, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "queryVector": { + "type": "Value", + "id": 2, + "options": { + "(google.api.field_behavior)": "REQUIRED" } }, - { - "(google.api.method_signature)": "parent" + "distanceMeasure": { + "type": "DistanceMeasure", + "id": 3, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "limit": { + "type": "google.protobuf.Int32Value", + "id": 4, + "options": { + "(google.api.field_behavior)": "REQUIRED" + } + }, + "distanceResultField": { + "type": "string", + "id": 5, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + }, + "distanceThreshold": { + "type": "google.protobuf.DoubleValue", + "id": 6, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } } - ] - }, - "BatchWrite": { - "requestType": "BatchWriteRequest", - "responseType": "BatchWriteResponse", - "options": { - "(google.api.http).post": "/v1/{database=projects/*/databases/*}/documents:batchWrite", - "(google.api.http).body": "*" }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{database=projects/*/databases/*}/documents:batchWrite", - "body": "*" + "nested": { + "DistanceMeasure": { + "values": { + "DISTANCE_MEASURE_UNSPECIFIED": 0, + "EUCLIDEAN": 1, + "COSINE": 2, + "DOT_PRODUCT": 3 } } + } + } + } + }, + "StructuredAggregationQuery": { + "oneofs": { + "queryType": { + "oneof": [ + "structuredQuery" ] + } + }, + "fields": { + "structuredQuery": { + "type": "StructuredQuery", + "id": 1 }, - "CreateDocument": { - "requestType": "CreateDocumentRequest", - "responseType": "Document", + "aggregations": { + "rule": "repeated", + "type": "Aggregation", + "id": 3, "options": { - "(google.api.http).post": "/v1/{parent=projects/*/databases/*/documents/**}/{collection_id}", - "(google.api.http).body": "document" + "(google.api.field_behavior)": "OPTIONAL" + } + } + }, + "nested": { + "Aggregation": { + "oneofs": { + "operator": { + "oneof": [ + "count", + "sum", + "avg" + ] + } }, - "parsedOptions": [ - { - "(google.api.http)": { - "post": "/v1/{parent=projects/*/databases/*/documents/**}/{collection_id}", - "body": "document" + "fields": { + "count": { + "type": "Count", + "id": 1 + }, + "sum": { + "type": "Sum", + "id": 2 + }, + "avg": { + "type": "Avg", + "id": 3 + }, + "alias": { + "type": "string", + "id": 7, + "options": { + "(google.api.field_behavior)": "OPTIONAL" } } - ] + }, + "nested": { + "Count": { + "fields": { + "upTo": { + "type": "google.protobuf.Int64Value", + "id": 1, + "options": { + "(google.api.field_behavior)": "OPTIONAL" + } + } + } + }, + "Sum": { + "fields": { + "field": { + "type": "StructuredQuery.FieldReference", + "id": 1 + } + } + }, + "Avg": { + "fields": { + "field": { + "type": "StructuredQuery.FieldReference", + "id": 1 + } + } + } + } + } + } + }, + "Cursor": { + "fields": { + "values": { + "rule": "repeated", + "type": "Value", + "id": 1 + }, + "before": { + "type": "bool", + "id": 2 } } + } + } + } + } + }, + "api": { + "options": { + "go_package": "google.golang.org/genproto/googleapis/api/annotations;annotations", + "java_multiple_files": true, + "java_outer_classname": "ResourceProto", + "java_package": "com.google.api", + "objc_class_prefix": "GAPI" + }, + "nested": { + "fieldBehavior": { + "rule": "repeated", + "type": "google.api.FieldBehavior", + "id": 1052, + "extend": "google.protobuf.FieldOptions", + "options": { + "packed": false + } + }, + "FieldBehavior": { + "values": { + "FIELD_BEHAVIOR_UNSPECIFIED": 0, + "OPTIONAL": 1, + "REQUIRED": 2, + "OUTPUT_ONLY": 3, + "INPUT_ONLY": 4, + "IMMUTABLE": 5, + "UNORDERED_LIST": 6, + "NON_EMPTY_DEFAULT": 7, + "IDENTIFIER": 8 + } + }, + "http": { + "type": "HttpRule", + "id": 72295728, + "extend": "google.protobuf.MethodOptions" + }, + "Http": { + "fields": { + "rules": { + "rule": "repeated", + "type": "HttpRule", + "id": 1 + }, + "fullyDecodeReservedExpansion": { + "type": "bool", + "id": 2 + } + } + }, + "HttpRule": { + "oneofs": { + "pattern": { + "oneof": [ + "get", + "put", + "post", + "delete", + "patch", + "custom" + ] + } + }, + "fields": { + "selector": { + "type": "string", + "id": 1 + }, + "get": { + "type": "string", + "id": 2 + }, + "put": { + "type": "string", + "id": 3 + }, + "post": { + "type": "string", + "id": 4 + }, + "delete": { + "type": "string", + "id": 5 + }, + "patch": { + "type": "string", + "id": 6 + }, + "custom": { + "type": "CustomHttpPattern", + "id": 8 + }, + "body": { + "type": "string", + "id": 7 + }, + "responseBody": { + "type": "string", + "id": 12 + }, + "additionalBindings": { + "rule": "repeated", + "type": "HttpRule", + "id": 11 + } + } + }, + "CustomHttpPattern": { + "fields": { + "kind": { + "type": "string", + "id": 1 + }, + "path": { + "type": "string", + "id": 2 + } + } + }, + "methodSignature": { + "rule": "repeated", + "type": "string", + "id": 1051, + "extend": "google.protobuf.MethodOptions" + }, + "defaultHost": { + "type": "string", + "id": 1049, + "extend": "google.protobuf.ServiceOptions" + }, + "oauthScopes": { + "type": "string", + "id": 1050, + "extend": "google.protobuf.ServiceOptions" + }, + "apiVersion": { + "type": "string", + "id": 525000001, + "extend": "google.protobuf.ServiceOptions" + }, + "CommonLanguageSettings": { + "fields": { + "referenceDocsUri": { + "type": "string", + "id": 1, + "options": { + "deprecated": true + } }, - "GetDocumentRequest": { - "oneofs": { - "consistencySelector": { - "oneof": [ - "transaction", - "readTime" - ] - } - }, - "fields": { - "name": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "mask": { - "type": "DocumentMask", - "id": 2 - }, - "transaction": { - "type": "bytes", - "id": 3 - }, - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 5 - } - } + "destinations": { + "rule": "repeated", + "type": "ClientLibraryDestination", + "id": 2 }, - "ListDocumentsRequest": { - "oneofs": { - "consistencySelector": { - "oneof": [ - "transaction", - "readTime" - ] - } - }, - "fields": { - "parent": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "collectionId": { - "type": "string", - "id": 2, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "pageSize": { - "type": "int32", - "id": 3 - }, - "pageToken": { - "type": "string", - "id": 4 - }, - "orderBy": { - "type": "string", - "id": 6 - }, - "mask": { - "type": "DocumentMask", - "id": 7 - }, - "transaction": { - "type": "bytes", - "id": 8 - }, - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 10 - }, - "showMissing": { - "type": "bool", - "id": 12 - } - } + "selectiveGapicGeneration": { + "type": "SelectiveGapicGeneration", + "id": 3 + } + } + }, + "ClientLibrarySettings": { + "fields": { + "version": { + "type": "string", + "id": 1 }, - "ListDocumentsResponse": { + "launchStage": { + "type": "LaunchStage", + "id": 2 + }, + "restNumericEnums": { + "type": "bool", + "id": 3 + }, + "javaSettings": { + "type": "JavaSettings", + "id": 21 + }, + "cppSettings": { + "type": "CppSettings", + "id": 22 + }, + "phpSettings": { + "type": "PhpSettings", + "id": 23 + }, + "pythonSettings": { + "type": "PythonSettings", + "id": 24 + }, + "nodeSettings": { + "type": "NodeSettings", + "id": 25 + }, + "dotnetSettings": { + "type": "DotnetSettings", + "id": 26 + }, + "rubySettings": { + "type": "RubySettings", + "id": 27 + }, + "goSettings": { + "type": "GoSettings", + "id": 28 + } + } + }, + "Publishing": { + "fields": { + "methodSettings": { + "rule": "repeated", + "type": "MethodSettings", + "id": 2 + }, + "newIssueUri": { + "type": "string", + "id": 101 + }, + "documentationUri": { + "type": "string", + "id": 102 + }, + "apiShortName": { + "type": "string", + "id": 103 + }, + "githubLabel": { + "type": "string", + "id": 104 + }, + "codeownerGithubTeams": { + "rule": "repeated", + "type": "string", + "id": 105 + }, + "docTagPrefix": { + "type": "string", + "id": 106 + }, + "organization": { + "type": "ClientLibraryOrganization", + "id": 107 + }, + "librarySettings": { + "rule": "repeated", + "type": "ClientLibrarySettings", + "id": 109 + }, + "protoReferenceDocumentationUri": { + "type": "string", + "id": 110 + }, + "restReferenceDocumentationUri": { + "type": "string", + "id": 111 + } + } + }, + "JavaSettings": { + "fields": { + "libraryPackage": { + "type": "string", + "id": 1 + }, + "serviceClassNames": { + "keyType": "string", + "type": "string", + "id": 2 + }, + "common": { + "type": "CommonLanguageSettings", + "id": 3 + } + } + }, + "CppSettings": { + "fields": { + "common": { + "type": "CommonLanguageSettings", + "id": 1 + } + } + }, + "PhpSettings": { + "fields": { + "common": { + "type": "CommonLanguageSettings", + "id": 1 + }, + "libraryPackage": { + "type": "string", + "id": 2 + } + } + }, + "PythonSettings": { + "fields": { + "common": { + "type": "CommonLanguageSettings", + "id": 1 + }, + "experimentalFeatures": { + "type": "ExperimentalFeatures", + "id": 2 + } + }, + "nested": { + "ExperimentalFeatures": { "fields": { - "documents": { - "rule": "repeated", - "type": "Document", + "restAsyncIoEnabled": { + "type": "bool", "id": 1 }, - "nextPageToken": { - "type": "string", + "protobufPythonicTypesEnabled": { + "type": "bool", "id": 2 - } - } - }, - "CreateDocumentRequest": { - "fields": { - "parent": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "collectionId": { - "type": "string", - "id": 2, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } }, - "documentId": { - "type": "string", + "unversionedPackageDisabled": { + "type": "bool", "id": 3 - }, - "document": { - "type": "Document", - "id": 4, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "mask": { - "type": "DocumentMask", - "id": 5 } } + } + } + }, + "NodeSettings": { + "fields": { + "common": { + "type": "CommonLanguageSettings", + "id": 1 + } + } + }, + "DotnetSettings": { + "fields": { + "common": { + "type": "CommonLanguageSettings", + "id": 1 + }, + "renamedServices": { + "keyType": "string", + "type": "string", + "id": 2 + }, + "renamedResources": { + "keyType": "string", + "type": "string", + "id": 3 + }, + "ignoredResources": { + "rule": "repeated", + "type": "string", + "id": 4 + }, + "forcedNamespaceAliases": { + "rule": "repeated", + "type": "string", + "id": 5 + }, + "handwrittenSignatures": { + "rule": "repeated", + "type": "string", + "id": 6 + } + } + }, + "RubySettings": { + "fields": { + "common": { + "type": "CommonLanguageSettings", + "id": 1 + } + } + }, + "GoSettings": { + "fields": { + "common": { + "type": "CommonLanguageSettings", + "id": 1 + }, + "renamedServices": { + "keyType": "string", + "type": "string", + "id": 2 + } + } + }, + "MethodSettings": { + "fields": { + "selector": { + "type": "string", + "id": 1 }, - "UpdateDocumentRequest": { + "longRunning": { + "type": "LongRunning", + "id": 2 + }, + "autoPopulatedFields": { + "rule": "repeated", + "type": "string", + "id": 3 + }, + "batching": { + "type": "BatchingConfigProto", + "id": 4 + } + }, + "nested": { + "LongRunning": { "fields": { - "document": { - "type": "Document", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } + "initialPollDelay": { + "type": "google.protobuf.Duration", + "id": 1 }, - "updateMask": { - "type": "DocumentMask", + "pollDelayMultiplier": { + "type": "float", "id": 2 }, - "mask": { - "type": "DocumentMask", + "maxPollDelay": { + "type": "google.protobuf.Duration", "id": 3 }, - "currentDocument": { - "type": "Precondition", + "totalPollTimeout": { + "type": "google.protobuf.Duration", "id": 4 } } + } + } + }, + "ClientLibraryOrganization": { + "values": { + "CLIENT_LIBRARY_ORGANIZATION_UNSPECIFIED": 0, + "CLOUD": 1, + "ADS": 2, + "PHOTOS": 3, + "STREET_VIEW": 4, + "SHOPPING": 5, + "GEO": 6, + "GENERATIVE_AI": 7 + } + }, + "ClientLibraryDestination": { + "values": { + "CLIENT_LIBRARY_DESTINATION_UNSPECIFIED": 0, + "GITHUB": 10, + "PACKAGE_MANAGER": 20 + } + }, + "SelectiveGapicGeneration": { + "fields": { + "methods": { + "rule": "repeated", + "type": "string", + "id": 1 }, - "DeleteDocumentRequest": { - "fields": { - "name": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "currentDocument": { - "type": "Precondition", - "id": 2 - } + "generateOmittedAsInternal": { + "type": "bool", + "id": 2 + } + } + }, + "BatchingConfigProto": { + "fields": { + "thresholds": { + "type": "BatchingSettingsProto", + "id": 1 + }, + "batchDescriptor": { + "type": "BatchingDescriptorProto", + "id": 2 + } + } + }, + "BatchingSettingsProto": { + "fields": { + "elementCountThreshold": { + "type": "int32", + "id": 1 + }, + "requestByteThreshold": { + "type": "int64", + "id": 2 + }, + "delayThreshold": { + "type": "google.protobuf.Duration", + "id": 3 + }, + "elementCountLimit": { + "type": "int32", + "id": 4 + }, + "requestByteLimit": { + "type": "int32", + "id": 5 + }, + "flowControlElementLimit": { + "type": "int32", + "id": 6 + }, + "flowControlByteLimit": { + "type": "int32", + "id": 7 + }, + "flowControlLimitExceededBehavior": { + "type": "FlowControlLimitExceededBehaviorProto", + "id": 8 + } + } + }, + "FlowControlLimitExceededBehaviorProto": { + "values": { + "UNSET_BEHAVIOR": 0, + "THROW_EXCEPTION": 1, + "BLOCK": 2, + "IGNORE": 3 + } + }, + "BatchingDescriptorProto": { + "fields": { + "batchedField": { + "type": "string", + "id": 1 + }, + "discriminatorFields": { + "rule": "repeated", + "type": "string", + "id": 2 + }, + "subresponseField": { + "type": "string", + "id": 3 + } + } + }, + "LaunchStage": { + "values": { + "LAUNCH_STAGE_UNSPECIFIED": 0, + "UNIMPLEMENTED": 6, + "PRELAUNCH": 7, + "EARLY_ACCESS": 1, + "ALPHA": 2, + "BETA": 3, + "GA": 4, + "DEPRECATED": 5 + } + }, + "routing": { + "type": "google.api.RoutingRule", + "id": 72295729, + "extend": "google.protobuf.MethodOptions" + }, + "RoutingRule": { + "fields": { + "routingParameters": { + "rule": "repeated", + "type": "RoutingParameter", + "id": 2 + } + } + }, + "RoutingParameter": { + "fields": { + "field": { + "type": "string", + "id": 1 + }, + "pathTemplate": { + "type": "string", + "id": 2 + } + } + }, + "resourceReference": { + "type": "google.api.ResourceReference", + "id": 1055, + "extend": "google.protobuf.FieldOptions" + }, + "resourceDefinition": { + "rule": "repeated", + "type": "google.api.ResourceDescriptor", + "id": 1053, + "extend": "google.protobuf.FileOptions" + }, + "resource": { + "type": "google.api.ResourceDescriptor", + "id": 1053, + "extend": "google.protobuf.MessageOptions" + }, + "ResourceDescriptor": { + "fields": { + "type": { + "type": "string", + "id": 1 + }, + "pattern": { + "rule": "repeated", + "type": "string", + "id": 2 + }, + "nameField": { + "type": "string", + "id": 3 + }, + "history": { + "type": "History", + "id": 4 + }, + "plural": { + "type": "string", + "id": 5 + }, + "singular": { + "type": "string", + "id": 6 + }, + "style": { + "rule": "repeated", + "type": "Style", + "id": 10 + } + }, + "nested": { + "History": { + "values": { + "HISTORY_UNSPECIFIED": 0, + "ORIGINALLY_SINGLE_PATTERN": 1, + "FUTURE_MULTI_PATTERN": 2 } }, - "BatchGetDocumentsRequest": { - "oneofs": { - "consistencySelector": { - "oneof": [ - "transaction", - "newTransaction", - "readTime" - ] - } - }, - "fields": { - "database": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "documents": { - "rule": "repeated", - "type": "string", - "id": 2 - }, - "mask": { - "type": "DocumentMask", - "id": 3 - }, - "transaction": { - "type": "bytes", - "id": 4 - }, - "newTransaction": { - "type": "TransactionOptions", - "id": 5 - }, - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 7 - } + "Style": { + "values": { + "STYLE_UNSPECIFIED": 0, + "DECLARATIVE_FRIENDLY": 1 } + } + } + }, + "ResourceReference": { + "fields": { + "type": { + "type": "string", + "id": 1 + }, + "childType": { + "type": "string", + "id": 2 + } + } + } + } + }, + "protobuf": { + "options": { + "go_package": "google.golang.org/protobuf/types/descriptorpb", + "java_package": "com.google.protobuf", + "java_outer_classname": "DescriptorProtos", + "csharp_namespace": "Google.Protobuf.Reflection", + "objc_class_prefix": "GPB", + "cc_enable_arenas": true, + "optimize_for": "SPEED" + }, + "nested": { + "FileDescriptorSet": { + "fields": { + "file": { + "rule": "repeated", + "type": "FileDescriptorProto", + "id": 1 + } + }, + "extensions": [ + [ + 536000000, + 536000000 + ] + ] + }, + "Edition": { + "values": { + "EDITION_UNKNOWN": 0, + "EDITION_LEGACY": 900, + "EDITION_PROTO2": 998, + "EDITION_PROTO3": 999, + "EDITION_2023": 1000, + "EDITION_2024": 1001, + "EDITION_2026": 1002, + "EDITION_UNSTABLE": 9999, + "EDITION_1_TEST_ONLY": 1, + "EDITION_2_TEST_ONLY": 2, + "EDITION_99997_TEST_ONLY": 99997, + "EDITION_99998_TEST_ONLY": 99998, + "EDITION_99999_TEST_ONLY": 99999, + "EDITION_MAX": 2147483647 + } + }, + "FileDescriptorProto": { + "fields": { + "name": { + "type": "string", + "id": 1 + }, + "package": { + "type": "string", + "id": 2 }, - "BatchGetDocumentsResponse": { - "oneofs": { - "result": { - "oneof": [ - "found", - "missing" - ] - } - }, - "fields": { - "found": { - "type": "Document", - "id": 1 - }, - "missing": { - "type": "string", - "id": 2 - }, - "transaction": { - "type": "bytes", - "id": 3 - }, - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 4 - } - } + "dependency": { + "rule": "repeated", + "type": "string", + "id": 3 }, - "BeginTransactionRequest": { - "fields": { - "database": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "options": { - "type": "TransactionOptions", - "id": 2 - } + "publicDependency": { + "rule": "repeated", + "type": "int32", + "id": 10, + "options": { + "packed": false } }, - "BeginTransactionResponse": { - "fields": { - "transaction": { - "type": "bytes", - "id": 1 - } + "weakDependency": { + "rule": "repeated", + "type": "int32", + "id": 11, + "options": { + "packed": false } }, - "CommitRequest": { - "fields": { - "database": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "writes": { - "rule": "repeated", - "type": "Write", - "id": 2 - }, - "transaction": { - "type": "bytes", - "id": 3 - } - } + "optionDependency": { + "rule": "repeated", + "type": "string", + "id": 15 }, - "CommitResponse": { - "fields": { - "writeResults": { - "rule": "repeated", - "type": "WriteResult", - "id": 1 - }, - "commitTime": { - "type": "google.protobuf.Timestamp", - "id": 2 - } - } + "messageType": { + "rule": "repeated", + "type": "DescriptorProto", + "id": 4 }, - "RollbackRequest": { - "fields": { - "database": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "transaction": { - "type": "bytes", - "id": 2, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - } - } + "enumType": { + "rule": "repeated", + "type": "EnumDescriptorProto", + "id": 5 }, - "RunQueryRequest": { - "oneofs": { - "queryType": { - "oneof": [ - "structuredQuery" - ] - }, - "consistencySelector": { - "oneof": [ - "transaction", - "newTransaction", - "readTime" - ] - } - }, - "fields": { - "parent": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "structuredQuery": { - "type": "StructuredQuery", - "id": 2 - }, - "transaction": { - "type": "bytes", - "id": 5 - }, - "newTransaction": { - "type": "TransactionOptions", - "id": 6 - }, - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 7 - } - } + "service": { + "rule": "repeated", + "type": "ServiceDescriptorProto", + "id": 6 }, - "RunQueryResponse": { - "fields": { - "transaction": { - "type": "bytes", - "id": 2 - }, - "document": { - "type": "Document", - "id": 1 - }, - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 3 - }, - "skippedResults": { - "type": "int32", - "id": 4 - } - } + "extension": { + "rule": "repeated", + "type": "FieldDescriptorProto", + "id": 7 }, - "ExecutePipelineRequest": { - "oneofs": { - "pipelineType": { - "oneof": [ - "structuredPipeline" - ] - }, - "consistencySelector": { - "oneof": [ - "transaction", - "newTransaction", - "readTime" - ] - } - }, + "options": { + "type": "FileOptions", + "id": 8 + }, + "sourceCodeInfo": { + "type": "SourceCodeInfo", + "id": 9 + }, + "syntax": { + "type": "string", + "id": 12 + }, + "edition": { + "type": "Edition", + "id": 14 + } + } + }, + "DescriptorProto": { + "fields": { + "name": { + "type": "string", + "id": 1 + }, + "field": { + "rule": "repeated", + "type": "FieldDescriptorProto", + "id": 2 + }, + "extension": { + "rule": "repeated", + "type": "FieldDescriptorProto", + "id": 6 + }, + "nestedType": { + "rule": "repeated", + "type": "DescriptorProto", + "id": 3 + }, + "enumType": { + "rule": "repeated", + "type": "EnumDescriptorProto", + "id": 4 + }, + "extensionRange": { + "rule": "repeated", + "type": "ExtensionRange", + "id": 5 + }, + "oneofDecl": { + "rule": "repeated", + "type": "OneofDescriptorProto", + "id": 8 + }, + "options": { + "type": "MessageOptions", + "id": 7 + }, + "reservedRange": { + "rule": "repeated", + "type": "ReservedRange", + "id": 9 + }, + "reservedName": { + "rule": "repeated", + "type": "string", + "id": 10 + }, + "visibility": { + "type": "SymbolVisibility", + "id": 11 + } + }, + "nested": { + "ExtensionRange": { "fields": { - "database": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } + "start": { + "type": "int32", + "id": 1 }, - "structuredPipeline": { - "type": "StructuredPipeline", + "end": { + "type": "int32", "id": 2 }, - "transaction": { - "type": "bytes", - "id": 5 - }, - "newTransaction": { - "type": "TransactionOptions", - "id": 6 - }, - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 7 + "options": { + "type": "ExtensionRangeOptions", + "id": 3 } } }, - "ExecutePipelineResponse": { + "ReservedRange": { "fields": { - "transaction": { - "type": "bytes", + "start": { + "type": "int32", "id": 1 }, - "results": { - "rule": "repeated", - "type": "Document", + "end": { + "type": "int32", "id": 2 - }, - "executionTime": { - "type": "google.protobuf.Timestamp", - "id": 3 } } + } + } + }, + "ExtensionRangeOptions": { + "fields": { + "uninterpretedOption": { + "rule": "repeated", + "type": "UninterpretedOption", + "id": 999 + }, + "declaration": { + "rule": "repeated", + "type": "Declaration", + "id": 2, + "options": { + "retention": "RETENTION_SOURCE" + } }, - "RunAggregationQueryRequest": { - "oneofs": { - "queryType": { - "oneof": [ - "structuredAggregationQuery" - ] - }, - "consistencySelector": { - "oneof": [ - "transaction", - "newTransaction", - "readTime" - ] - } - }, + "features": { + "type": "FeatureSet", + "id": 50 + }, + "verification": { + "type": "VerificationState", + "id": 3, + "options": { + "default": "UNVERIFIED", + "retention": "RETENTION_SOURCE" + } + } + }, + "extensions": [ + [ + 990, + 998 + ], + [ + 1000, + 536870911 + ] + ], + "nested": { + "Declaration": { "fields": { - "parent": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } + "number": { + "type": "int32", + "id": 1 }, - "structuredAggregationQuery": { - "type": "StructuredAggregationQuery", + "fullName": { + "type": "string", "id": 2 }, - "transaction": { - "type": "bytes", - "id": 4 + "type": { + "type": "string", + "id": 3 }, - "newTransaction": { - "type": "TransactionOptions", + "reserved": { + "type": "bool", "id": 5 }, - "readTime": { - "type": "google.protobuf.Timestamp", + "repeated": { + "type": "bool", "id": 6 } + }, + "reserved": [ + [ + 4, + 4 + ] + ] + }, + "VerificationState": { + "values": { + "DECLARATION": 0, + "UNVERIFIED": 1 } + } + } + }, + "FieldDescriptorProto": { + "fields": { + "name": { + "type": "string", + "id": 1 }, - "RunAggregationQueryResponse": { - "fields": { - "result": { - "type": "AggregationResult", - "id": 1 - }, - "transaction": { - "type": "bytes", - "id": 2 - }, - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 3 - } + "number": { + "type": "int32", + "id": 3 + }, + "label": { + "type": "Label", + "id": 4 + }, + "type": { + "type": "Type", + "id": 5 + }, + "typeName": { + "type": "string", + "id": 6 + }, + "extendee": { + "type": "string", + "id": 2 + }, + "defaultValue": { + "type": "string", + "id": 7 + }, + "oneofIndex": { + "type": "int32", + "id": 9 + }, + "jsonName": { + "type": "string", + "id": 10 + }, + "options": { + "type": "FieldOptions", + "id": 8 + }, + "proto3Optional": { + "type": "bool", + "id": 17 + } + }, + "nested": { + "Type": { + "values": { + "TYPE_DOUBLE": 1, + "TYPE_FLOAT": 2, + "TYPE_INT64": 3, + "TYPE_UINT64": 4, + "TYPE_INT32": 5, + "TYPE_FIXED64": 6, + "TYPE_FIXED32": 7, + "TYPE_BOOL": 8, + "TYPE_STRING": 9, + "TYPE_GROUP": 10, + "TYPE_MESSAGE": 11, + "TYPE_BYTES": 12, + "TYPE_UINT32": 13, + "TYPE_ENUM": 14, + "TYPE_SFIXED32": 15, + "TYPE_SFIXED64": 16, + "TYPE_SINT32": 17, + "TYPE_SINT64": 18 } }, - "PartitionQueryRequest": { - "oneofs": { - "queryType": { - "oneof": [ - "structuredQuery" - ] - } - }, - "fields": { - "parent": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "structuredQuery": { - "type": "StructuredQuery", - "id": 2 - }, - "partitionCount": { - "type": "int64", - "id": 3 - }, - "pageToken": { - "type": "string", - "id": 4 - }, - "pageSize": { - "type": "int32", - "id": 5 - } + "Label": { + "values": { + "LABEL_OPTIONAL": 1, + "LABEL_REPEATED": 3, + "LABEL_REQUIRED": 2 } + } + } + }, + "OneofDescriptorProto": { + "fields": { + "name": { + "type": "string", + "id": 1 + }, + "options": { + "type": "OneofOptions", + "id": 2 + } + } + }, + "EnumDescriptorProto": { + "fields": { + "name": { + "type": "string", + "id": 1 }, - "PartitionQueryResponse": { + "value": { + "rule": "repeated", + "type": "EnumValueDescriptorProto", + "id": 2 + }, + "options": { + "type": "EnumOptions", + "id": 3 + }, + "reservedRange": { + "rule": "repeated", + "type": "EnumReservedRange", + "id": 4 + }, + "reservedName": { + "rule": "repeated", + "type": "string", + "id": 5 + }, + "visibility": { + "type": "SymbolVisibility", + "id": 6 + } + }, + "nested": { + "EnumReservedRange": { "fields": { - "partitions": { - "rule": "repeated", - "type": "Cursor", + "start": { + "type": "int32", "id": 1 }, - "nextPageToken": { - "type": "string", + "end": { + "type": "int32", "id": 2 } } + } + } + }, + "EnumValueDescriptorProto": { + "fields": { + "name": { + "type": "string", + "id": 1 }, - "WriteRequest": { - "fields": { - "database": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "streamId": { - "type": "string", - "id": 2 - }, - "writes": { - "rule": "repeated", - "type": "Write", - "id": 3 - }, - "streamToken": { - "type": "bytes", - "id": 4 - }, - "labels": { - "keyType": "string", - "type": "string", - "id": 5 - } + "number": { + "type": "int32", + "id": 2 + }, + "options": { + "type": "EnumValueOptions", + "id": 3 + } + } + }, + "ServiceDescriptorProto": { + "fields": { + "name": { + "type": "string", + "id": 1 + }, + "method": { + "rule": "repeated", + "type": "MethodDescriptorProto", + "id": 2 + }, + "options": { + "type": "ServiceOptions", + "id": 3 + } + }, + "reserved": [ + [ + 4, + 4 + ], + "stream" + ] + }, + "MethodDescriptorProto": { + "fields": { + "name": { + "type": "string", + "id": 1 + }, + "inputType": { + "type": "string", + "id": 2 + }, + "outputType": { + "type": "string", + "id": 3 + }, + "options": { + "type": "MethodOptions", + "id": 4 + }, + "clientStreaming": { + "type": "bool", + "id": 5, + "options": { + "default": false } }, - "WriteResponse": { - "fields": { - "streamId": { - "type": "string", - "id": 1 - }, - "streamToken": { - "type": "bytes", - "id": 2 - }, - "writeResults": { - "rule": "repeated", - "type": "WriteResult", - "id": 3 - }, - "commitTime": { - "type": "google.protobuf.Timestamp", - "id": 4 - } + "serverStreaming": { + "type": "bool", + "id": 6, + "options": { + "default": false } + } + } + }, + "FileOptions": { + "fields": { + "javaPackage": { + "type": "string", + "id": 1 }, - "ListenRequest": { - "oneofs": { - "targetChange": { - "oneof": [ - "addTarget", - "removeTarget" - ] - } - }, - "fields": { - "database": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "addTarget": { - "type": "Target", - "id": 2 - }, - "removeTarget": { - "type": "int32", - "id": 3 - }, - "labels": { - "keyType": "string", - "type": "string", - "id": 4 - } + "javaOuterClassname": { + "type": "string", + "id": 8 + }, + "javaMultipleFiles": { + "type": "bool", + "id": 10, + "options": { + "default": false, + "feature_support.edition_introduced": "EDITION_PROTO2", + "feature_support.edition_removed": "EDITION_2024", + "feature_support.removal_error": "This behavior is enabled by default in editions 2024 and above. To disable it, you can set `features.(pb.java).nest_in_file_class = YES` on individual messages, enums, or services." } }, - "ListenResponse": { - "oneofs": { - "responseType": { - "oneof": [ - "targetChange", - "documentChange", - "documentDelete", - "documentRemove", - "filter" - ] - } - }, - "fields": { - "targetChange": { - "type": "TargetChange", - "id": 2 - }, - "documentChange": { - "type": "DocumentChange", - "id": 3 - }, - "documentDelete": { - "type": "DocumentDelete", - "id": 4 - }, - "documentRemove": { - "type": "DocumentRemove", - "id": 6 - }, - "filter": { - "type": "ExistenceFilter", - "id": 5 - } + "javaGenerateEqualsAndHash": { + "type": "bool", + "id": 20, + "options": { + "deprecated": true + } + }, + "javaStringCheckUtf8": { + "type": "bool", + "id": 27, + "options": { + "default": false + } + }, + "optimizeFor": { + "type": "OptimizeMode", + "id": 9, + "options": { + "default": "SPEED" + } + }, + "goPackage": { + "type": "string", + "id": 11 + }, + "ccGenericServices": { + "type": "bool", + "id": 16, + "options": { + "default": false } }, - "Target": { - "oneofs": { - "targetType": { - "oneof": [ - "query", - "documents" - ] - }, - "resumeType": { - "oneof": [ - "resumeToken", - "readTime" - ] - } - }, - "fields": { - "query": { - "type": "QueryTarget", - "id": 2 - }, - "documents": { - "type": "DocumentsTarget", - "id": 3 - }, - "resumeToken": { - "type": "bytes", - "id": 4 - }, - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 11 - }, - "targetId": { - "type": "int32", - "id": 5 - }, - "once": { - "type": "bool", - "id": 6 - }, - "expectedCount": { - "type": "google.protobuf.Int32Value", - "id": 12 - } - }, - "nested": { - "DocumentsTarget": { - "fields": { - "documents": { - "rule": "repeated", - "type": "string", - "id": 2 - } - } - }, - "QueryTarget": { - "oneofs": { - "queryType": { - "oneof": [ - "structuredQuery" - ] - } - }, - "fields": { - "parent": { - "type": "string", - "id": 1 - }, - "structuredQuery": { - "type": "StructuredQuery", - "id": 2 - } - } - } + "javaGenericServices": { + "type": "bool", + "id": 17, + "options": { + "default": false } }, - "TargetChange": { - "fields": { - "targetChangeType": { - "type": "TargetChangeType", - "id": 1 - }, - "targetIds": { - "rule": "repeated", - "type": "int32", - "id": 2 - }, - "cause": { - "type": "google.rpc.Status", - "id": 3 - }, - "resumeToken": { - "type": "bytes", - "id": 4 - }, - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 6 - } - }, - "nested": { - "TargetChangeType": { - "values": { - "NO_CHANGE": 0, - "ADD": 1, - "REMOVE": 2, - "CURRENT": 3, - "RESET": 4 - } - } + "pyGenericServices": { + "type": "bool", + "id": 18, + "options": { + "default": false } }, - "ListCollectionIdsRequest": { - "fields": { - "parent": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "pageSize": { - "type": "int32", - "id": 2 - }, - "pageToken": { - "type": "string", - "id": 3 - } + "deprecated": { + "type": "bool", + "id": 23, + "options": { + "default": false } }, - "ListCollectionIdsResponse": { - "fields": { - "collectionIds": { - "rule": "repeated", - "type": "string", - "id": 1 - }, - "nextPageToken": { - "type": "string", - "id": 2 - } + "ccEnableArenas": { + "type": "bool", + "id": 31, + "options": { + "default": true } }, - "BatchWriteRequest": { - "fields": { - "database": { - "type": "string", - "id": 1, - "options": { - "(google.api.field_behavior)": "REQUIRED" - } - }, - "writes": { - "rule": "repeated", - "type": "Write", - "id": 2 - }, - "labels": { - "keyType": "string", - "type": "string", - "id": 3 - } + "objcClassPrefix": { + "type": "string", + "id": 36 + }, + "csharpNamespace": { + "type": "string", + "id": 37 + }, + "swiftPrefix": { + "type": "string", + "id": 39 + }, + "phpClassPrefix": { + "type": "string", + "id": 40 + }, + "phpNamespace": { + "type": "string", + "id": 41 + }, + "phpMetadataNamespace": { + "type": "string", + "id": 44 + }, + "rubyPackage": { + "type": "string", + "id": 45 + }, + "features": { + "type": "FeatureSet", + "id": 50 + }, + "uninterpretedOption": { + "rule": "repeated", + "type": "UninterpretedOption", + "id": 999 + } + }, + "extensions": [ + [ + 990, + 998 + ], + [ + 1000, + 536870911 + ] + ], + "reserved": [ + [ + 42, + 42 + ], + "php_generic_services", + [ + 38, + 38 + ] + ], + "nested": { + "OptimizeMode": { + "values": { + "SPEED": 1, + "CODE_SIZE": 2, + "LITE_RUNTIME": 3 + } + } + } + }, + "MessageOptions": { + "fields": { + "messageSetWireFormat": { + "type": "bool", + "id": 1, + "options": { + "default": false + } + }, + "noStandardDescriptorAccessor": { + "type": "bool", + "id": 2, + "options": { + "default": false } }, - "BatchWriteResponse": { - "fields": { - "writeResults": { - "rule": "repeated", - "type": "WriteResult", - "id": 1 - }, - "status": { - "rule": "repeated", - "type": "google.rpc.Status", - "id": 2 - } + "deprecated": { + "type": "bool", + "id": 3, + "options": { + "default": false } }, - "StructuredPipeline": { - "fields": { - "pipeline": { - "type": "Pipeline", - "id": 1 - }, - "options": { - "keyType": "string", - "type": "Value", - "id": 2 - } + "mapEntry": { + "type": "bool", + "id": 7 + }, + "deprecatedLegacyJsonFieldConflicts": { + "type": "bool", + "id": 11, + "options": { + "deprecated": true } }, - "StructuredQuery": { - "fields": { - "select": { - "type": "Projection", - "id": 1 - }, - "from": { - "rule": "repeated", - "type": "CollectionSelector", - "id": 2 - }, - "where": { - "type": "Filter", - "id": 3 - }, - "orderBy": { - "rule": "repeated", - "type": "Order", - "id": 4 - }, - "startAt": { - "type": "Cursor", - "id": 7 - }, - "endAt": { - "type": "Cursor", - "id": 8 - }, - "offset": { - "type": "int32", - "id": 6 - }, - "limit": { - "type": "google.protobuf.Int32Value", - "id": 5 - } - }, - "nested": { - "CollectionSelector": { - "fields": { - "collectionId": { - "type": "string", - "id": 2 - }, - "allDescendants": { - "type": "bool", - "id": 3 - } - } - }, - "Filter": { - "oneofs": { - "filterType": { - "oneof": [ - "compositeFilter", - "fieldFilter", - "unaryFilter" - ] - } - }, - "fields": { - "compositeFilter": { - "type": "CompositeFilter", - "id": 1 - }, - "fieldFilter": { - "type": "FieldFilter", - "id": 2 - }, - "unaryFilter": { - "type": "UnaryFilter", - "id": 3 - } - } - }, - "CompositeFilter": { - "fields": { - "op": { - "type": "Operator", - "id": 1 - }, - "filters": { - "rule": "repeated", - "type": "Filter", - "id": 2 - } - }, - "nested": { - "Operator": { - "values": { - "OPERATOR_UNSPECIFIED": 0, - "AND": 1, - "OR": 2 - } - } - } - }, - "FieldFilter": { - "fields": { - "field": { - "type": "FieldReference", - "id": 1 - }, - "op": { - "type": "Operator", - "id": 2 - }, - "value": { - "type": "Value", - "id": 3 - } - }, - "nested": { - "Operator": { - "values": { - "OPERATOR_UNSPECIFIED": 0, - "LESS_THAN": 1, - "LESS_THAN_OR_EQUAL": 2, - "GREATER_THAN": 3, - "GREATER_THAN_OR_EQUAL": 4, - "EQUAL": 5, - "NOT_EQUAL": 6, - "ARRAY_CONTAINS": 7, - "IN": 8, - "ARRAY_CONTAINS_ANY": 9, - "NOT_IN": 10 - } - } - } - }, - "UnaryFilter": { - "oneofs": { - "operandType": { - "oneof": [ - "field" - ] - } - }, - "fields": { - "op": { - "type": "Operator", - "id": 1 - }, - "field": { - "type": "FieldReference", - "id": 2 - } - }, - "nested": { - "Operator": { - "values": { - "OPERATOR_UNSPECIFIED": 0, - "IS_NAN": 2, - "IS_NULL": 3, - "IS_NOT_NAN": 4, - "IS_NOT_NULL": 5 - } - } - } - }, - "Order": { - "fields": { - "field": { - "type": "FieldReference", - "id": 1 - }, - "direction": { - "type": "Direction", - "id": 2 - } - } - }, - "FieldReference": { - "fields": { - "fieldPath": { - "type": "string", - "id": 2 - } - } - }, - "Projection": { - "fields": { - "fields": { - "rule": "repeated", - "type": "FieldReference", - "id": 2 - } - } - }, - "Direction": { - "values": { - "DIRECTION_UNSPECIFIED": 0, - "ASCENDING": 1, - "DESCENDING": 2 - } - } + "features": { + "type": "FeatureSet", + "id": 12 + }, + "uninterpretedOption": { + "rule": "repeated", + "type": "UninterpretedOption", + "id": 999 + } + }, + "extensions": [ + [ + 990, + 998 + ], + [ + 1000, + 536870911 + ] + ], + "reserved": [ + [ + 4, + 4 + ], + [ + 5, + 5 + ], + [ + 6, + 6 + ], + [ + 8, + 8 + ], + [ + 9, + 9 + ] + ] + }, + "FieldOptions": { + "fields": { + "ctype": { + "type": "CType", + "id": 1, + "options": { + "default": "STRING" } }, - "StructuredAggregationQuery": { - "oneofs": { - "queryType": { - "oneof": [ - "structuredQuery" - ] - } - }, - "fields": { - "structuredQuery": { - "type": "StructuredQuery", - "id": 1 - }, - "aggregations": { - "rule": "repeated", - "type": "Aggregation", - "id": 3 - } - }, - "nested": { - "Aggregation": { - "oneofs": { - "operator": { - "oneof": [ - "count", - "sum", - "avg" - ] - } - }, - "fields": { - "count": { - "type": "Count", - "id": 1 - }, - "sum": { - "type": "Sum", - "id": 2 - }, - "avg": { - "type": "Avg", - "id": 3 - }, - "alias": { - "type": "string", - "id": 7 - } - }, - "nested": { - "Count": { - "fields": { - "upTo": { - "type": "google.protobuf.Int64Value", - "id": 1 - } - } - }, - "Sum": { - "fields": { - "field": { - "type": "StructuredQuery.FieldReference", - "id": 1 - } - } - }, - "Avg": { - "fields": { - "field": { - "type": "StructuredQuery.FieldReference", - "id": 1 - } - } - } - } - } + "packed": { + "type": "bool", + "id": 2 + }, + "jstype": { + "type": "JSType", + "id": 6, + "options": { + "default": "JS_NORMAL" } }, - "Cursor": { - "fields": { - "values": { - "rule": "repeated", - "type": "Value", - "id": 1 - }, - "before": { - "type": "bool", - "id": 2 - } + "lazy": { + "type": "bool", + "id": 5, + "options": { + "default": false } }, - "Write": { - "oneofs": { - "operation": { - "oneof": [ - "update", - "delete", - "verify", - "transform" - ] - } - }, - "fields": { - "update": { - "type": "Document", - "id": 1 - }, - "delete": { - "type": "string", - "id": 2 - }, - "verify": { - "type": "string", - "id": 5 - }, - "transform": { - "type": "DocumentTransform", - "id": 6 - }, - "updateMask": { - "type": "DocumentMask", - "id": 3 - }, - "updateTransforms": { - "rule": "repeated", - "type": "DocumentTransform.FieldTransform", - "id": 7 - }, - "currentDocument": { - "type": "Precondition", - "id": 4 - } + "unverifiedLazy": { + "type": "bool", + "id": 15, + "options": { + "default": false } }, - "DocumentTransform": { - "fields": { - "document": { - "type": "string", - "id": 1 - }, - "fieldTransforms": { - "rule": "repeated", - "type": "FieldTransform", - "id": 2 - } - }, - "nested": { - "FieldTransform": { - "oneofs": { - "transformType": { - "oneof": [ - "setToServerValue", - "increment", - "maximum", - "minimum", - "appendMissingElements", - "removeAllFromArray" - ] - } - }, - "fields": { - "fieldPath": { - "type": "string", - "id": 1 - }, - "setToServerValue": { - "type": "ServerValue", - "id": 2 - }, - "increment": { - "type": "Value", - "id": 3 - }, - "maximum": { - "type": "Value", - "id": 4 - }, - "minimum": { - "type": "Value", - "id": 5 - }, - "appendMissingElements": { - "type": "ArrayValue", - "id": 6 - }, - "removeAllFromArray": { - "type": "ArrayValue", - "id": 7 - } - }, - "nested": { - "ServerValue": { - "values": { - "SERVER_VALUE_UNSPECIFIED": 0, - "REQUEST_TIME": 1 - } - } - } - } + "deprecated": { + "type": "bool", + "id": 3, + "options": { + "default": false + } + }, + "weak": { + "type": "bool", + "id": 10, + "options": { + "default": false, + "deprecated": true + } + }, + "debugRedact": { + "type": "bool", + "id": 16, + "options": { + "default": false + } + }, + "retention": { + "type": "OptionRetention", + "id": 17 + }, + "targets": { + "rule": "repeated", + "type": "OptionTargetType", + "id": 19, + "options": { + "packed": false + } + }, + "editionDefaults": { + "rule": "repeated", + "type": "EditionDefault", + "id": 20 + }, + "features": { + "type": "FeatureSet", + "id": 21 + }, + "featureSupport": { + "type": "FeatureSupport", + "id": 22 + }, + "uninterpretedOption": { + "rule": "repeated", + "type": "UninterpretedOption", + "id": 999 + } + }, + "extensions": [ + [ + 990, + 998 + ], + [ + 1000, + 536870911 + ] + ], + "reserved": [ + [ + 4, + 4 + ], + [ + 18, + 18 + ] + ], + "nested": { + "CType": { + "values": { + "STRING": 0, + "CORD": 1, + "STRING_PIECE": 2 } }, - "WriteResult": { + "JSType": { + "values": { + "JS_NORMAL": 0, + "JS_STRING": 1, + "JS_NUMBER": 2 + } + }, + "OptionRetention": { + "values": { + "RETENTION_UNKNOWN": 0, + "RETENTION_RUNTIME": 1, + "RETENTION_SOURCE": 2 + } + }, + "OptionTargetType": { + "values": { + "TARGET_TYPE_UNKNOWN": 0, + "TARGET_TYPE_FILE": 1, + "TARGET_TYPE_EXTENSION_RANGE": 2, + "TARGET_TYPE_MESSAGE": 3, + "TARGET_TYPE_FIELD": 4, + "TARGET_TYPE_ONEOF": 5, + "TARGET_TYPE_ENUM": 6, + "TARGET_TYPE_ENUM_ENTRY": 7, + "TARGET_TYPE_SERVICE": 8, + "TARGET_TYPE_METHOD": 9 + } + }, + "EditionDefault": { "fields": { - "updateTime": { - "type": "google.protobuf.Timestamp", - "id": 1 + "edition": { + "type": "Edition", + "id": 3 }, - "transformResults": { - "rule": "repeated", - "type": "Value", + "value": { + "type": "string", "id": 2 } } }, - "DocumentChange": { + "FeatureSupport": { "fields": { - "document": { - "type": "Document", + "editionIntroduced": { + "type": "Edition", "id": 1 }, - "targetIds": { - "rule": "repeated", - "type": "int32", - "id": 5 + "editionDeprecated": { + "type": "Edition", + "id": 2 }, - "removedTargetIds": { - "rule": "repeated", - "type": "int32", - "id": 6 + "deprecationWarning": { + "type": "string", + "id": 3 + }, + "editionRemoved": { + "type": "Edition", + "id": 4 + }, + "removalError": { + "type": "string", + "id": 5 } } + } + } + }, + "OneofOptions": { + "fields": { + "features": { + "type": "FeatureSet", + "id": 1 + }, + "uninterpretedOption": { + "rule": "repeated", + "type": "UninterpretedOption", + "id": 999 + } + }, + "extensions": [ + [ + 990, + 998 + ], + [ + 1000, + 536870911 + ] + ] + }, + "EnumOptions": { + "fields": { + "allowAlias": { + "type": "bool", + "id": 2 + }, + "deprecated": { + "type": "bool", + "id": 3, + "options": { + "default": false + } + }, + "deprecatedLegacyJsonFieldConflicts": { + "type": "bool", + "id": 6, + "options": { + "deprecated": true + } + }, + "features": { + "type": "FeatureSet", + "id": 7 + }, + "uninterpretedOption": { + "rule": "repeated", + "type": "UninterpretedOption", + "id": 999 + } + }, + "extensions": [ + [ + 990, + 998 + ], + [ + 1000, + 536870911 + ] + ], + "reserved": [ + [ + 5, + 5 + ] + ] + }, + "EnumValueOptions": { + "fields": { + "deprecated": { + "type": "bool", + "id": 1, + "options": { + "default": false + } + }, + "features": { + "type": "FeatureSet", + "id": 2 + }, + "debugRedact": { + "type": "bool", + "id": 3, + "options": { + "default": false + } + }, + "featureSupport": { + "type": "FieldOptions.FeatureSupport", + "id": 4 + }, + "uninterpretedOption": { + "rule": "repeated", + "type": "UninterpretedOption", + "id": 999 + } + }, + "extensions": [ + [ + 990, + 998 + ], + [ + 1000, + 536870911 + ] + ] + }, + "ServiceOptions": { + "fields": { + "features": { + "type": "FeatureSet", + "id": 34 + }, + "deprecated": { + "type": "bool", + "id": 33, + "options": { + "default": false + } + }, + "uninterpretedOption": { + "rule": "repeated", + "type": "UninterpretedOption", + "id": 999 + } + }, + "extensions": [ + [ + 990, + 998 + ], + [ + 1000, + 536870911 + ] + ] + }, + "MethodOptions": { + "fields": { + "deprecated": { + "type": "bool", + "id": 33, + "options": { + "default": false + } + }, + "idempotencyLevel": { + "type": "IdempotencyLevel", + "id": 34, + "options": { + "default": "IDEMPOTENCY_UNKNOWN" + } + }, + "features": { + "type": "FeatureSet", + "id": 35 + }, + "uninterpretedOption": { + "rule": "repeated", + "type": "UninterpretedOption", + "id": 999 + } + }, + "extensions": [ + [ + 990, + 998 + ], + [ + 1000, + 536870911 + ] + ], + "nested": { + "IdempotencyLevel": { + "values": { + "IDEMPOTENCY_UNKNOWN": 0, + "NO_SIDE_EFFECTS": 1, + "IDEMPOTENT": 2 + } + } + } + }, + "UninterpretedOption": { + "fields": { + "name": { + "rule": "repeated", + "type": "NamePart", + "id": 2 + }, + "identifierValue": { + "type": "string", + "id": 3 + }, + "positiveIntValue": { + "type": "uint64", + "id": 4 + }, + "negativeIntValue": { + "type": "int64", + "id": 5 + }, + "doubleValue": { + "type": "double", + "id": 6 }, - "DocumentDelete": { - "fields": { - "document": { - "type": "string", - "id": 1 - }, - "removedTargetIds": { - "rule": "repeated", - "type": "int32", - "id": 6 - }, - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 4 - } - } + "stringValue": { + "type": "bytes", + "id": 7 }, - "DocumentRemove": { + "aggregateValue": { + "type": "string", + "id": 8 + } + }, + "nested": { + "NamePart": { "fields": { - "document": { + "namePart": { + "rule": "required", "type": "string", "id": 1 }, - "removedTargetIds": { - "rule": "repeated", - "type": "int32", + "isExtension": { + "rule": "required", + "type": "bool", "id": 2 - }, - "readTime": { - "type": "google.protobuf.Timestamp", - "id": 4 } } + } + } + }, + "FeatureSet": { + "fields": { + "fieldPresence": { + "type": "FieldPresence", + "id": 1, + "options": { + "retention": "RETENTION_RUNTIME", + "targets": "TARGET_TYPE_FILE", + "feature_support.edition_introduced": "EDITION_2023", + "edition_defaults.edition": "EDITION_2023", + "edition_defaults.value": "EXPLICIT" + } }, - "ExistenceFilter": { - "fields": { - "targetId": { - "type": "int32", - "id": 1 - }, - "count": { - "type": "int32", - "id": 2 - }, - "unchangedNames": { - "type": "BloomFilter", - "id": 3 - } + "enumType": { + "type": "EnumType", + "id": 2, + "options": { + "retention": "RETENTION_RUNTIME", + "targets": "TARGET_TYPE_FILE", + "feature_support.edition_introduced": "EDITION_2023", + "edition_defaults.edition": "EDITION_PROTO3", + "edition_defaults.value": "OPEN" } }, - "ExplainOptions": { - "fields": { - "analyze": { - "type": "bool", - "id": 1, - "options": { - "(google.api.field_behavior)": "OPTIONAL" + "repeatedFieldEncoding": { + "type": "RepeatedFieldEncoding", + "id": 3, + "options": { + "retention": "RETENTION_RUNTIME", + "targets": "TARGET_TYPE_FILE", + "feature_support.edition_introduced": "EDITION_2023", + "edition_defaults.edition": "EDITION_PROTO3", + "edition_defaults.value": "PACKED" + } + }, + "utf8Validation": { + "type": "Utf8Validation", + "id": 4, + "options": { + "retention": "RETENTION_RUNTIME", + "targets": "TARGET_TYPE_FILE", + "feature_support.edition_introduced": "EDITION_2023", + "edition_defaults.edition": "EDITION_PROTO3", + "edition_defaults.value": "VERIFY" + } + }, + "messageEncoding": { + "type": "MessageEncoding", + "id": 5, + "options": { + "retention": "RETENTION_RUNTIME", + "targets": "TARGET_TYPE_FILE", + "feature_support.edition_introduced": "EDITION_2023", + "edition_defaults.edition": "EDITION_LEGACY", + "edition_defaults.value": "LENGTH_PREFIXED" + } + }, + "jsonFormat": { + "type": "JsonFormat", + "id": 6, + "options": { + "retention": "RETENTION_RUNTIME", + "targets": "TARGET_TYPE_FILE", + "feature_support.edition_introduced": "EDITION_2023", + "edition_defaults.edition": "EDITION_PROTO3", + "edition_defaults.value": "ALLOW" + } + }, + "enforceNamingStyle": { + "type": "EnforceNamingStyle", + "id": 7, + "options": { + "retention": "RETENTION_SOURCE", + "targets": "TARGET_TYPE_METHOD", + "feature_support.edition_introduced": "EDITION_2024", + "edition_defaults.edition": "EDITION_UNSTABLE", + "edition_defaults.value": "STYLE2026" + } + }, + "defaultSymbolVisibility": { + "type": "VisibilityFeature.DefaultSymbolVisibility", + "id": 8, + "options": { + "retention": "RETENTION_SOURCE", + "targets": "TARGET_TYPE_FILE", + "feature_support.edition_introduced": "EDITION_2024", + "edition_defaults.edition": "EDITION_2024", + "edition_defaults.value": "EXPORT_TOP_LEVEL" + } + } + }, + "extensions": [ + [ + 1000, + 9994 + ], + [ + 9995, + 9999 + ], + [ + 10000, + 10000 + ] + ], + "reserved": [ + [ + 999, + 999 + ] + ], + "nested": { + "FieldPresence": { + "values": { + "FIELD_PRESENCE_UNKNOWN": 0, + "EXPLICIT": 1, + "IMPLICIT": 2, + "LEGACY_REQUIRED": 3 + } + }, + "EnumType": { + "values": { + "ENUM_TYPE_UNKNOWN": 0, + "OPEN": 1, + "CLOSED": 2 + } + }, + "RepeatedFieldEncoding": { + "values": { + "REPEATED_FIELD_ENCODING_UNKNOWN": 0, + "PACKED": 1, + "EXPANDED": 2 + } + }, + "Utf8Validation": { + "values": { + "UTF8_VALIDATION_UNKNOWN": 0, + "VERIFY": 2, + "NONE": 3 + }, + "reserved": [ + [ + 1, + 1 + ] + ] + }, + "MessageEncoding": { + "values": { + "MESSAGE_ENCODING_UNKNOWN": 0, + "LENGTH_PREFIXED": 1, + "DELIMITED": 2 + } + }, + "JsonFormat": { + "values": { + "JSON_FORMAT_UNKNOWN": 0, + "ALLOW": 1, + "LEGACY_BEST_EFFORT": 2 + } + }, + "EnforceNamingStyle": { + "values": { + "ENFORCE_NAMING_STYLE_UNKNOWN": 0, + "STYLE2024": 1, + "STYLE_LEGACY": 2, + "STYLE2026": 3 + } + }, + "VisibilityFeature": { + "fields": {}, + "reserved": [ + [ + 1, + 536870911 + ] + ], + "nested": { + "DefaultSymbolVisibility": { + "values": { + "DEFAULT_SYMBOL_VISIBILITY_UNKNOWN": 0, + "EXPORT_ALL": 1, + "EXPORT_TOP_LEVEL": 2, + "LOCAL_ALL": 3, + "STRICT": 4 } } } + } + } + }, + "FeatureSetDefaults": { + "fields": { + "defaults": { + "rule": "repeated", + "type": "FeatureSetEditionDefault", + "id": 1 }, - "ExplainMetrics": { + "minimumEdition": { + "type": "Edition", + "id": 4 + }, + "maximumEdition": { + "type": "Edition", + "id": 5 + } + }, + "nested": { + "FeatureSetEditionDefault": { "fields": { - "planSummary": { - "type": "PlanSummary", - "id": 1 + "edition": { + "type": "Edition", + "id": 3 }, - "executionStats": { - "type": "ExecutionStats", - "id": 2 + "overridableFeatures": { + "type": "FeatureSet", + "id": 4 + }, + "fixedFeatures": { + "type": "FeatureSet", + "id": 5 } - } - }, - "PlanSummary": { + }, + "reserved": [ + [ + 1, + 1 + ], + [ + 2, + 2 + ], + "features" + ] + } + } + }, + "SourceCodeInfo": { + "fields": { + "location": { + "rule": "repeated", + "type": "Location", + "id": 1 + } + }, + "extensions": [ + [ + 536000000, + 536000000 + ] + ], + "nested": { + "Location": { "fields": { - "indexesUsed": { + "path": { "rule": "repeated", - "type": "google.protobuf.Struct", - "id": 1 - } - } - }, - "ExecutionStats": { - "fields": { - "resultsReturned": { - "type": "int64", + "type": "int32", "id": 1 }, - "executionDuration": { - "type": "google.protobuf.Duration", + "span": { + "rule": "repeated", + "type": "int32", + "id": 2 + }, + "leadingComments": { + "type": "string", "id": 3 }, - "readOperations": { - "type": "int64", + "trailingComments": { + "type": "string", "id": 4 }, - "debugStats": { - "type": "google.protobuf.Struct", - "id": 5 + "leadingDetachedComments": { + "rule": "repeated", + "type": "string", + "id": 6 } } } } - } - } - }, - "type": { - "options": { - "cc_enable_arenas": true, - "go_package": "google.golang.org/genproto/googleapis/type/latlng;latlng", - "java_multiple_files": true, - "java_outer_classname": "LatLngProto", - "java_package": "com.google.type", - "objc_class_prefix": "GTP" - }, - "nested": { - "LatLng": { + }, + "GeneratedCodeInfo": { "fields": { - "latitude": { - "type": "double", + "annotation": { + "rule": "repeated", + "type": "Annotation", "id": 1 - }, - "longitude": { - "type": "double", - "id": 2 + } + }, + "nested": { + "Annotation": { + "fields": { + "path": { + "rule": "repeated", + "type": "int32", + "id": 1 + }, + "sourceFile": { + "type": "string", + "id": 2 + }, + "begin": { + "type": "int32", + "id": 3 + }, + "end": { + "type": "int32", + "id": 4 + }, + "semantic": { + "type": "Semantic", + "id": 5 + } + }, + "nested": { + "Semantic": { + "values": { + "NONE": 0, + "SET": 1, + "ALIAS": 2 + } + } + } } } - } - } - }, - "api": { - "options": { - "go_package": "google.golang.org/genproto/googleapis/api/annotations;annotations", - "java_multiple_files": true, - "java_outer_classname": "FieldBehaviorProto", - "java_package": "com.google.api", - "objc_class_prefix": "GAPI", - "cc_enable_arenas": true - }, - "nested": { - "http": { - "type": "HttpRule", - "id": 72295728, - "extend": "google.protobuf.MethodOptions" }, - "Http": { + "SymbolVisibility": { + "values": { + "VISIBILITY_UNSET": 0, + "VISIBILITY_LOCAL": 1, + "VISIBILITY_EXPORT": 2 + } + }, + "Struct": { "fields": { - "rules": { - "rule": "repeated", - "type": "HttpRule", + "fields": { + "keyType": "string", + "type": "Value", "id": 1 - }, - "fullyDecodeReservedExpansion": { - "type": "bool", - "id": 2 } } }, - "HttpRule": { + "Value": { "oneofs": { - "pattern": { + "kind": { "oneof": [ - "get", - "put", - "post", - "delete", - "patch", - "custom" + "nullValue", + "numberValue", + "stringValue", + "boolValue", + "structValue", + "listValue" ] } }, "fields": { - "selector": { - "type": "string", + "nullValue": { + "type": "NullValue", "id": 1 }, - "get": { - "type": "string", + "numberValue": { + "type": "double", "id": 2 }, - "put": { + "stringValue": { "type": "string", "id": 3 }, - "post": { - "type": "string", + "boolValue": { + "type": "bool", "id": 4 }, - "delete": { - "type": "string", + "structValue": { + "type": "Struct", "id": 5 }, - "patch": { - "type": "string", + "listValue": { + "type": "ListValue", "id": 6 + } + } + }, + "NullValue": { + "values": { + "NULL_VALUE": 0 + } + }, + "ListValue": { + "fields": { + "values": { + "rule": "repeated", + "type": "Value", + "id": 1 + } + } + }, + "Timestamp": { + "fields": { + "seconds": { + "type": "int64", + "id": 1 }, - "custom": { - "type": "CustomHttpPattern", - "id": 8 - }, - "body": { - "type": "string", - "id": 7 - }, - "responseBody": { + "nanos": { + "type": "int32", + "id": 2 + } + } + }, + "Any": { + "fields": { + "type_url": { "type": "string", - "id": 12 + "id": 1 }, - "additionalBindings": { - "rule": "repeated", - "type": "HttpRule", - "id": 11 + "value": { + "type": "bytes", + "id": 2 } } }, - "CustomHttpPattern": { + "Duration": { "fields": { - "kind": { - "type": "string", + "seconds": { + "type": "int64", "id": 1 }, - "path": { - "type": "string", + "nanos": { + "type": "int32", "id": 2 } } }, - "methodSignature": { - "rule": "repeated", - "type": "string", - "id": 1051, - "extend": "google.protobuf.MethodOptions" + "DoubleValue": { + "fields": { + "value": { + "type": "double", + "id": 1 + } + } }, - "defaultHost": { - "type": "string", - "id": 1049, - "extend": "google.protobuf.ServiceOptions" + "FloatValue": { + "fields": { + "value": { + "type": "float", + "id": 1 + } + } }, - "oauthScopes": { - "type": "string", - "id": 1050, - "extend": "google.protobuf.ServiceOptions" + "Int64Value": { + "fields": { + "value": { + "type": "int64", + "id": 1 + } + } }, - "fieldBehavior": { - "rule": "repeated", - "type": "google.api.FieldBehavior", - "id": 1052, - "extend": "google.protobuf.FieldOptions" + "UInt64Value": { + "fields": { + "value": { + "type": "uint64", + "id": 1 + } + } }, - "FieldBehavior": { - "values": { - "FIELD_BEHAVIOR_UNSPECIFIED": 0, - "OPTIONAL": 1, - "REQUIRED": 2, - "OUTPUT_ONLY": 3, - "INPUT_ONLY": 4, - "IMMUTABLE": 5, - "UNORDERED_LIST": 6, - "NON_EMPTY_DEFAULT": 7 + "Int32Value": { + "fields": { + "value": { + "type": "int32", + "id": 1 + } + } + }, + "UInt32Value": { + "fields": { + "value": { + "type": "uint32", + "id": 1 + } + } + }, + "BoolValue": { + "fields": { + "value": { + "type": "bool", + "id": 1 + } + } + }, + "StringValue": { + "fields": { + "value": { + "type": "string", + "id": 1 + } + } + }, + "BytesValue": { + "fields": { + "value": { + "type": "bytes", + "id": 1 + } + } + }, + "Empty": { + "fields": {} + } + } + }, + "type": { + "options": { + "go_package": "google.golang.org/genproto/googleapis/type/latlng;latlng", + "java_multiple_files": true, + "java_outer_classname": "LatLngProto", + "java_package": "com.google.type", + "objc_class_prefix": "GTP" + }, + "nested": { + "LatLng": { + "fields": { + "latitude": { + "type": "double", + "id": 1 + }, + "longitude": { + "type": "double", + "id": 2 + } } } } }, "rpc": { "options": { - "cc_enable_arenas": true, "go_package": "google.golang.org/genproto/googleapis/rpc/status;status", "java_multiple_files": true, "java_outer_classname": "StatusProto", diff --git a/packages/firestore/src/protos/update.sh b/packages/firestore/src/protos/update.sh index 9f2ea2bce0..a0defe6985 100755 --- a/packages/firestore/src/protos/update.sh +++ b/packages/firestore/src/protos/update.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright 2017 Google Inc. +# Copyright 2026 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,10 +17,16 @@ set -euo pipefail IFS=$'\n\t' -# Variables +# Verify dependencies +for cmd in git patch npx; do + if ! command -v "$cmd" &> /dev/null; then + echo "Error: $cmd is required but not installed." >&2 + exit 1 + fi +done + PROTOS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -WORK_DIR=`mktemp -d` -PBJS="$(npm bin)/pbjs" +WORK_DIR=$(mktemp -d) # deletes the temp directory on exit function cleanup { @@ -32,15 +38,15 @@ function cleanup { trap cleanup EXIT # Enter work dir -pushd "$WORK_DIR" +pushd "$WORK_DIR" > /dev/null -# Clone necessary git repos. +# Clone necessary git repos git clone --depth 1 https://github.com/googleapis/googleapis.git git clone --depth 1 https://github.com/google/protobuf.git # Copy necessary protos. mkdir -p "${PROTOS_DIR}/google/api" -cp googleapis/google/api/{annotations.proto,http.proto,client.proto,field_behavior.proto} \ +cp googleapis/google/api/{annotations.proto,http.proto,client.proto,field_behavior.proto,launch_stage.proto,routing.proto,resource.proto} \ "${PROTOS_DIR}/google/api/" mkdir -p "${PROTOS_DIR}/google/firestore/v1" @@ -55,22 +61,17 @@ mkdir -p "${PROTOS_DIR}/google/type" cp googleapis/google/type/latlng.proto \ "${PROTOS_DIR}/google/type/" -# Hack in `verify` support -ex "${PROTOS_DIR}/google/firestore/v1/write.proto" < /dev/null + +# Apply patch for `verify` support +if [ -f "${PROTOS_DIR}/verify.patch" ]; then + patch -f -d "${PROTOS_DIR}" -p1 < "${PROTOS_DIR}/verify.patch" + find "${PROTOS_DIR}" -name "*.orig" -delete +fi + +# Run compile script to generate outputs +bash "${PROTOS_DIR}/compile.sh" diff --git a/packages/firestore/src/protos/verify.patch b/packages/firestore/src/protos/verify.patch new file mode 100644 index 0000000000..1b5e74212c --- /dev/null +++ b/packages/firestore/src/protos/verify.patch @@ -0,0 +1,15 @@ +--- a/google/firestore/v1/write.proto ++++ b/google/firestore/v1/write.proto +@@ -38,6 +38,11 @@ + // A document name to delete. In the format: + // `projects/{project_id}/databases/{database_id}/documents/{document_path}`. + string delete = 2; + ++ // The name of a document on which to verify the `current_document` ++ // precondition. ++ // This only requires read access to the document. ++ string verify = 5; ++ + // Applies a transformation to a document. + DocumentTransform transform = 6; + } \ No newline at end of file From 77018d7c5f05ba45552b47183c7b55a16da4affd Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 21 Apr 2026 13:22:14 -0400 Subject: [PATCH 144/174] chore(firestore): improve contributor documentation and test infra (#9864) --- packages/firestore/CONTRIBUTING.md | 148 ++++++++++++++++-------- packages/firestore/package.json | 2 + packages/firestore/scripts/run-tests.ts | 39 ++++++- 3 files changed, 135 insertions(+), 54 deletions(-) diff --git a/packages/firestore/CONTRIBUTING.md b/packages/firestore/CONTRIBUTING.md index 49780249ea..eef05cf6cf 100644 --- a/packages/firestore/CONTRIBUTING.md +++ b/packages/firestore/CONTRIBUTING.md @@ -7,70 +7,118 @@ the testing environment. ## Integration Testing -### Setting up a project for testing +### Setting up the Firestore emulator -You will need a production project to test the Firestore SDK. You can create -a new project by visiting the -[Firebase Console](https://console.firebase.google.com/). Make sure that the -project has Cloud Firestore enabled in the database section of the console. +Integration tests that run against the Firestore emulator expect +that it runs on port 8080. + +- [Install the Firebase CLI](https://firebase.google.com/docs/cli/). + ```bash + npm install -g firebase-tools + ``` +- [Install the Firestore emulator](https://firebase.google.com/docs/firestore/security/test-rules-emulator#install_the_emulator). + ```bash + firebase setup:emulators:firestore + ``` +- Run the emulator: + ```bash + firebase emulators:start --only firestore + ``` + +## Testing Firestore + +Testing Firestore is organized along three dimensions: + +1. **Environment**: Where the code runs. + - **Node.js**: Fast, V8-based testing using Mocha. Perfect for logic that doesn't require a browser. + - **Browsers**: Uses Karma to run tests in real browser engines (Chrome, Firefox, WebKit). Essential for testing IndexedDB and WebChannels. +2. **SDK Type**: Which version of the SDK is being tested. + - **Full SDK**: Includes real-time listeners, offline persistence, and caching. + - **Lite SDK**: A REST-only, lightweight version without persistence or real-time support. +3. **Backend**: Which server the tests communicate with. + - **Emulator**: Local server (default). + - **Production**: The live Firebase backend. + - **Nightly**: Pre-release backend for catching upcoming server changes. + +### Running Tests + +All commands must be run from the `packages/firestore/` directory. + +```bash +# Full SDK - Node (Emulator) +yarn test:node -See -[Automated Setup](https://github.com/firebase/firebase-js-sdk#automated-setup) -for more details. +# Full SDK - Browser (Chrome Headless, Emulator) +yarn test:browser -### Setting up the Firestore emulator +# Lite SDK - Node (Emulator) +yarn test:lite -The integration tests require that the Firestore emulator is running -on port 8080, which is default when running it via CLI. +# Lite SDK - Browser (Chrome Headless, Emulator) +yarn test:lite:browser +``` - * [Install the Firebase CLI](https://firebase.google.com/docs/cli/). - ``` - npm install -g firebase-tools - ``` - * [Install the Firestore - emulator](https://firebase.google.com/docs/firestore/security/test-rules-emulator#install_the_emulator). - ``` - firebase setup:emulators:firestore - ``` - * Run the emulator - ``` - firebase emulators:start --only firestore - ``` +### Environment Variables & Flags -### Running Firestore Tests +Use these variables to change the target backend or database: -All commands must be run from the `packages/firestore/` directory. +- **`FIRESTORE_TARGET_BACKEND`**: Set to `emulator`, `prod`, or `nightly`. `nightly` is only available to Googlers. +- **`FIRESTORE_TARGET_DB_ID`**: Targets a specific database ID (default is `(default)`). +- **`--firestoreEdition=enterprise`**: Enables enterprise-specific tests (sets `RUN_ENTERPRISE_TESTS=true`). +- **`BROWSERS`**: (Browser tests only) A comma-separated list of browsers: `ChromeHeadless`, `Firefox`, `WebkitHeadless`. + - Example: `BROWSERS=Firefox,WebkitHeadless yarn test:browser` -``` -# Come up to date on dependencies after performing git pull -(cd ../../; yarn && yarn build) +### Persistence -# Run all tests once (browser and node) -yarn test +- **Browsers**: Persistence (IndexedDB) is tested natively. +- **Node.js**: Node lacks a native database. Use `yarn test:node:persistence` to enable a mock persistence layer for testing offline logic in Node. -# Run all browser tests once (unit and integration) -yarn test:browser +### Filtering Tests (Grep) -# Debug browser tests in Chrome and keep the browser open (and watch for file -# changes). -yarn test:browser:debug +Use the `--grep` flag to run specific tests. -# Run only the browser unit or integration tests -yarn test:browser --unit -yarn test:browser --integration +```bash +yarn test:node --grep 'SortedSet' +yarn test:browser --grep 'Query' +``` -# Run browser integration tests against a Firestore server running on -# localhost:8080. -yarn test:browser:emulator --integration +## Testing Firestore Pipelines -# Run all node tests once (unit and integration) against the emulator. -yarn test:node +### Enterprise Edition & Database IDs + +To test Pipeline features that require the Enterprise backend: + +- **Named Databases**: Use a database ID other than `(default)`. In our automated tests, we typically use the ID `enterprise`. +- **Edition Flag**: Pass `--firestoreEdition=enterprise` to enable Enterprise-specific test cases and assertions. -# Run a subset of tests whose names match a filter. -yarn test:browser --grep 'SortedSet keeps elements in the right order' -yarn test:node --grep 'SortedSet keeps elements in the right order' +Example: Running Pipeline integration tests against production with an enterprise database: -# Run tests against the production backend. -yarn test:node:prod -yarn test:node:persistence:prod +```bash +yarn test:node:prod:enterprise --grep 'Pipeline' ``` + +### Testing Environments for Pipelines + +- **Emulator**: Supports basic pipeline structures and some aggregations. +- **Nightly**: Preferred for testing new Pipeline features before they reach Production. Use `FIRESTORE_TARGET_BACKEND=nightly`. +- **Production**: Used for final validation of released Pipeline features. + +## Debugging + +### CLI Debugging + +We provide `:debug` scripts that wait for a debugger to attach: + +- **Node**: `yarn test:node:debug` (uses `node --inspect-brk`). +- **Browser**: `yarn test:browser:debug` (keeps Chrome open and watches for file changes). + +### VSCode Debugging + +Use the **Run and Debug** pane in VSCode. Recommended configurations: + +- **Firestore Unit Tests (Node)**: Fast debugging for Node logic. +- **Firestore Integration Tests (Node)**: Debugs against the emulator. +- **Firestore Integration Tests (Browser)**: Debugs in Chrome. +- **Firestore Enterprise Lite Tests**: Debugs Lite SDK against Nightly/Enterprise. + +Most configurations will prompt you for a `grepString` to filter tests before starting. diff --git a/packages/firestore/package.json b/packages/firestore/package.json index e37e032494..7425412d99 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -45,6 +45,8 @@ "test:node": "ts-node ./scripts/run-tests.ts --main=test/register.ts --emulator 'test/{,!(browser|lite)/**/}*.test.ts'", "test:node:prod": "ts-node ./scripts/run-tests.ts --main=test/register.ts 'test/{,!(browser|lite)/**/}*.test.ts'", "test:node:prod:enterprise": "ts-node ./scripts/run-tests.ts --main=test/register.ts --databaseId=enterprise --firestoreEdition=enterprise 'test/{,!(browser|lite)/**/}*.test.ts'", + "test:node:nightly": "ts-node ./scripts/run-tests.ts --main=test/register.ts 'test/{,!(browser|lite)/**/}*.test.ts' --targetBackend=nightly", + "test:node:debug": "ts-node ./scripts/run-tests.ts --main=test/register.ts --emulator --debug 'test/{,!(browser|lite)/**/}*.test.ts'", "test:node:persistence": "ts-node ./scripts/run-tests.ts --main=test/register.ts --persistence --emulator 'test/{,!(browser|lite)/**/}*.test.ts'", "test:node:persistence:prod": "ts-node ./scripts/run-tests.ts --main=test/register.ts --persistence 'test/{,!(browser|lite)/**/}*.test.ts'", "test:travis": "ts-node --compiler-options='{\"module\":\"commonjs\"}' ../../scripts/emulator-testing/firestore-test-runner.ts", diff --git a/packages/firestore/scripts/run-tests.ts b/packages/firestore/scripts/run-tests.ts index 2ec66ce167..c65206756b 100644 --- a/packages/firestore/scripts/run-tests.ts +++ b/packages/firestore/scripts/run-tests.ts @@ -46,6 +46,14 @@ const argv = yargs type: 'string', description: 'Filter tests by name (regex)' }, + targetBackend: { + type: 'string', + description: 'The backend to test against (emulator, prod, nightly)' + }, + debug: { + type: 'boolean', + description: 'Run tests in debug mode (node --inspect-brk)' + } }) .parseSync(); @@ -57,6 +65,11 @@ const babel = resolve(__dirname, '../babel-register.js'); process.env.NO_TS_NODE = 'true'; process.env.TEST_PLATFORM = argv.platform; +if (argv.targetBackend) { + process.env.FIRESTORE_TARGET_BACKEND = argv.targetBackend; +} + +let executable = nyc; let args = [ '--reporter', 'lcovonly', @@ -69,6 +82,22 @@ let args = [ '../../config/mocharc.node.js' ]; +if (argv.debug) { + // Bypassing nyc for debug mode + executable = 'node'; + args = [ + '--inspect-brk', + mocha, + '--require', + babel, + '--require', + argv.main, + '--config', + '../../config/mocharc.node.js', + '--no-timeouts' + ]; +} + if (argv.emulator) { process.env.FIRESTORE_TARGET_BACKEND = 'emulator'; } @@ -94,7 +123,7 @@ if (argv.grep) { args = args.concat(argv._ as string[]); -const spawnPromise = spawn(nyc, args, { +const spawnPromise = spawn(executable, args, { stdio: 'inherit', cwd: process.cwd() }); @@ -104,11 +133,13 @@ const childProcess = spawnPromise.childProcess; spawnPromise.catch(error => { // When a test fails, there will be a non-zero error code. Simply exit this process, // and don't print a stack trace. - if (typeof error.code === 'number') { + // Note: error.code is the exit code of the spawned process. + if (typeof error.code === 'number' && error.code > 0) { + // If it's a standard test failure (mocha exit code), we don't need a runner stack trace. process.exit(error.code); } else { - // The error code will not be a number for a real crash (e.g., spawn - // failed to start), so print the entire stack trace for debugging. + // For other errors (spawn failed, runner crash, etc.), print the stack trace. + console.error('Test runner failed to execute:'); console.error(error); process.exit(1); } From 1517d1d23d7b2c2a6e9fb2d66d1a4d82bda5aeb5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:41:00 -0700 Subject: [PATCH 145/174] build(deps): bump follow-redirects in /e2e/smoke-tests (#9855) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.9 to 1.16.0. - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.9...v1.16.0) --- updated-dependencies: - dependency-name: follow-redirects dependency-version: 1.16.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- e2e/smoke-tests/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/smoke-tests/yarn.lock b/e2e/smoke-tests/yarn.lock index 636c64fb01..2f815ecfb2 100644 --- a/e2e/smoke-tests/yarn.lock +++ b/e2e/smoke-tests/yarn.lock @@ -3781,9 +3781,9 @@ flat@^5.0.2: integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== follow-redirects@^1.0.0: - version "1.15.9" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz" - integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + version "1.16.0" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" + integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== foreground-child@^3.1.0: version "3.3.1" From 7415cf0978f7e533260712c24b86d2494ab8caed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:41:21 -0700 Subject: [PATCH 146/174] build(deps): bump protobufjs from 7.4.0 to 7.5.5 in /e2e/smoke-tests (#9854) Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.4.0 to 7.5.5. - [Release notes](https://github.com/protobufjs/protobuf.js/releases) - [Changelog](https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.4.0...protobufjs-v7.5.5) --- updated-dependencies: - dependency-name: protobufjs dependency-version: 7.5.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- e2e/smoke-tests/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/smoke-tests/yarn.lock b/e2e/smoke-tests/yarn.lock index 2f815ecfb2..f072d16465 100644 --- a/e2e/smoke-tests/yarn.lock +++ b/e2e/smoke-tests/yarn.lock @@ -5149,9 +5149,9 @@ process-nextick-args@~2.0.0: integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== protobufjs@^7.2.5: - version "7.4.0" - resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz" - integrity sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw== + version "7.5.5" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.5.tgz#b7089ca4410374c75150baf277353ef76db69f96" + integrity sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" From e26a46b82d74fca5d58fafa09402d85ca5492cdb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:42:26 -0700 Subject: [PATCH 147/174] build(deps-dev): bump protobufjs from 7.4.0 to 7.5.5 (#9859) Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.4.0 to 7.5.5. - [Release notes](https://github.com/protobufjs/protobuf.js/releases) - [Changelog](https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.4.0...protobufjs-v7.5.5) --- updated-dependencies: - dependency-name: protobufjs dependency-version: 7.5.5 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/firestore/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 7425412d99..485e99abb6 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -155,7 +155,7 @@ "@types/eslint": "7.29.0", "chai-exclude": "2.1.1", "json-stable-stringify": "1.2.1", - "protobufjs": "7.4.0", + "protobufjs": "7.5.5", "rollup": "2.79.2", "rollup-plugin-copy": "3.5.0", "rollup-plugin-copy-assets": "2.0.3", diff --git a/yarn.lock b/yarn.lock index 4609749883..a18f66b1fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13615,10 +13615,10 @@ protobufjs-cli@^1.1.3: tmp "^0.2.1" uglify-js "^3.7.7" -protobufjs@7.4.0, protobufjs@^7.2.5, protobufjs@^7.3.2: - version "7.4.0" - resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz#7efe324ce9b3b61c82aae5de810d287bc08a248a" - integrity sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw== +protobufjs@7.5.5, protobufjs@^7.2.5, protobufjs@^7.3.2: + version "7.5.5" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.5.tgz#b7089ca4410374c75150baf277353ef76db69f96" + integrity sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" From 3cc9afcfc0e8e344f815608026cef6e44b1d285f Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 21 Apr 2026 15:20:49 -0700 Subject: [PATCH 148/174] Clean up workflows (#9873) --- .github/workflows/canary-deploy.yml | 105 ---------------------------- .github/workflows/combine-prs.yml | 37 ---------- .github/workflows/e2e-test.yml | 10 --- 3 files changed, 152 deletions(-) delete mode 100644 .github/workflows/canary-deploy.yml delete mode 100644 .github/workflows/combine-prs.yml diff --git a/.github/workflows/canary-deploy.yml b/.github/workflows/canary-deploy.yml deleted file mode 100644 index 043a9f9f06..0000000000 --- a/.github/workflows/canary-deploy.yml +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright 2023 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. - -name: Canary Deploy - -on: - push: - branches: - - main - workflow_dispatch: - -jobs: - deploy: - environment: release - name: Canary Deploy - runs-on: ubuntu-latest - - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - # Canary release script requires git history and tags. - fetch-depth: 0 - - name: Set up Node (22) - uses: actions/setup-node@v4 - with: - node-version: 22.10.0 - - name: Yarn install - run: yarn - - name: Deploy canary - run: yarn release canary - env: - NPM_TOKEN_ANALYTICS: ${{secrets.NPM_TOKEN_ANALYTICS}} - NPM_TOKEN_ANALYTICS_INTEROP_TYPES: ${{secrets.NPM_TOKEN_ANALYTICS_INTEROP_TYPES}} - NPM_TOKEN_ANALYTICS_TYPES: ${{secrets.NPM_TOKEN_ANALYTICS_TYPES}} - NPM_TOKEN_APP: ${{secrets.NPM_TOKEN_APP}} - NPM_TOKEN_APP_TYPES: ${{secrets.NPM_TOKEN_APP_TYPES}} - NPM_TOKEN_APP_CHECK: ${{secrets.NPM_TOKEN_APP_CHECK}} - NPM_TOKEN_APP_CHECK_INTEROP_TYPES: ${{secrets.NPM_TOKEN_APP_CHECK_INTEROP_TYPES}} - NPM_TOKEN_APP_CHECK_TYPES: ${{secrets.NPM_TOKEN_APP_CHECK_TYPES}} - NPM_TOKEN_AUTH: ${{secrets.NPM_TOKEN_AUTH}} - NPM_TOKEN_AUTH_INTEROP_TYPES: ${{secrets.NPM_TOKEN_AUTH_INTEROP_TYPES}} - NPM_TOKEN_AUTH_TYPES: ${{secrets.NPM_TOKEN_AUTH_TYPES}} - NPM_TOKEN_COMPONENT: ${{secrets.NPM_TOKEN_COMPONENT}} - NPM_TOKEN_DATA_CONNECT: ${{secrets.NPM_TOKEN_DATA_CONNECT}} - NPM_TOKEN_DATABASE: ${{secrets.NPM_TOKEN_DATABASE}} - NPM_TOKEN_DATABASE_TYPES: ${{secrets.NPM_TOKEN_DATABASE_TYPES}} - NPM_TOKEN_FIRESTORE: ${{secrets.NPM_TOKEN_FIRESTORE}} - NPM_TOKEN_FIRESTORE_TYPES: ${{secrets.NPM_TOKEN_FIRESTORE_TYPES}} - NPM_TOKEN_FUNCTIONS: ${{secrets.NPM_TOKEN_FUNCTIONS}} - NPM_TOKEN_FUNCTIONS_TYPES: ${{secrets.NPM_TOKEN_FUNCTIONS_TYPES}} - NPM_TOKEN_INSTALLATIONS: ${{secrets.NPM_TOKEN_INSTALLATIONS}} - NPM_TOKEN_INSTALLATIONS_TYPES: ${{secrets.NPM_TOKEN_INSTALLATIONS_TYPES}} - NPM_TOKEN_LOGGER: ${{secrets.NPM_TOKEN_LOGGER}} - NPM_TOKEN_MESSAGING: ${{secrets.NPM_TOKEN_MESSAGING}} - NPM_TOKEN_PERFORMANCE: ${{secrets.NPM_TOKEN_PERFORMANCE}} - NPM_TOKEN_PERFORMANCE_TYPES: ${{secrets.NPM_TOKEN_PERFORMANCE_TYPES}} - NPM_TOKEN_REMOTE_CONFIG: ${{secrets.NPM_TOKEN_REMOTE_CONFIG}} - NPM_TOKEN_REMOTE_CONFIG_TYPES: ${{secrets.NPM_TOKEN_REMOTE_CONFIG_TYPES}} - NPM_TOKEN_RULES_UNIT_TESTING: ${{secrets.NPM_TOKEN_RULES_UNIT_TESTING}} - NPM_TOKEN_STORAGE: ${{secrets.NPM_TOKEN_STORAGE}} - NPM_TOKEN_STORAGE_TYPES: ${{secrets.NPM_TOKEN_STORAGE_TYPES}} - NPM_TOKEN_UTIL: ${{secrets.NPM_TOKEN_UTIL}} - NPM_TOKEN_AI: ${{secrets.NPM_TOKEN_AI}} - NPM_TOKEN_VERTEXAI: ${{secrets.NPM_TOKEN_VERTEXAI}} - NPM_TOKEN_WEBCHANNEL_WRAPPER: ${{secrets.NPM_TOKEN_WEBCHANNEL_WRAPPER}} - NPM_TOKEN_FIREBASE: ${{secrets.NPM_TOKEN_FIREBASE}} - NPM_TOKEN_APP_COMPAT: ${{ secrets.NPM_TOKEN_APP_COMPAT }} - NPM_TOKEN_INSTALLATIONS_COMPAT: ${{ secrets.NPM_TOKEN_INSTALLATIONS_COMPAT }} - NPM_TOKEN_ANALYTICS_COMPAT: ${{ secrets.NPM_TOKEN_ANALYTICS_COMPAT }} - NPM_TOKEN_AUTH_COMPAT: ${{ secrets.NPM_TOKEN_AUTH_COMPAT }} - NPM_TOKEN_MESSAGING_INTEROP_TYPES: ${{ secrets.NPM_TOKEN_MESSAGING_INTEROP_TYPES }} - NPM_TOKEN_FUNCTIONS_COMPAT: ${{ secrets.NPM_TOKEN_FUNCTIONS_COMPAT }} - NPM_TOKEN_MESSAGING_COMPAT: ${{ secrets.NPM_TOKEN_MESSAGING_COMPAT }} - NPM_TOKEN_PERFORMANCE_COMPAT: ${{ secrets.NPM_TOKEN_PERFORMANCE_COMPAT }} - NPM_TOKEN_REMOTE_CONFIG_COMPAT: ${{ secrets.NPM_TOKEN_REMOTE_CONFIG_COMPAT }} - NPM_TOKEN_DATABASE_COMPAT: ${{ secrets.NPM_TOKEN_DATABASE_COMPAT }} - NPM_TOKEN_FIRESTORE_COMPAT: ${{ secrets.NPM_TOKEN_FIRESTORE_COMPAT }} - NPM_TOKEN_STORAGE_COMPAT: ${{ secrets.NPM_TOKEN_STORAGE_COMPAT }} - NPM_TOKEN_APP_CHECK_COMPAT: ${{ secrets.NPM_TOKEN_APP_CHECK_COMPAT }} - NPM_TOKEN_API_DOCUMENTER: ${{ secrets.NPM_TOKEN_API_DOCUMENTER }} - CI: true - - name: Launch E2E tests workflow - # Trigger e2e-test.yml - run: | - VERSION_SCRIPT="const pkg = require('./packages/firebase/package.json'); console.log(pkg.version);" - VERSION_OR_TAG=`node -e "${VERSION_SCRIPT}"` - OSS_BOT_GITHUB_TOKEN=${{ secrets.OSS_BOT_GITHUB_TOKEN }} - curl -X POST \ - -H "Content-Type:application/json" \ - -H "Accept:application/vnd.github.v3+json" \ - -H "Authorization:Bearer $OSS_BOT_GITHUB_TOKEN" \ - -d "{\"event_type\":\"canary-tests\", \"client_payload\":{\"versionOrTag\":\"$VERSION_OR_TAG\"}}" \ - https://api.github.com/repos/firebase/firebase-js-sdk/dispatches \ No newline at end of file diff --git a/.github/workflows/combine-prs.yml b/.github/workflows/combine-prs.yml deleted file mode 100644 index 36f73c3e03..0000000000 --- a/.github/workflows/combine-prs.yml +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2026 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. - -name: Combine PRs - -on: - workflow_dispatch: # allows you to manually trigger the workflow - -# The minimum permissions required to run this Action -permissions: - contents: write - pull-requests: write - checks: read - -jobs: - combine-prs: - runs-on: ubuntu-latest - - steps: - - name: combine-prs - id: combine-prs - # This action defaults to combining branches that begin with - # "dependabot" but can be configured. - uses: github/combine-prs@v5.2.0 - with: - labels: combined-pr # Optional: add a label to the combined PR \ No newline at end of file diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 5fc9c710ec..ccf28a7dc0 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -66,16 +66,6 @@ jobs: yarn env: GITHUB_EVENT_CLIENT_PAYLOAD_VERSIONORTAG: ${{ github.event.client_payload.versionOrTag }} - - name: Deploy "callTest" cloud function - continue-on-error: true - run: | - pushd functions - npm install - popd - npx firebase-tools@14.24.2 deploy --only functions:callTest --project jscore-sandbox-141b5 --token $FIREBASE_CLI_TOKEN - working-directory: ./config - env: - FIREBASE_CLI_TOKEN: ${{ secrets.FIREBASE_CLI_TOKEN }} - name: Do modular build run: yarn build:modular - name: Do compat build From 31fcb5c60ae71d6e0b2fee2a7eb74410cc7d79a7 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 22 Apr 2026 11:14:46 -0700 Subject: [PATCH 149/174] chore: Update a group of dependabot merges (#9875) --- e2e/smoke-tests/yarn.lock | 6 +- packages/auth-compat/demo/functions/yarn.lock | 58 ++++++++--------- packages/auth-compat/demo/yarn.lock | 6 +- packages/auth/demo/functions/yarn.lock | 58 ++++++++--------- .../rules-unit-testing/functions/yarn.lock | 64 +++++++++---------- 5 files changed, 96 insertions(+), 96 deletions(-) diff --git a/e2e/smoke-tests/yarn.lock b/e2e/smoke-tests/yarn.lock index f072d16465..ce525e4ed9 100644 --- a/e2e/smoke-tests/yarn.lock +++ b/e2e/smoke-tests/yarn.lock @@ -4923,9 +4923,9 @@ neo-async@^2.6.2: integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== node-forge@^1: - version "1.3.1" - resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz" - integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + version "1.4.0" + resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz#1c7b7d8bdc2d078739f58287d589d903a11b2fc2" + integrity sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ== node-int64@^0.4.0: version "0.4.0" diff --git a/packages/auth-compat/demo/functions/yarn.lock b/packages/auth-compat/demo/functions/yarn.lock index dced704185..d18abe9a9b 100644 --- a/packages/auth-compat/demo/functions/yarn.lock +++ b/packages/auth-compat/demo/functions/yarn.lock @@ -461,16 +461,16 @@ body-parser@1.19.0: type-is "~1.6.17" brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + version "2.0.3" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz#0493338bdd58e319b1039c67cf7ee439892c01d9" + integrity sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA== dependencies: balanced-match "^1.0.0" -buffer-equal-constant-time@1.0.1: +buffer-equal-constant-time@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== bytes@3.1.0: version "3.1.0" @@ -763,9 +763,9 @@ fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3: integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== fast-xml-parser@^4.2.2: - version "4.5.4" - resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.4.tgz#64e52ddf1308001893bd225d5b1768840511c797" - integrity sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ== + version "4.5.6" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.6.tgz#4ff57d4aca13a2d11aa42ad460495cf00f32b655" + integrity sha512-Yd4vkROfJf8AuJrDIVMVmYfULKmIJszVsMv7Vo71aocsKgFxpdlpSHXSaInvyYfgw2PRuObQSW2GFpVMUjxu9A== dependencies: strnum "^1.0.5" @@ -1079,21 +1079,21 @@ jsonwebtoken@^9.0.0: ms "^2.1.1" semver "^7.5.4" -jwa@^1.4.1: - version "1.4.1" - resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" - integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== +jwa@^1.4.2: + version "1.4.2" + resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz#16011ac6db48de7b102777e57897901520eec7b9" + integrity sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw== dependencies: - buffer-equal-constant-time "1.0.1" + buffer-equal-constant-time "^1.0.1" ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" -jwa@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" - integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== +jwa@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz#bf8176d1ad0cd72e0f3f58338595a13e110bc804" + integrity sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg== dependencies: - buffer-equal-constant-time "1.0.1" + buffer-equal-constant-time "^1.0.1" ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" @@ -1110,19 +1110,19 @@ jwks-rsa@^3.0.1: lru-memoizer "^2.2.0" jws@^3.2.2: - version "3.2.2" - resolved "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" - integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + version "3.2.3" + resolved "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz#5ac0690b460900a27265de24520526853c0b8ca1" + integrity sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g== dependencies: - jwa "^1.4.1" + jwa "^1.4.2" safe-buffer "^5.0.1" jws@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" - integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + version "4.0.1" + resolved "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz#07edc1be8fac20e677b283ece261498bd38f0690" + integrity sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA== dependencies: - jwa "^2.0.0" + jwa "^2.0.1" safe-buffer "^5.0.1" klaw@^3.0.0: @@ -1355,9 +1355,9 @@ node-fetch@^2.6.9: whatwg-url "^5.0.0" node-forge@^1.3.1: - version "1.3.1" - resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" - integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + version "1.4.0" + resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz#1c7b7d8bdc2d078739f58287d589d903a11b2fc2" + integrity sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ== object-assign@^4: version "4.1.1" diff --git a/packages/auth-compat/demo/yarn.lock b/packages/auth-compat/demo/yarn.lock index 3b8e3cb9e9..af35355c37 100644 --- a/packages/auth-compat/demo/yarn.lock +++ b/packages/auth-compat/demo/yarn.lock @@ -1212,9 +1212,9 @@ before-after-hook@^2.2.0: integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.13" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz#d37875c01dc9eff988dd49d112a57cb67b54efe6" + integrity sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" diff --git a/packages/auth/demo/functions/yarn.lock b/packages/auth/demo/functions/yarn.lock index edc7dd71ca..5977fe98ea 100644 --- a/packages/auth/demo/functions/yarn.lock +++ b/packages/auth/demo/functions/yarn.lock @@ -461,16 +461,16 @@ body-parser@1.19.0: type-is "~1.6.17" brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + version "2.0.3" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz#0493338bdd58e319b1039c67cf7ee439892c01d9" + integrity sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA== dependencies: balanced-match "^1.0.0" -buffer-equal-constant-time@1.0.1: +buffer-equal-constant-time@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== bytes@3.1.0: version "3.1.0" @@ -763,9 +763,9 @@ fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3: integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== fast-xml-parser@^4.2.2: - version "4.5.4" - resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.4.tgz#64e52ddf1308001893bd225d5b1768840511c797" - integrity sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ== + version "4.5.6" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.6.tgz#4ff57d4aca13a2d11aa42ad460495cf00f32b655" + integrity sha512-Yd4vkROfJf8AuJrDIVMVmYfULKmIJszVsMv7Vo71aocsKgFxpdlpSHXSaInvyYfgw2PRuObQSW2GFpVMUjxu9A== dependencies: strnum "^1.0.5" @@ -1079,21 +1079,21 @@ jsonwebtoken@^9.0.0: ms "^2.1.1" semver "^7.5.4" -jwa@^1.4.1: - version "1.4.1" - resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" - integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== +jwa@^1.4.2: + version "1.4.2" + resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz#16011ac6db48de7b102777e57897901520eec7b9" + integrity sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw== dependencies: - buffer-equal-constant-time "1.0.1" + buffer-equal-constant-time "^1.0.1" ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" -jwa@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" - integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== +jwa@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz#bf8176d1ad0cd72e0f3f58338595a13e110bc804" + integrity sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg== dependencies: - buffer-equal-constant-time "1.0.1" + buffer-equal-constant-time "^1.0.1" ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" @@ -1110,19 +1110,19 @@ jwks-rsa@^3.0.1: lru-memoizer "^2.2.0" jws@^3.2.2: - version "3.2.2" - resolved "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" - integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + version "3.2.3" + resolved "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz#5ac0690b460900a27265de24520526853c0b8ca1" + integrity sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g== dependencies: - jwa "^1.4.1" + jwa "^1.4.2" safe-buffer "^5.0.1" jws@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" - integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + version "4.0.1" + resolved "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz#07edc1be8fac20e677b283ece261498bd38f0690" + integrity sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA== dependencies: - jwa "^2.0.0" + jwa "^2.0.1" safe-buffer "^5.0.1" klaw@^3.0.0: @@ -1355,9 +1355,9 @@ node-fetch@^2.6.9: whatwg-url "^5.0.0" node-forge@^1.3.1: - version "1.3.1" - resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" - integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + version "1.4.0" + resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz#1c7b7d8bdc2d078739f58287d589d903a11b2fc2" + integrity sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ== object-assign@^4: version "4.1.1" diff --git a/packages/rules-unit-testing/functions/yarn.lock b/packages/rules-unit-testing/functions/yarn.lock index 42e67eed61..6e13cd4a63 100644 --- a/packages/rules-unit-testing/functions/yarn.lock +++ b/packages/rules-unit-testing/functions/yarn.lock @@ -462,24 +462,24 @@ body-parser@1.19.0: type-is "~1.6.17" brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.12" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + version "2.0.2" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== dependencies: balanced-match "^1.0.0" -buffer-equal-constant-time@1.0.1: +buffer-equal-constant-time@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== bytes@3.1.0: version "3.1.0" @@ -777,9 +777,9 @@ fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3: integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== fast-xml-parser@^4.2.2: - version "4.5.4" - resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.4.tgz#64e52ddf1308001893bd225d5b1768840511c797" - integrity sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ== + version "4.5.6" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.6.tgz#4ff57d4aca13a2d11aa42ad460495cf00f32b655" + integrity sha512-Yd4vkROfJf8AuJrDIVMVmYfULKmIJszVsMv7Vo71aocsKgFxpdlpSHXSaInvyYfgw2PRuObQSW2GFpVMUjxu9A== dependencies: strnum "^1.0.5" @@ -1120,21 +1120,21 @@ jsonwebtoken@^9.0.0: ms "^2.1.1" semver "^7.5.4" -jwa@^1.4.1: - version "1.4.1" - resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" - integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== +jwa@^1.4.2: + version "1.4.2" + resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz#16011ac6db48de7b102777e57897901520eec7b9" + integrity sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw== dependencies: - buffer-equal-constant-time "1.0.1" + buffer-equal-constant-time "^1.0.1" ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" -jwa@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" - integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== +jwa@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz#bf8176d1ad0cd72e0f3f58338595a13e110bc804" + integrity sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg== dependencies: - buffer-equal-constant-time "1.0.1" + buffer-equal-constant-time "^1.0.1" ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" @@ -1151,19 +1151,19 @@ jwks-rsa@^3.0.1: lru-memoizer "^2.2.0" jws@^3.2.2: - version "3.2.2" - resolved "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" - integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + version "3.2.3" + resolved "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz#5ac0690b460900a27265de24520526853c0b8ca1" + integrity sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g== dependencies: - jwa "^1.4.1" + jwa "^1.4.2" safe-buffer "^5.0.1" jws@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" - integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + version "4.0.1" + resolved "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz#07edc1be8fac20e677b283ece261498bd38f0690" + integrity sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA== dependencies: - jwa "^2.0.0" + jwa "^2.0.1" safe-buffer "^5.0.1" klaw@^3.0.0: @@ -1408,9 +1408,9 @@ node-fetch@^2.6.7: whatwg-url "^5.0.0" node-forge@^1.3.1: - version "1.3.1" - resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" - integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + version "1.4.0" + resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz#1c7b7d8bdc2d078739f58287d589d903a11b2fc2" + integrity sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ== object-assign@^4: version "4.1.1" From b5de49f74c566dea994cdc911d113bea450fda20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:57:19 -0700 Subject: [PATCH 150/174] build(deps): bump follow-redirects from 1.15.9 to 1.16.0 (#9844) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.9 to 1.16.0. - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.9...v1.16.0) --- updated-dependencies: - dependency-name: follow-redirects dependency-version: 1.16.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/yarn.lock b/yarn.lock index a18f66b1fc..212438a681 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7947,15 +7947,10 @@ fn.name@1.x.x: resolved "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.0.0: - version "1.15.9" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" - integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== - -follow-redirects@^1.15.11: - version "1.15.11" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340" - integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== +follow-redirects@^1.0.0, follow-redirects@^1.15.11: + version "1.16.0" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" + integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== for-each@^0.3.3: version "0.3.4" From 4569354462ffd5f7dccee0c14d6542e48df71b83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:26:59 -0700 Subject: [PATCH 151/174] build(deps-dev): bump playwright from 1.51.1 to 1.55.1 (#9333) Bumps [playwright](https://github.com/microsoft/playwright) from 1.51.1 to 1.55.1. - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](https://github.com/microsoft/playwright/compare/v1.51.1...v1.55.1) --- updated-dependencies: - dependency-name: playwright dependency-version: 1.55.1 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 958a90ff59..f6a0cf06f1 100644 --- a/package.json +++ b/package.json @@ -139,7 +139,7 @@ "nyc": "15.1.0", "ora": "5.4.1", "patch-package": "7.0.2", - "playwright": "1.51.1", + "playwright": "1.55.1", "postinstall-postinstall": "2.1.0", "prettier": "2.8.8", "protobufjs-cli": "^1.1.3", diff --git a/yarn.lock b/yarn.lock index 212438a681..116c6521b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13400,17 +13400,17 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -playwright-core@1.51.1: - version "1.51.1" - resolved "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.1.tgz#d57f0393e02416f32a47cf82b27533656a8acce1" - integrity sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw== +playwright-core@1.55.1: + version "1.55.1" + resolved "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.1.tgz#5d3bb1846bc4289d364ea1a9dcb33f14545802e9" + integrity sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w== -playwright@1.51.1: - version "1.51.1" - resolved "https://registry.npmjs.org/playwright/-/playwright-1.51.1.tgz#ae1467ee318083968ad28d6990db59f47a55390f" - integrity sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw== +playwright@1.55.1: + version "1.55.1" + resolved "https://registry.npmjs.org/playwright/-/playwright-1.55.1.tgz#8a9954e9e61ed1ab479212af9be336888f8b3f0e" + integrity sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A== dependencies: - playwright-core "1.51.1" + playwright-core "1.55.1" optionalDependencies: fsevents "2.3.2" From ad81f95ad68d9886366237e6919ef31b3d610e9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 16:18:30 -0700 Subject: [PATCH 152/174] build(deps): bump flatted from 3.3.2 to 3.4.2 (#9738) Bumps [flatted](https://github.com/WebReflection/flatted) from 3.3.2 to 3.4.2. - [Commits](https://github.com/WebReflection/flatted/compare/v3.3.2...v3.4.2) --- updated-dependencies: - dependency-name: flatted dependency-version: 3.4.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 116c6521b4..33228293c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7930,9 +7930,9 @@ flat@^5.0.2: integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatted@^3.2.7, flatted@^3.2.9: - version "3.3.2" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" - integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== + version "3.4.2" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz#f5c23c107f0f37de8dbdf24f13722b3b98d52726" + integrity sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA== flush-write-stream@^1.0.2: version "1.1.1" From c53fc40d2aa9777e70f796746dbabd59ecce7b77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 16:20:04 -0700 Subject: [PATCH 153/174] build(deps): bump pbkdf2 from 3.1.2 to 3.1.5 (#9573) Bumps [pbkdf2](https://github.com/browserify/pbkdf2) from 3.1.2 to 3.1.5. - [Changelog](https://github.com/browserify/pbkdf2/blob/master/CHANGELOG.md) - [Commits](https://github.com/browserify/pbkdf2/compare/v3.1.2...v3.1.5) --- updated-dependencies: - dependency-name: pbkdf2 dependency-version: 3.1.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 57 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/yarn.lock b/yarn.lock index 33228293c0..97e13dc625 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6091,7 +6091,7 @@ create-ecdh@^4.0.4: bn.js "^4.1.0" elliptic "^6.5.3" -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: +create-hash@^1.1.0, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== @@ -6102,7 +6102,7 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.4, create-hmac@^1.1.7: +create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -8926,6 +8926,16 @@ hash-base@^3.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" +hash-base@^3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz#79d72def7611c3f6e3c3b5730652638001b10a74" + integrity sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg== + dependencies: + inherits "^2.0.4" + readable-stream "^2.3.8" + safe-buffer "^5.2.1" + to-buffer "^1.2.1" + hash-base@~3.0, hash-base@~3.0.4: version "3.0.5" resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz#52480e285395cf7fba17dc4c9e47acdc7f248a8a" @@ -13248,15 +13258,16 @@ pathval@^1.1.1: integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== pbkdf2@^3.1.2: - version "3.1.2" - resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + version "3.1.5" + resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz#444a59d7a259a95536c56e80c89de31cc01ed366" + integrity sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ== dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" + create-hash "^1.2.0" + create-hmac "^1.1.7" + ripemd160 "^2.0.3" + safe-buffer "^5.2.1" + sha.js "^2.4.12" + to-buffer "^1.2.1" pend@~1.2.0: version "1.2.0" @@ -14459,6 +14470,14 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +ripemd160@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz#9be54e4ba5e3559c8eee06a25cd7648bbccdf5a8" + integrity sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA== + dependencies: + hash-base "^3.1.2" + inherits "^2.0.4" + rollup-plugin-copy-assets@2.0.3: version "2.0.3" resolved "https://registry.npmjs.org/rollup-plugin-copy-assets/-/rollup-plugin-copy-assets-2.0.3.tgz#9a9098894c3ded16d2eee8c4108055e332b5f59f" @@ -14913,6 +14932,15 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +sha.js@^2.4.12: + version "2.4.12" + resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz#eb8b568bf383dfd1867a32c3f2b74eb52bdbf23f" + integrity sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w== + dependencies: + inherits "^2.0.4" + safe-buffer "^5.2.1" + to-buffer "^1.2.0" + shallow-clone@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" @@ -16130,6 +16158,15 @@ to-absolute-glob@^2.0.0, to-absolute-glob@^2.0.2: is-absolute "^1.0.0" is-negated-glob "^1.0.0" +to-buffer@^1.2.0, to-buffer@^1.2.1: + version "1.2.2" + resolved "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz#ffe59ef7522ada0a2d1cb5dfe03bb8abc3cdc133" + integrity sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw== + dependencies: + isarray "^2.0.5" + safe-buffer "^5.2.1" + typed-array-buffer "^1.0.3" + to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" From 0499b9171a2d5903ce35d137dd1edcc0196934db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 16:51:37 -0700 Subject: [PATCH 154/174] build(deps-dev): bump lodash from 4.17.23 to 4.18.1 (#9804) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.23...4.18.1) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.18.1 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f6a0cf06f1..20306196f6 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "lcov-result-merger": "3.3.0", "lerna": "4.0.0", "listr": "0.14.3", - "lodash": "4.17.23", + "lodash": "4.18.1", "long": "3.2.0", "merge2": "1.4.1", "mkdirp": "1.0.4", diff --git a/yarn.lock b/yarn.lock index 97e13dc625..f6a9fd26d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11169,7 +11169,12 @@ lodash.templatesettings@^4.0.0: dependencies: lodash._reinterpolate "^3.0.0" -lodash@4.17.23, lodash@^4.16.6, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.7.0, lodash@~4.17.15, lodash@~4.17.21: +lodash@4.18.1, lodash@^4.16.6, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.7.0: + version "4.18.1" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c" + integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== + +lodash@~4.17.15, lodash@~4.17.21: version "4.17.23" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== From f0813ce8e656955956df9cd1af982fe3dde968df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 10:13:58 -0700 Subject: [PATCH 155/174] build(deps-dev): bump protobufjs in /packages/firestore (#9874) Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.4.0 to 7.5.5. - [Release notes](https://github.com/protobufjs/protobuf.js/releases) - [Changelog](https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.4.0...protobufjs-v7.5.5) --- updated-dependencies: - dependency-name: protobufjs dependency-version: 7.5.5 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From ffa39f61c36e9d90a26573f042863e0086ee01e2 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 23 Apr 2026 11:55:31 -0700 Subject: [PATCH 156/174] feat(ai): Implement session resumption and context window compression for live api (#9795) --- .changeset/little-apples-rush.md | 6 + common/api-review/ai.api.md | 39 +++- docs-devsite/_toc.yaml | 8 + .../ai.contextwindowcompressionconfig.md | 57 +++++ docs-devsite/ai.livegenerationconfig.md | 14 ++ docs-devsite/ai.livegenerativemodel.md | 11 +- docs-devsite/ai.livesession.md | 48 +++- .../ai.livesessionresumptionupdate.md | 83 +++++++ docs-devsite/ai.md | 5 + docs-devsite/ai.segment.md | 4 +- docs-devsite/ai.sessionresumptionconfig.md | 45 ++++ docs-devsite/ai.slidingwindow.md | 43 ++++ packages/ai/integration/live.test.ts | 4 +- packages/ai/src/api.ts | 4 +- packages/ai/src/methods/live-session.test.ts | 75 ++++++- packages/ai/src/methods/live-session.ts | 210 +++++++++++++----- .../ai/src/models/live-generative-model.ts | 55 ++--- packages/ai/src/types/live-responses.ts | 4 + packages/ai/src/types/requests.ts | 64 ++++++ packages/ai/src/types/responses.ts | 29 ++- 20 files changed, 697 insertions(+), 111 deletions(-) create mode 100644 .changeset/little-apples-rush.md create mode 100644 docs-devsite/ai.contextwindowcompressionconfig.md create mode 100644 docs-devsite/ai.livesessionresumptionupdate.md create mode 100644 docs-devsite/ai.sessionresumptionconfig.md create mode 100644 docs-devsite/ai.slidingwindow.md diff --git a/.changeset/little-apples-rush.md b/.changeset/little-apples-rush.md new file mode 100644 index 0000000000..a007193a83 --- /dev/null +++ b/.changeset/little-apples-rush.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +Added `LiveSession.resumeSession()` to allow resuming a previous `LiveSession`. Also added `contextWindowCompression` feature. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index aee764ee7e..f4ba0806d6 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -264,6 +264,12 @@ export interface Content { role: Role; } +// @beta +export interface ContextWindowCompressionConfig { + slidingWindow?: SlidingWindow; + triggerTokens?: number; +} + // @public export interface CountTokensRequest { // (undocumented) @@ -983,6 +989,7 @@ export interface LanguageModelPromptOptions { // @beta export interface LiveGenerationConfig { + contextWindowCompression?: ContextWindowCompressionConfig; frequencyPenalty?: number; inputAudioTranscription?: AudioTranscriptionConfig; maxOutputTokens?: number; @@ -1001,8 +1008,8 @@ export class LiveGenerativeModel extends AIModel { // // @internal constructor(ai: AI, modelParams: LiveModelParams, - _webSocketHandler: WebSocketHandler); - connect(): Promise; + _webSocketHandler?: WebSocketHandler | undefined); + connect(sessionResumption?: SessionResumptionConfig): Promise; // (undocumented) generationConfig: LiveGenerationConfig; // (undocumented) @@ -1033,6 +1040,7 @@ export const LiveResponseType: { TOOL_CALL: string; TOOL_CALL_CANCELLATION: string; GOING_AWAY_NOTICE: string; + SESSION_RESUMPTION_UPDATE: string; }; // @beta @@ -1072,12 +1080,16 @@ export interface LiveServerToolCallCancellation { // @beta export class LiveSession { + // Warning: (ae-forgotten-export) The symbol "_LiveClientSetup" needs to be exported by the entry point index.d.ts + // // @internal - constructor(webSocketHandler: WebSocketHandler, serverMessages: AsyncGenerator); + constructor(_setupMessage: _LiveClientSetup, _apiSettings: ApiSettings, _sessionResumption?: SessionResumptionConfig | undefined, webSocketHandler?: WebSocketHandler); close(): Promise; + connectionPromise: Promise; inConversation: boolean; isClosed: boolean; - receive(): AsyncGenerator; + receive(): AsyncGenerator; + resumeSession(sessionResumption?: SessionResumptionConfig): Promise; send(request: string | Array, turnComplete?: boolean): Promise; sendAudioRealtime(blob: GenerativeContentBlob): Promise; sendFunctionResponses(functionResponses: FunctionResponse[]): Promise; @@ -1089,6 +1101,15 @@ export class LiveSession { sendVideoRealtime(blob: GenerativeContentBlob): Promise; } +// @beta +export interface LiveSessionResumptionUpdate { + lastConsumedClientMessageIndex?: number; + newHandle?: string; + resumable?: boolean; + // (undocumented) + type: 'sessionResumptionUpdate'; +} + // @public export const Modality: { readonly MODALITY_UNSPECIFIED: "MODALITY_UNSPECIFIED"; @@ -1342,11 +1363,21 @@ export interface Segment { text: string; } +// @beta +export interface SessionResumptionConfig { + handle?: string; +} + // @public export interface SingleRequestOptions extends RequestOptions { signal?: AbortSignal; } +// @beta +export interface SlidingWindow { + targetTokens?: number; +} + // @beta export interface SpeechConfig { voiceConfig?: VoiceConfig; diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index a17095729e..4310b3b280 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -44,6 +44,8 @@ toc: path: /docs/reference/js/ai.codeexecutiontool.md - title: Content path: /docs/reference/js/ai.content.md + - title: ContextWindowCompressionConfig + path: /docs/reference/js/ai.contextwindowcompressionconfig.md - title: CountTokensRequest path: /docs/reference/js/ai.counttokensrequest.md - title: CountTokensResponse @@ -156,6 +158,8 @@ toc: path: /docs/reference/js/ai.liveservertoolcallcancellation.md - title: LiveSession path: /docs/reference/js/ai.livesession.md + - title: LiveSessionResumptionUpdate + path: /docs/reference/js/ai.livesessionresumptionupdate.md - title: ModalityTokenCount path: /docs/reference/js/ai.modalitytokencount.md - title: ModelParams @@ -194,8 +198,12 @@ toc: path: /docs/reference/js/ai.searchentrypoint.md - title: Segment path: /docs/reference/js/ai.segment.md + - title: SessionResumptionConfig + path: /docs/reference/js/ai.sessionresumptionconfig.md - title: SingleRequestOptions path: /docs/reference/js/ai.singlerequestoptions.md + - title: SlidingWindow + path: /docs/reference/js/ai.slidingwindow.md - title: SpeechConfig path: /docs/reference/js/ai.speechconfig.md - title: StartAudioConversationOptions diff --git a/docs-devsite/ai.contextwindowcompressionconfig.md b/docs-devsite/ai.contextwindowcompressionconfig.md new file mode 100644 index 0000000000..1342e44c03 --- /dev/null +++ b/docs-devsite/ai.contextwindowcompressionconfig.md @@ -0,0 +1,57 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# ContextWindowCompressionConfig interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Enables context window compression to manage the model's context window. + +This mechanism prevents the context from exceeding a given length. + +Signature: + +```typescript +export interface ContextWindowCompressionConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [slidingWindow](./ai.contextwindowcompressionconfig.md#contextwindowcompressionconfigslidingwindow) | [SlidingWindow](./ai.slidingwindow.md#slidingwindow_interface) | (Public Preview) The sliding window compression mechanism. | +| [triggerTokens](./ai.contextwindowcompressionconfig.md#contextwindowcompressionconfigtriggertokens) | number | (Public Preview) The number of tokens (before running a turn) that triggers the context window compression. | + +## ContextWindowCompressionConfig.slidingWindow + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The sliding window compression mechanism. + +Signature: + +```typescript +slidingWindow?: SlidingWindow; +``` + +## ContextWindowCompressionConfig.triggerTokens + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The number of tokens (before running a turn) that triggers the context window compression. + +Signature: + +```typescript +triggerTokens?: number; +``` diff --git a/docs-devsite/ai.livegenerationconfig.md b/docs-devsite/ai.livegenerationconfig.md index 2e842a3431..266a41b240 100644 --- a/docs-devsite/ai.livegenerationconfig.md +++ b/docs-devsite/ai.livegenerationconfig.md @@ -25,6 +25,7 @@ export interface LiveGenerationConfig | Property | Type | Description | | --- | --- | --- | +| [contextWindowCompression](./ai.livegenerationconfig.md#livegenerationconfigcontextwindowcompression) | [ContextWindowCompressionConfig](./ai.contextwindowcompressionconfig.md#contextwindowcompressionconfig_interface) | (Public Preview) The context window compression configuration. | | [frequencyPenalty](./ai.livegenerationconfig.md#livegenerationconfigfrequencypenalty) | number | (Public Preview) Frequency penalties. | | [inputAudioTranscription](./ai.livegenerationconfig.md#livegenerationconfiginputaudiotranscription) | [AudioTranscriptionConfig](./ai.audiotranscriptionconfig.md#audiotranscriptionconfig_interface) | (Public Preview) Enables transcription of audio input.When enabled, the model will respond with transcriptions of your audio input in the inputTranscriptions property in [LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) messages. Note that the transcriptions are broken up across messages, so you may only receive small amounts of text per message. For example, if you ask the model "How are you today?", the model may transcribe that input across three messages, broken up as "How a", "re yo", "u today?". | | [maxOutputTokens](./ai.livegenerationconfig.md#livegenerationconfigmaxoutputtokens) | number | (Public Preview) Specifies the maximum number of tokens that can be generated in the response. The number of tokens per word varies depending on the language outputted. Is unbounded by default. | @@ -36,6 +37,19 @@ export interface LiveGenerationConfig | [topK](./ai.livegenerationconfig.md#livegenerationconfigtopk) | number | (Public Preview) Changes how the model selects token for output. A topK value of 1 means the select token is the most probable among all tokens in the model's vocabulary, while a topK value 3 means that the next token is selected from among the 3 most probably using probabilities sampled. Tokens are then further filtered with the highest selected temperature sampling. Defaults to 40 if unspecified. | | [topP](./ai.livegenerationconfig.md#livegenerationconfigtopp) | number | (Public Preview) Changes how the model selects tokens for output. Tokens are selected from the most to least probable until the sum of their probabilities equals the topP value. For example, if tokens A, B, and C have probabilities of 0.3, 0.2, and 0.1 respectively and the topP value is 0.5, then the model will select either A or B as the next token by using the temperature and exclude C as a candidate. Defaults to 0.95 if unset. | +## LiveGenerationConfig.contextWindowCompression + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The context window compression configuration. + +Signature: + +```typescript +contextWindowCompression?: ContextWindowCompressionConfig; +``` + ## LiveGenerationConfig.frequencyPenalty > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/ai.livegenerativemodel.md b/docs-devsite/ai.livegenerativemodel.md index 7c52cad1a3..51cf490c23 100644 --- a/docs-devsite/ai.livegenerativemodel.md +++ b/docs-devsite/ai.livegenerativemodel.md @@ -39,7 +39,7 @@ export declare class LiveGenerativeModel extends AIModel | Method | Modifiers | Description | | --- | --- | --- | -| [connect()](./ai.livegenerativemodel.md#livegenerativemodelconnect) | | (Public Preview) Starts a [LiveSession](./ai.livesession.md#livesession_class). | +| [connect(sessionResumption)](./ai.livegenerativemodel.md#livegenerativemodelconnect) | | (Public Preview) Starts a [LiveSession](./ai.livesession.md#livesession_class). | ## LiveGenerativeModel.generationConfig @@ -95,8 +95,15 @@ Starts a [LiveSession](./ai.livesession.md#livesession_class). Signature: ```typescript -connect(): Promise; +connect(sessionResumption?: SessionResumptionConfig): Promise; ``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| sessionResumption | [SessionResumptionConfig](./ai.sessionresumptionconfig.md#sessionresumptionconfig_interface) | | + Returns: Promise<[LiveSession](./ai.livesession.md#livesession_class)> diff --git a/docs-devsite/ai.livesession.md b/docs-devsite/ai.livesession.md index eb760aed2a..f328a9e7c4 100644 --- a/docs-devsite/ai.livesession.md +++ b/docs-devsite/ai.livesession.md @@ -29,6 +29,7 @@ export declare class LiveSession | Property | Modifiers | Type | Description | | --- | --- | --- | --- | +| [connectionPromise](./ai.livesession.md#livesessionconnectionpromise) | | Promise<void> | (Public Preview) Allows external code to await the opening of the WebSocket connection. | | [inConversation](./ai.livesession.md#livesessioninconversation) | | boolean | (Public Preview) Indicates whether this Live session is being controlled by an AudioConversationController. | | [isClosed](./ai.livesession.md#livesessionisclosed) | | boolean | (Public Preview) Indicates whether this Live session is closed. | @@ -38,6 +39,7 @@ export declare class LiveSession | --- | --- | --- | | [close()](./ai.livesession.md#livesessionclose) | | (Public Preview) Closes this session. All methods on this session will throw an error once this resolves. | | [receive()](./ai.livesession.md#livesessionreceive) | | (Public Preview) Yields messages received from the server. This can only be used by one consumer at a time. | +| [resumeSession(sessionResumption)](./ai.livesession.md#livesessionresumesession) | | (Public Preview) Resumes an existing live session with the server.This closes the current WebSocket connection and establishes a new one using the same configuration (URI, headers, model, system instruction, tools, etc.) as the original session. | | [send(request, turnComplete)](./ai.livesession.md#livesessionsend) | | (Public Preview) Sends content to the server. | | [sendAudioRealtime(blob)](./ai.livesession.md#livesessionsendaudiorealtime) | | (Public Preview) Sends audio data to the server in realtime. | | [sendFunctionResponses(functionResponses)](./ai.livesession.md#livesessionsendfunctionresponses) | | (Public Preview) Sends function responses to the server. | @@ -46,6 +48,19 @@ export declare class LiveSession | [sendTextRealtime(text)](./ai.livesession.md#livesessionsendtextrealtime) | | (Public Preview) Sends text to the server in realtime. | | [sendVideoRealtime(blob)](./ai.livesession.md#livesessionsendvideorealtime) | | (Public Preview) Sends video data to the server in realtime. | +## LiveSession.connectionPromise + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Allows external code to await the opening of the WebSocket connection. + +Signature: + +```typescript +connectionPromise: Promise; +``` + ## LiveSession.inConversation > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. @@ -98,11 +113,11 @@ Yields messages received from the server. This can only be used by one consumer Signature: ```typescript -receive(): AsyncGenerator; +receive(): AsyncGenerator; ``` Returns: -AsyncGenerator<[LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) \| [LiveServerToolCall](./ai.liveservertoolcall.md#liveservertoolcall_interface) \| [LiveServerToolCallCancellation](./ai.liveservertoolcallcancellation.md#liveservertoolcallcancellation_interface) \| [LiveServerGoingAwayNotice](./ai.liveservergoingawaynotice.md#liveservergoingawaynotice_interface)> +AsyncGenerator<[LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) \| [LiveServerToolCall](./ai.liveservertoolcall.md#liveservertoolcall_interface) \| [LiveServerToolCallCancellation](./ai.liveservertoolcallcancellation.md#liveservertoolcallcancellation_interface) \| [LiveServerGoingAwayNotice](./ai.liveservergoingawaynotice.md#liveservergoingawaynotice_interface) \| [LiveSessionResumptionUpdate](./ai.livesessionresumptionupdate.md#livesessionresumptionupdate_interface)> An `AsyncGenerator` that yields server messages as they arrive. @@ -110,6 +125,35 @@ An `AsyncGenerator` that yields server messages as they arrive. If the session is already closed, or if we receive a response that we don't support. +## LiveSession.resumeSession() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Resumes an existing live session with the server. + +This closes the current WebSocket connection and establishes a new one using the same configuration (URI, headers, model, system instruction, tools, etc.) as the original session. + +Signature: + +```typescript +resumeSession(sessionResumption?: SessionResumptionConfig): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| sessionResumption | [SessionResumptionConfig](./ai.sessionresumptionconfig.md#sessionresumptionconfig_interface) | The configuration for session resumption, such as the handle to the previous session state to restore. | + +Returns: + +Promise<void> + +#### Exceptions + +If the session resumption configuration is unsupported. + ## LiveSession.send() > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. diff --git a/docs-devsite/ai.livesessionresumptionupdate.md b/docs-devsite/ai.livesessionresumptionupdate.md new file mode 100644 index 0000000000..0b3df8096d --- /dev/null +++ b/docs-devsite/ai.livesessionresumptionupdate.md @@ -0,0 +1,83 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# LiveSessionResumptionUpdate interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An update of the session resumption state. + +This message is only sent if [SessionResumptionConfig](./ai.sessionresumptionconfig.md#sessionresumptionconfig_interface) was set in the session setup. + +Signature: + +```typescript +export interface LiveSessionResumptionUpdate +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [lastConsumedClientMessageIndex](./ai.livesessionresumptionupdate.md#livesessionresumptionupdatelastconsumedclientmessageindex) | number | (Public Preview) The index of the last client message that is included in the state represented by this update. | +| [newHandle](./ai.livesessionresumptionupdate.md#livesessionresumptionupdatenewhandle) | string | (Public Preview) The new handle that represents the state that can be resumed. Empty if resumable is false. | +| [resumable](./ai.livesessionresumptionupdate.md#livesessionresumptionupdateresumable) | boolean | (Public Preview) Indicates if the session can be resumed at this point. | +| [type](./ai.livesessionresumptionupdate.md#livesessionresumptionupdatetype) | 'sessionResumptionUpdate' | (Public Preview) | + +## LiveSessionResumptionUpdate.lastConsumedClientMessageIndex + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The index of the last client message that is included in the state represented by this update. + +Signature: + +```typescript +lastConsumedClientMessageIndex?: number; +``` + +## LiveSessionResumptionUpdate.newHandle + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The new handle that represents the state that can be resumed. Empty if `resumable` is false. + +Signature: + +```typescript +newHandle?: string; +``` + +## LiveSessionResumptionUpdate.resumable + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Indicates if the session can be resumed at this point. + +Signature: + +```typescript +resumable?: boolean; +``` + +## LiveSessionResumptionUpdate.type + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +type: 'sessionResumptionUpdate'; +``` diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index be98207f35..0bf2679cb1 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -70,6 +70,7 @@ The Firebase AI Web SDK. | [CodeExecutionResultPart](./ai.codeexecutionresultpart.md#codeexecutionresultpart_interface) | Represents the code execution result from the model. | | [CodeExecutionTool](./ai.codeexecutiontool.md#codeexecutiontool_interface) | A tool that enables the model to use code execution. | | [Content](./ai.content.md#content_interface) | Content type for both prompts and response candidates. | +| [ContextWindowCompressionConfig](./ai.contextwindowcompressionconfig.md#contextwindowcompressionconfig_interface) | (Public Preview) Enables context window compression to manage the model's context window. | | [CountTokensRequest](./ai.counttokensrequest.md#counttokensrequest_interface) | Params for calling [GenerativeModel.countTokens()](./ai.generativemodel.md#generativemodelcounttokens) | | [CountTokensResponse](./ai.counttokensresponse.md#counttokensresponse_interface) | Response from calling [GenerativeModel.countTokens()](./ai.generativemodel.md#generativemodelcounttokens). | | [CustomErrorData](./ai.customerrordata.md#customerrordata_interface) | Details object that contains data originating from a bad HTTP response. | @@ -119,6 +120,7 @@ The Firebase AI Web SDK. | [LiveServerGoingAwayNotice](./ai.liveservergoingawaynotice.md#liveservergoingawaynotice_interface) | (Public Preview) Notification that the server will not be able to service the client soon. | | [LiveServerToolCall](./ai.liveservertoolcall.md#liveservertoolcall_interface) | (Public Preview) A request from the model for the client to execute one or more functions. | | [LiveServerToolCallCancellation](./ai.liveservertoolcallcancellation.md#liveservertoolcallcancellation_interface) | (Public Preview) Notification to cancel a previous function call triggered by [LiveServerToolCall](./ai.liveservertoolcall.md#liveservertoolcall_interface). | +| [LiveSessionResumptionUpdate](./ai.livesessionresumptionupdate.md#livesessionresumptionupdate_interface) | (Public Preview) An update of the session resumption state.This message is only sent if [SessionResumptionConfig](./ai.sessionresumptionconfig.md#sessionresumptionconfig_interface) was set in the session setup. | | [ModalityTokenCount](./ai.modalitytokencount.md#modalitytokencount_interface) | Represents token counting info for a single modality. | | [ModelParams](./ai.modelparams.md#modelparams_interface) | Params passed to [getGenerativeModel()](./ai.md#getgenerativemodel_c63f46a). | | [ObjectSchemaRequest](./ai.objectschemarequest.md#objectschemarequest_interface) | Interface for JSON parameters in a schema of [SchemaType](./ai.md#schematype) "object" when not using the Schema.object() helper. | @@ -135,7 +137,9 @@ The Firebase AI Web SDK. | [SchemaShared](./ai.schemashared.md#schemashared_interface) | Basic [Schema](./ai.schema.md#schema_class) properties shared across several Schema-related types. | | [SearchEntrypoint](./ai.searchentrypoint.md#searchentrypoint_interface) | Google search entry point. | | [Segment](./ai.segment.md#segment_interface) | Represents a specific segment within a [Content](./ai.content.md#content_interface) object, often used to pinpoint the exact location of text or data that grounding information refers to. | +| [SessionResumptionConfig](./ai.sessionresumptionconfig.md#sessionresumptionconfig_interface) | (Public Preview) Configuration for the session resumption mechanism. | | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | Options that can be provided per-request. Extends the base [RequestOptions](./ai.requestoptions.md#requestoptions_interface) (like timeout and baseUrl) with request-specific controls like cancellation via AbortSignal.Options specified here will override any default [RequestOptions](./ai.requestoptions.md#requestoptions_interface) configured on a model (for example, [GenerativeModel](./ai.generativemodel.md#generativemodel_class)). | +| [SlidingWindow](./ai.slidingwindow.md#slidingwindow_interface) | (Public Preview) Configures the sliding window context compression mechanism. | | [SpeechConfig](./ai.speechconfig.md#speechconfig_interface) | (Public Preview) Configures speech synthesis. | | [StartAudioConversationOptions](./ai.startaudioconversationoptions.md#startaudioconversationoptions_interface) | (Public Preview) Options for [startAudioConversation()](./ai.md#startaudioconversation_01c8e7f). | | [StartChatParams](./ai.startchatparams.md#startchatparams_interface) | Params for [GenerativeModel.startChat()](./ai.generativemodel.md#generativemodelstartchat). | @@ -775,6 +779,7 @@ LiveResponseType: { TOOL_CALL: string; TOOL_CALL_CANCELLATION: string; GOING_AWAY_NOTICE: string; + SESSION_RESUMPTION_UPDATE: string; } ``` diff --git a/docs-devsite/ai.segment.md b/docs-devsite/ai.segment.md index 35db1be5e8..df1b7f90db 100644 --- a/docs-devsite/ai.segment.md +++ b/docs-devsite/ai.segment.md @@ -24,7 +24,7 @@ export interface Segment | --- | --- | --- | | [endIndex](./ai.segment.md#segmentendindex) | number | The zero-based end index of the segment within the specified Part, measured in UTF-8 bytes. This offset is exclusive, meaning the character at this index is not included in the segment. | | [partIndex](./ai.segment.md#segmentpartindex) | number | The zero-based index of the [Part](./ai.md#part) object within the parts array of its parent [Content](./ai.content.md#content_interface) object. This identifies which part of the content the segment belongs to. | -| [startIndex](./ai.segment.md#segmentstartindex) | number | The zero-based start index of the segment within the specified Part, measured in UTF-8 bytes. This offset is inclusive, starting from 0 at the beginning of the part's content (e.g., Part.text). | +| [startIndex](./ai.segment.md#segmentstartindex) | number | The zero-based start index of the segment within the specified Part, measured in UTF-8 bytes. This offset is inclusive, starting from 0 at the beginning of the part's content (for example, Part.text). | | [text](./ai.segment.md#segmenttext) | string | The text corresponding to the segment from the response. | ## Segment.endIndex @@ -49,7 +49,7 @@ partIndex: number; ## Segment.startIndex -The zero-based start index of the segment within the specified `Part`, measured in UTF-8 bytes. This offset is inclusive, starting from 0 at the beginning of the part's content (e.g., `Part.text`). +The zero-based start index of the segment within the specified `Part`, measured in UTF-8 bytes. This offset is inclusive, starting from 0 at the beginning of the part's content (for example, `Part.text`). Signature: diff --git a/docs-devsite/ai.sessionresumptionconfig.md b/docs-devsite/ai.sessionresumptionconfig.md new file mode 100644 index 0000000000..989d530d81 --- /dev/null +++ b/docs-devsite/ai.sessionresumptionconfig.md @@ -0,0 +1,45 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# SessionResumptionConfig interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Configuration for the session resumption mechanism. + +When included in the session setup, the server will send [LiveSessionResumptionUpdate](./ai.livesessionresumptionupdate.md#livesessionresumptionupdate_interface) messages in the response stream. + +Signature: + +```typescript +export interface SessionResumptionConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [handle](./ai.sessionresumptionconfig.md#sessionresumptionconfighandle) | string | (Public Preview) The session resumption handle of the previous session to restore.If not present, a new session will be started. | + +## SessionResumptionConfig.handle + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The session resumption handle of the previous session to restore. + +If not present, a new session will be started. + +Signature: + +```typescript +handle?: string; +``` diff --git a/docs-devsite/ai.slidingwindow.md b/docs-devsite/ai.slidingwindow.md new file mode 100644 index 0000000000..856da0b7e3 --- /dev/null +++ b/docs-devsite/ai.slidingwindow.md @@ -0,0 +1,43 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# SlidingWindow interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Configures the sliding window context compression mechanism. + +The sliding window discards content at the beginning of the context window. The resulting context will always begin at the start of a `user` role turn. System instructions will always remain at the start of the result. + +Signature: + +```typescript +export interface SlidingWindow +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [targetTokens](./ai.slidingwindow.md#slidingwindowtargettokens) | number | (Public Preview) The session reduction target, for example, how many tokens the model should keep. | + +## SlidingWindow.targetTokens + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The session reduction target, for example, how many tokens the model should keep. + +Signature: + +```typescript +targetTokens?: number; +``` diff --git a/packages/ai/integration/live.test.ts b/packages/ai/integration/live.test.ts index 4a8f663abe..10387a2041 100644 --- a/packages/ai/integration/live.test.ts +++ b/packages/ai/integration/live.test.ts @@ -23,7 +23,8 @@ import { LiveServerToolCall, LiveServerToolCallCancellation, LiveServerGoingAwayNotice, - ResponseModality + ResponseModality, + LiveSessionResumptionUpdate } from '../src'; import { liveTestConfigs } from './constants'; import { HELLO_AUDIO_PCM_BASE64 } from './sample-data/hello-audio'; @@ -35,6 +36,7 @@ async function nextTurnData( | LiveServerToolCall | LiveServerToolCallCancellation | LiveServerGoingAwayNotice + | LiveSessionResumptionUpdate > ): Promise<{ text: string; diff --git a/packages/ai/src/api.ts b/packages/ai/src/api.ts index 2c3f125a03..461df984a3 100644 --- a/packages/ai/src/api.ts +++ b/packages/ai/src/api.ts @@ -38,7 +38,6 @@ import { } from './models'; import { encodeInstanceIdentifier } from './helpers'; import { GoogleAIBackend } from './backend'; -import { WebSocketHandlerImpl } from './websocket'; import { TemplateGenerativeModel } from './models/template-generative-model'; import { TemplateImagenModel } from './models/template-imagen-model'; import { logger } from './logger'; @@ -243,8 +242,7 @@ export function getLiveGenerativeModel( `Must provide a model name for getLiveGenerativeModel. Example: getLiveGenerativeModel(ai, { model: 'my-model-name' })` ); } - const webSocketHandler = new WebSocketHandlerImpl(); - return new LiveGenerativeModel(ai, modelParams, webSocketHandler); + return new LiveGenerativeModel(ai, modelParams); } /** diff --git a/packages/ai/src/methods/live-session.test.ts b/packages/ai/src/methods/live-session.test.ts index c4ee675c67..081ddf03f9 100644 --- a/packages/ai/src/methods/live-session.test.ts +++ b/packages/ai/src/methods/live-session.test.ts @@ -16,7 +16,7 @@ */ import { expect, use } from 'chai'; -import { spy, stub } from 'sinon'; +import { match, spy, stub } from 'sinon'; import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; import { @@ -25,16 +25,26 @@ import { LiveServerContent, LiveServerGoingAwayNotice, LiveServerToolCall, - LiveServerToolCallCancellation + LiveServerToolCallCancellation, + LiveSessionResumptionUpdate } from '../types'; import { LiveSession } from './live-session'; import { WebSocketHandler } from '../websocket'; import { AIError } from '../errors'; import { logger } from '../logger'; +import { GoogleAIBackend } from '../backend'; use(sinonChai); use(chaiAsPromised); +const fakeApiSettings = { + apiKey: 'MY_KEY', + project: 'my-project', + appId: 'id', + location: 'here', + backend: new GoogleAIBackend() +}; + class MockWebSocketHandler implements WebSocketHandler { connect = stub().resolves(); send = spy(); @@ -78,12 +88,20 @@ class MockWebSocketHandler implements WebSocketHandler { describe('LiveSession', () => { let mockHandler: MockWebSocketHandler; let session: LiveSession; - let serverMessagesGenerator: AsyncGenerator; - beforeEach(() => { + beforeEach(async () => { mockHandler = new MockWebSocketHandler(); - serverMessagesGenerator = mockHandler.listen(); - session = new LiveSession(mockHandler, serverMessagesGenerator); + session = new LiveSession( + { setup: { model: 'my-model' } }, + fakeApiSettings, + {}, + mockHandler + ); + mockHandler.simulateServerMessage({ + setupComplete: true + }); + await session.connectionPromise; + mockHandler.send.resetHistory(); }); describe('send()', () => { @@ -220,6 +238,34 @@ describe('LiveSession', () => { }); }); + describe('resumeSession()', () => { + it('should close existing session and start a new one using handle.send', async () => { + expect(session.isClosed).to.be.false; + + mockHandler.simulateServerMessage({ + setupComplete: true + }); + await session.resumeSession({ handle: 'testHandle' }); + + expect(mockHandler.close).to.have.been.calledOnce; + expect(mockHandler.send).to.have.been.calledWith(match('testHandle')); + expect(session.isClosed).to.be.false; + }); + + it('should throw if sessionResumption is not provided', async () => { + const basicSession = new LiveSession( + { setup: { model: 'my-model' } }, + fakeApiSettings, + undefined, + mockHandler + ); + await expect(basicSession.resumeSession()).to.be.rejectedWith( + AIError, + /Cannot resume session/ + ); + }); + }); + describe('receive()', () => { it('should correctly parse and transform all server message types', async () => { const receivePromise = (async () => { @@ -229,7 +275,6 @@ describe('LiveSession', () => { } return responses; })(); - mockHandler.simulateServerMessage({ serverContent: { modelTurn: { parts: [{ text: 'response 1' }] } } }); @@ -242,14 +287,22 @@ describe('LiveSession', () => { mockHandler.simulateServerMessage({ goAway: { timeLeft: '30s' } }); + mockHandler.simulateServerMessage({ + sessionResumptionUpdate: { + newHandle: 'test', + resumable: true, + lastConsumedClientMessageIndex: 5 + } + }); mockHandler.simulateServerMessage({ serverContent: { turnComplete: true } }); + await new Promise(r => setTimeout(() => r(), 10)); // Wait for the listener to process messages mockHandler.endStream(); const responses = await receivePromise; - expect(responses).to.have.lengthOf(5); + expect(responses).to.have.lengthOf(6); expect(responses[0]).to.deep.equal({ type: LiveResponseType.SERVER_CONTENT, modelTurn: { parts: [{ text: 'response 1' }] } @@ -267,6 +320,12 @@ describe('LiveSession', () => { timeLeft: 30 } as LiveServerGoingAwayNotice); expect(responses[4]).to.deep.equal({ + type: LiveResponseType.SESSION_RESUMPTION_UPDATE, + newHandle: 'test', + resumable: true, + lastConsumedClientMessageIndex: 5 + } as LiveSessionResumptionUpdate); + expect(responses[5]).to.deep.equal({ type: LiveResponseType.SERVER_CONTENT, turnComplete: true } as LiveServerContent); diff --git a/packages/ai/src/methods/live-session.ts b/packages/ai/src/methods/live-session.ts index 3af5b67f03..4e43434ab6 100644 --- a/packages/ai/src/methods/live-session.ts +++ b/packages/ai/src/methods/live-session.ts @@ -24,17 +24,22 @@ import { LiveServerGoingAwayNotice, LiveServerToolCall, LiveServerToolCallCancellation, - Part + LiveSessionResumptionUpdate, + Part, + SessionResumptionConfig } from '../public-types'; import { formatNewContent } from '../requests/request-helpers'; import { AIError } from '../errors'; -import { WebSocketHandler } from '../websocket'; +import { WebSocketHandler, WebSocketHandlerImpl } from '../websocket'; import { logger } from '../logger'; import { _LiveClientContent, _LiveClientRealtimeInput, + _LiveClientSetup, _LiveClientToolResponse } from '../types/live-responses'; +import { WebSocketUrl } from '../requests/request'; +import { ApiSettings } from '../types/internal'; /** * Represents an active, real-time, bidirectional conversation with the model. @@ -56,14 +61,98 @@ export class LiveSession { * @beta */ inConversation = false; + /** + * Allows external code to await the opening of the WebSocket connection. + */ + connectionPromise: Promise; + /** + * Generator yielding WebSocket messages from the server. + */ + private _serverMessages: AsyncGenerator | null = null; + /** + * WebSocket handler. Injectable for testing. + */ + private _webSocketHandler: WebSocketHandler; /** * @internal */ constructor( - private webSocketHandler: WebSocketHandler, - private serverMessages: AsyncGenerator - ) {} + private _setupMessage: _LiveClientSetup, + private _apiSettings: ApiSettings, + private _sessionResumption?: SessionResumptionConfig, + webSocketHandler?: WebSocketHandler + ) { + this._webSocketHandler = webSocketHandler || new WebSocketHandlerImpl(); + this.connectionPromise = this._connectSession(this._sessionResumption); + } + + /** + * Initializes connection to the WebSocket. Should be called immediately + * after instantiation. + * + * @internal + */ + private async _connectSession( + sessionResumption?: SessionResumptionConfig + ): Promise { + const url = new WebSocketUrl(this._apiSettings); + await this._webSocketHandler.connect(url.toString()); + + try { + // Begin listening for server messages, and begin the handshake by sending the 'setupMessage' + this._serverMessages = this._webSocketHandler.listen(); + const setupMessage = { ...this._setupMessage }; + if (sessionResumption) { + setupMessage.setup.sessionResumption = sessionResumption; + } + this._webSocketHandler.send(JSON.stringify(setupMessage)); + + // Verify we received the handshake response 'setupComplete' + const firstMessage = (await this._serverMessages.next()).value; + if ( + !firstMessage || + !(typeof firstMessage === 'object') || + !('setupComplete' in firstMessage) + ) { + await this._webSocketHandler.close(1011, 'Handshake failure'); + throw new AIError( + AIErrorCode.RESPONSE_ERROR, + 'Server connection handshake failed. The server did not respond with a setupComplete message.' + ); + } + this.isClosed = false; + } catch (e) { + // Ensure connection is closed on any setup error + await this._webSocketHandler.close(); + throw e; + } + } + + /** + * Resumes an existing live session with the server. + * + * This closes the current WebSocket connection and establishes a new one using + * the same configuration (URI, headers, model, system instruction, tools, etc.) + * as the original session. + * + * @param sessionResumption - The configuration for session resumption, such as the handle to the previous session state to restore. + * @throws If the session resumption configuration is unsupported. + * + * @beta + */ + async resumeSession( + sessionResumption?: SessionResumptionConfig + ): Promise { + if (!this._sessionResumption) { + throw new AIError( + AIErrorCode.UNSUPPORTED, + 'Cannot resume session: no sessionResumption config provided' + ); + } + await this.close(); + await this._connectSession(sessionResumption); + } /** * Sends content to the server. @@ -93,7 +182,7 @@ export class LiveSession { turnComplete } }; - this.webSocketHandler.send(JSON.stringify(message)); + this._webSocketHandler.send(JSON.stringify(message)); } /** @@ -122,7 +211,7 @@ export class LiveSession { text } }; - this.webSocketHandler.send(JSON.stringify(message)); + this._webSocketHandler.send(JSON.stringify(message)); } /** @@ -156,7 +245,7 @@ export class LiveSession { audio: blob } }; - this.webSocketHandler.send(JSON.stringify(message)); + this._webSocketHandler.send(JSON.stringify(message)); } /** @@ -189,7 +278,7 @@ export class LiveSession { video: blob } }; - this.webSocketHandler.send(JSON.stringify(message)); + this._webSocketHandler.send(JSON.stringify(message)); } /** @@ -215,7 +304,7 @@ export class LiveSession { functionResponses } }; - this.webSocketHandler.send(JSON.stringify(message)); + this._webSocketHandler.send(JSON.stringify(message)); } /** @@ -232,6 +321,7 @@ export class LiveSession { | LiveServerToolCall | LiveServerToolCallCancellation | LiveServerGoingAwayNotice + | LiveSessionResumptionUpdate > { if (this.isClosed) { throw new AIError( @@ -239,55 +329,69 @@ export class LiveSession { 'Cannot read from a Live session that is closed. Try starting a new Live session.' ); } - for await (const message of this.serverMessages) { - if (message && typeof message === 'object') { - if (LiveResponseType.SERVER_CONTENT in message) { - yield { - type: 'serverContent', - ...(message as { serverContent: Omit }) - .serverContent - } as LiveServerContent; - } else if (LiveResponseType.TOOL_CALL in message) { - yield { - type: 'toolCall', - ...(message as { toolCall: Omit }) - .toolCall - } as LiveServerToolCall; - } else if (LiveResponseType.TOOL_CALL_CANCELLATION in message) { - yield { - type: 'toolCallCancellation', - ...( + if (this._serverMessages) { + for await (const message of this._serverMessages) { + if (message && typeof message === 'object') { + if (LiveResponseType.SERVER_CONTENT in message) { + yield { + type: 'serverContent', + ...(message as { serverContent: Omit }) + .serverContent + } as LiveServerContent; + } else if (LiveResponseType.TOOL_CALL in message) { + yield { + type: 'toolCall', + ...(message as { toolCall: Omit }) + .toolCall + } as LiveServerToolCall; + } else if (LiveResponseType.TOOL_CALL_CANCELLATION in message) { + yield { + type: 'toolCallCancellation', + ...( + message as { + toolCallCancellation: Omit< + LiveServerToolCallCancellation, + 'type' + >; + } + ).toolCallCancellation + } as LiveServerToolCallCancellation; + } else if ('goAway' in message) { + const notice = ( message as { - toolCallCancellation: Omit< - LiveServerToolCallCancellation, - 'type' - >; + goAway: { timeLeft: string }; } - ).toolCallCancellation - } as LiveServerToolCallCancellation; - } else if ('goAway' in message) { - const notice = ( - message as { - goAway: { timeLeft: string }; - } - ).goAway; - yield { - type: LiveResponseType.GOING_AWAY_NOTICE, - timeLeft: parseDuration(notice.timeLeft) - } as LiveServerGoingAwayNotice; + ).goAway; + yield { + type: LiveResponseType.GOING_AWAY_NOTICE, + timeLeft: parseDuration(notice.timeLeft) + } as LiveServerGoingAwayNotice; + } else if (LiveResponseType.SESSION_RESUMPTION_UPDATE in message) { + yield { + type: LiveResponseType.SESSION_RESUMPTION_UPDATE, + ...( + message as { + sessionResumptionUpdate: Omit< + LiveSessionResumptionUpdate, + 'type' + >; + } + ).sessionResumptionUpdate + } as LiveSessionResumptionUpdate; + } else { + logger.warn( + `Received an unknown message type from the server: ${JSON.stringify( + message + )}` + ); + } } else { logger.warn( - `Received an unknown message type from the server: ${JSON.stringify( + `Received an invalid message from the server: ${JSON.stringify( message )}` ); } - } else { - logger.warn( - `Received an invalid message from the server: ${JSON.stringify( - message - )}` - ); } } } @@ -301,7 +405,7 @@ export class LiveSession { async close(): Promise { if (!this.isClosed) { this.isClosed = true; - await this.webSocketHandler.close(1000, 'Client closed session.'); + await this._webSocketHandler.close(1000, 'Client closed session.'); } } @@ -329,7 +433,7 @@ export class LiveSession { const message: _LiveClientRealtimeInput = { realtimeInput: { mediaChunks: [mediaChunk] } }; - this.webSocketHandler.send(JSON.stringify(message)); + this._webSocketHandler.send(JSON.stringify(message)); }); } diff --git a/packages/ai/src/models/live-generative-model.ts b/packages/ai/src/models/live-generative-model.ts index a89921070e..189093c781 100644 --- a/packages/ai/src/models/live-generative-model.ts +++ b/packages/ai/src/models/live-generative-model.ts @@ -17,21 +17,19 @@ import { AIModel } from './ai-model'; import { LiveSession } from '../methods/live-session'; -import { AIError } from '../errors'; import { AI, - AIErrorCode, BackendType, Content, LiveGenerationConfig, LiveModelParams, + SessionResumptionConfig, Tool, ToolConfig } from '../public-types'; -import { WebSocketHandler } from '../websocket'; -import { WebSocketUrl } from '../requests/request'; import { formatSystemInstruction } from '../requests/request-helpers'; import { _LiveClientSetup } from '../types/live-responses'; +import { WebSocketHandler } from '../websocket'; /** * Class for Live generative model APIs. The Live API enables low-latency, two-way multimodal @@ -54,9 +52,10 @@ export class LiveGenerativeModel extends AIModel { ai: AI, modelParams: LiveModelParams, /** + * For testing injection * @internal */ - private _webSocketHandler: WebSocketHandler + private _webSocketHandler?: WebSocketHandler ) { super(ai, modelParams.model); this.generationConfig = modelParams.generationConfig || {}; @@ -75,10 +74,9 @@ export class LiveGenerativeModel extends AIModel { * * @beta */ - async connect(): Promise { - const url = new WebSocketUrl(this._apiSettings); - await this._webSocketHandler.connect(url.toString()); - + async connect( + sessionResumption?: SessionResumptionConfig + ): Promise { let fullModelPath: string; if (this._apiSettings.backend.backendType === BackendType.GOOGLE_AI) { fullModelPath = `projects/${this._apiSettings.project}/${this.model}`; @@ -94,42 +92,31 @@ export class LiveGenerativeModel extends AIModel { ...generationConfig } = this.generationConfig; + const contextWindowCompression = generationConfig.contextWindowCompression; + delete generationConfig.contextWindowCompression; + const setupMessage: _LiveClientSetup = { setup: { model: fullModelPath, generationConfig, + contextWindowCompression, tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction, inputAudioTranscription, - outputAudioTranscription + outputAudioTranscription, + sessionResumption } }; - try { - // Begin listening for server messages, and begin the handshake by sending the 'setupMessage' - const serverMessages = this._webSocketHandler.listen(); - this._webSocketHandler.send(JSON.stringify(setupMessage)); - - // Verify we received the handshake response 'setupComplete' - const firstMessage = (await serverMessages.next()).value; - if ( - !firstMessage || - !(typeof firstMessage === 'object') || - !('setupComplete' in firstMessage) - ) { - await this._webSocketHandler.close(1011, 'Handshake failure'); - throw new AIError( - AIErrorCode.RESPONSE_ERROR, - 'Server connection handshake failed. The server did not respond with a setupComplete message.' - ); - } + const session = new LiveSession( + setupMessage, + this._apiSettings, + sessionResumption, + this._webSocketHandler + ); - return new LiveSession(this._webSocketHandler, serverMessages); - } catch (e) { - // Ensure connection is closed on any setup error - await this._webSocketHandler.close(); - throw e; - } + await session.connectionPromise; + return session; } } diff --git a/packages/ai/src/types/live-responses.ts b/packages/ai/src/types/live-responses.ts index 3bdb32c126..ef46f8eec0 100644 --- a/packages/ai/src/types/live-responses.ts +++ b/packages/ai/src/types/live-responses.ts @@ -23,7 +23,9 @@ import { } from './content'; import { AudioTranscriptionConfig, + ContextWindowCompressionConfig, LiveGenerationConfig, + SessionResumptionConfig, Tool, ToolConfig } from './requests'; @@ -88,6 +90,8 @@ export interface _LiveClientSetup { systemInstruction?: string | Part | Content; inputAudioTranscription?: AudioTranscriptionConfig; outputAudioTranscription?: AudioTranscriptionConfig; + sessionResumption?: SessionResumptionConfig; + contextWindowCompression?: ContextWindowCompressionConfig; }; } diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index 3b10836bb8..93eb557358 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -232,6 +232,70 @@ export interface LiveGenerationConfig { * "How are you today?", the model may transcribe that output across three messages, broken up as "How a", "re yo", "u today?". */ outputAudioTranscription?: AudioTranscriptionConfig; + /** + * The context window compression configuration. + * + * @beta + */ + contextWindowCompression?: ContextWindowCompressionConfig; +} + +/** + * Configures the sliding window context compression mechanism. + * + * @remarks + * The sliding window discards content at the beginning of the + * context window. The resulting context will always begin at + * the start of a `user` role turn. System instructions + * will always remain at the start of the result. + * + * @beta + */ +export interface SlidingWindow { + /** + * The session reduction target, for example, how many tokens the model + * should keep. + */ + targetTokens?: number; +} + +/** + * Enables context window compression to manage the model's context window. + * + * @remarks + * This mechanism prevents the context from exceeding a given length. + * + * @beta + */ +export interface ContextWindowCompressionConfig { + /** + * The number of tokens (before running a turn) that triggers the context + * window compression. + */ + triggerTokens?: number; + + /** + * The sliding window compression mechanism. + */ + slidingWindow?: SlidingWindow; +} + +/** + * Configuration for the session resumption mechanism. + * + * @remarks + * When included in the session setup, the server will send + * {@link LiveSessionResumptionUpdate} messages in the response stream. + * + * @beta + */ +export interface SessionResumptionConfig { + /** + * The session resumption handle of the previous session to restore. + * + * If not present, a new session will be started. + */ + handle?: string; } /** diff --git a/packages/ai/src/types/responses.ts b/packages/ai/src/types/responses.ts index 0f9a86e103..c99381f140 100644 --- a/packages/ai/src/types/responses.ts +++ b/packages/ai/src/types/responses.ts @@ -362,7 +362,7 @@ export interface Segment { /** * The zero-based start index of the segment within the specified `Part`, * measured in UTF-8 bytes. This offset is inclusive, starting from 0 at the - * beginning of the part's content (e.g., `Part.text`). + * beginning of the part's content (for example, `Part.text`). */ startIndex: number; /** @@ -629,6 +629,30 @@ export interface LiveServerGoingAwayNotice { timeLeft: number; } +/** + * An update of the session resumption state. + * + * This message is only sent if {@link SessionResumptionConfig} was set in the + * session setup. + * + * @beta + */ +export interface LiveSessionResumptionUpdate { + type: 'sessionResumptionUpdate'; + /** + * The new handle that represents the state that can be resumed. Empty if `resumable` is false. + */ + newHandle?: string; + /** + * Indicates if the session can be resumed at this point. + */ + resumable?: boolean; + /** + * The index of the last client message that is included in the state represented by this update. + */ + lastConsumedClientMessageIndex?: number; +} + /** * The types of responses that can be returned by {@link LiveSession.receive}. * @@ -638,7 +662,8 @@ export const LiveResponseType = { SERVER_CONTENT: 'serverContent', TOOL_CALL: 'toolCall', TOOL_CALL_CANCELLATION: 'toolCallCancellation', - GOING_AWAY_NOTICE: 'goingAwayNotice' + GOING_AWAY_NOTICE: 'goingAwayNotice', + SESSION_RESUMPTION_UPDATE: 'sessionResumptionUpdate' }; /** From 8e384c947de73c7f74346b1c01640f3515a4ef0e Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 23 Apr 2026 11:57:15 -0700 Subject: [PATCH 157/174] chore: Combine a group of dependabot security updates (#9883) * Bump decode-uri-component in /packages/auth-compat/demo Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2. - [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases) - [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2) --- updated-dependencies: - dependency-name: decode-uri-component dependency-type: indirect ... Signed-off-by: dependabot[bot] * Bump word-wrap in /packages/rules-unit-testing/functions Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.5. - [Release notes](https://github.com/jonschlinkert/word-wrap/releases) - [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.5) --- updated-dependencies: - dependency-name: word-wrap dependency-type: indirect ... Signed-off-by: dependabot[bot] * Bump @grpc/grpc-js in /packages/rules-unit-testing/functions Bumps [@grpc/grpc-js](https://github.com/grpc/grpc-node) from 1.8.21 to 1.8.22. - [Release notes](https://github.com/grpc/grpc-node/releases) - [Commits](https://github.com/grpc/grpc-node/compare/@grpc/grpc-js@1.8.21...@grpc/grpc-js@1.8.22) --- updated-dependencies: - dependency-name: "@grpc/grpc-js" dependency-type: indirect ... Signed-off-by: dependabot[bot] * Bump micromatch from 4.0.4 to 4.0.8 in /packages/auth-compat/demo Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.4 to 4.0.8. - [Release notes](https://github.com/micromatch/micromatch/releases) - [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/micromatch/compare/4.0.4...4.0.8) --- updated-dependencies: - dependency-name: micromatch dependency-type: indirect ... Signed-off-by: dependabot[bot] * Bump express in /packages/auth-compat/demo/functions Bumps [express](https://github.com/expressjs/express) from 4.17.1 to 4.21.0. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md) - [Commits](https://github.com/expressjs/express/compare/4.17.1...4.21.0) --- updated-dependencies: - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] * Bump webpack-dev-server from 5.2.0 to 5.2.1 in /e2e/smoke-tests Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 5.2.0 to 5.2.1. - [Release notes](https://github.com/webpack/webpack-dev-server/releases) - [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md) - [Commits](https://github.com/webpack/webpack-dev-server/compare/v5.2.0...v5.2.1) --- updated-dependencies: - dependency-name: webpack-dev-server dependency-version: 5.2.1 dependency-type: direct:development ... Signed-off-by: dependabot[bot] * build(deps): bump tmp in /packages/auth-compat/demo/functions Bumps [tmp](https://github.com/raszi/node-tmp) from 0.2.3 to 0.2.4. - [Changelog](https://github.com/raszi/node-tmp/blob/master/CHANGELOG.md) - [Commits](https://github.com/raszi/node-tmp/compare/v0.2.3...v0.2.4) --- updated-dependencies: - dependency-name: tmp dependency-version: 0.2.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] * build(deps): bump sha.js from 2.4.11 to 2.4.12 Bumps [sha.js](https://github.com/crypto-browserify/sha.js) from 2.4.11 to 2.4.12. - [Changelog](https://github.com/browserify/sha.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/crypto-browserify/sha.js/compare/v2.4.11...v2.4.12) --- updated-dependencies: - dependency-name: sha.js dependency-version: 2.4.12 dependency-type: indirect ... Signed-off-by: dependabot[bot] * build(deps): bump tmp in /packages/rules-unit-testing/functions Bumps [tmp](https://github.com/raszi/node-tmp) from 0.2.1 to 0.2.5. - [Changelog](https://github.com/raszi/node-tmp/blob/master/CHANGELOG.md) - [Commits](https://github.com/raszi/node-tmp/compare/v0.2.1...v0.2.5) --- updated-dependencies: - dependency-name: tmp dependency-version: 0.2.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] * build(deps): bump tar-fs from 2.1.2 to 2.1.4 Bumps [tar-fs](https://github.com/mafintosh/tar-fs) from 2.1.2 to 2.1.4. - [Commits](https://github.com/mafintosh/tar-fs/compare/v2.1.2...v2.1.4) --- updated-dependencies: - dependency-name: tar-fs dependency-version: 2.1.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] * build(deps): bump tmp from 0.2.3 to 0.2.4 in /repo-scripts/size-analysis Bumps [tmp](https://github.com/raszi/node-tmp) from 0.2.3 to 0.2.4. - [Changelog](https://github.com/raszi/node-tmp/blob/master/CHANGELOG.md) - [Commits](https://github.com/raszi/node-tmp/compare/v0.2.3...v0.2.4) --- updated-dependencies: - dependency-name: tmp dependency-version: 0.2.4 dependency-type: direct:production ... Signed-off-by: dependabot[bot] * build(deps): bump js-yaml from 4.1.0 to 4.1.1 Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.0 to 4.1.1. - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.1.0...4.1.1) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.1.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] * build(deps): bump js-yaml in /repo-scripts/api-documenter Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.0 to 4.1.1. - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.1.0...4.1.1) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.1.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] * build(deps): bump picomatch from 2.3.1 to 2.3.2 Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2. - [Release notes](https://github.com/micromatch/picomatch/releases) - [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2) --- updated-dependencies: - dependency-name: picomatch dependency-version: 2.3.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] * build(deps): bump handlebars in /packages/auth-compat/demo Bumps [handlebars](https://github.com/handlebars-lang/handlebars.js) from 4.7.7 to 4.7.9. - [Release notes](https://github.com/handlebars-lang/handlebars.js/releases) - [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/v4.7.9/release-notes.md) - [Commits](https://github.com/handlebars-lang/handlebars.js/compare/v4.7.7...v4.7.9) --- updated-dependencies: - dependency-name: handlebars dependency-version: 4.7.9 dependency-type: indirect ... Signed-off-by: dependabot[bot] * build(deps): bump yaml in /packages/auth-compat/demo Bumps [yaml](https://github.com/eemeli/yaml) from 1.10.2 to 1.10.3. - [Release notes](https://github.com/eemeli/yaml/releases) - [Commits](https://github.com/eemeli/yaml/compare/v1.10.2...v1.10.3) --- updated-dependencies: - dependency-name: yaml dependency-version: 1.10.3 dependency-type: indirect ... Signed-off-by: dependabot[bot] * build(deps): bump basic-ftp from 5.2.0 to 5.2.2 Bumps [basic-ftp](https://github.com/patrickjuchli/basic-ftp) from 5.2.0 to 5.2.2. - [Release notes](https://github.com/patrickjuchli/basic-ftp/releases) - [Changelog](https://github.com/patrickjuchli/basic-ftp/blob/master/CHANGELOG.md) - [Commits](https://github.com/patrickjuchli/basic-ftp/compare/v5.2.0...v5.2.2) --- updated-dependencies: - dependency-name: basic-ftp dependency-version: 5.2.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] * Add changeset * revert picomatch --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .changeset/nasty-kiwis-yell.md | 53 +++ e2e/smoke-tests/yarn.lock | 24 +- package.json | 2 +- packages/auth-compat/demo/functions/yarn.lock | 427 +++++++++++------- packages/auth-compat/demo/yarn.lock | 52 +-- .../rules-unit-testing/functions/yarn.lock | 64 +-- repo-scripts/api-documenter/package.json | 2 +- yarn.lock | 32 +- 8 files changed, 379 insertions(+), 277 deletions(-) create mode 100644 .changeset/nasty-kiwis-yell.md diff --git a/.changeset/nasty-kiwis-yell.md b/.changeset/nasty-kiwis-yell.md new file mode 100644 index 0000000000..656e6842d7 --- /dev/null +++ b/.changeset/nasty-kiwis-yell.md @@ -0,0 +1,53 @@ +--- +'@firebase/rules-unit-testing': patch +'@firebase/auth-compat': patch +'@firebase/ai': patch +'@firebase/analytics': patch +'@firebase/analytics-compat': patch +'@firebase/analytics-interop-types': patch +'@firebase/analytics-types': patch +'@firebase/app': patch +'@firebase/app-check': patch +'@firebase/app-check-compat': patch +'@firebase/app-check-interop-types': patch +'@firebase/app-check-types': patch +'@firebase/app-compat': patch +'@firebase/app-types': patch +'@firebase/auth': patch +'@firebase/auth-interop-types': patch +'@firebase/auth-types': patch +'@firebase/component': patch +'@firebase/data-connect': patch +'@firebase/database': patch +'@firebase/database-compat': patch +'@firebase/database-types': patch +'firebase': patch +'@firebase/firestore': patch +'@firebase/firestore-compat': patch +'@firebase/firestore-types': patch +'@firebase/functions': patch +'@firebase/functions-compat': patch +'@firebase/functions-types': patch +'@firebase/installations': patch +'@firebase/installations-compat': patch +'@firebase/installations-types': patch +'@firebase/logger': patch +'@firebase/messaging': patch +'@firebase/messaging-compat': patch +'@firebase/messaging-interop-types': patch +'@firebase/performance': patch +'@firebase/performance-compat': patch +'@firebase/performance-types': patch +'@firebase/remote-config': patch +'@firebase/remote-config-compat': patch +'@firebase/remote-config-types': patch +'@firebase/storage': patch +'@firebase/storage-compat': patch +'@firebase/storage-types': patch +'@firebase/template': patch +'@firebase/template-types': patch +'@firebase/util': patch +'@firebase/webchannel-wrapper': patch +--- + +Updated dependencies. diff --git a/e2e/smoke-tests/yarn.lock b/e2e/smoke-tests/yarn.lock index ce525e4ed9..823c955ec7 100644 --- a/e2e/smoke-tests/yarn.lock +++ b/e2e/smoke-tests/yarn.lock @@ -2303,7 +2303,7 @@ "@types/range-parser" "*" "@types/send" "*" -"@types/express-serve-static-core@^4.17.21": +"@types/express-serve-static-core@^4.17.21", "@types/express-serve-static-core@^4.17.33": version "4.19.8" resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz#99b960322a4d576b239a640ab52ef191989b036f" integrity sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA== @@ -2313,16 +2313,6 @@ "@types/range-parser" "*" "@types/send" "*" -"@types/express-serve-static-core@^4.17.33": - version "4.19.6" - resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz" - integrity sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - "@types/send" "*" - "@types/express@*": version "5.0.0" resolved "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz" @@ -5384,17 +5374,7 @@ schema-utils@^2.6.5: ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^4.0.0, schema-utils@^4.2.0: - version "4.2.0" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz" - integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== - dependencies: - "@types/json-schema" "^7.0.9" - ajv "^8.9.0" - ajv-formats "^2.1.1" - ajv-keywords "^5.1.0" - -schema-utils@^4.3.0: +schema-utils@^4.0.0, schema-utils@^4.2.0, schema-utils@^4.3.0: version "4.3.0" resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz" integrity sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g== diff --git a/package.json b/package.json index 20306196f6..016efa9adc 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "http-server": "14.1.1", "indexeddbshim": "10.1.0", "inquirer": "8.2.6", - "js-yaml": "4.1.0", + "js-yaml": "4.1.1", "karma": "6.4.4", "karma-chrome-launcher": "3.2.0", "karma-cli": "2.0.0", diff --git a/packages/auth-compat/demo/functions/yarn.lock b/packages/auth-compat/demo/functions/yarn.lock index d18abe9a9b..4584f7a996 100644 --- a/packages/auth-compat/demo/functions/yarn.lock +++ b/packages/auth-compat/demo/functions/yarn.lock @@ -365,13 +365,13 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" -accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" + mime-types "~2.1.34" + negotiator "0.6.3" acorn-jsx@^5.3.2: version "5.3.2" @@ -444,21 +444,23 @@ bluebird@^3.7.2: resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== +body-parser@1.20.3: + version "1.20.3" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== dependencies: - bytes "3.1.0" - content-type "~1.0.4" + bytes "3.1.2" + content-type "~1.0.5" debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" + on-finished "2.4.1" + qs "6.13.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" brace-expansion@^2.0.1: version "2.0.3" @@ -472,10 +474,21 @@ buffer-equal-constant-time@^1.0.1: resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" catharsis@^0.9.0: version "0.9.0" @@ -520,27 +533,32 @@ compressible@^2.0.12: dependencies: mime-db ">= 1.43.0 < 2" -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: - safe-buffer "5.1.2" + safe-buffer "5.2.1" content-type@~1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== cors@^2.8.5: version "2.8.5" @@ -576,15 +594,24 @@ deep-is@~0.1.3: resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +depd@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== duplexify@^4.0.0: version "4.1.2" @@ -618,6 +645,11 @@ encodeurl@~1.0.2: resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -635,6 +667,18 @@ entities@~2.1.0: resolved "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + escalade@^3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -707,37 +751,38 @@ event-target-shim@^5.0.0: integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== express@^4.17.1: - version "4.17.1" - resolved "https://registry.npmjs.org/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + version "4.21.0" + resolved "https://registry.npmjs.org/express/-/express-4.21.0.tgz#d57cb706d49623d4ac27833f1cbc466b668eb915" + integrity sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" + body-parser "1.20.3" + content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.0" + cookie "0.6.0" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" + depd "2.0.0" + encodeurl "~2.0.0" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "~1.1.2" + finalhandler "1.3.1" fresh "0.5.2" - merge-descriptors "1.0.1" + http-errors "2.0.0" + merge-descriptors "1.0.3" methods "~1.1.2" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" + path-to-regexp "0.1.10" + proxy-addr "~2.0.7" + qs "6.13.0" range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" + safe-buffer "5.2.1" + send "0.19.0" + serve-static "1.16.2" + setprototypeof "1.2.0" + statuses "2.0.1" type-is "~1.6.18" utils-merge "1.0.1" vary "~1.1.2" @@ -776,17 +821,17 @@ faye-websocket@0.11.4: dependencies: websocket-driver ">=0.5.1" -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== +finalhandler@1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== dependencies: debug "2.6.9" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" - statuses "~1.5.0" + statuses "2.0.1" unpipe "~1.0.0" firebase-admin@11.11.1: @@ -833,6 +878,11 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" @@ -861,6 +911,17 @@ get-caller-file@^2.0.5: resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + glob@^8.0.0: version "8.1.0" resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" @@ -915,6 +976,13 @@ google-p12-pem@^4.0.0: dependencies: node-forge "^1.3.1" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + graceful-fs@^4.1.9: version "4.2.11" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" @@ -934,27 +1002,40 @@ has-flag@^4.0.0: resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: - depd "~1.1.2" + function-bind "^1.1.2" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" http-parser-js@>=0.5.1: version "0.5.3" @@ -998,11 +1079,6 @@ inherits@2, inherits@2.0.4, inherits@^2.0.3: resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -1261,10 +1337,10 @@ media-typer@0.3.0: resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= +merge-descriptors@1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== methods@~1.1.2: version "1.1.2" @@ -1276,6 +1352,11 @@ mime-db@1.49.0: resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + "mime-db@>= 1.43.0 < 2": version "1.50.0" resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" @@ -1288,6 +1369,13 @@ mime-types@^2.0.8, mime-types@~2.1.24: dependencies: mime-db "1.49.0" +mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + mime@1.6.0: version "1.6.0" resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -1320,25 +1408,20 @@ ms@2.0.0: resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - ms@2.1.2: version "2.1.2" resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@2.1.3, ms@^2.1.1: version "2.1.3" resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" @@ -1369,10 +1452,15 @@ object-hash@^3.0.0: resolved "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== dependencies: ee-first "1.1.1" @@ -1407,10 +1495,10 @@ parseurl@~1.3.3: resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= +path-to-regexp@0.1.10: + version "0.1.10" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b" + integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w== prelude-ls@~1.1.2: version "1.1.2" @@ -1476,7 +1564,7 @@ protobufjs@^7.0.0, protobufjs@^7.2.4, protobufjs@^7.2.5: "@types/node" ">=13.7.0" long "^5.0.0" -proxy-addr@~2.0.5: +proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== @@ -1489,23 +1577,25 @@ pseudomap@^1.0.1: resolved "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -qs@6.7.0: - version "6.7.0" - resolved "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== +qs@6.13.0: + version "6.13.0" + resolved "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== + dependencies: + side-channel "^1.0.6" range-parser@~1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: - bytes "3.1.0" - http-errors "1.7.2" + bytes "3.1.2" + http-errors "2.0.0" iconv-lite "0.4.24" unpipe "1.0.0" @@ -1543,12 +1633,7 @@ retry@0.13.1: resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== -safe-buffer@5.1.2: - version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -1565,49 +1650,71 @@ semver@^7.1.2, semver@^7.5.4: dependencies: lru-cache "^6.0.0" -send@0.17.1: - version "0.17.1" - resolved "https://registry.npmjs.org/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== +send@0.19.0: + version "0.19.0" + resolved "https://registry.npmjs.org/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== dependencies: debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" + depd "2.0.0" + destroy "1.2.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "~1.7.2" + http-errors "2.0.0" mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" + ms "2.1.3" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~1.5.0" + statuses "2.0.1" -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== +serve-static@1.16.2: + version "1.16.2" + resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== dependencies: - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.17.1" - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + send "0.19.0" + +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" source-map@~0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== stream-events@^1.0.5: version "1.0.5" @@ -1683,14 +1790,14 @@ text-decoding@^1.0.0: integrity sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA== tmp@^0.2.1: - version "0.2.3" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" - integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== + version "0.2.4" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz#c6db987a2ccc97f812f17137b36af2b6521b0d13" + integrity sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ== -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== tr46@~0.0.3: version "0.0.3" @@ -1709,7 +1816,7 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-is@~1.6.17, type-is@~1.6.18: +type-is@~1.6.18: version "1.6.18" resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== diff --git a/packages/auth-compat/demo/yarn.lock b/packages/auth-compat/demo/yarn.lock index af35355c37..2ca0d14072 100644 --- a/packages/auth-compat/demo/yarn.lock +++ b/packages/auth-compat/demo/yarn.lock @@ -1219,12 +1219,12 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1: - version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" buffer-from@^1.0.0: version "1.1.2" @@ -1626,9 +1626,9 @@ decamelize@^1.1.0: integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== dedent@^0.7.0: version "0.7.0" @@ -1897,10 +1897,10 @@ figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" @@ -2157,12 +2157,12 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== handlebars@^4.7.6: - version "4.7.7" - resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + version "4.7.9" + resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz#6f139082ab58dc4e5a0e51efe7db5ae890d56a0f" + integrity sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ== dependencies: minimist "^1.2.5" - neo-async "^2.6.0" + neo-async "^2.6.2" source-map "^0.6.1" wordwrap "^1.0.0" optionalDependencies: @@ -2928,12 +2928,12 @@ merge2@^1.3.0: integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + version "4.0.8" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: - braces "^3.0.1" - picomatch "^2.2.3" + braces "^3.0.3" + picomatch "^2.3.1" mime-db@1.49.0: version "1.49.0" @@ -3112,7 +3112,7 @@ negotiator@^0.6.2: resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.6.0: +neo-async@^2.6.2: version "2.6.2" resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -3605,7 +3605,7 @@ performance-now@^2.1.0: resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picomatch@^2.2.2, picomatch@^2.2.3: +picomatch@^2.2.2: version "2.3.0" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== @@ -4840,9 +4840,9 @@ yallist@^4.0.0: integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yaml@^1.10.0: - version "1.10.2" - resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + version "1.10.3" + resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz#76e407ed95c42684fb8e14641e5de62fe65bbcb3" + integrity sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA== yargs-parser@20.2.4: version "20.2.4" diff --git a/packages/rules-unit-testing/functions/yarn.lock b/packages/rules-unit-testing/functions/yarn.lock index 6e13cd4a63..eca4701e61 100644 --- a/packages/rules-unit-testing/functions/yarn.lock +++ b/packages/rules-unit-testing/functions/yarn.lock @@ -131,9 +131,9 @@ uuid "^8.0.0" "@grpc/grpc-js@~1.8.0": - version "1.8.21" - resolved "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.21.tgz#d282b122c71227859bf6c5866f4c40f4a2696513" - integrity sha512-KeyQeZpxeEBSqFVTi3q2K7PiPXmgBfECc4updA1ejCLjYmoAlvvM3ZMp5ztTDUCUQmoY3CpDxvchjO1+rFkoHg== + version "1.8.22" + resolved "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.22.tgz#847930c9af46e14df05b57fc12325db140ceff1d" + integrity sha512-oAjDdN7fzbUi+4hZjKG96MR6KTEubAeMpQEb+77qy+3r0Ua5xTFuie6JOLr4ZZgl5g+W5/uRTS2M1V8mVAFPuA== dependencies: "@grpc/proto-loader" "^0.7.0" "@types/node" ">=12.12.47" @@ -461,14 +461,6 @@ body-parser@1.19.0: raw-body "2.4.0" type-is "~1.6.17" -brace-expansion@^1.1.7: - version "1.1.12" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" - integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - brace-expansion@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" @@ -529,11 +521,6 @@ compressible@^2.0.12: dependencies: mime-db ">= 1.43.0 < 2" -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - content-disposition@0.5.3: version "0.5.3" resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -875,18 +862,6 @@ get-caller-file@^2.0.5: resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^8.0.0: version "8.0.3" resolved "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e" @@ -1344,13 +1319,6 @@ mime@^3.0.0: resolved "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== -minimatch@^3.1.1: - version "3.1.4" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.4.tgz#89d910ea3970a77ac8edfd30340ccd038b758079" - integrity sha512-twmL+S8+7yIsE9wsqgzU3E8/LumN3M3QELrBZ20OdmQ9jB2JvW5oZtBEmft84k/Gs5CG9mqtWc6Y9vW+JEzGxw== - dependencies: - brace-expansion "^1.1.7" - minimatch@^5.0.1: version "5.1.8" resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.8.tgz#32a16ebcccd6421c674430acb199b8806c68169b" @@ -1460,11 +1428,6 @@ parseurl@~1.3.3: resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -1619,13 +1582,6 @@ retry@0.13.1: resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== -rimraf@^3.0.0: - version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - safe-buffer@5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -1773,11 +1729,9 @@ text-decoding@^1.0.0: integrity sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA== tmp@^0.2.1: - version "0.2.1" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" - integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== - dependencies: - rimraf "^3.0.0" + version "0.2.5" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz#b06bcd23f0f3c8357b426891726d16015abfd8f8" + integrity sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow== toidentifier@1.0.0: version "1.0.0" @@ -1882,9 +1836,9 @@ whatwg-url@^5.0.0: webidl-conversions "^3.0.0" word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + version "1.2.5" + resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== wrap-ansi@^7.0.0: version "7.0.0" diff --git a/repo-scripts/api-documenter/package.json b/repo-scripts/api-documenter/package.json index 39573bdd6f..9ab41da3af 100644 --- a/repo-scripts/api-documenter/package.json +++ b/repo-scripts/api-documenter/package.json @@ -28,7 +28,7 @@ "colors": "~1.4.0", "resolve": "~1.22.0", "tslib": "^2.1.0", - "js-yaml": "4.1.0" + "js-yaml": "4.1.1" }, "devDependencies": { "@types/js-yaml": "4.0.9", diff --git a/yarn.lock b/yarn.lock index f6a9fd26d9..bf7bf5d9b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4766,9 +4766,9 @@ basic-auth@^2.0.1, basic-auth@~2.0.1: safe-buffer "5.1.2" basic-ftp@^5.0.2: - version "5.2.0" - resolved "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.0.tgz#7c2dff63c918bde60e6bad1f2ff93dcf5137a40a" - integrity sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw== + version "5.2.2" + resolved "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.2.tgz#4cb2422deddf432896bdb3c9b8f13b944ad4842c" + integrity sha512-1tDrzKsdCg70WGvbFss/ulVAxupNauGnOlgpyjKzeQxzyllBLS0CGLV7tjIXTK3ZQA9/FBEm9qyFFN1bciA6pw== bcrypt-pbkdf@^1.0.0: version "1.0.2" @@ -10337,13 +10337,20 @@ js-tokens@^4.0.0: resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@4.1.0, js-yaml@^4.1.0: +js-yaml@4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" +js-yaml@4.1.1, js-yaml@^4.1.0: + version "4.1.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== + dependencies: + argparse "^2.0.1" + js-yaml@^3.13.1, js-yaml@^3.14.1, js-yaml@^3.6.1: version "3.14.1" resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -14930,12 +14937,13 @@ setprototypeof@1.2.0: integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + version "2.4.12" + resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz#eb8b568bf383dfd1867a32c3f2b74eb52bdbf23f" + integrity sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + safe-buffer "^5.2.1" + to-buffer "^1.2.0" sha.js@^2.4.12: version "2.4.12" @@ -15863,9 +15871,9 @@ tapable@^2.1.1, tapable@^2.2.0: integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== tar-fs@^2.0.0: - version "2.1.2" - resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz#425f154f3404cb16cb8ff6e671d45ab2ed9596c5" - integrity sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA== + version "2.1.4" + resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz#800824dbf4ef06ded9afea4acafe71c67c76b930" + integrity sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ== dependencies: chownr "^1.1.1" mkdirp-classic "^0.5.2" From 345c5f6235492b45e84034f364fd95280bd6e428 Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Thu, 23 Apr 2026 15:47:21 -0400 Subject: [PATCH 158/174] feat(ai) Google Maps Grounding Support (#9458) ### Discussion Implement new tools to use Grounding with Google Maps, similar to how Grounding with Google Search works. ### Testing Integration tests. Unit tests. Node standalone app. Updated Quickstart React-based app (not part of this PR). ### API Changes - Grounding with Google Maps support, see internal doc: go/fal-maps-grounding-api - TemplateToolConfig, see internal doc: go/firebase-ai-server-prompt-template --- .changeset/quick-cars-obey.md | 6 + common/api-review/ai.api.md | 47 +++- docs-devsite/_toc.yaml | 12 + docs-devsite/ai.googlemaps.md | 33 +++ docs-devsite/ai.googlemapsgroundingchunk.md | 70 ++++++ docs-devsite/ai.googlemapstool.md | 39 ++++ docs-devsite/ai.groundingchunk.md | 11 + docs-devsite/ai.groundingmetadata.md | 15 +- docs-devsite/ai.latlng.md | 46 ++++ docs-devsite/ai.md | 10 +- docs-devsite/ai.retrievalconfig.md | 46 ++++ docs-devsite/ai.templategenerativemodel.md | 14 +- docs-devsite/ai.templatetoolconfig.md | 33 +++ docs-devsite/ai.toolconfig.md | 9 + .../ai/integration/generate-content.test.ts | 211 ++++++++++++++++++ .../ai/src/methods/generate-content.test.ts | 58 +++++ .../models/template-generative-model.test.ts | 154 ++++++++++++- .../src/models/template-generative-model.ts | 23 +- packages/ai/src/types/requests.ts | 78 +++++++ packages/ai/src/types/responses.ts | 47 +++- 20 files changed, 940 insertions(+), 22 deletions(-) create mode 100644 .changeset/quick-cars-obey.md create mode 100644 docs-devsite/ai.googlemaps.md create mode 100644 docs-devsite/ai.googlemapsgroundingchunk.md create mode 100644 docs-devsite/ai.googlemapstool.md create mode 100644 docs-devsite/ai.latlng.md create mode 100644 docs-devsite/ai.retrievalconfig.md create mode 100644 docs-devsite/ai.templatetoolconfig.md diff --git a/.changeset/quick-cars-obey.md b/.changeset/quick-cars-obey.md new file mode 100644 index 0000000000..12aef6e4a9 --- /dev/null +++ b/.changeset/quick-cars-obey.md @@ -0,0 +1,6 @@ +--- +'@firebase/ai': minor +'firebase': minor +--- + +AI Logic : Feature : Added support for Grounding with Google Maps. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index f4ba0806d6..faa099c0ab 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -690,6 +690,25 @@ export interface GoogleAIGenerateContentResponse { usageMetadata?: UsageMetadata; } +// @public +export interface GoogleMaps { + // (undocumented) + enableWidget?: boolean; +} + +// @public +export interface GoogleMapsGroundingChunk { + placeId?: string; + text?: string; + title?: string; + uri?: string; +} + +// @public +export interface GoogleMapsTool { + googleMaps: GoogleMaps; +} + // @public export interface GoogleSearch { } @@ -701,11 +720,13 @@ export interface GoogleSearchTool { // @public export interface GroundingChunk { + maps?: GoogleMapsGroundingChunk; web?: WebGroundingChunk; } // @public export interface GroundingMetadata { + googleMapsWidgetContextToken?: string; groundingChunks?: GroundingChunk[]; groundingSupports?: GroundingSupport[]; // @deprecated (undocumented) @@ -987,6 +1008,12 @@ export interface LanguageModelPromptOptions { responseConstraint?: object; } +// @public +export interface LatLng { + latitude?: number; + longitude?: number; +} + // @beta export interface LiveGenerationConfig { contextWindowCompression?: ContextWindowCompressionConfig; @@ -1224,6 +1251,12 @@ export const ResponseModality: { // @beta export type ResponseModality = (typeof ResponseModality)[keyof typeof ResponseModality]; +// @public +export interface RetrievalConfig { + languageCode?: string; + latLng?: LatLng; +} + // @public (undocumented) export interface RetrievedContextAttribution { // (undocumented) @@ -1480,8 +1513,8 @@ export class TemplateGenerativeModel { constructor(ai: AI, requestOptions?: RequestOptions); // @internal (undocumented) _apiSettings: ApiSettings; - generateContent(templateId: string, templateVariables: Record, singleRequestOptions?: SingleRequestOptions): Promise; - generateContentStream(templateId: string, templateVariables: Record, singleRequestOptions?: SingleRequestOptions): Promise; + generateContent(templateId: string, templateVariables: Record, singleRequestOptions?: SingleRequestOptions, templateToolConfig?: TemplateToolConfig): Promise; + generateContentStream(templateId: string, templateVariables: Record, singleRequestOptions?: SingleRequestOptions, templateToolConfig?: TemplateToolConfig): Promise; requestOptions?: RequestOptions; startChat(params: StartTemplateChatParams): TemplateChatSession; } @@ -1507,6 +1540,12 @@ export interface TemplateRequestInternal extends OmitSignature: + +```typescript +export interface GoogleMaps +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [enableWidget](./ai.googlemaps.md#googlemapsenablewidget) | boolean | | + +## GoogleMaps.enableWidget + +Signature: + +```typescript +enableWidget?: boolean; +``` diff --git a/docs-devsite/ai.googlemapsgroundingchunk.md b/docs-devsite/ai.googlemapsgroundingchunk.md new file mode 100644 index 0000000000..64e63fa812 --- /dev/null +++ b/docs-devsite/ai.googlemapsgroundingchunk.md @@ -0,0 +1,70 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GoogleMapsGroundingChunk interface +A grounding chunk from Google Maps. + +Important: If using Grounding with Google Maps, you are required to comply with the [Service Specific Terms](https://cloud.google.com/terms/service-terms) for "Grounding with Google Maps". + +Signature: + +```typescript +export interface GoogleMapsGroundingChunk +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [placeId](./ai.googlemapsgroundingchunk.md#googlemapsgroundingchunkplaceid) | string | This Place's resource name, in places/{place_id} format. This can be used to look up the place in the Google Maps API. | +| [text](./ai.googlemapsgroundingchunk.md#googlemapsgroundingchunktext) | string | The text of the place answer. | +| [title](./ai.googlemapsgroundingchunk.md#googlemapsgroundingchunktitle) | string | The title of the place. | +| [uri](./ai.googlemapsgroundingchunk.md#googlemapsgroundingchunkuri) | string | The URI of the place. | + +## GoogleMapsGroundingChunk.placeId + +This Place's resource name, in `places/{place_id}` format. This can be used to look up the place in the Google Maps API. + +Signature: + +```typescript +placeId?: string; +``` + +## GoogleMapsGroundingChunk.text + +The text of the place answer. + +Signature: + +```typescript +text?: string; +``` + +## GoogleMapsGroundingChunk.title + +The title of the place. + +Signature: + +```typescript +title?: string; +``` + +## GoogleMapsGroundingChunk.uri + +The URI of the place. + +Signature: + +```typescript +uri?: string; +``` diff --git a/docs-devsite/ai.googlemapstool.md b/docs-devsite/ai.googlemapstool.md new file mode 100644 index 0000000000..47e7538daa --- /dev/null +++ b/docs-devsite/ai.googlemapstool.md @@ -0,0 +1,39 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GoogleMapsTool interface +A tool that allows a Gemini model to connect to Google Maps to access and incorporate location-based information into its responses. + +Important: If using Grounding with Google Maps, you are required to comply with the "Grounding with Google Maps" usage requirements for your chosen API provider: [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-maps) or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section within the Service Specific Terms). + +Signature: + +```typescript +export interface GoogleMapsTool +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [googleMaps](./ai.googlemapstool.md#googlemapstoolgooglemaps) | [GoogleMaps](./ai.googlemaps.md#googlemaps_interface) | Specifies the Google Maps configuration.When using this feature, you are required to comply with the "Grounding with Google Maps" usage requirements for your chosen API provider: [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-maps) or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section within the Service Specific Terms). | + +## GoogleMapsTool.googleMaps + +Specifies the Google Maps configuration. + +When using this feature, you are required to comply with the "Grounding with Google Maps" usage requirements for your chosen API provider: [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-maps) or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section within the Service Specific Terms). + +Signature: + +```typescript +googleMaps: GoogleMaps; +``` diff --git a/docs-devsite/ai.groundingchunk.md b/docs-devsite/ai.groundingchunk.md index 2b84af29d8..a6b1f20172 100644 --- a/docs-devsite/ai.groundingchunk.md +++ b/docs-devsite/ai.groundingchunk.md @@ -22,8 +22,19 @@ export interface GroundingChunk | Property | Type | Description | | --- | --- | --- | +| [maps](./ai.groundingchunk.md#groundingchunkmaps) | [GoogleMapsGroundingChunk](./ai.googlemapsgroundingchunk.md#googlemapsgroundingchunk_interface) | Contains details if the grounding chunk is from a Google Maps source. | | [web](./ai.groundingchunk.md#groundingchunkweb) | [WebGroundingChunk](./ai.webgroundingchunk.md#webgroundingchunk_interface) | Contains details if the grounding chunk is from a web source. | +## GroundingChunk.maps + +Contains details if the grounding chunk is from a Google Maps source. + +Signature: + +```typescript +maps?: GoogleMapsGroundingChunk; +``` + ## GroundingChunk.web Contains details if the grounding chunk is from a web source. diff --git a/docs-devsite/ai.groundingmetadata.md b/docs-devsite/ai.groundingmetadata.md index 3eaa42bfed..21ce907623 100644 --- a/docs-devsite/ai.groundingmetadata.md +++ b/docs-devsite/ai.groundingmetadata.md @@ -12,10 +12,12 @@ https://github.com/firebase/firebase-js-sdk # GroundingMetadata interface Metadata returned when grounding is enabled. -Currently, only Grounding with Google Search is supported (see [GoogleSearchTool](./ai.googlesearchtool.md#googlesearchtool_interface)). +Currently, only Grounding with Google Search and Grounding with Google Maps are supported (see [GoogleSearchTool](./ai.googlesearchtool.md#googlesearchtool_interface) and [GoogleMapsTool](./ai.googlemapstool.md#googlemapstool_interface), respectively). Important: If using Grounding with Google Search, you are required to comply with the "Grounding with Google Search" usage requirements for your chosen API provider: [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-search) or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section within the Service Specific Terms). +Important: If using Grounding with Google Maps, you are required to comply with the "Grounding with Google Maps" usage requirements for your chosen API provider: [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-maps) or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section within the Service Specific Terms). + Signature: ```typescript @@ -26,12 +28,23 @@ export interface GroundingMetadata | Property | Type | Description | | --- | --- | --- | +| [googleMapsWidgetContextToken](./ai.groundingmetadata.md#groundingmetadatagooglemapswidgetcontexttoken) | string | Resource name of the Google Maps widget context token that can be used with the PlacesContextElement widget in order to render contextual data. Only populated in the case that grounding with Google Maps is enabled. | | [groundingChunks](./ai.groundingmetadata.md#groundingmetadatagroundingchunks) | [GroundingChunk](./ai.groundingchunk.md#groundingchunk_interface)\[\] | A list of [GroundingChunk](./ai.groundingchunk.md#groundingchunk_interface) objects. Each chunk represents a piece of retrieved content (for example, from a web page). that the model used to ground its response. | | [groundingSupports](./ai.groundingmetadata.md#groundingmetadatagroundingsupports) | [GroundingSupport](./ai.groundingsupport.md#groundingsupport_interface)\[\] | A list of [GroundingSupport](./ai.groundingsupport.md#groundingsupport_interface) objects. Each object details how specific segments of the model's response are supported by the groundingChunks. | | [retrievalQueries](./ai.groundingmetadata.md#groundingmetadataretrievalqueries) | string\[\] | | | [searchEntryPoint](./ai.groundingmetadata.md#groundingmetadatasearchentrypoint) | [SearchEntrypoint](./ai.searchentrypoint.md#searchentrypoint_interface) | Google Search entry point for web searches. This contains an HTML/CSS snippet that must be embedded in an app to display a Google Search entry point for follow-up web searches related to a model's "Grounded Response". | | [webSearchQueries](./ai.groundingmetadata.md#groundingmetadatawebsearchqueries) | string\[\] | A list of web search queries that the model performed to gather the grounding information. These can be used to allow users to explore the search results themselves. | +## GroundingMetadata.googleMapsWidgetContextToken + +Resource name of the Google Maps widget context token that can be used with the `PlacesContextElement` widget in order to render contextual data. Only populated in the case that grounding with Google Maps is enabled. + +Signature: + +```typescript +googleMapsWidgetContextToken?: string; +``` + ## GroundingMetadata.groundingChunks A list of [GroundingChunk](./ai.groundingchunk.md#groundingchunk_interface) objects. Each chunk represents a piece of retrieved content (for example, from a web page). that the model used to ground its response. diff --git a/docs-devsite/ai.latlng.md b/docs-devsite/ai.latlng.md new file mode 100644 index 0000000000..5c04dda81d --- /dev/null +++ b/docs-devsite/ai.latlng.md @@ -0,0 +1,46 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# LatLng interface +An object that represents a latitude/longitude pair. + +Signature: + +```typescript +export interface LatLng +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [latitude](./ai.latlng.md#latlnglatitude) | number | The latitude in degrees. It must be in the range [-90.0, +90.0]. | +| [longitude](./ai.latlng.md#latlnglongitude) | number | The longitude in degrees. It must be in the range [-180.0, +180.0]. | + +## LatLng.latitude + +The latitude in degrees. It must be in the range `[-90.0, +90.0]`. + +Signature: + +```typescript +latitude?: number; +``` + +## LatLng.longitude + +The longitude in degrees. It must be in the range `[-180.0, +180.0]`. + +Signature: + +```typescript +longitude?: number; +``` diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index 0bf2679cb1..53d9ad65ce 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -95,10 +95,13 @@ The Firebase AI Web SDK. | [GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface) | Result object returned from [GenerativeModel.generateContentStream()](./ai.generativemodel.md#generativemodelgeneratecontentstream) call. Iterate over stream to get chunks as they come in and/or use the response promise to get the aggregated response when the stream is done. | | [GenerationConfig](./ai.generationconfig.md#generationconfig_interface) | Config options for content-related requests | | [GenerativeContentBlob](./ai.generativecontentblob.md#generativecontentblob_interface) | Interface for sending an image. | +| [GoogleMaps](./ai.googlemaps.md#googlemaps_interface) | Specifies the Google Maps configuration. | +| [GoogleMapsGroundingChunk](./ai.googlemapsgroundingchunk.md#googlemapsgroundingchunk_interface) | A grounding chunk from Google Maps.Important: If using Grounding with Google Maps, you are required to comply with the [Service Specific Terms](https://cloud.google.com/terms/service-terms) for "Grounding with Google Maps". | +| [GoogleMapsTool](./ai.googlemapstool.md#googlemapstool_interface) | A tool that allows a Gemini model to connect to Google Maps to access and incorporate location-based information into its responses.Important: If using Grounding with Google Maps, you are required to comply with the "Grounding with Google Maps" usage requirements for your chosen API provider: [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-maps) or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section within the Service Specific Terms). | | [GoogleSearch](./ai.googlesearch.md#googlesearch_interface) | Specifies the Google Search configuration. | | [GoogleSearchTool](./ai.googlesearchtool.md#googlesearchtool_interface) | A tool that allows a Gemini model to connect to Google Search to access and incorporate up-to-date information from the web into its responses.Important: If using Grounding with Google Search, you are required to comply with the "Grounding with Google Search" usage requirements for your chosen API provider: [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-search) or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section within the Service Specific Terms). | | [GroundingChunk](./ai.groundingchunk.md#groundingchunk_interface) | Represents a chunk of retrieved data that supports a claim in the model's response. This is part of the grounding information provided when grounding is enabled. | -| [GroundingMetadata](./ai.groundingmetadata.md#groundingmetadata_interface) | Metadata returned when grounding is enabled.Currently, only Grounding with Google Search is supported (see [GoogleSearchTool](./ai.googlesearchtool.md#googlesearchtool_interface)).Important: If using Grounding with Google Search, you are required to comply with the "Grounding with Google Search" usage requirements for your chosen API provider: [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-search) or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section within the Service Specific Terms). | +| [GroundingMetadata](./ai.groundingmetadata.md#groundingmetadata_interface) | Metadata returned when grounding is enabled.Currently, only Grounding with Google Search and Grounding with Google Maps are supported (see [GoogleSearchTool](./ai.googlesearchtool.md#googlesearchtool_interface) and [GoogleMapsTool](./ai.googlemapstool.md#googlemapstool_interface), respectively).Important: If using Grounding with Google Search, you are required to comply with the "Grounding with Google Search" usage requirements for your chosen API provider: [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-search) or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section within the Service Specific Terms).Important: If using Grounding with Google Maps, you are required to comply with the "Grounding with Google Maps" usage requirements for your chosen API provider: [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-maps) or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section within the Service Specific Terms). | | [GroundingSupport](./ai.groundingsupport.md#groundingsupport_interface) | Provides information about how a specific segment of the model's response is supported by the retrieved grounding chunks. | | [HybridParams](./ai.hybridparams.md#hybridparams_interface) | (Public Preview) Configures hybrid inference. | | [ImagenGCSImage](./ai.imagengcsimage.md#imagengcsimage_interface) | An image generated by Imagen, stored in a Cloud Storage for Firebase bucket.This feature is not available yet. | @@ -114,6 +117,7 @@ The Firebase AI Web SDK. | [LanguageModelMessage](./ai.languagemodelmessage.md#languagemodelmessage_interface) | (Public Preview) An on-device language model message. | | [LanguageModelMessageContent](./ai.languagemodelmessagecontent.md#languagemodelmessagecontent_interface) | (Public Preview) An on-device language model content object. | | [LanguageModelPromptOptions](./ai.languagemodelpromptoptions.md#languagemodelpromptoptions_interface) | (Public Preview) Options for an on-device language model prompt. | +| [LatLng](./ai.latlng.md#latlng_interface) | An object that represents a latitude/longitude pair. | | [LiveGenerationConfig](./ai.livegenerationconfig.md#livegenerationconfig_interface) | (Public Preview) Configuration parameters used by [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) to control live content generation. | | [LiveModelParams](./ai.livemodelparams.md#livemodelparams_interface) | (Public Preview) Params passed to [getLiveGenerativeModel()](./ai.md#getlivegenerativemodel_f2099ac). | | [LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) | (Public Preview) An incremental content update from the model. | @@ -128,6 +132,7 @@ The Firebase AI Web SDK. | [PrebuiltVoiceConfig](./ai.prebuiltvoiceconfig.md#prebuiltvoiceconfig_interface) | (Public Preview) Configuration for a pre-built voice. | | [PromptFeedback](./ai.promptfeedback.md#promptfeedback_interface) | If the prompt was blocked, this will be populated with blockReason and the relevant safetyRatings. | | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) | Params passed to [getGenerativeModel()](./ai.md#getgenerativemodel_c63f46a). | +| [RetrievalConfig](./ai.retrievalconfig.md#retrievalconfig_interface) | Configuration options for data retrieval tools. | | [RetrievedContextAttribution](./ai.retrievedcontextattribution.md#retrievedcontextattribution_interface) | | | [SafetyRating](./ai.safetyrating.md#safetyrating_interface) | A safety rating associated with a [GenerateContentCandidate](./ai.generatecontentcandidate.md#generatecontentcandidate_interface) | | [SafetySetting](./ai.safetysetting.md#safetysetting_interface) | Safety setting that can be sent as part of request parameters. | @@ -147,6 +152,7 @@ The Firebase AI Web SDK. | [TemplateChatSession](./ai.templatechatsession.md#templatechatsession_interface) | (Public Preview) Interface representing a ChatSession class for use with server prompt templates that enables sending chat messages and stores history of sent and received messages so far. | | [TemplateFunctionDeclaration](./ai.templatefunctiondeclaration.md#templatefunctiondeclaration_interface) | (Public Preview) Structured representation of a template function declaration. Included in this declaration are the function name and parameters. This TemplateFunctionDeclaration is a representation of a block of code that can be used as a Tool by the model and executed by the client. Note: Template function declarations do not support description fields. | | [TemplateFunctionDeclarationsTool](./ai.templatefunctiondeclarationstool.md#templatefunctiondeclarationstool_interface) | (Public Preview) A piece of code that enables the system to interact with external systems. | +| [TemplateToolConfig](./ai.templatetoolconfig.md#templatetoolconfig_interface) | Tool configuration for TemplateGenerativeModels. This config is shared for all tools provided in the server prompt template request. | | [TextPart](./ai.textpart.md#textpart_interface) | Content part interface if the part represents a text string. | | [ThinkingConfig](./ai.thinkingconfig.md#thinkingconfig_interface) | Configuration for "thinking" behavior of compatible Gemini models.Certain models utilize a thinking process before generating a response. This allows them to reason through complex problems and plan a more coherent and accurate answer. | | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. | @@ -1225,7 +1231,7 @@ Defines a tool that model can call to access external knowledge. Signature: ```typescript -export type Tool = FunctionDeclarationsTool | GoogleSearchTool | CodeExecutionTool | URLContextTool; +export type Tool = FunctionDeclarationsTool | GoogleMapsTool | GoogleSearchTool | CodeExecutionTool | URLContextTool; ``` ## TypedSchema diff --git a/docs-devsite/ai.retrievalconfig.md b/docs-devsite/ai.retrievalconfig.md new file mode 100644 index 0000000000..49723a811f --- /dev/null +++ b/docs-devsite/ai.retrievalconfig.md @@ -0,0 +1,46 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# RetrievalConfig interface +Configuration options for data retrieval tools. + +Signature: + +```typescript +export interface RetrievalConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [languageCode](./ai.retrievalconfig.md#retrievalconfiglanguagecode) | string | The language code of the user. | +| [latLng](./ai.retrievalconfig.md#retrievalconfiglatlng) | [LatLng](./ai.latlng.md#latlng_interface) | The location of the user. | + +## RetrievalConfig.languageCode + +The language code of the user. + +Signature: + +```typescript +languageCode?: string; +``` + +## RetrievalConfig.latLng + +The location of the user. + +Signature: + +```typescript +latLng?: LatLng; +``` diff --git a/docs-devsite/ai.templategenerativemodel.md b/docs-devsite/ai.templategenerativemodel.md index ced5ad9722..700fa94671 100644 --- a/docs-devsite/ai.templategenerativemodel.md +++ b/docs-devsite/ai.templategenerativemodel.md @@ -39,8 +39,8 @@ export declare class TemplateGenerativeModel | Method | Modifiers | Description | | --- | --- | --- | -| [generateContent(templateId, templateVariables, singleRequestOptions)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontent) | | (Public Preview) Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | -| [generateContentStream(templateId, templateVariables, singleRequestOptions)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontentstream) | | (Public Preview) Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. | +| [generateContent(templateId, templateVariables, singleRequestOptions, templateToolConfig)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontent) | | (Public Preview) Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | +| [generateContentStream(templateId, templateVariables, singleRequestOptions, templateToolConfig)](./ai.templategenerativemodel.md#templategenerativemodelgeneratecontentstream) | | (Public Preview) Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. | | [startChat(params)](./ai.templategenerativemodel.md#templategenerativemodelstartchat) | | (Public Preview) Starts a [TemplateChatSession](./ai.templatechatsession.md#templatechatsession_interface) that will use this template to respond to messages. | ## TemplateGenerativeModel.(constructor) @@ -86,7 +86,7 @@ Makes a single non-streaming call to the model and returns an object containing Signature: ```typescript -generateContent(templateId: string, templateVariables: Record, singleRequestOptions?: SingleRequestOptions): Promise; +generateContent(templateId: string, templateVariables: Record, singleRequestOptions?: SingleRequestOptions, templateToolConfig?: TemplateToolConfig): Promise; ``` #### Parameters @@ -95,7 +95,8 @@ generateContent(templateId: string, templateVariables: Record, | --- | --- | --- | | templateId | string | The ID of the server-side template to execute. | | templateVariables | Record<string, unknown> | A key-value map of variables to populate the template with. | -| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | Optional. Options to use for this request. | +| templateToolConfig | [TemplateToolConfig](./ai.templatetoolconfig.md#templatetoolconfig_interface) | Optional. Configuration for tools to use with this request. | Returns: @@ -111,7 +112,7 @@ Makes a single streaming call to the model and returns an object containing an i Signature: ```typescript -generateContentStream(templateId: string, templateVariables: Record, singleRequestOptions?: SingleRequestOptions): Promise; +generateContentStream(templateId: string, templateVariables: Record, singleRequestOptions?: SingleRequestOptions, templateToolConfig?: TemplateToolConfig): Promise; ``` #### Parameters @@ -120,7 +121,8 @@ generateContentStream(templateId: string, templateVariables: RecordReturns: diff --git a/docs-devsite/ai.templatetoolconfig.md b/docs-devsite/ai.templatetoolconfig.md new file mode 100644 index 0000000000..4e42ea51df --- /dev/null +++ b/docs-devsite/ai.templatetoolconfig.md @@ -0,0 +1,33 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# TemplateToolConfig interface +Tool configuration for `TemplateGenerativeModel`s. This config is shared for all tools provided in the server prompt template request. + +Signature: + +```typescript +export interface TemplateToolConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [retrievalConfig](./ai.templatetoolconfig.md#templatetoolconfigretrievalconfig) | [RetrievalConfig](./ai.retrievalconfig.md#retrievalconfig_interface) | | + +## TemplateToolConfig.retrievalConfig + +Signature: + +```typescript +retrievalConfig?: RetrievalConfig; +``` diff --git a/docs-devsite/ai.toolconfig.md b/docs-devsite/ai.toolconfig.md index 81bd6ccd8f..1e132f5c40 100644 --- a/docs-devsite/ai.toolconfig.md +++ b/docs-devsite/ai.toolconfig.md @@ -23,6 +23,7 @@ export interface ToolConfig | Property | Type | Description | | --- | --- | --- | | [functionCallingConfig](./ai.toolconfig.md#toolconfigfunctioncallingconfig) | [FunctionCallingConfig](./ai.functioncallingconfig.md#functioncallingconfig_interface) | | +| [retrievalConfig](./ai.toolconfig.md#toolconfigretrievalconfig) | [RetrievalConfig](./ai.retrievalconfig.md#retrievalconfig_interface) | | ## ToolConfig.functionCallingConfig @@ -31,3 +32,11 @@ export interface ToolConfig ```typescript functionCallingConfig?: FunctionCallingConfig; ``` + +## ToolConfig.retrievalConfig + +Signature: + +```typescript +retrievalConfig?: RetrievalConfig; +``` diff --git a/packages/ai/integration/generate-content.test.ts b/packages/ai/integration/generate-content.test.ts index 6cd6640285..8ccee9b208 100644 --- a/packages/ai/integration/generate-content.test.ts +++ b/packages/ai/integration/generate-content.test.ts @@ -181,6 +181,217 @@ describe('Generate Content', function () { expect(groundingSupport.segment?.text).to.exist; // Since partIndex and startIndex are commonly 0, they may be omitted from responses. }); + expect(groundingMetadata!.googleMapsWidgetContextToken).to.not.exist; + }); + + it('generateContent: google maps grounding prompt location', async () => { + const model = getGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: commonGenerationConfig, + safetySettings: commonSafetySettings, + tools: [{ googleMaps: {} }] + }); + + const result = await model.generateContent( + 'Where is a good place to grab a coffee near Arlington, MA?' + ); + const response = result.response; + const groundingMetadata = response.candidates?.[0].groundingMetadata; + expect(groundingMetadata).to.exist; + expect( + groundingMetadata!.groundingChunks + ).to.have.length.greaterThanOrEqual(1); + groundingMetadata!.groundingChunks!.forEach(groundingChunk => { + expect(groundingChunk.maps).to.exist; + expect(groundingChunk.maps!.uri).to.exist; + expect(groundingChunk.maps!.title).to.exist; + expect(groundingChunk.maps!.placeId).to.exist; + }); + expect( + groundingMetadata?.groundingSupports + ).to.have.length.greaterThanOrEqual(1); + groundingMetadata!.groundingSupports!.forEach(groundingSupport => { + expect( + groundingSupport.groundingChunkIndices + ).to.have.length.greaterThanOrEqual(1); + expect(groundingSupport.segment).to.exist; + expect(groundingSupport.segment?.endIndex).to.exist; + expect(groundingSupport.segment?.text).to.exist; + }); + expect(groundingMetadata!.googleMapsWidgetContextToken).to.not.exist; + }); + + it('generateContent: google maps grounding prompt location enableWidget true', async () => { + const model = getGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: commonGenerationConfig, + safetySettings: commonSafetySettings, + tools: [{ googleMaps: { enableWidget: true } }] + }); + + const result = await model.generateContent( + 'Where is a good place to grab a coffee in New York City?' + ); + const response = result.response; + const groundingMetadata = response.candidates?.[0].groundingMetadata; + expect(groundingMetadata).to.exist; + expect( + groundingMetadata!.groundingChunks + ).to.have.length.greaterThanOrEqual(1); + groundingMetadata!.groundingChunks!.forEach(groundingChunk => { + expect(groundingChunk.maps).to.exist; + expect(groundingChunk.maps!.uri).to.exist; + expect(groundingChunk.maps!.title).to.exist; + expect(groundingChunk.maps!.placeId).to.exist; + }); + expect( + groundingMetadata?.groundingSupports + ).to.have.length.greaterThanOrEqual(1); + groundingMetadata!.groundingSupports!.forEach(groundingSupport => { + expect( + groundingSupport.groundingChunkIndices + ).to.have.length.greaterThanOrEqual(1); + expect(groundingSupport.segment).to.exist; + expect(groundingSupport.segment?.endIndex).to.exist; + expect(groundingSupport.segment?.text).to.exist; + }); + expect(groundingMetadata!.googleMapsWidgetContextToken).to.exist; + }); + + it('generateContent: google maps grounding prompt location enableWidget false', async () => { + const model = getGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: commonGenerationConfig, + safetySettings: commonSafetySettings, + tools: [{ googleMaps: { enableWidget: false } }] + }); + + const result = await model.generateContent( + 'Where is a good place to grab a coffee in New York City?' + ); + const response = result.response; + const groundingMetadata = response.candidates?.[0].groundingMetadata; + expect(groundingMetadata).to.exist; + expect( + groundingMetadata!.groundingChunks + ).to.have.length.greaterThanOrEqual(1); + groundingMetadata!.groundingChunks!.forEach(groundingChunk => { + expect(groundingChunk.maps).to.exist; + expect(groundingChunk.maps!.uri).to.exist; + expect(groundingChunk.maps!.title).to.exist; + expect(groundingChunk.maps!.placeId).to.exist; + }); + expect( + groundingMetadata?.groundingSupports + ).to.have.length.greaterThanOrEqual(1); + groundingMetadata!.groundingSupports!.forEach(groundingSupport => { + expect( + groundingSupport.groundingChunkIndices + ).to.have.length.greaterThanOrEqual(1); + expect(groundingSupport.segment).to.exist; + expect(groundingSupport.segment?.endIndex).to.exist; + expect(groundingSupport.segment?.text).to.exist; + }); + expect(groundingMetadata!.googleMapsWidgetContextToken).to.not.exist; + }); + + it('generateContent: google maps grounding with RetrievalConfig', async () => { + if (testConfig.model === 'gemini-3-pro-preview') { + // Maps grounding is not supported in gemini-3-pro-preview. + return; + } + const model = getGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: commonGenerationConfig, + safetySettings: commonSafetySettings, + tools: [{ googleMaps: {} }], + toolConfig: { + retrievalConfig: { + latLng: { + latitude: 42.4154, + longitude: -71.1565 + } + } + } + }); + + const result = await model.generateContent( + 'Where is a good place to grab a coffee near here?' + ); + const response = result.response; + const groundingMetadata = response.candidates?.[0].groundingMetadata; + expect(groundingMetadata).to.exist; + expect( + groundingMetadata!.groundingChunks + ).to.have.length.greaterThanOrEqual(1); + groundingMetadata!.groundingChunks!.forEach(groundingChunk => { + expect(groundingChunk.maps).to.exist; + expect(groundingChunk.maps!.uri).to.exist; + expect(groundingChunk.maps!.title).to.exist; + expect(groundingChunk.maps!.placeId).to.exist; + }); + expect( + groundingMetadata?.groundingSupports + ).to.have.length.greaterThanOrEqual(1); + groundingMetadata!.groundingSupports!.forEach(groundingSupport => { + expect( + groundingSupport.groundingChunkIndices + ).to.have.length.greaterThanOrEqual(1); + expect(groundingSupport.segment).to.exist; + expect(groundingSupport.segment?.endIndex).to.exist; + expect(groundingSupport.segment?.text).to.exist; + }); + expect(groundingMetadata!.googleMapsWidgetContextToken).to.not.exist; + }); + + it('generateContent: google maps grounding RetrievalConfig enableWidget true', async () => { + if (testConfig.model === 'gemini-3-pro-preview') { + // Maps grounding is not supported in gemini-3-pro-preview. + return; + } + const model = getGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: commonGenerationConfig, + safetySettings: commonSafetySettings, + tools: [{ googleMaps: { enableWidget: true } }], + toolConfig: { + retrievalConfig: { + latLng: { + latitude: 42.4154, + longitude: -71.1565 + } + } + } + }); + + const result = await model.generateContent( + 'Where is a good place to grab a coffee near here?' + //'Where is the closest starbucks?' + ); + const response = result.response; + const groundingMetadata = response.candidates?.[0].groundingMetadata; + expect(groundingMetadata).to.exist; + expect( + groundingMetadata!.groundingChunks + ).to.have.length.greaterThanOrEqual(1); + groundingMetadata!.groundingChunks!.forEach(groundingChunk => { + expect(groundingChunk.maps).to.exist; + expect(groundingChunk.maps!.uri).to.exist; + expect(groundingChunk.maps!.title).to.exist; + expect(groundingChunk.maps!.placeId).to.exist; + }); + expect( + groundingMetadata?.groundingSupports + ).to.have.length.greaterThanOrEqual(1); + groundingMetadata!.groundingSupports!.forEach(groundingSupport => { + expect( + groundingSupport.groundingChunkIndices + ).to.have.length.greaterThanOrEqual(1); + expect(groundingSupport.segment).to.exist; + expect(groundingSupport.segment?.endIndex).to.exist; + expect(groundingSupport.segment?.text).to.exist; + }); + expect(groundingMetadata!.googleMapsWidgetContextToken).to.exist; }); describe('URL Context', async () => { diff --git a/packages/ai/src/methods/generate-content.test.ts b/packages/ai/src/methods/generate-content.test.ts index ea8876b07d..bb18fffed0 100644 --- a/packages/ai/src/methods/generate-content.test.ts +++ b/packages/ai/src/methods/generate-content.test.ts @@ -319,6 +319,64 @@ describe('generateContent()', () => { ); }); }); + it('google maps grounding', async () => { + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-success-google-maps-grounding.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const result = await generateContent( + fakeApiSettings, + 'model', + fakeRequestParams + ); + expect(result.response.text()).to.include( + 'Here are some pizza restaurants near you:' + ); + const groundingMetadata = result.response.candidates?.[0].groundingMetadata; + expect(groundingMetadata).to.not.be.undefined; + expect(groundingMetadata!.groundingChunks?.length).to.equal(20); + expect(groundingMetadata!.groundingChunks?.[0].maps?.title).to.equal( + 'Joe’s Pizza' + ); + expect(groundingMetadata!.groundingChunks?.[0].maps?.placeId).to.equal( + 'places/ChIJqdNaaBVbwokRLTafYrQlZI8' + ); + expect(groundingMetadata!.groundingChunks?.[0].maps?.uri).to.contain( + 'https://maps.google.com/?cid=10332424901773702701' + ); + expect(groundingMetadata!.groundingSupports?.length).to.equal(39); + expect(groundingMetadata!.groundingSupports?.[0].segment?.partIndex).to.be + .undefined; + expect(groundingMetadata!.groundingSupports?.[0].segment?.startIndex).to.not + .be.undefined; + expect(groundingMetadata!.groundingSupports?.[0].segment?.endIndex).to.not + .be.undefined; + expect(groundingMetadata!.groundingSupports?.[0].segment?.text).to.not.be + .undefined; + expect( + groundingMetadata!.groundingSupports?.[0].segment?.startIndex + ).to.equal(43); + expect( + groundingMetadata!.groundingSupports?.[0].segment?.endIndex + ).to.equal(152); + expect(groundingMetadata!.groundingSupports?.[0].segment?.text).to.contain( + "Joe's Pizza" + ); + + expect(makeRequestStub).to.be.calledWith( + { + model: 'model', + task: Task.GENERATE_CONTENT, + apiSettings: fakeApiSettings, + stream: false, + singleRequestOptions: undefined + }, + JSON.stringify(fakeRequestParams) + ); + }); it('codeExecution', async () => { const mockResponse = getMockResponse( 'vertexAI', diff --git a/packages/ai/src/models/template-generative-model.test.ts b/packages/ai/src/models/template-generative-model.test.ts index c33cc27d20..929b426ebd 100644 --- a/packages/ai/src/models/template-generative-model.test.ts +++ b/packages/ai/src/models/template-generative-model.test.ts @@ -18,7 +18,12 @@ import { use, expect } from 'chai'; import sinonChai from 'sinon-chai'; import { restore, stub } from 'sinon'; -import { AI } from '../public-types'; +import { + AI, + TemplateToolConfig, + RetrievalConfig, + LatLng +} from '../public-types'; import { VertexAIBackend } from '../backend'; import { TemplateGenerativeModel } from './template-generative-model'; import * as generateContentMethods from '../methods/generate-content'; @@ -57,19 +62,89 @@ describe('TemplateGenerativeModel', () => { }); describe('generateContent', () => { - it('should call templateGenerateContent with correct parameters', async () => { + it('should call templateGenerateContent with correct parameters no options', async () => { const templateGenerateContentStub = stub( generateContentMethods, 'templateGenerateContent' ).resolves({} as any); - const model = new TemplateGenerativeModel(fakeAI, { timeout: 5000 }); + const model = new TemplateGenerativeModel(fakeAI); await model.generateContent(TEMPLATE_ID, TEMPLATE_VARS); expect(templateGenerateContentStub).to.have.been.calledOnceWith( model._apiSettings, TEMPLATE_ID, - { inputs: TEMPLATE_VARS }, + { inputs: TEMPLATE_VARS } + ); + }); + + it('should call templateGenerateContent with correct parameters w/ request options', async () => { + const templateGenerateContentStub = stub( + generateContentMethods, + 'templateGenerateContent' + ).resolves({} as any); + const model = new TemplateGenerativeModel(fakeAI); + + await model.generateContent(TEMPLATE_ID, TEMPLATE_VARS); + + expect(templateGenerateContentStub).to.have.been.calledOnceWith( + model._apiSettings, + TEMPLATE_ID, + { inputs: TEMPLATE_VARS } + ); + }); + + it('should call templateGenerateContent with correct parameters w/ tool config', async () => { + const templateGenerateContentStub = stub( + generateContentMethods, + 'templateGenerateContent' + ).resolves({} as any); + const model = new TemplateGenerativeModel(fakeAI); + const latLng: LatLng = { + latitude: 50.0, + longitude: 50.0 + }; + const retrievalConfig: RetrievalConfig = { latLng }; + const templateToolConfig: TemplateToolConfig = { retrievalConfig }; + + await model.generateContent( + TEMPLATE_ID, + TEMPLATE_VARS, + undefined, + templateToolConfig + ); + + expect(templateGenerateContentStub).to.have.been.calledOnceWith( + model._apiSettings, + TEMPLATE_ID, + { inputs: TEMPLATE_VARS, toolConfig: templateToolConfig } + ); + }); + + it('should call templateGenerateContent with correct parameters w/ both optional params', async () => { + const templateGenerateContentStub = stub( + generateContentMethods, + 'templateGenerateContent' + ).resolves({} as any); + const model = new TemplateGenerativeModel(fakeAI); + const latLng: LatLng = { + latitude: 50.0, + longitude: 50.0 + }; + const retrievalConfig: RetrievalConfig = { latLng }; + const templateToolConfig: TemplateToolConfig = { retrievalConfig }; + + await model.generateContent( + TEMPLATE_ID, + TEMPLATE_VARS, + { timeout: 5000 }, + templateToolConfig + ); + + expect(templateGenerateContentStub).to.have.been.calledOnceWith( + model._apiSettings, + TEMPLATE_ID, + { inputs: TEMPLATE_VARS, toolConfig: templateToolConfig }, { timeout: 5000 } ); }); @@ -138,6 +213,77 @@ describe('TemplateGenerativeModel', () => { ); }); + it('should call templateGenerateContentStream with correct parameters w/ request options', async () => { + const templateGenerateContentStreamStub = stub( + generateContentMethods, + 'templateGenerateContentStream' + ).resolves({} as any); + const model = new TemplateGenerativeModel(fakeAI); + await model.generateContentStream(TEMPLATE_ID, TEMPLATE_VARS, { + timeout: 5000 + }); + + expect(templateGenerateContentStreamStub).to.have.been.calledOnceWith( + model._apiSettings, + TEMPLATE_ID, + { inputs: TEMPLATE_VARS }, + { timeout: 5000 } + ); + }); + + it('should call templateGenerateContentStream with correct parameters w/ tool config', async () => { + const templateGenerateContentStreamStub = stub( + generateContentMethods, + 'templateGenerateContentStream' + ).resolves({} as any); + const latLng: LatLng = { + latitude: 50.0, + longitude: 50.0 + }; + const retrievalConfig: RetrievalConfig = { latLng }; + const templateToolConfig: TemplateToolConfig = { retrievalConfig }; + const model = new TemplateGenerativeModel(fakeAI); + await model.generateContentStream( + TEMPLATE_ID, + TEMPLATE_VARS, + undefined, + templateToolConfig + ); + + expect(templateGenerateContentStreamStub).to.have.been.calledOnceWith( + model._apiSettings, + TEMPLATE_ID, + { inputs: TEMPLATE_VARS, toolConfig: templateToolConfig } + ); + }); + + it('should call templateGenerateContent with correct parameters w/ both optional params', async () => { + const templateGenerateContentStreamStub = stub( + generateContentMethods, + 'templateGenerateContentStream' + ).resolves({} as any); + const latLng: LatLng = { + latitude: 50.0, + longitude: 50.0 + }; + const retrievalConfig: RetrievalConfig = { latLng }; + const templateToolConfig: TemplateToolConfig = { retrievalConfig }; + const model = new TemplateGenerativeModel(fakeAI); + await model.generateContentStream( + TEMPLATE_ID, + TEMPLATE_VARS, + { timeout: 5000 }, + templateToolConfig + ); + + expect(templateGenerateContentStreamStub).to.have.been.calledOnceWith( + model._apiSettings, + TEMPLATE_ID, + { inputs: TEMPLATE_VARS, toolConfig: templateToolConfig }, + { timeout: 5000 } + ); + }); + it('singleRequestOptions overrides requestOptions', async () => { const templateGenerateContentStreamStub = stub( generateContentMethods, diff --git a/packages/ai/src/models/template-generative-model.ts b/packages/ai/src/models/template-generative-model.ts index 666c5ff842..af4235e1f0 100644 --- a/packages/ai/src/models/template-generative-model.ts +++ b/packages/ai/src/models/template-generative-model.ts @@ -25,7 +25,8 @@ import { GenerateContentStreamResult, SingleRequestOptions, StartTemplateChatParams, - TemplateChatSession + TemplateChatSession, + TemplateToolConfig } from '../public-types'; import { ApiSettings } from '../types/internal'; import { initApiSettings } from './utils'; @@ -64,18 +65,24 @@ export class TemplateGenerativeModel { * @param templateId - The ID of the server-side template to execute. * @param templateVariables - A key-value map of variables to populate the * template with. + * @param singleRequestOptions - Optional. Options to use for this request. + * @param templateToolConfig - Optional. Configuration for tools to use with this request. * * @beta */ async generateContent( templateId: string, templateVariables: Record, - singleRequestOptions?: SingleRequestOptions + singleRequestOptions?: SingleRequestOptions, + templateToolConfig?: TemplateToolConfig ): Promise { return templateGenerateContent( this._apiSettings, templateId, - { inputs: templateVariables }, + { + inputs: templateVariables, + ...(templateToolConfig && { toolConfig: templateToolConfig }) + }, { ...this.requestOptions, ...singleRequestOptions @@ -92,18 +99,24 @@ export class TemplateGenerativeModel { * @param templateId - The ID of the server-side template to execute. * @param templateVariables - A key-value map of variables to populate the * template with. + * @param singleRequestOptions - Optional.Options to use for this request. + * @param templateToolConfig - Optional. Configuration for tools to use with this request. * * @beta */ async generateContentStream( templateId: string, templateVariables: Record, - singleRequestOptions?: SingleRequestOptions + singleRequestOptions?: SingleRequestOptions, + templateToolConfig?: TemplateToolConfig ): Promise { return templateGenerateContentStream( this._apiSettings, templateId, - { inputs: templateVariables }, + { + inputs: templateVariables, + ...(templateToolConfig && { toolConfig: templateToolConfig }) + }, { ...this.requestOptions, ...singleRequestOptions diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index 93eb557358..cd2f640bf5 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -420,6 +420,7 @@ export interface SingleRequestOptions extends RequestOptions { */ export type Tool = | FunctionDeclarationsTool + | GoogleMapsTool | GoogleSearchTool | CodeExecutionTool | URLContextTool; @@ -483,6 +484,29 @@ export interface GoogleSearchTool { googleSearch: GoogleSearch; } +/** + * A tool that allows a Gemini model to connect to Google Maps to access and incorporate + * location-based information into its responses. + * + * Important: If using Grounding with Google Maps, you are required to comply with the + * "Grounding with Google Maps" usage requirements for your chosen API provider: {@link https://ai.google.dev/gemini-api/terms#grounding-with-google-maps | Gemini Developer API} + * or Vertex AI Gemini API (see {@link https://cloud.google.com/terms/service-terms | Service Terms} + * section within the Service Specific Terms). + * + * @public + */ +export interface GoogleMapsTool { + /** + * Specifies the Google Maps configuration. + * + * When using this feature, you are required to comply with the "Grounding with Google Maps" + * usage requirements for your chosen API provider: {@link https://ai.google.dev/gemini-api/terms#grounding-with-google-maps | Gemini Developer API} + * or Vertex AI Gemini API (see {@link https://cloud.google.com/terms/service-terms | Service Terms} + * section within the Service Specific Terms). + */ + googleMaps: GoogleMaps; +} + /** * A tool that enables the model to use code execution. * @@ -504,6 +528,18 @@ export interface CodeExecutionTool { */ export interface GoogleSearch {} +/** + * Specifies the Google Maps configuration. + * + * @public + */ +export interface GoogleMaps { + /* + * If true, include the widget context token in the response. + */ + enableWidget?: boolean; +} + /** * A tool that allows you to provide additional context to the models in the form of public web * URLs. By including URLs in your request, the Gemini model will access the content from those @@ -545,6 +581,22 @@ export interface FunctionDeclarationsTool { functionDeclarations?: FunctionDeclaration[]; } +/** + * An object that represents a latitude/longitude pair. + * @public + */ +export interface LatLng { + /** + * The latitude in degrees. It must be in the range `[-90.0, +90.0]`. + */ + latitude?: number; + + /** + * The longitude in degrees. It must be in the range `[-180.0, +180.0]`. + */ + longitude?: number; +} + /** * Structured representation of a template function declaration. * Included in this declaration are the function name and parameters. This @@ -624,6 +676,16 @@ export type TemplateTool = TemplateFunctionDeclarationsTool; */ export interface ToolConfig { functionCallingConfig?: FunctionCallingConfig; + retrievalConfig?: RetrievalConfig; +} + +/** + * Tool configuration for `TemplateGenerativeModel`s. + * This config is shared for all tools provided in the server prompt template request. + * @public + */ +export interface TemplateToolConfig { + retrievalConfig?: RetrievalConfig; } /** @@ -634,6 +696,22 @@ export interface FunctionCallingConfig { allowedFunctionNames?: string[]; } +/** + * Configuration options for data retrieval tools. + * @public + */ +export interface RetrievalConfig { + /** + * The location of the user. + */ + latLng?: LatLng; + + /** + * The language code of the user. + */ + languageCode?: string; +} + /** * Encapsulates configuration for on-device inference. * diff --git a/packages/ai/src/types/responses.ts b/packages/ai/src/types/responses.ts index c99381f140..95bb3b7e54 100644 --- a/packages/ai/src/types/responses.ts +++ b/packages/ai/src/types/responses.ts @@ -224,13 +224,19 @@ export interface Citation { /** * Metadata returned when grounding is enabled. * - * Currently, only Grounding with Google Search is supported (see {@link GoogleSearchTool}). + * Currently, only Grounding with Google Search and Grounding with Google Maps are supported + * (see {@link GoogleSearchTool} and {@link GoogleMapsTool}, respectively). * * Important: If using Grounding with Google Search, you are required to comply with the * "Grounding with Google Search" usage requirements for your chosen API provider: {@link https://ai.google.dev/gemini-api/terms#grounding-with-google-search | Gemini Developer API} * or Vertex AI Gemini API (see {@link https://cloud.google.com/terms/service-terms | Service Terms} * section within the Service Specific Terms). * + * Important: If using Grounding with Google Maps, you are required to comply with the + * "Grounding with Google Maps" usage requirements for your chosen API provider: {@link https://ai.google.dev/gemini-api/terms#grounding-with-google-maps | Gemini Developer API} + * or Vertex AI Gemini API (see {@link https://cloud.google.com/terms/service-terms | Service Terms} + * section within the Service Specific Terms). + * * @public */ export interface GroundingMetadata { @@ -259,6 +265,12 @@ export interface GroundingMetadata { * @deprecated Use {@link GroundingSupport} instead. */ retrievalQueries?: string[]; + /** + * Resource name of the Google Maps widget context token that can be used with the + * `PlacesContextElement` widget in order to render contextual data. Only populated in the case + * that grounding with Google Maps is enabled. + */ + googleMapsWidgetContextToken?: string; } /** @@ -296,6 +308,11 @@ export interface GroundingChunk { * Contains details if the grounding chunk is from a web source. */ web?: WebGroundingChunk; + + /** + * Contains details if the grounding chunk is from a Google Maps source. + */ + maps?: GoogleMapsGroundingChunk; } /** @@ -325,6 +342,34 @@ export interface WebGroundingChunk { domain?: string; } +/** + * A grounding chunk from Google Maps. + * + * Important: If using Grounding with Google Maps, you are required to comply with the + * {@link https://cloud.google.com/terms/service-terms | Service Specific Terms} for "Grounding with Google Maps". + * + * @public + */ +export interface GoogleMapsGroundingChunk { + /** + * The URI of the place. + */ + uri?: string; + /** + * The title of the place. + */ + title?: string; + /** + * The text of the place answer. + */ + text?: string; + /** + * This Place's resource name, in `places/{place_id}` format. This can be used to look up the + * place in the Google Maps API. + */ + placeId?: string; +} + /** * Provides information about how a specific segment of the model's response is supported by the * retrieved grounding chunks. From c0a0a547042fdd4f82150f72fb936a82086c2cf1 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Fri, 24 Apr 2026 10:02:02 -0400 Subject: [PATCH 159/174] build(firestore): modernize and improve protobuf generation scripts (#9862) From 89ab3f3378d2022df59a809cffad55af8f9760bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:04:13 -0700 Subject: [PATCH 160/174] build(deps-dev): bump simple-git from 3.27.0 to 3.32.3 (#9710) Bumps [simple-git](https://github.com/steveukx/git-js/tree/HEAD/simple-git) from 3.27.0 to 3.32.3. - [Release notes](https://github.com/steveukx/git-js/releases) - [Changelog](https://github.com/steveukx/git-js/blob/main/simple-git/CHANGELOG.md) - [Commits](https://github.com/steveukx/git-js/commits/simple-git@3.32.3/simple-git) --- updated-dependencies: - dependency-name: simple-git dependency-version: 3.32.3 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 016efa9adc..deebcf46a3 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,7 @@ "protractor": "5.4.2", "request": "2.88.2", "semver": "7.7.1", - "simple-git": "3.27.0", + "simple-git": "3.32.3", "sinon": "9.2.4", "sinon-chai": "3.7.0", "source-map-loader": "1.1.3", diff --git a/yarn.lock b/yarn.lock index bf7bf5d9b0..1a09e37e35 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6280,10 +6280,10 @@ debug@3.X, debug@^3.1.0, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5: - version "4.4.0" - resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.4.0: + version "4.4.3" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== dependencies: ms "^2.1.3" @@ -15051,14 +15051,14 @@ simple-get@^4.0.0: once "^1.3.1" simple-concat "^1.0.0" -simple-git@3.27.0: - version "3.27.0" - resolved "https://registry.npmjs.org/simple-git/-/simple-git-3.27.0.tgz#f4b09e807bda56a4a3968f635c0e4888d3decbd5" - integrity sha512-ivHoFS9Yi9GY49ogc6/YAi3Fl9ROnF4VyubNylgCkA+RVqLaKWnDSzXOVzya8csELIaWaYNutsEuAhZrtOjozA== +simple-git@3.32.3: + version "3.32.3" + resolved "https://registry.npmjs.org/simple-git/-/simple-git-3.32.3.tgz#1dd6030fd03df4533a9e5a941314335e6265055d" + integrity sha512-56a5oxFdWlsGygOXHWrG+xjj5w9ZIt2uQbzqiIGdR/6i5iococ7WQ/bNPzWxCJdEUGUCmyMH0t9zMpRJTaKxmw== dependencies: "@kwsites/file-exists" "^1.1.1" "@kwsites/promise-deferred" "^1.1.1" - debug "^4.3.5" + debug "^4.4.0" simple-swizzle@^0.2.2: version "0.2.2" From 1bfcb188e19ec51945678edfcc493b89df4b7e6f Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Mon, 27 Apr 2026 13:58:41 -0400 Subject: [PATCH 161/174] build(firestore): remove `declare` statements from Console types (#9895) --- .../scripts/build-console-ui-types.ts | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/firestore/scripts/build-console-ui-types.ts b/packages/firestore/scripts/build-console-ui-types.ts index 8240a4e8aa..1790ec6440 100644 --- a/packages/firestore/scripts/build-console-ui-types.ts +++ b/packages/firestore/scripts/build-console-ui-types.ts @@ -47,7 +47,7 @@ for (let i = 0; i < args.length; i++) { } if (!sourceDtsPath || !destTxtPath) { - console.error('❌ Error: Missing required arguments.'); + console.error('Error: Missing required arguments.'); console.error( 'Usage: ts-node build-console-ui-types.ts --input --output ' ); @@ -55,7 +55,7 @@ if (!sourceDtsPath || !destTxtPath) { } if (!fs.existsSync(sourceDtsPath)) { - console.error(`❌ Error: Source file not found: ${sourceDtsPath}`); + console.error(`Error: Source file not found: ${sourceDtsPath}`); process.exit(1); } @@ -89,7 +89,7 @@ interface Firestore { /** * @type {Firestore} */ -declare var db: Firestore; +var db: Firestore; /** * Not supported in the query editor. @@ -109,7 +109,7 @@ type DocumentReference = never; * Create a \`FieldPath\` by providing field names. If more than one field * name is provided, the path will point to a nested field in a document. */ -declare class FieldPath { +class FieldPath { /** * Creates a \`FieldPath\` from the provided field names. If more than one field * name is provided, the path will point to a nested field in a document. @@ -133,7 +133,7 @@ declare class FieldPath { * * @returns A new \`VectorValue\` constructed with a copy of the given array of numbers. */ -declare function vector(values?: number[]): VectorValue; +function vector(values?: number[]): VectorValue; /** * Represents a vector type in Firestore documents. @@ -141,7 +141,7 @@ declare function vector(values?: number[]): VectorValue; * * @class VectorValue */ -declare class VectorValue { +class VectorValue { /** * Returns a copy of the raw number array form of the vector. */ @@ -169,7 +169,7 @@ declare class VectorValue { /** * An immutable object representing an array of bytes. */ -declare class Bytes { +class Bytes { private constructor(); /** * Creates a new \`Bytes\` object from the given Base64 string, converting it to @@ -239,7 +239,7 @@ declare class Bytes { * For examples and further specifications, refer to the * {@link https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto | Timestamp definition}. */ -declare class Timestamp { +class Timestamp { /** * The number of seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. */ @@ -343,7 +343,7 @@ declare class Timestamp { * Latitude values are in the range of [-90, 90]. * Longitude values are in the range of [-180, 180]. */ -declare class GeoPoint { +class GeoPoint { /** * Creates a new immutable \`GeoPoint\` object with the provided latitude and * longitude values. @@ -405,7 +405,7 @@ dtsContent = dtsContent.replace(/^export\s+\{[\s\S]*?\};?\s*$/gm, ''); // Strip 'export ' modifiers from the beginning of lines. // This converts 'export declare class' -> 'declare class', which is standard // for ambient global declaration files. -dtsContent = dtsContent.replace(/^\s*export\s+/gm, ''); +dtsContent = dtsContent.replace(/^\s*((export|declare)\s+)+/gm, ''); const finalContent: string = HEADER + '\n' + dtsContent; @@ -473,4 +473,4 @@ if (diagnostics.length > 0) { // Write output fs.writeFileSync(destTxtPath, finalContent); -console.log(`✅ Successfully generated and verified console UI types at ${destTxtPath}`); +console.log(`Successfully generated and verified console UI types at ${destTxtPath}`); From 3ed9c39aef34ea247caa4151870b1808a6fdc8ed Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 27 Apr 2026 12:08:23 -0700 Subject: [PATCH 162/174] chore: Upgrade webpack to 5.104.1 (#9891) --- e2e/smoke-tests/package.json | 2 +- e2e/smoke-tests/yarn.lock | 178 +++++++----- package.json | 2 +- repo-scripts/size-analysis/package.json | 16 +- yarn.lock | 366 +++++++++++++++++++++--- 5 files changed, 445 insertions(+), 119 deletions(-) diff --git a/e2e/smoke-tests/package.json b/e2e/smoke-tests/package.json index 2ddf668490..f4894c9e52 100644 --- a/e2e/smoke-tests/package.json +++ b/e2e/smoke-tests/package.json @@ -30,7 +30,7 @@ "jest-environment-jsdom": "30.2.0", "ts-node": "10.9.2", "typescript": "5.5.4", - "webpack": "5.98.0", + "webpack": "5.104.1", "webpack-cli": "5.1.4", "webpack-dev-server": "5.2.1" }, diff --git a/e2e/smoke-tests/yarn.lock b/e2e/smoke-tests/yarn.lock index 823c955ec7..139e34073f 100644 --- a/e2e/smoke-tests/yarn.lock +++ b/e2e/smoke-tests/yarn.lock @@ -2288,11 +2288,16 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^1.0.6": +"@types/estree@*": version "1.0.7" resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== +"@types/estree@^1.0.8": + version "1.0.8" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + "@types/express-serve-static-core@*", "@types/express-serve-static-core@^5.0.0": version "5.0.1" resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz" @@ -2386,7 +2391,7 @@ "@types/tough-cookie" "*" parse5 "^7.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -2741,6 +2746,11 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" +acorn-import-phases@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz#16eb850ba99a056cb7cbfe872ffb8972e18c8bd7" + integrity sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ== + acorn-walk@^8.1.1: version "8.3.4" resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz" @@ -2753,10 +2763,10 @@ acorn@^8.11.0, acorn@^8.4.1: resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== -acorn@^8.14.0: - version "8.14.1" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" - integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== +acorn@^8.15.0: + version "8.16.0" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a" + integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== acorn@^8.8.2: version "8.13.0" @@ -2970,6 +2980,11 @@ balanced-match@^1.0.0: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +baseline-browser-mapping@^2.10.12: + version "2.10.21" + resolved "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.21.tgz#136f9f181ee0d7ca6e3edbf42d9559763d2c1141" + integrity sha512-Q+rUQ7Uz8AHM7DEaNdwvfFCTq7a43lNTzuS94eiWqwyxfV/wJv+oUivef51T91mmRY4d4A1u9rcSvkeufCVXlA== + batch@0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz" @@ -3053,6 +3068,17 @@ browserslist@^4.24.4: node-releases "^2.0.19" update-browserslist-db "^1.1.1" +browserslist@^4.28.1: + version "4.28.2" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz#f50b65362ef48974ca9f50b3680566d786b811d2" + integrity sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg== + dependencies: + baseline-browser-mapping "^2.10.12" + caniuse-lite "^1.0.30001782" + electron-to-chromium "^1.5.328" + node-releases "^2.0.36" + update-browserslist-db "^1.2.3" + bser@2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" @@ -3118,6 +3144,11 @@ caniuse-lite@^1.0.30001688: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001702.tgz" integrity sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA== +caniuse-lite@^1.0.30001782: + version "1.0.30001790" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001790.tgz#04660c7de15f445d86dd10ac88a8936ac0698e45" + integrity sha512-bOoxfJPyYo+ds6W0YfptaCWbFnJYjh2Y1Eow5lRv+vI2u8ganPZqNm1JwNh0t2ELQCqIWg4B3dWEusgAmsoyOw== + chalk@^4.1.2: version "4.1.2" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" @@ -3439,6 +3470,11 @@ ee-first@1.1.1: resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== +electron-to-chromium@^1.5.328: + version "1.5.344" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.344.tgz#6437cc08a7d9b914a98120e182f37793c9eaffd4" + integrity sha512-4MxfbmNDm+KPh066EZy+eUnkcDPcZ35wNmOWzFuh/ijvHsve6kbLTLURy88uCNK5FbpN+yk2nQY6BYh1GEt+wg== + electron-to-chromium@^1.5.41: version "1.5.45" resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.45.tgz" @@ -3479,13 +3515,13 @@ encodeurl@~2.0.0: resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz" integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== -enhanced-resolve@^5.17.1: - version "5.18.1" - resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz" - integrity sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg== +enhanced-resolve@^5.17.4: + version "5.21.0" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz#bb8e6fabaf74930de70e61397798750429e5b1ae" + integrity sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA== dependencies: graceful-fs "^4.2.4" - tapable "^2.2.0" + tapable "^2.3.3" entities@^4.5.0: version "4.5.0" @@ -3521,10 +3557,10 @@ es-errors@^1.3.0: resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es-module-lexer@^1.2.1: - version "1.6.0" - resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz" - integrity sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ== +es-module-lexer@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz#f657cd7a9448dcdda9c070a3cb75e5dc1e85f5b1" + integrity sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw== escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" @@ -4711,10 +4747,10 @@ lines-and-columns@^1.1.6: resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -loader-runner@^4.2.0: - version "4.3.0" - resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz" - integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== +loader-runner@^4.3.1: + version "4.3.2" + resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz#9913d3a15971f8f635915e601fb5c9d495d918e9" + integrity sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w== loader-utils@^2.0.4: version "2.0.4" @@ -4932,6 +4968,11 @@ node-releases@^2.0.19: resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz" integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== +node-releases@^2.0.36: + version "2.0.38" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz#791569b9e4424a044e12c3abfad418ed83ce9947" + integrity sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw== + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" @@ -5181,13 +5222,6 @@ qs@6.13.0: dependencies: side-channel "^1.0.6" -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" @@ -5348,7 +5382,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -5384,6 +5418,16 @@ schema-utils@^4.0.0, schema-utils@^4.2.0, schema-utils@^4.3.0: ajv-formats "^2.1.1" ajv-keywords "^5.1.0" +schema-utils@^4.3.3: + version "4.3.3" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz#5b1850912fa31df90716963d45d9121fdfc09f46" + integrity sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.9.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.1.0" + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" @@ -5431,13 +5475,6 @@ send@0.19.0: range-parser "~1.2.1" statuses "2.0.1" -serialize-javascript@^6.0.2: - version "6.0.2" - resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz" - integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== - dependencies: - randombytes "^2.1.0" - serve-index@^1.9.1: version "1.9.1" resolved "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz" @@ -5723,20 +5760,19 @@ synckit@^0.11.8: dependencies: "@pkgr/core" "^0.2.9" -tapable@^2.1.1, tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tapable@^2.3.0, tapable@^2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz#5da7c9992c46038221267985ab28421a8879f160" + integrity sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A== -terser-webpack-plugin@^5.3.11: - version "5.3.14" - resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz#9031d48e57ab27567f02ace85c7d690db66c3e06" - integrity sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw== +terser-webpack-plugin@^5.3.16: + version "5.5.0" + resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.5.0.tgz#d92b8e2c892dd09c683c38120394267e8d8660ef" + integrity sha512-UYhptBwhWvfIjKd/UuFo6D8uq9xpGLDK+z8EDsj/zWhrTaH34cKEbrkMKfV5YWqGBvAYA3tlzZbs2R+qYrbQJA== dependencies: "@jridgewell/trace-mapping" "^0.3.25" jest-worker "^27.4.5" schema-utils "^4.3.0" - serialize-javascript "^6.0.2" terser "^5.31.1" terser@^5.31.1: @@ -5936,6 +5972,14 @@ update-browserslist-db@^1.1.1: escalade "^3.2.0" picocolors "^1.1.0" +update-browserslist-db@^1.2.3: + version "1.2.3" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" + integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" @@ -5991,10 +6035,10 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" -watchpack@^2.4.1: - version "2.4.2" - resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz" - integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== +watchpack@^2.4.4: + version "2.5.1" + resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz#dd38b601f669e0cbf567cb802e75cead82cde102" + integrity sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -6090,39 +6134,41 @@ webpack-merge@^5.7.3: flat "^5.0.2" wildcard "^2.0.0" -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== +webpack-sources@^3.3.3: + version "3.4.0" + resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.0.tgz#67cdfdff349ff1e3e7ca5c1ed6a2802b84cf6cf5" + integrity sha512-gHwIe1cgBvvfLeu1Yz/dcFpmHfKDVxxyqI+kzqmuxZED81z2ChxpyqPaWcNqigPywhaEke7AjSGga+kxY55gjQ== -webpack@5.98.0: - version "5.98.0" - resolved "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz#44ae19a8f2ba97537978246072fb89d10d1fbd17" - integrity sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA== +webpack@5.104.1: + version "5.104.1" + resolved "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz#94bd41eb5dbf06e93be165ba8be41b8260d4fb1a" + integrity sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA== dependencies: "@types/eslint-scope" "^3.7.7" - "@types/estree" "^1.0.6" + "@types/estree" "^1.0.8" + "@types/json-schema" "^7.0.15" "@webassemblyjs/ast" "^1.14.1" "@webassemblyjs/wasm-edit" "^1.14.1" "@webassemblyjs/wasm-parser" "^1.14.1" - acorn "^8.14.0" - browserslist "^4.24.0" + acorn "^8.15.0" + acorn-import-phases "^1.0.3" + browserslist "^4.28.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.17.1" - es-module-lexer "^1.2.1" + enhanced-resolve "^5.17.4" + es-module-lexer "^2.0.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" graceful-fs "^4.2.11" json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" + loader-runner "^4.3.1" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^4.3.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.3.11" - watchpack "^2.4.1" - webpack-sources "^3.2.3" + schema-utils "^4.3.3" + tapable "^2.3.0" + terser-webpack-plugin "^5.3.16" + watchpack "^2.4.4" + webpack-sources "^3.3.3" websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" diff --git a/package.json b/package.json index deebcf46a3..7349c5c203 100644 --- a/package.json +++ b/package.json @@ -159,7 +159,7 @@ "typedoc": "0.16.11", "typescript": "5.5.4", "watch": "1.0.2", - "webpack": "5.98.0", + "webpack": "5.104.1", "yargs": "17.7.2" } } diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index 4c2437860d..e8c6adc582 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -21,21 +21,21 @@ "license": "Apache-2.0", "dependencies": { "@firebase/util": "1.15.0", - "child-process-promise": "2.2.1", - "glob": "7.2.3", - "tmp": "0.2.4", - "gzip-size": "6.0.0", - "memfs": "3.5.3", - "terser": "5.37.0", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-node-resolve": "16.0.0", "@rollup/plugin-virtual": "3.0.2", + "child-process-promise": "2.2.1", + "glob": "7.2.3", + "gzip-size": "6.0.0", + "memfs": "4.57.2", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.36.0", + "terser": "5.37.0", + "tmp": "0.2.4", "typescript": "5.5.4", - "webpack": "5.98.0", + "webpack": "5.104.1", "webpack-virtual-modules": "0.6.2", "yargs": "17.7.2" }, @@ -61,4 +61,4 @@ "engines": { "node": ">=20.0.0" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 1a09e37e35..1f9e54c043 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1778,6 +1778,166 @@ dependencies: lodash "^4.17.21" +"@jsonjoy.com/base64@17.67.0": + version "17.67.0" + resolved "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.67.0.tgz#7eeda3cb41138d77a90408fd2e42b2aba10576d7" + integrity sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw== + +"@jsonjoy.com/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz#cf8ea9dcb849b81c95f14fc0aaa151c6b54d2578" + integrity sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA== + +"@jsonjoy.com/buffers@17.67.0", "@jsonjoy.com/buffers@^17.65.0": + version "17.67.0" + resolved "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.67.0.tgz#5c58dbcdeea8824ce296bd1cfce006c2eb167b3d" + integrity sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw== + +"@jsonjoy.com/buffers@^1.0.0", "@jsonjoy.com/buffers@^1.2.0": + version "1.2.1" + resolved "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz#8d99c7f67eaf724d3428dfd9826c6455266a5c83" + integrity sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA== + +"@jsonjoy.com/codegen@17.67.0": + version "17.67.0" + resolved "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.67.0.tgz#3635fd8769d77e19b75dc5574bc9756019b2e591" + integrity sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q== + +"@jsonjoy.com/codegen@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz#5c23f796c47675f166d23b948cdb889184b93207" + integrity sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g== + +"@jsonjoy.com/fs-core@4.57.2": + version "4.57.2" + resolved "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.57.2.tgz#e28f357ba9983ce53577ba34fc72d344f19ec459" + integrity sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ== + dependencies: + "@jsonjoy.com/fs-node-builtins" "4.57.2" + "@jsonjoy.com/fs-node-utils" "4.57.2" + thingies "^2.5.0" + +"@jsonjoy.com/fs-fsa@4.57.2": + version "4.57.2" + resolved "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.57.2.tgz#ec6dd492ff8c104a0c1eae74959a013960fe8969" + integrity sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g== + dependencies: + "@jsonjoy.com/fs-core" "4.57.2" + "@jsonjoy.com/fs-node-builtins" "4.57.2" + "@jsonjoy.com/fs-node-utils" "4.57.2" + thingies "^2.5.0" + +"@jsonjoy.com/fs-node-builtins@4.57.2": + version "4.57.2" + resolved "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.57.2.tgz#9174b87e70213b38caf1ac8669b130c4dfd6a909" + integrity sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg== + +"@jsonjoy.com/fs-node-to-fsa@4.57.2": + version "4.57.2" + resolved "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.57.2.tgz#8542449b72dfc48f3bfe311a7b0af5323f9bc926" + integrity sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ== + dependencies: + "@jsonjoy.com/fs-fsa" "4.57.2" + "@jsonjoy.com/fs-node-builtins" "4.57.2" + "@jsonjoy.com/fs-node-utils" "4.57.2" + +"@jsonjoy.com/fs-node-utils@4.57.2": + version "4.57.2" + resolved "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.57.2.tgz#c3234c03b1e59d609a0915572dd6f450be0463b1" + integrity sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ== + dependencies: + "@jsonjoy.com/fs-node-builtins" "4.57.2" + +"@jsonjoy.com/fs-node@4.57.2": + version "4.57.2" + resolved "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.57.2.tgz#8db2875df19683683e5852053e0099e233dc45d2" + integrity sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg== + dependencies: + "@jsonjoy.com/fs-core" "4.57.2" + "@jsonjoy.com/fs-node-builtins" "4.57.2" + "@jsonjoy.com/fs-node-utils" "4.57.2" + "@jsonjoy.com/fs-print" "4.57.2" + "@jsonjoy.com/fs-snapshot" "4.57.2" + glob-to-regex.js "^1.0.0" + thingies "^2.5.0" + +"@jsonjoy.com/fs-print@4.57.2": + version "4.57.2" + resolved "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.57.2.tgz#286c4ceda19225a5c54aaad657ad9f466d5bd0c1" + integrity sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ== + dependencies: + "@jsonjoy.com/fs-node-utils" "4.57.2" + tree-dump "^1.1.0" + +"@jsonjoy.com/fs-snapshot@4.57.2": + version "4.57.2" + resolved "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.57.2.tgz#800424a076638a605dad5ef1540915bc0167d7f8" + integrity sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw== + dependencies: + "@jsonjoy.com/buffers" "^17.65.0" + "@jsonjoy.com/fs-node-utils" "4.57.2" + "@jsonjoy.com/json-pack" "^17.65.0" + "@jsonjoy.com/util" "^17.65.0" + +"@jsonjoy.com/json-pack@^1.11.0": + version "1.21.0" + resolved "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.21.0.tgz#93f8dd57fe3a3a92132b33d1eb182dcd9e7629fa" + integrity sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg== + dependencies: + "@jsonjoy.com/base64" "^1.1.2" + "@jsonjoy.com/buffers" "^1.2.0" + "@jsonjoy.com/codegen" "^1.0.0" + "@jsonjoy.com/json-pointer" "^1.0.2" + "@jsonjoy.com/util" "^1.9.0" + hyperdyperid "^1.2.0" + thingies "^2.5.0" + tree-dump "^1.1.0" + +"@jsonjoy.com/json-pack@^17.65.0": + version "17.67.0" + resolved "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.67.0.tgz#8dd8ff65dd999c5d4d26df46c63915c7bdec093a" + integrity sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w== + dependencies: + "@jsonjoy.com/base64" "17.67.0" + "@jsonjoy.com/buffers" "17.67.0" + "@jsonjoy.com/codegen" "17.67.0" + "@jsonjoy.com/json-pointer" "17.67.0" + "@jsonjoy.com/util" "17.67.0" + hyperdyperid "^1.2.0" + thingies "^2.5.0" + tree-dump "^1.1.0" + +"@jsonjoy.com/json-pointer@17.67.0": + version "17.67.0" + resolved "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.67.0.tgz#74439573dc046e0c9a3a552fb94b391bc75313b8" + integrity sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA== + dependencies: + "@jsonjoy.com/util" "17.67.0" + +"@jsonjoy.com/json-pointer@^1.0.2": + version "1.0.2" + resolved "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz#049cb530ac24e84cba08590c5e36b431c4843408" + integrity sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg== + dependencies: + "@jsonjoy.com/codegen" "^1.0.0" + "@jsonjoy.com/util" "^1.9.0" + +"@jsonjoy.com/util@17.67.0", "@jsonjoy.com/util@^17.65.0": + version "17.67.0" + resolved "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.67.0.tgz#7c4288fc3808233e55c7610101e7bb4590cddd3f" + integrity sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew== + dependencies: + "@jsonjoy.com/buffers" "17.67.0" + "@jsonjoy.com/codegen" "17.67.0" + +"@jsonjoy.com/util@^1.9.0": + version "1.9.0" + resolved "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.9.0.tgz#7ee95586aed0a766b746cd8d8363e336c3c47c46" + integrity sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ== + dependencies: + "@jsonjoy.com/buffers" "^1.0.0" + "@jsonjoy.com/codegen" "^1.0.0" + "@kwsites/file-exists@^1.1.1": version "1.1.1" resolved "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz#ad1efcac13e1987d8dbaf235ef3be5b0d96faa99" @@ -3174,6 +3334,11 @@ resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/estree@^1.0.8": + version "1.0.8" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + "@types/expect@^1.20.4": version "1.20.4" resolved "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz#8288e51737bf7e3ab5d7c77bfa695883745264e5" @@ -3268,7 +3433,7 @@ resolved "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz#cd82382c4f902fed9691a2ed79ec68c5898af4c2" integrity sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg== -"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -3869,6 +4034,11 @@ accepts@~1.3.4, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" +acorn-import-phases@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz#16eb850ba99a056cb7cbfe872ffb8972e18c8bd7" + integrity sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ== + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -3891,6 +4061,11 @@ acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1, acorn@^8.8.2, acorn@^8.9.0: resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== +acorn@^8.15.0: + version "8.16.0" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a" + integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== + add-stream@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" @@ -4751,6 +4926,11 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" +baseline-browser-mapping@^2.10.12: + version "2.10.21" + resolved "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.21.tgz#136f9f181ee0d7ca6e3edbf42d9559763d2c1141" + integrity sha512-Q+rUQ7Uz8AHM7DEaNdwvfFCTq7a43lNTzuS94eiWqwyxfV/wJv+oUivef51T91mmRY4d4A1u9rcSvkeufCVXlA== + basic-auth-connect@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.1.0.tgz#b44af37d5b3bd7561b56491e58cf26ae1578f0c7" @@ -5005,6 +5185,17 @@ browserslist@^4.24.0, browserslist@^4.24.3: node-releases "^2.0.19" update-browserslist-db "^1.1.1" +browserslist@^4.28.1: + version "4.28.2" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz#f50b65362ef48974ca9f50b3680566d786b811d2" + integrity sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg== + dependencies: + baseline-browser-mapping "^2.10.12" + caniuse-lite "^1.0.30001782" + electron-to-chromium "^1.5.328" + node-releases "^2.0.36" + update-browserslist-db "^1.2.3" + browserstack@^1.5.1: version "1.6.1" resolved "https://registry.npmjs.org/browserstack/-/browserstack-1.6.1.tgz#e051f9733ec3b507659f395c7a4765a1b1e358b3" @@ -5245,6 +5436,11 @@ caniuse-lite@^1.0.30001688: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz" integrity sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA== +caniuse-lite@^1.0.30001782: + version "1.0.30001790" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001790.tgz#04660c7de15f445d86dd10ac88a8936ac0698e45" + integrity sha512-bOoxfJPyYo+ds6W0YfptaCWbFnJYjh2Y1Eow5lRv+vI2u8ganPZqNm1JwNh0t2ELQCqIWg4B3dWEusgAmsoyOw== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -6722,6 +6918,11 @@ ee-first@1.1.1: resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== +electron-to-chromium@^1.5.328: + version "1.5.344" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.344.tgz#6437cc08a7d9b914a98120e182f37793c9eaffd4" + integrity sha512-4MxfbmNDm+KPh066EZy+eUnkcDPcZ35wNmOWzFuh/ijvHsve6kbLTLURy88uCNK5FbpN+yk2nQY6BYh1GEt+wg== + electron-to-chromium@^1.5.73: version "1.5.87" resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.87.tgz#3a89bec85e43a8b32445ec938228e4ec982e0f79" @@ -6822,6 +7023,14 @@ enhanced-resolve@^5.0.0, enhanced-resolve@^5.17.1: graceful-fs "^4.2.4" tapable "^2.2.0" +enhanced-resolve@^5.17.4: + version "5.21.0" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz#bb8e6fabaf74930de70e61397798750429e5b1ae" + integrity sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.3.3" + enquirer@^2.4.1: version "2.4.1" resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" @@ -6956,6 +7165,11 @@ es-module-lexer@^1.2.1: resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz#da49f587fd9e68ee2404fe4e256c0c7d3a81be21" integrity sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ== +es-module-lexer@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz#f657cd7a9448dcdda9c070a3cb75e5dc1e85f5b1" + integrity sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw== + es-object-atoms@^1.0.0: version "1.1.1" resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" @@ -8133,11 +8347,6 @@ fs-mkdirp-stream@^1.0.0: graceful-fs "^4.1.11" through2 "^2.0.3" -fs-monkey@^1.0.4: - version "1.0.6" - resolved "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz#8ead082953e88d992cf3ff844faa907b26756da2" - integrity sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg== - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -8463,6 +8672,11 @@ glob-stream@^6.1.0: to-absolute-glob "^2.0.0" unique-stream "^2.0.2" +glob-to-regex.js@^1.0.0, glob-to-regex.js@^1.0.1: + version "1.2.0" + resolved "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz#2b323728271d133830850e32311f40766c5f6413" + integrity sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ== + glob-to-regexp@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" @@ -9173,6 +9387,11 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +hyperdyperid@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz#59668d323ada92228d2a869d3e474d5a33b69e6b" + integrity sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A== + iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -11010,6 +11229,11 @@ loader-runner@^4.2.0: resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== +loader-runner@^4.3.1: + version "4.3.2" + resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz#9913d3a15971f8f635915e601fb5c9d495d918e9" + integrity sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w== + loader-utils@^2.0.0, loader-utils@^2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" @@ -11536,12 +11760,25 @@ media-typer@0.3.0: resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -memfs@3.5.3: - version "3.5.3" - resolved "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz#d9b40fe4f8d5788c5f895bda804cd0d9eeee9f3b" - integrity sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw== - dependencies: - fs-monkey "^1.0.4" +memfs@4.57.2: + version "4.57.2" + resolved "https://registry.npmjs.org/memfs/-/memfs-4.57.2.tgz#5f74e977c9a14681ea10d427b3ce5d7db5f817e7" + integrity sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ== + dependencies: + "@jsonjoy.com/fs-core" "4.57.2" + "@jsonjoy.com/fs-fsa" "4.57.2" + "@jsonjoy.com/fs-node" "4.57.2" + "@jsonjoy.com/fs-node-builtins" "4.57.2" + "@jsonjoy.com/fs-node-to-fsa" "4.57.2" + "@jsonjoy.com/fs-node-utils" "4.57.2" + "@jsonjoy.com/fs-print" "4.57.2" + "@jsonjoy.com/fs-snapshot" "4.57.2" + "@jsonjoy.com/json-pack" "^1.11.0" + "@jsonjoy.com/util" "^1.9.0" + glob-to-regex.js "^1.0.1" + thingies "^2.5.0" + tree-dump "^1.0.3" + tslib "^2.0.0" memoizee@0.4.X: version "0.4.17" @@ -12260,6 +12497,11 @@ node-releases@^2.0.19: resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== +node-releases@^2.0.36: + version "2.0.38" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz#791569b9e4424a044e12c3abfad418ed83ce9947" + integrity sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw== + node-version@^1.0.0: version "1.2.0" resolved "https://registry.npmjs.org/node-version/-/node-version-1.2.0.tgz#34fde3ffa8e1149bd323983479dda620e1b5060d" @@ -14727,6 +14969,16 @@ schema-utils@^4.3.0: ajv-formats "^2.1.1" ajv-keywords "^5.1.0" +schema-utils@^4.3.3: + version "4.3.3" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz#5b1850912fa31df90716963d45d9121fdfc09f46" + integrity sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.9.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.1.0" + secure-compare@3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz#f1a0329b308b221fae37b9974f3d578d0ca999e3" @@ -14936,16 +15188,7 @@ setprototypeof@1.2.0: resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.12" - resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz#eb8b568bf383dfd1867a32c3f2b74eb52bdbf23f" - integrity sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w== - dependencies: - inherits "^2.0.4" - safe-buffer "^5.2.1" - to-buffer "^1.2.0" - -sha.js@^2.4.12: +sha.js@^2.4.0, sha.js@^2.4.12, sha.js@^2.4.8: version "2.4.12" resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz#eb8b568bf383dfd1867a32c3f2b74eb52bdbf23f" integrity sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w== @@ -15870,6 +16113,11 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tapable@^2.3.0, tapable@^2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz#5da7c9992c46038221267985ab28421a8879f160" + integrity sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A== + tar-fs@^2.0.0: version "2.1.4" resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz#800824dbf4ef06ded9afea4acafe71c67c76b930" @@ -15988,15 +16236,14 @@ terser-webpack-plugin@^5.3.10: serialize-javascript "^6.0.2" terser "^5.31.1" -terser-webpack-plugin@^5.3.11: - version "5.3.14" - resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz#9031d48e57ab27567f02ace85c7d690db66c3e06" - integrity sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw== +terser-webpack-plugin@^5.3.16: + version "5.5.0" + resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.5.0.tgz#d92b8e2c892dd09c683c38120394267e8d8660ef" + integrity sha512-UYhptBwhWvfIjKd/UuFo6D8uq9xpGLDK+z8EDsj/zWhrTaH34cKEbrkMKfV5YWqGBvAYA3tlzZbs2R+qYrbQJA== dependencies: "@jridgewell/trace-mapping" "^0.3.25" jest-worker "^27.4.5" schema-utils "^4.3.0" - serialize-javascript "^6.0.2" terser "^5.31.1" terser@5.37.0, terser@^5.17.4, terser@^5.31.1: @@ -16069,6 +16316,11 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" +thingies@^2.5.0: + version "2.6.0" + resolved "https://registry.npmjs.org/thingies/-/thingies-2.6.0.tgz#e09b98b9e6f6caf8a759eca8481fea1de974d2b1" + integrity sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg== + through2-filter@^3.0.0: version "3.1.0" resolved "https://registry.npmjs.org/through2-filter/-/through2-filter-3.1.0.tgz#4a1b45d2b76b3ac93ec137951e372c268efc1a4e" @@ -16265,6 +16517,11 @@ tr46@~0.0.3: resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +tree-dump@^1.0.3, tree-dump@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz#ab29129169dc46004414f5a9d4a3c6e89f13e8a4" + integrity sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA== + trim-newlines@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" @@ -16343,7 +16600,7 @@ tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.1, tslib@^2.1.0, tslib@^2.6.2: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.6.2: version "2.8.1" resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -16799,6 +17056,14 @@ update-browserslist-db@^1.1.1: escalade "^3.2.0" picocolors "^1.1.1" +update-browserslist-db@^1.2.3: + version "1.2.3" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" + integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + update-notifier-cjs@^5.1.6: version "5.1.7" resolved "https://registry.npmjs.org/update-notifier-cjs/-/update-notifier-cjs-5.1.7.tgz#995733b43bdaeb136b999d55061fc385ef787a7f" @@ -17046,6 +17311,14 @@ watchpack@^2.4.1: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" +watchpack@^2.4.4: + version "2.5.1" + resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz#dd38b601f669e0cbf567cb802e75cead82cde102" + integrity sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + wcwidth@^1.0.0, wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" @@ -17110,6 +17383,11 @@ webpack-sources@^3.2.3: resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== +webpack-sources@^3.3.3: + version "3.4.0" + resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.0.tgz#67cdfdff349ff1e3e7ca5c1ed6a2802b84cf6cf5" + integrity sha512-gHwIe1cgBvvfLeu1Yz/dcFpmHfKDVxxyqI+kzqmuxZED81z2ChxpyqPaWcNqigPywhaEke7AjSGga+kxY55gjQ== + webpack-stream@7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/webpack-stream/-/webpack-stream-7.0.0.tgz#e6a1edb9568198499af872678e95031752d72f00" @@ -17129,34 +17407,36 @@ webpack-virtual-modules@0.6.2: resolved "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz#057faa9065c8acf48f24cb57ac0e77739ab9a7e8" integrity sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ== -webpack@5.98.0: - version "5.98.0" - resolved "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz#44ae19a8f2ba97537978246072fb89d10d1fbd17" - integrity sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA== +webpack@5.104.1: + version "5.104.1" + resolved "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz#94bd41eb5dbf06e93be165ba8be41b8260d4fb1a" + integrity sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA== dependencies: "@types/eslint-scope" "^3.7.7" - "@types/estree" "^1.0.6" + "@types/estree" "^1.0.8" + "@types/json-schema" "^7.0.15" "@webassemblyjs/ast" "^1.14.1" "@webassemblyjs/wasm-edit" "^1.14.1" "@webassemblyjs/wasm-parser" "^1.14.1" - acorn "^8.14.0" - browserslist "^4.24.0" + acorn "^8.15.0" + acorn-import-phases "^1.0.3" + browserslist "^4.28.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.17.1" - es-module-lexer "^1.2.1" + enhanced-resolve "^5.17.4" + es-module-lexer "^2.0.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" graceful-fs "^4.2.11" json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" + loader-runner "^4.3.1" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^4.3.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.3.11" - watchpack "^2.4.1" - webpack-sources "^3.2.3" + schema-utils "^4.3.3" + tapable "^2.3.0" + terser-webpack-plugin "^5.3.16" + watchpack "^2.4.4" + webpack-sources "^3.3.3" webpack@^5: version "5.97.1" From 81a4abc433067ab0c6b51108e9bf5f5fa3617855 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Mon, 27 Apr 2026 15:44:37 -0400 Subject: [PATCH 163/174] test(firestore): extend database source test timeout to 30s (#9896) * test(firestore): extend database source test timeout to 30s Extend the timeout of the database source pipeline test from 20s to 30s. This test is very slow and is exceeding the 20s timeout, causing the test to fail locally and in CI. * Update packages/firestore/test/lite/pipeline.test.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * add to browser tests --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- packages/firestore/test/integration/api/pipeline.test.ts | 2 +- packages/firestore/test/lite/pipeline.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index 4b06ceb273..a620b66d07 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -623,7 +623,7 @@ apiDescribe.skipClassic('Pipelines', persistence => { .sort(ascending('order')) ); expectResults(snapshot, doc1.id, doc2.id); - }); + }).timeout(30_000); }); describe('supported data types', () => { diff --git a/packages/firestore/test/lite/pipeline.test.ts b/packages/firestore/test/lite/pipeline.test.ts index 64bcf7b2c0..9b2ef03dbb 100644 --- a/packages/firestore/test/lite/pipeline.test.ts +++ b/packages/firestore/test/lite/pipeline.test.ts @@ -623,7 +623,7 @@ describe.skipClassic('Firestore Pipelines', () => { .sort(ascending('order')) ); expectResults(snapshot, doc1.id, doc2.id); - }); + }).timeout(30_000); // Database-wide pipelines can be slow to execute. it('can create pipeline from a query', async () => { const snapshot = await execute( From 96e81ffe9a6efd557685eea7db9d78e5594f43aa Mon Sep 17 00:00:00 2001 From: Mark Duckworth <1124037+MarkDuckworth@users.noreply.github.com> Date: Wed, 29 Apr 2026 13:55:37 -0600 Subject: [PATCH 164/174] feat(firestore): Added search stage support for languageCode, offset, limit, and retrievalDepth (#9884) * feat(firestore): Added search stage support for languageCode, offset, limit, and retrievalDepth * Create four-bottles-marry.md * docgen * PR feedback * Update packages/firestore/src/lite-api/stage_options.ts Co-authored-by: Daniel La Rocque * Improve ref doc * More search refDoc improvements * Consistent capitalization of search within ref docs * remove deleted rut file * docs devsite --------- Co-authored-by: Daniel La Rocque --- .changeset/four-bottles-marry.md | 5 + .../firestore-lite-pipelines.api.md | 4 + common/api-review/firestore-pipelines.api.md | 4 + .../firestore_lite_pipelines.field.md | 2 +- docs-devsite/firestore_lite_pipelines.md | 14 +- docs-devsite/firestore_pipelines.field.md | 2 +- docs-devsite/firestore_pipelines.md | 14 +- .../firestore/src/lite-api/expressions.ts | 20 +-- .../firestore/src/lite-api/stage_options.ts | 53 +++--- .../test/integration/api/pipeline.test.ts | 160 +++++++++++------- 10 files changed, 165 insertions(+), 113 deletions(-) create mode 100644 .changeset/four-bottles-marry.md diff --git a/.changeset/four-bottles-marry.md b/.changeset/four-bottles-marry.md new file mode 100644 index 0000000000..8a32d70ba1 --- /dev/null +++ b/.changeset/four-bottles-marry.md @@ -0,0 +1,5 @@ +--- +"@firebase/firestore": patch +--- + +Added search stage support for languageCode, offset, limit, and retrievalDepth diff --git a/common/api-review/firestore-lite-pipelines.api.md b/common/api-review/firestore-lite-pipelines.api.md index b701f1ffeb..7f5241d451 100644 --- a/common/api-review/firestore-lite-pipelines.api.md +++ b/common/api-review/firestore-lite-pipelines.api.md @@ -1447,7 +1447,11 @@ export function score(): Expression; // @beta export type SearchStageOptions = StageOptions & { query: BooleanExpression | string; + languageCode?: string; + retrievalDepth?: number; sort?: Ordering | Ordering[]; + offset?: number; + limit?: number; addFields?: Selectable[]; }; diff --git a/common/api-review/firestore-pipelines.api.md b/common/api-review/firestore-pipelines.api.md index cf7bff1fa8..fb3b3d0756 100644 --- a/common/api-review/firestore-pipelines.api.md +++ b/common/api-review/firestore-pipelines.api.md @@ -1475,7 +1475,11 @@ export function score(): Expression; // @beta export type SearchStageOptions = StageOptions & { query: BooleanExpression | string; + languageCode?: string; + retrievalDepth?: number; sort?: Ordering | Ordering[]; + offset?: number; + limit?: number; addFields?: Selectable[]; }; diff --git a/docs-devsite/firestore_lite_pipelines.field.md b/docs-devsite/firestore_lite_pipelines.field.md index 614459d8a4..c13e557512 100644 --- a/docs-devsite/firestore_lite_pipelines.field.md +++ b/docs-devsite/firestore_lite_pipelines.field.md @@ -88,7 +88,7 @@ selectable: true; Evaluates to the distance in meters between the location specified by this field and the query location. -This Expression can only be used within a `Search` stage. +This Expression can only be used within a `search` stage. Signature: diff --git a/docs-devsite/firestore_lite_pipelines.md b/docs-devsite/firestore_lite_pipelines.md index b3c5fa4b3b..12a83e4b86 100644 --- a/docs-devsite/firestore_lite_pipelines.md +++ b/docs-devsite/firestore_lite_pipelines.md @@ -478,7 +478,7 @@ https://github.com/firebase/firebase-js-sdk | [RemoveFieldsStageOptions](./firestore_lite_pipelines.md#removefieldsstageoptions) | Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). | | [ReplaceWithStageOptions](./firestore_lite_pipelines.md#replacewithstageoptions) | Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). | | [SampleStageOptions](./firestore_lite_pipelines.md#samplestageoptions) | Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.md#stageoptions) with a specific configuration where only one of the defined sampling methods can be applied.See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. | -| [SearchStageOptions](./firestore_lite_pipelines.md#searchstageoptions) | (Public Preview) Options defining how a SearchStage is evaluated. See . | +| [SearchStageOptions](./firestore_lite_pipelines.md#searchstageoptions) | (Public Preview) Options defining how a search stage is evaluated. See [Pipeline.search()](./firestore_pipelines.pipeline.md#pipelinesearch). | | [SelectStageOptions](./firestore_lite_pipelines.md#selectstageoptions) | Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). | | [SetOptions](./firestore_lite_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | | [SortStageOptions](./firestore_lite_pipelines.md#sortstageoptions) | Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | @@ -600,7 +600,7 @@ rand(); Evaluates to the search score that reflects the topicality of the document to all of the text predicates (for example: `documentMatches`) in the search query. If `SearchOptions.query` is not set or does not contain any text predicates, then this topicality score will always be `0`. -This Expression can only be used within a `Search` stage. +This Expression can only be used within a `search` stage. Signature: @@ -6196,7 +6196,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe Evaluates to the distance in meters between the location in the specified field and the query location. -This Expression can only be used within a `Search` stage. +This Expression can only be used within a `search` stage. Signature: @@ -10351,7 +10351,7 @@ const results: PipelineResults = snapshot.results; Perform a full-text search on all indexed search fields in the document. -This Expression can only be used within a `Search` stage. +This Expression can only be used within a `search` stage. Signature: @@ -12243,14 +12243,18 @@ export declare type SampleStageOptions = StageOptions & OneOf<{ > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a SearchStage is evaluated. See . +Options defining how a search stage is evaluated. See [Pipeline.search()](./firestore_pipelines.pipeline.md#pipelinesearch). Signature: ```typescript export declare type SearchStageOptions = StageOptions & { query: BooleanExpression | string; + languageCode?: string; + retrievalDepth?: number; sort?: Ordering | Ordering[]; + offset?: number; + limit?: number; addFields?: Selectable[]; }; ``` diff --git a/docs-devsite/firestore_pipelines.field.md b/docs-devsite/firestore_pipelines.field.md index 058117f032..7e7d0f568f 100644 --- a/docs-devsite/firestore_pipelines.field.md +++ b/docs-devsite/firestore_pipelines.field.md @@ -88,7 +88,7 @@ selectable: true; Evaluates to the distance in meters between the location specified by this field and the query location. -This Expression can only be used within a `Search` stage. +This Expression can only be used within a `search` stage. Signature: diff --git a/docs-devsite/firestore_pipelines.md b/docs-devsite/firestore_pipelines.md index 1b2dce4ea0..2d99ab5908 100644 --- a/docs-devsite/firestore_pipelines.md +++ b/docs-devsite/firestore_pipelines.md @@ -483,7 +483,7 @@ https://github.com/firebase/firebase-js-sdk | [RemoveFieldsStageOptions](./firestore_pipelines.md#removefieldsstageoptions) | Options defining how a RemoveFieldsStage is evaluated. See [Pipeline.removeFields()](./firestore_pipelines.pipeline.md#pipelineremovefields). | | [ReplaceWithStageOptions](./firestore_pipelines.md#replacewithstageoptions) | Options defining how a ReplaceWithStage is evaluated. See [Pipeline.replaceWith()](./firestore_pipelines.pipeline.md#pipelinereplacewith). | | [SampleStageOptions](./firestore_pipelines.md#samplestageoptions) | Defines the options for evaluating a sample stage within a pipeline. This type combines common [StageOptions](./firestore_pipelines.md#stageoptions) with a specific configuration where only one of the defined sampling methods can be applied.See [Pipeline.sample()](./firestore_pipelines.pipeline.md#pipelinesample) to create a sample stage.. | -| [SearchStageOptions](./firestore_pipelines.md#searchstageoptions) | (Public Preview) Options defining how a SearchStage is evaluated. See . | +| [SearchStageOptions](./firestore_pipelines.md#searchstageoptions) | (Public Preview) Options defining how a search stage is evaluated. See [Pipeline.search()](./firestore_pipelines.pipeline.md#pipelinesearch). | | [SelectStageOptions](./firestore_pipelines.md#selectstageoptions) | Options defining how a SelectStage is evaluated. See [Pipeline.select()](./firestore_pipelines.pipeline.md#pipelineselect). | | [SetOptions](./firestore_pipelines.md#setoptions) | An options object that configures the behavior of [setDoc()](./firestore_lite.md#setdoc_ee215ad), and calls. These calls can be configured to perform granular merges instead of overwriting the target documents in their entirety by providing a SetOptions with merge: true. | | [SortStageOptions](./firestore_pipelines.md#sortstageoptions) | Options defining how a SortStage is evaluated. See [Pipeline.sort()](./firestore_pipelines.pipeline.md#pipelinesort). | @@ -605,7 +605,7 @@ rand(); Evaluates to the search score that reflects the topicality of the document to all of the text predicates (for example: `documentMatches`) in the search query. If `SearchOptions.query` is not set or does not contain any text predicates, then this topicality score will always be `0`. -This Expression can only be used within a `Search` stage. +This Expression can only be used within a `search` stage. Signature: @@ -6201,7 +6201,7 @@ A new [Expression](./firestore_pipelines.expression.md#expression_class) represe Evaluates to the distance in meters between the location in the specified field and the query location. -This Expression can only be used within a `Search` stage. +This Expression can only be used within a `search` stage. Signature: @@ -10417,7 +10417,7 @@ const results: PipelineResult[] = snapshot.results; Perform a full-text search on all indexed search fields in the document. -This Expression can only be used within a `Search` stage. +This Expression can only be used within a `search` stage. Signature: @@ -12309,14 +12309,18 @@ export declare type SampleStageOptions = StageOptions & OneOf<{ > This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. > -Options defining how a SearchStage is evaluated. See . +Options defining how a search stage is evaluated. See [Pipeline.search()](./firestore_pipelines.pipeline.md#pipelinesearch). Signature: ```typescript export declare type SearchStageOptions = StageOptions & { query: BooleanExpression | string; + languageCode?: string; + retrievalDepth?: number; sort?: Ordering | Ordering[]; + offset?: number; + limit?: number; addFields?: Selectable[]; }; ``` diff --git a/packages/firestore/src/lite-api/expressions.ts b/packages/firestore/src/lite-api/expressions.ts index 20c4426306..6652782a21 100644 --- a/packages/firestore/src/lite-api/expressions.ts +++ b/packages/firestore/src/lite-api/expressions.ts @@ -3456,7 +3456,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { // * Evaluates to an HTML-formatted text snippet that renders terms matching // * the search query in `bold`. // * - // * @remarks This Expression can only be used within a `Search` stage. + // * @remarks This Expression can only be used within a `search` stage. // * // * @param rquery Define the search query using the search domain-specific language (DSL). // */ @@ -3466,7 +3466,7 @@ export abstract class Expression implements ProtoValueSerializable, UserData { // * Evaluates to an HTML-formatted text snippet that renders terms matching // * the search query in `bold`. // * - // * @remarks This Expression can only be used within a `Search` stage. + // * @remarks This Expression can only be used within a `search` stage. // * // * @param options Define how snippeting behaves. // */ @@ -3795,7 +3795,7 @@ export class Field extends Expression implements Selectable { // /** // * Perform a full-text search on this field. // * - // * @remarks This Expression can only be used within a `Search` stage. + // * @remarks This Expression can only be used within a `search` stage. // * // * @param rquery Define the search query using the search domain-specific language (DSL). // */ @@ -3812,7 +3812,7 @@ export class Field extends Expression implements Selectable { * Evaluates to the distance in meters between the location specified * by this field and the query location. * - * @remarks This Expression can only be used within a `Search` stage. + * @remarks This Expression can only be used within a `search` stage. * * @param location - Compute distance to this GeoPoint. */ @@ -11649,7 +11649,7 @@ export function timestampExtract( // /** // * Perform a full-text search on the specified field. // * -// * @remarks This Expression can only be used within a `Search` stage. +// * @remarks This Expression can only be used within a `search` stage. // * // * @example // * ```typescript @@ -11672,7 +11672,7 @@ export function timestampExtract( * @beta * Perform a full-text search on all indexed search fields in the document. * - * @remarks This Expression can only be used within a `Search` stage. + * @remarks This Expression can only be used within a `search` stage. * * @example * ```typescript @@ -11709,7 +11709,7 @@ export function documentMatches( * }) * ``` * - * @remarks This Expression can only be used within a `Search` stage. + * @remarks This Expression can only be used within a `search` stage. */ export function score(): Expression { return new FunctionExpression('score', [], 'score'); @@ -11747,7 +11747,7 @@ export function score(): Expression { // * Evaluates to an HTML-formatted text snippet that highlights terms matching // * the search query in `bold`. // * -// * @remarks This Expression can only be used within a `Search` stage. +// * @remarks This Expression can only be used within a `search` stage. // * // * @example // * ```typescript @@ -11769,7 +11769,7 @@ export function score(): Expression { // * Evaluates to an HTML-formatted text snippet that highlights terms matching // * the search query in `bold`. // * -// * @remarks This Expression can only be used within a `Search` stage. +// * @remarks This Expression can only be used within a `search` stage. // * // * @param searchField Search the specified field for matching terms. // * @param options Define the search query using the search domain-specific language (DSL). @@ -11792,7 +11792,7 @@ export function score(): Expression { * Evaluates to the distance in meters between the location in the specified * field and the query location. * - * @remarks This Expression can only be used within a `Search` stage. + * @remarks This Expression can only be used within a `search` stage. * * @example * ```typescript diff --git a/packages/firestore/src/lite-api/stage_options.ts b/packages/firestore/src/lite-api/stage_options.ts index 692a3004d5..b9c3103307 100644 --- a/packages/firestore/src/lite-api/stage_options.ts +++ b/packages/firestore/src/lite-api/stage_options.ts @@ -270,7 +270,7 @@ export type QueryEnhancement = 'disabled' | 'required' | 'preferred'; /** * @beta - * Options defining how a SearchStage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(search)}. + * Options defining how a search stage is evaluated. See {@link @firebase/firestore/pipelines#Pipeline.(search:1)}. */ export type SearchStageOptions = StageOptions & { /** @@ -279,7 +279,7 @@ export type SearchStageOptions = StageOptions & { * * The query can be expressed as an `Expression`, which will be used to score * and filter the results. Not all expressions supported by Pipelines - * are supported in the Search query. + * are supported in the search query. * * @example * ```typescript @@ -291,13 +291,14 @@ export type SearchStageOptions = StageOptions & { * }) * ``` * - * The query can also be expressed as a string in the Search domain-specific language (DSL): + * The query can also be expressed as a string in the search domain-specific language (DSL), which will be used for searching the document. * * @example * ```typescript - * db.pipeline().collection('restaurants').search({ - * query: 'menu:(waffle and coffee) OR breakfast' - * }) + * db.pipeline().collection('restaurants').search({ query: 'breakfast -diner' }); + * + * // The above query is equivalent to: + * db.pipeline().collection('restaurants').search({ query: documentMatches('breakfast -diner') }); * ``` * * The query can also represent a geoDistance query: @@ -311,20 +312,19 @@ export type SearchStageOptions = StageOptions & { */ query: BooleanExpression | string; - // TODO(search) enable with backend support - // /** - // * The BCP-47 language code of text in the search query, such as, “en-US” or “sr-Latn” - // */ - // languageCode?: string; + /** + * The BCP-47 language code of text in the search query, such as “en” or “sr”. + */ + languageCode?: string; // TODO(search) add indexPartition after languageCode - // TODO(search) enable with backend support - // /** - // * The maximum number of documents to retrieve. Documents will be retrieved in the - // * pre-sort order specified by the search index. - // */ - // retrievalDepth?: number; + /** + * The maximum number of documents to retrieve from the search index. Documents will be retrieved in the + * pre-sort order specified by the search index. The `retrievalDepth` is a limit applied before documents + * are scored and sorted, which can reduce costs of expensive scoring and sorting operations. + */ + retrievalDepth?: number; /** * Orderings specify how the returned documents are sorted. @@ -332,17 +332,16 @@ export type SearchStageOptions = StageOptions & { */ sort?: Ordering | Ordering[]; - // TODO(search) enable with backend support - // /** - // * The number of documents to skip from the beginning of the search result set. - // */ - // offset?: number; + /** + * The number of documents to skip from the beginning of the search result set. + */ + offset?: number; - // TODO(search) enable with backend support - // /** - // * The maximum number of documents to return from the Search stage. - // */ - // limit?: number; + /** + * The maximum number of documents to return from the `search` stage. The `limit` is applied after documents + * are scored and sorted. + */ + limit?: number; // TODO(search) enable with backend support // /** diff --git a/packages/firestore/test/integration/api/pipeline.test.ts b/packages/firestore/test/integration/api/pipeline.test.ts index a620b66d07..93e1d7dc76 100644 --- a/packages/firestore/test/integration/api/pipeline.test.ts +++ b/packages/firestore/test/integration/api/pipeline.test.ts @@ -6962,7 +6962,7 @@ apiDescribe.skipClassic('Pipelines', persistence => { 1, async firestoreInstance => { firestore = firestoreInstance[0]; - restaurantsCollection = collection(firestore, 'SearchIntegrationTests'); + restaurantsCollection = collection(firestore, COLLECTION_NAME); await setupRestaurantDocs(restaurantsCollection); setupDeferred.resolve(); @@ -7299,70 +7299,102 @@ apiDescribe.skipClassic('Pipelines', persistence => { // }); }); - // TODO(search) enable with backend support - // describe('limit', () => { - // it('limits the number of documents returned', async () => { - // const ppl = firestore - // .pipeline() - // .collection(COLLECTION_NAME) - // .search({ - // query: constant(true), - // sort: field('location') - // .geoDistance(new GeoPoint(39.6985, -105.024)) - // .ascending(), - // limit: 5, - // queryEnhancement: 'disabled' - // }); - // - // const snapshot = await execute(ppl); - // expectResults( - // snapshot, - // 'solTacos', - // 'lotusBlossomThai', - // 'goldenWaffle' - // ); - // }); - // - // it('limits the number of documents scored', async () => { - // const ppl = firestore - // .pipeline() - // .collection(COLLECTION_NAME) - // .search({ - // query: field('menu').matches( - // 'chicken OR tacos OR fish OR waffles' - // ), - // retrievalDepth: 6, - // queryEnhancement: 'disabled' - // }); - // - // const snapshot = await execute(ppl); - // expectResults( - // snapshot, - // 'eastsideChicken', - // 'eastsideTacos', - // 'solTacos', - // 'mileHighCatch' - // ); - // }); - // }); + describe('languageCode', () => { + const rquery = 'al pastor'; + it('en', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: documentMatches(rquery), + sort: score().descending(), + languageCode: 'en' + // queryEnhancement: 'disabled' + }); - // TODO(search) enable with backend support - // describe('offset', () => { - // it('skips N documents', async () => { - // const ppl = firestore - // .pipeline() - // .collection(COLLECTION_NAME) - // .search({ - // query: constant(true), - // limit: 2, - // offset: 2, - // queryEnhancement: 'disabled' - // }); - // - // const snapshot = await execute(ppl); - // expectResults(snapshot, 'eastsideChicken', 'eastsideTacos'); - // }); - // }); + const snapshot = await execute(ppl); + expectResults(snapshot, 'solTacos'); + }); + + it('unknown', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: documentMatches(rquery), + sort: score().descending(), + languageCode: 'unknown' + // queryEnhancement: 'disabled' + }); + + await expect(execute(ppl)).to.be.rejectedWith(/3 INVALID_ARGUMENT.*/); + }); + }); + + describe('limit', () => { + it('limits the number of documents returned', async () => { + const ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ + query: field('location') + .geoDistance(new GeoPoint(39.6985, -105.024)) + .lessThanOrEqual(100000000), + sort: field('location') + .geoDistance(new GeoPoint(39.6985, -105.024)) + .ascending(), + limit: 3 + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults( + snapshot, + 'solTacos', + 'lotusBlossomThai', + 'mileHighCatch' + ); + }); + + it('limits the number of documents scored via retrievalDepth', async () => { + const commonSearchParams = { + query: documentMatches('taco'), + addFields: [score().as('score')], + sort: score().descending() + // queryEnhancement: 'disabled' as QueryEnhancement + }; + + let ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ ...commonSearchParams, retrievalDepth: 2 }); + + let snapshot = await execute(ppl); + expectResults(snapshot, 'solTacos', 'eastsideTacos'); + + ppl = firestore + .pipeline() + .collection(COLLECTION_NAME) + .search({ ...commonSearchParams, retrievalDepth: 1 }); + + snapshot = await execute(ppl); + expectResults(snapshot, 'eastsideTacos'); + }); + }); + + describe('offset', () => { + it('skips N documents', async () => { + const ppl = firestore.pipeline().collection(COLLECTION_NAME).search({ + query: 'chicken', + limit: 2, + offset: 2 + // queryEnhancement: 'disabled' + }); + + const snapshot = await execute(ppl); + expectResults(snapshot, 'goldenWaffle'); + }); + }); }); // TODO(search) enable with backend support From 62ae2e203aa1720aa192967340f70f2872c8442e Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 29 Apr 2026 13:05:59 -0700 Subject: [PATCH 165/174] chore: Update picomatch and rollup-plugin-typescript2 (#9892) * build(deps): bump picomatch from 2.3.1 to 2.3.2 Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2. - [Release notes](https://github.com/micromatch/picomatch/releases) - [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2) --- updated-dependencies: - dependency-name: picomatch dependency-version: 2.3.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] * Upgrade picomatch and rollup-plugin-typescript2 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/ai/package.json | 2 +- packages/analytics-compat/package.json | 2 +- packages/analytics/package.json | 2 +- packages/app-check-compat/package.json | 2 +- packages/app-check/package.json | 2 +- packages/app-compat/package.json | 2 +- packages/app/package.json | 2 +- packages/auth-compat/package.json | 2 +- packages/auth/package.json | 2 +- packages/component/package.json | 2 +- packages/data-connect/package.json | 2 +- packages/database/package.json | 2 +- packages/firebase/package.json | 2 +- packages/firestore-compat/package.json | 2 +- packages/firestore/package.json | 2 +- packages/functions-compat/package.json | 2 +- packages/functions/package.json | 2 +- packages/installations-compat/package.json | 2 +- packages/installations/package.json | 2 +- packages/logger/package.json | 2 +- packages/messaging-compat/package.json | 2 +- packages/messaging/package.json | 2 +- packages/performance-compat/package.json | 2 +- packages/performance/package.json | 2 +- packages/remote-config-compat/package.json | 2 +- packages/remote-config/package.json | 2 +- packages/rules-unit-testing/package.json | 2 +- packages/storage-compat/package.json | 2 +- packages/storage/package.json | 2 +- packages/template/package.json | 2 +- packages/util/package.json | 2 +- packages/webchannel-wrapper/package.json | 2 +- repo-scripts/size-analysis/package.json | 2 +- yarn.lock | 20 ++++++++++---------- 34 files changed, 43 insertions(+), 43 deletions(-) diff --git a/packages/ai/package.json b/packages/ai/package.json index d9139a3369..b493a76123 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -64,7 +64,7 @@ "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/analytics-compat/package.json b/packages/analytics-compat/package.json index 22683f75d3..12fe60bc0d 100644 --- a/packages/analytics-compat/package.json +++ b/packages/analytics-compat/package.json @@ -25,7 +25,7 @@ "@firebase/app-compat": "0.5.11", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/analytics/package.json b/packages/analytics/package.json index c6b9eb35ad..814e291e94 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -53,7 +53,7 @@ "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-node-resolve": "16.0.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/app-check-compat/package.json b/packages/app-check-compat/package.json index aee72f1914..c039efc4ca 100644 --- a/packages/app-check-compat/package.json +++ b/packages/app-check-compat/package.json @@ -48,7 +48,7 @@ "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-node-resolve": "16.0.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/app-check/package.json b/packages/app-check/package.json index 7ed374f48a..10a9e31317 100644 --- a/packages/app-check/package.json +++ b/packages/app-check/package.json @@ -49,7 +49,7 @@ "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-node-resolve": "16.0.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/app-compat/package.json b/packages/app-compat/package.json index c281a6fc90..5d76faf837 100644 --- a/packages/app-compat/package.json +++ b/packages/app-compat/package.json @@ -47,7 +47,7 @@ "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-replace": "2.2.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/app/package.json b/packages/app/package.json index b5c33c970c..d39539ed5e 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -50,7 +50,7 @@ "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "rollup-plugin-dts": "5.3.1", "typescript": "5.5.4" }, diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index e31b7a4db4..5a4cfa7274 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -61,7 +61,7 @@ "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "selenium-webdriver": "4.30.0", "typescript": "5.5.4" }, diff --git a/packages/auth/package.json b/packages/auth/package.json index 66dc2265ad..24f7c8208d 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -139,7 +139,7 @@ "cookie-store": "4.0.0-next.4", "rollup": "2.79.2", "rollup-plugin-sourcemaps": "0.6.3", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "selenium-webdriver": "4.30.0", "totp-generator": "0.0.14", "typescript": "5.5.4" diff --git a/packages/component/package.json b/packages/component/package.json index 756501e1ac..e7e50b053b 100644 --- a/packages/component/package.json +++ b/packages/component/package.json @@ -37,7 +37,7 @@ "license": "Apache-2.0", "devDependencies": { "rollup": "2.79.2", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/data-connect/package.json b/packages/data-connect/package.json index 93903d9621..7d5c032042 100644 --- a/packages/data-connect/package.json +++ b/packages/data-connect/package.json @@ -57,7 +57,7 @@ "devDependencies": { "@firebase/app": "0.14.11", "rollup": "2.79.2", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/database/package.json b/packages/database/package.json index 3190989e7e..a35f543cbd 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -59,7 +59,7 @@ "devDependencies": { "@firebase/app": "0.14.11", "rollup": "2.79.2", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/firebase/package.json b/packages/firebase/package.json index 6e0bc7ee03..4df75322fd 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -458,7 +458,7 @@ "@rollup/plugin-node-resolve": "16.0.0", "rollup-plugin-sourcemaps": "0.6.3", "@rollup/plugin-terser": "0.4.4", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "rollup-plugin-uglify": "6.0.4", "gulp": "4.0.2", "gulp-sourcemaps": "3.0.0", diff --git a/packages/firestore-compat/package.json b/packages/firestore-compat/package.json index 60c80ef212..dd2a17d6a0 100644 --- a/packages/firestore-compat/package.json +++ b/packages/firestore-compat/package.json @@ -58,7 +58,7 @@ "rollup": "2.79.2", "rollup-plugin-sourcemaps": "0.6.3", "@rollup/plugin-terser": "0.4.4", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "@rollup/plugin-node-resolve": "16.0.0", "ts-node": "10.9.2", "typescript": "5.5.4" diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 485e99abb6..d43056bb97 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -162,7 +162,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-sourcemaps": "0.6.3", "@rollup/plugin-terser": "0.4.4", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "rollup-plugin-dts": "5.3.1", "ts-node": "10.9.2", "typescript": "5.5.4" diff --git a/packages/functions-compat/package.json b/packages/functions-compat/package.json index 41b0407eba..d3674b32b4 100644 --- a/packages/functions-compat/package.json +++ b/packages/functions-compat/package.json @@ -32,7 +32,7 @@ "@firebase/app-compat": "0.5.11", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/functions/package.json b/packages/functions/package.json index 46d506eb08..f4f29be0d4 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -52,7 +52,7 @@ "@firebase/app": "0.14.11", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/installations-compat/package.json b/packages/installations-compat/package.json index 61f2ca699d..e3ffab8932 100644 --- a/packages/installations-compat/package.json +++ b/packages/installations-compat/package.json @@ -49,7 +49,7 @@ "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-node-resolve": "16.0.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "rollup-plugin-uglify": "6.0.4", "typescript": "5.5.4" }, diff --git a/packages/installations/package.json b/packages/installations/package.json index ab128fb773..067c1bcc28 100644 --- a/packages/installations/package.json +++ b/packages/installations/package.json @@ -54,7 +54,7 @@ "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-node-resolve": "16.0.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "rollup-plugin-uglify": "6.0.4", "typescript": "5.5.4" }, diff --git a/packages/logger/package.json b/packages/logger/package.json index f44fa21d52..6a2c456430 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -36,7 +36,7 @@ }, "devDependencies": { "rollup": "2.79.2", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/messaging-compat/package.json b/packages/messaging-compat/package.json index 42ca7f159e..706b946366 100644 --- a/packages/messaging-compat/package.json +++ b/packages/messaging-compat/package.json @@ -46,7 +46,7 @@ "devDependencies": { "@firebase/app-compat": "0.5.11", "@rollup/plugin-json": "6.1.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "ts-essentials": "9.4.2", "typescript": "5.5.4" }, diff --git a/packages/messaging/package.json b/packages/messaging/package.json index 7527654c39..92b668832c 100644 --- a/packages/messaging/package.json +++ b/packages/messaging/package.json @@ -62,7 +62,7 @@ "devDependencies": { "@firebase/app": "0.14.11", "rollup": "2.79.2", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "@rollup/plugin-json": "6.1.0", "ts-essentials": "10.0.4", "typescript": "5.5.4" diff --git a/packages/performance-compat/package.json b/packages/performance-compat/package.json index 4115734915..94b3759a1b 100644 --- a/packages/performance-compat/package.json +++ b/packages/performance-compat/package.json @@ -49,7 +49,7 @@ "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-replace": "2.2.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4", "@firebase/app-compat": "0.5.11" }, diff --git a/packages/performance/package.json b/packages/performance/package.json index f2834a9978..ba8ea4e5a8 100644 --- a/packages/performance/package.json +++ b/packages/performance/package.json @@ -50,7 +50,7 @@ "@firebase/app": "0.14.11", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/remote-config-compat/package.json b/packages/remote-config-compat/package.json index c302dac56e..08548831f8 100644 --- a/packages/remote-config-compat/package.json +++ b/packages/remote-config-compat/package.json @@ -48,7 +48,7 @@ "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-replace": "2.2.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4", "@firebase/app-compat": "0.5.11" }, diff --git a/packages/remote-config/package.json b/packages/remote-config/package.json index fc9ce1379f..7383bbc6dc 100644 --- a/packages/remote-config/package.json +++ b/packages/remote-config/package.json @@ -51,7 +51,7 @@ "@firebase/app": "0.14.11", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/rules-unit-testing/package.json b/packages/rules-unit-testing/package.json index 68657c9cac..227ebf78e4 100644 --- a/packages/rules-unit-testing/package.json +++ b/packages/rules-unit-testing/package.json @@ -40,7 +40,7 @@ "license": "Apache-2.0", "devDependencies": { "rollup": "2.79.2", - "rollup-plugin-typescript2": "0.36.0" + "rollup-plugin-typescript2": "0.37.0" }, "peerDependencies": { "firebase": "^12.0.0" diff --git a/packages/storage-compat/package.json b/packages/storage-compat/package.json index 297cbaa47b..7547dff221 100644 --- a/packages/storage-compat/package.json +++ b/packages/storage-compat/package.json @@ -48,7 +48,7 @@ "@firebase/auth-compat": "0.6.5", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "files": [ diff --git a/packages/storage/package.json b/packages/storage/package.json index 3f0a04b29c..1701d95fea 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -59,7 +59,7 @@ "rollup": "2.79.2", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/template/package.json b/packages/template/package.json index d60f1f8351..6547c8dd2b 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -50,7 +50,7 @@ "devDependencies": { "@firebase/app": "0.14.11", "rollup": "2.79.2", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/util/package.json b/packages/util/package.json index 4ac6664275..fee8b99879 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -49,7 +49,7 @@ "devDependencies": { "@rollup/plugin-replace": "6.0.2", "rollup": "2.79.2", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/packages/webchannel-wrapper/package.json b/packages/webchannel-wrapper/package.json index bddf3cec8e..65171a58c8 100644 --- a/packages/webchannel-wrapper/package.json +++ b/packages/webchannel-wrapper/package.json @@ -36,7 +36,7 @@ "rollup": "2.79.2", "rollup-plugin-copy": "3.5.0", "rollup-plugin-sourcemaps": "0.6.3", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" }, "repository": { diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index e8c6adc582..ee251ac298 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -31,7 +31,7 @@ "memfs": "4.57.2", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", - "rollup-plugin-typescript2": "0.36.0", + "rollup-plugin-typescript2": "0.37.0", "terser": "5.37.0", "tmp": "0.2.4", "typescript": "5.5.4", diff --git a/yarn.lock b/yarn.lock index 1f9e54c043..83f738e592 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13600,14 +13600,14 @@ picocolors@^1.0.0, picocolors@^1.1.0, picocolors@^1.1.1: integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + version "2.3.2" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601" + integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + version "4.0.4" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589" + integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== pidtree@^0.5.0: version "0.5.0" @@ -14789,10 +14789,10 @@ rollup-plugin-sourcemaps@0.6.3: "@rollup/pluginutils" "^3.0.9" source-map-resolve "^0.6.0" -rollup-plugin-typescript2@0.36.0: - version "0.36.0" - resolved "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.36.0.tgz#309564eb70d710412f5901344ca92045e180ed53" - integrity sha512-NB2CSQDxSe9+Oe2ahZbf+B4bh7pHwjV5L+RSYpCu7Q5ROuN94F9b6ioWwKfz3ueL3KTtmX4o2MUH2cgHDIEUsw== +rollup-plugin-typescript2@0.37.0: + version "0.37.0" + resolved "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.37.0.tgz#7e244d7d0e321673a43bc723b6d0c81789627c4e" + integrity sha512-S1r/4Ufi13Yg/chPlh4iSHWq2Zs/sIAodW5SKUoCQfy/DEQhkS2XRFEtv+NRq3iBO4WHHfqKtDPOC5lJTYm7OQ== dependencies: "@rollup/pluginutils" "^4.1.2" find-cache-dir "^3.3.2" From 86dc0db9218d9ae52282d595007fc60b40c98b6e Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Wed, 29 Apr 2026 13:28:51 -0700 Subject: [PATCH 166/174] feat(ai): ImageConfig and FinishReasons (#9819) --- .changeset/pb-add-image-config.md | 7 ++ common/api-review/ai.api.md | 49 ++++++++++ docs-devsite/_toc.yaml | 2 + docs-devsite/ai.generationconfig.md | 11 +++ docs-devsite/ai.imageconfig.md | 46 ++++++++++ docs-devsite/ai.md | 75 ++++++++++++++++ .../ai/src/models/generative-model.test.ts | 20 ++++- packages/ai/src/requests/response-helpers.ts | 19 +++- packages/ai/src/types/enums.ts | 90 ++++++++++++++++++- packages/ai/src/types/requests.ts | 22 +++++ 10 files changed, 338 insertions(+), 3 deletions(-) create mode 100644 .changeset/pb-add-image-config.md create mode 100644 docs-devsite/ai.imageconfig.md diff --git a/.changeset/pb-add-image-config.md b/.changeset/pb-add-image-config.md new file mode 100644 index 0000000000..13a393deff --- /dev/null +++ b/.changeset/pb-add-image-config.md @@ -0,0 +1,7 @@ +--- +"@firebase/ai": minor +"firebase": minor +--- + +Added support for `ImageConfig` (aspect ratio and size). +Expanded `FinishReason` values to include all currently available values provided by the models. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index faa099c0ab..6bf410c441 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -396,6 +396,16 @@ export const FinishReason: { readonly PROHIBITED_CONTENT: "PROHIBITED_CONTENT"; readonly SPII: "SPII"; readonly MALFORMED_FUNCTION_CALL: "MALFORMED_FUNCTION_CALL"; + readonly IMAGE_SAFETY: "IMAGE_SAFETY"; + readonly IMAGE_PROHIBITED_CONTENT: "IMAGE_PROHIBITED_CONTENT"; + readonly IMAGE_OTHER: "IMAGE_OTHER"; + readonly NO_IMAGE: "NO_IMAGE"; + readonly IMAGE_RECITATION: "IMAGE_RECITATION"; + readonly LANGUAGE: "LANGUAGE"; + readonly UNEXPECTED_TOOL_CALL: "UNEXPECTED_TOOL_CALL"; + readonly TOO_MANY_TOOL_CALLS: "TOO_MANY_TOOL_CALLS"; + readonly MISSING_THOUGHT_SIGNATURE: "MISSING_THOUGHT_SIGNATURE"; + readonly MALFORMED_RESPONSE: "MALFORMED_RESPONSE"; }; // @public @@ -554,6 +564,7 @@ export interface GenerationConfig { candidateCount?: number; // (undocumented) frequencyPenalty?: number; + imageConfig?: ImageConfig; // (undocumented) maxOutputTokens?: number; // (undocumented) @@ -803,6 +814,44 @@ export interface HybridParams { onDeviceParams?: OnDeviceParams; } +// @public +export interface ImageConfig { + aspectRatio?: ImageConfigAspectRatio; + imageSize?: ImageConfigImageSize; +} + +// @public +export const ImageConfigAspectRatio: { + readonly SQUARE_1x1: "1:1"; + readonly PORTRAIT_9x16: "9:16"; + readonly LANDSCAPE_16x9: "16:9"; + readonly PORTRAIT_3x4: "3:4"; + readonly LANDSCAPE_4x3: "4:3"; + readonly PORTRAIT_2x3: "2:3"; + readonly LANDSCAPE_3x2: "3:2"; + readonly PORTRAIT_4x5: "4:5"; + readonly LANDSCAPE_5x4: "5:4"; + readonly PORTRAIT_1x4: "1:4"; + readonly LANDSCAPE_4x1: "4:1"; + readonly PORTRAIT_1x8: "1:8"; + readonly LANDSCAPE_8x1: "8:1"; + readonly ULTRAWIDE_21x9: "21:9"; +}; + +// @public +export type ImageConfigAspectRatio = (typeof ImageConfigAspectRatio)[keyof typeof ImageConfigAspectRatio]; + +// @public +export const ImageConfigImageSize: { + readonly SIZE_512: "512"; + readonly SIZE_1K: "1K"; + readonly SIZE_2K: "2K"; + readonly SIZE_4K: "4K"; +}; + +// @public +export type ImageConfigImageSize = (typeof ImageConfigImageSize)[keyof typeof ImageConfigImageSize]; + // @public @deprecated export const ImagenAspectRatio: { readonly SQUARE: "1:1"; diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index 08bf93197d..d7fd3af1b6 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -116,6 +116,8 @@ toc: path: /docs/reference/js/ai.groundingsupport.md - title: HybridParams path: /docs/reference/js/ai.hybridparams.md + - title: ImageConfig + path: /docs/reference/js/ai.imageconfig.md - title: ImagenGCSImage path: /docs/reference/js/ai.imagengcsimage.md - title: ImagenGenerationConfig diff --git a/docs-devsite/ai.generationconfig.md b/docs-devsite/ai.generationconfig.md index fbf39f1f15..4878203f9d 100644 --- a/docs-devsite/ai.generationconfig.md +++ b/docs-devsite/ai.generationconfig.md @@ -24,6 +24,7 @@ export interface GenerationConfig | --- | --- | --- | | [candidateCount](./ai.generationconfig.md#generationconfigcandidatecount) | number | | | [frequencyPenalty](./ai.generationconfig.md#generationconfigfrequencypenalty) | number | | +| [imageConfig](./ai.generationconfig.md#generationconfigimageconfig) | [ImageConfig](./ai.imageconfig.md#imageconfig_interface) | Configuration options for generating images with Gemini models. | | [maxOutputTokens](./ai.generationconfig.md#generationconfigmaxoutputtokens) | number | | | [presencePenalty](./ai.generationconfig.md#generationconfigpresencepenalty) | number | | | [responseJsonSchema](./ai.generationconfig.md#generationconfigresponsejsonschema) | { \[key: string\]: unknown; } | Output schema of the generated response. This is an alternative to responseSchema that accepts \[JSON Schema\](https://json-schema.org/).If set, responseSchema must be omitted, but responseMimeType is required and must be set to application/json. | @@ -52,6 +53,16 @@ candidateCount?: number; frequencyPenalty?: number; ``` +## GenerationConfig.imageConfig + +Configuration options for generating images with Gemini models. + +Signature: + +```typescript +imageConfig?: ImageConfig; +``` + ## GenerationConfig.maxOutputTokens Signature: diff --git a/docs-devsite/ai.imageconfig.md b/docs-devsite/ai.imageconfig.md new file mode 100644 index 0000000000..b6bd50e718 --- /dev/null +++ b/docs-devsite/ai.imageconfig.md @@ -0,0 +1,46 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# ImageConfig interface +Configuration options for generating images with Gemini models. + +Signature: + +```typescript +export interface ImageConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [aspectRatio](./ai.imageconfig.md#imageconfigaspectratio) | [ImageConfigAspectRatio](./ai.md#imageconfigaspectratio) | The aspect ratio of generated images. | +| [imageSize](./ai.imageconfig.md#imageconfigimagesize) | [ImageConfigImageSize](./ai.md#imageconfigimagesize) | The size of the generated images. | + +## ImageConfig.aspectRatio + +The aspect ratio of generated images. + +Signature: + +```typescript +aspectRatio?: ImageConfigAspectRatio; +``` + +## ImageConfig.imageSize + +The size of the generated images. + +Signature: + +```typescript +imageSize?: ImageConfigImageSize; +``` diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index 53d9ad65ce..675cf20271 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -104,6 +104,7 @@ The Firebase AI Web SDK. | [GroundingMetadata](./ai.groundingmetadata.md#groundingmetadata_interface) | Metadata returned when grounding is enabled.Currently, only Grounding with Google Search and Grounding with Google Maps are supported (see [GoogleSearchTool](./ai.googlesearchtool.md#googlesearchtool_interface) and [GoogleMapsTool](./ai.googlemapstool.md#googlemapstool_interface), respectively).Important: If using Grounding with Google Search, you are required to comply with the "Grounding with Google Search" usage requirements for your chosen API provider: [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-search) or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section within the Service Specific Terms).Important: If using Grounding with Google Maps, you are required to comply with the "Grounding with Google Maps" usage requirements for your chosen API provider: [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-maps) or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) section within the Service Specific Terms). | | [GroundingSupport](./ai.groundingsupport.md#groundingsupport_interface) | Provides information about how a specific segment of the model's response is supported by the retrieved grounding chunks. | | [HybridParams](./ai.hybridparams.md#hybridparams_interface) | (Public Preview) Configures hybrid inference. | +| [ImageConfig](./ai.imageconfig.md#imageconfig_interface) | Configuration options for generating images with Gemini models. | | [ImagenGCSImage](./ai.imagengcsimage.md#imagengcsimage_interface) | An image generated by Imagen, stored in a Cloud Storage for Firebase bucket.This feature is not available yet. | | [ImagenGenerationConfig](./ai.imagengenerationconfig.md#imagengenerationconfig_interface) | Configuration options for generating images with Imagen.See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images-imagen) for more details. | | [ImagenGenerationResponse](./ai.imagengenerationresponse.md#imagengenerationresponse_interface) | The response from a request to generate images with Imagen. | @@ -181,6 +182,8 @@ The Firebase AI Web SDK. | [HarmCategory](./ai.md#harmcategory) | Harm categories that would cause prompts or candidates to be blocked. | | [HarmProbability](./ai.md#harmprobability) | Probability that a prompt or candidate matches a harm category. | | [HarmSeverity](./ai.md#harmseverity) | Harm severity levels. | +| [ImageConfigAspectRatio](./ai.md#imageconfigaspectratio) | Aspect ratios for generated images. | +| [ImageConfigImageSize](./ai.md#imageconfigimagesize) | Sizes for generated images. For example, '1K' is 1024px, '2K' is 2048px, and '4K' is 4096px. | | [ImagenAspectRatio](./ai.md#imagenaspectratio) | Aspect ratios for Imagen images.To specify an aspect ratio for generated images, set the aspectRatio property in your [ImagenGenerationConfig](./ai.imagengenerationconfig.md#imagengenerationconfig_interface).See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) for more details and examples of the supported aspect ratios. | | [ImagenPersonFilterLevel](./ai.md#imagenpersonfilterlevel) | A filter level controlling whether generation of images containing people or faces is allowed.See the personGeneration documentation for more details. | | [ImagenSafetyFilterLevel](./ai.md#imagensafetyfilterlevel) | A filter level controlling how aggressively to filter sensitive content.Text prompts provided as inputs and images (generated or uploaded) through Imagen on Vertex AI are assessed against a list of safety filters, which include 'harmful categories' (for example, violence, sexual, derogatory, and toxic). This filter level controls how aggressively to filter out potentially harmful content from responses. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) and the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters) for more details. | @@ -210,6 +213,8 @@ The Firebase AI Web SDK. | [HarmCategory](./ai.md#harmcategory) | Harm categories that would cause prompts or candidates to be blocked. | | [HarmProbability](./ai.md#harmprobability) | Probability that a prompt or candidate matches a harm category. | | [HarmSeverity](./ai.md#harmseverity) | Harm severity levels. | +| [ImageConfigAspectRatio](./ai.md#imageconfigaspectratio) | Aspect ratios for generated images. | +| [ImageConfigImageSize](./ai.md#imageconfigimagesize) | Sizes for generated images. | | [ImagenAspectRatio](./ai.md#imagenaspectratio) | Aspect ratios for Imagen images.To specify an aspect ratio for generated images, set the aspectRatio property in your [ImagenGenerationConfig](./ai.imagengenerationconfig.md#imagengenerationconfig_interface).See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) for more details and examples of the supported aspect ratios. | | [ImagenPersonFilterLevel](./ai.md#imagenpersonfilterlevel) | A filter level controlling whether generation of images containing people or faces is allowed.See the personGeneration documentation for more details. | | [ImagenSafetyFilterLevel](./ai.md#imagensafetyfilterlevel) | A filter level controlling how aggressively to filter sensitive content.Text prompts provided as inputs and images (generated or uploaded) through Imagen on Vertex AI are assessed against a list of safety filters, which include 'harmful categories' (for example, violence, sexual, derogatory, and toxic). This filter level controls how aggressively to filter out potentially harmful content from responses. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) and the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters) for more details. | @@ -562,6 +567,16 @@ FinishReason: { readonly PROHIBITED_CONTENT: "PROHIBITED_CONTENT"; readonly SPII: "SPII"; readonly MALFORMED_FUNCTION_CALL: "MALFORMED_FUNCTION_CALL"; + readonly IMAGE_SAFETY: "IMAGE_SAFETY"; + readonly IMAGE_PROHIBITED_CONTENT: "IMAGE_PROHIBITED_CONTENT"; + readonly IMAGE_OTHER: "IMAGE_OTHER"; + readonly NO_IMAGE: "NO_IMAGE"; + readonly IMAGE_RECITATION: "IMAGE_RECITATION"; + readonly LANGUAGE: "LANGUAGE"; + readonly UNEXPECTED_TOOL_CALL: "UNEXPECTED_TOOL_CALL"; + readonly TOO_MANY_TOOL_CALLS: "TOO_MANY_TOOL_CALLS"; + readonly MISSING_THOUGHT_SIGNATURE: "MISSING_THOUGHT_SIGNATURE"; + readonly MALFORMED_RESPONSE: "MALFORMED_RESPONSE"; } ``` @@ -653,6 +668,46 @@ HarmSeverity: { } ``` +## ImageConfigAspectRatio + +Aspect ratios for generated images. + +Signature: + +```typescript +ImageConfigAspectRatio: { + readonly SQUARE_1x1: "1:1"; + readonly PORTRAIT_9x16: "9:16"; + readonly LANDSCAPE_16x9: "16:9"; + readonly PORTRAIT_3x4: "3:4"; + readonly LANDSCAPE_4x3: "4:3"; + readonly PORTRAIT_2x3: "2:3"; + readonly LANDSCAPE_3x2: "3:2"; + readonly PORTRAIT_4x5: "4:5"; + readonly LANDSCAPE_5x4: "5:4"; + readonly PORTRAIT_1x4: "1:4"; + readonly LANDSCAPE_4x1: "4:1"; + readonly PORTRAIT_1x8: "1:8"; + readonly LANDSCAPE_8x1: "8:1"; + readonly ULTRAWIDE_21x9: "21:9"; +} +``` + +## ImageConfigImageSize + +Sizes for generated images. For example, '1K' is 1024px, '2K' is 2048px, and '4K' is 4096px. + +Signature: + +```typescript +ImageConfigImageSize: { + readonly SIZE_512: "512"; + readonly SIZE_1K: "1K"; + readonly SIZE_2K: "2K"; + readonly SIZE_4K: "4K"; +} +``` + ## ImagenAspectRatio > Warning: This API is now obsolete. @@ -997,6 +1052,26 @@ Harm severity levels. export type HarmSeverity = (typeof HarmSeverity)[keyof typeof HarmSeverity]; ``` +## ImageConfigAspectRatio + +Aspect ratios for generated images. + +Signature: + +```typescript +export type ImageConfigAspectRatio = (typeof ImageConfigAspectRatio)[keyof typeof ImageConfigAspectRatio]; +``` + +## ImageConfigImageSize + +Sizes for generated images. + +Signature: + +```typescript +export type ImageConfigImageSize = (typeof ImageConfigImageSize)[keyof typeof ImageConfigImageSize]; +``` + ## ImagenAspectRatio > Warning: This API is now obsolete. diff --git a/packages/ai/src/models/generative-model.test.ts b/packages/ai/src/models/generative-model.test.ts index f11a24b66f..c4eb21d070 100644 --- a/packages/ai/src/models/generative-model.test.ts +++ b/packages/ai/src/models/generative-model.test.ts @@ -22,7 +22,9 @@ import { InferenceMode, AIErrorCode, ChromeAdapter, - ThinkingLevel + ThinkingLevel, + ImageConfigAspectRatio, + ImageConfigImageSize } from '../public-types'; import * as request from '../requests/request'; import { SinonStub, match, restore, stub } from 'sinon'; @@ -322,6 +324,22 @@ describe('GenerativeModel', () => { }); restore(); }); + it('passes imageConfig through to ChatSession', () => { + const genModel = new GenerativeModel(fakeAI, { + model: 'my-model', + generationConfig: { + imageConfig: { + aspectRatio: ImageConfigAspectRatio.SQUARE_1x1, + imageSize: ImageConfigImageSize.SIZE_512 + } + } + }); + const chatSession = genModel.startChat(); + expect(chatSession.params?.generationConfig?.imageConfig).to.deep.equal({ + aspectRatio: '1:1', + imageSize: '512' + }); + }); it('overrides base model params with startChatParams', () => { const genModel = new GenerativeModel(fakeAI, { model: 'my-model', diff --git a/packages/ai/src/requests/response-helpers.ts b/packages/ai/src/requests/response-helpers.ts index 34d2013007..c6d5ead085 100644 --- a/packages/ai/src/requests/response-helpers.ts +++ b/packages/ai/src/requests/response-helpers.ts @@ -229,7 +229,24 @@ export function getInlineDataParts( } } -const badFinishReasons = [FinishReason.RECITATION, FinishReason.SAFETY]; +const badFinishReasons = [ + FinishReason.RECITATION, + FinishReason.SAFETY, + FinishReason.BLOCKLIST, + FinishReason.PROHIBITED_CONTENT, + FinishReason.SPII, + FinishReason.MALFORMED_FUNCTION_CALL, + FinishReason.IMAGE_SAFETY, + FinishReason.IMAGE_PROHIBITED_CONTENT, + FinishReason.IMAGE_OTHER, + FinishReason.NO_IMAGE, + FinishReason.IMAGE_RECITATION, + FinishReason.LANGUAGE, + FinishReason.UNEXPECTED_TOOL_CALL, + FinishReason.TOO_MANY_TOOL_CALLS, + FinishReason.MISSING_THOUGHT_SIGNATURE, + FinishReason.MALFORMED_RESPONSE +]; function hadBadFinishReason(candidate: GenerateContentCandidate): boolean { return ( diff --git a/packages/ai/src/types/enums.ts b/packages/ai/src/types/enums.ts index 30b10138af..60f9071c7f 100644 --- a/packages/ai/src/types/enums.ts +++ b/packages/ai/src/types/enums.ts @@ -238,7 +238,47 @@ export const FinishReason = { /** * The function call generated by the model was invalid. */ - MALFORMED_FUNCTION_CALL: 'MALFORMED_FUNCTION_CALL' + MALFORMED_FUNCTION_CALL: 'MALFORMED_FUNCTION_CALL', + /** + * Token generation stopped because generated images contain safety violations. + */ + IMAGE_SAFETY: 'IMAGE_SAFETY', + /** + * Image generation stopped because generated images have other prohibited content. + */ + IMAGE_PROHIBITED_CONTENT: 'IMAGE_PROHIBITED_CONTENT', + /** + * Image generation stopped because of other miscellaneous issue. + */ + IMAGE_OTHER: 'IMAGE_OTHER', + /** + * The model was expected to generate an image, but none was generated. + */ + NO_IMAGE: 'NO_IMAGE', + /** + * Image generation stopped due to recitation. + */ + IMAGE_RECITATION: 'IMAGE_RECITATION', + /** + * The response candidate content was flagged for using an unsupported language. + */ + LANGUAGE: 'LANGUAGE', + /** + * Model generated a tool call but no tools were enabled in the request. + */ + UNEXPECTED_TOOL_CALL: 'UNEXPECTED_TOOL_CALL', + /** + * Model called too many tools consecutively, thus the system exited execution. + */ + TOO_MANY_TOOL_CALLS: 'TOO_MANY_TOOL_CALLS', + /** + * Request has at least one thought signature missing. + */ + MISSING_THOUGHT_SIGNATURE: 'MISSING_THOUGHT_SIGNATURE', + /** + * Finished due to malformed response. + */ + MALFORMED_RESPONSE: 'MALFORMED_RESPONSE' } as const; /** @@ -247,6 +287,54 @@ export const FinishReason = { */ export type FinishReason = (typeof FinishReason)[keyof typeof FinishReason]; +/** + * Aspect ratios for generated images. + * @public + */ +/* eslint-disable camelcase */ +export const ImageConfigAspectRatio = { + SQUARE_1x1: '1:1', + PORTRAIT_9x16: '9:16', + LANDSCAPE_16x9: '16:9', + PORTRAIT_3x4: '3:4', + LANDSCAPE_4x3: '4:3', + PORTRAIT_2x3: '2:3', + LANDSCAPE_3x2: '3:2', + PORTRAIT_4x5: '4:5', + LANDSCAPE_5x4: '5:4', + PORTRAIT_1x4: '1:4', + LANDSCAPE_4x1: '4:1', + PORTRAIT_1x8: '1:8', + LANDSCAPE_8x1: '8:1', + ULTRAWIDE_21x9: '21:9' +} as const; +/* eslint-enable camelcase */ + +/** + * Aspect ratios for generated images. + * @public + */ +export type ImageConfigAspectRatio = + (typeof ImageConfigAspectRatio)[keyof typeof ImageConfigAspectRatio]; + +/** + * Sizes for generated images. For example, '1K' is 1024px, '2K' is 2048px, and '4K' is 4096px. + * @public + */ +export const ImageConfigImageSize = { + SIZE_512: '512', + SIZE_1K: '1K', + SIZE_2K: '2K', + SIZE_4K: '4K' +} as const; + +/** + * Sizes for generated images. + * @public + */ +export type ImageConfigImageSize = + (typeof ImageConfigImageSize)[keyof typeof ImageConfigImageSize]; + /** * @public */ diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index cd2f640bf5..f9faee6a8a 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -26,6 +26,8 @@ import { HarmBlockMethod, HarmBlockThreshold, HarmCategory, + ImageConfigAspectRatio, + ImageConfigImageSize, InferenceMode, ResponseModality, ThinkingLevel @@ -112,6 +114,21 @@ export interface SafetySetting { method?: HarmBlockMethod; } +/** + * Configuration options for generating images with Gemini models. + * @public + */ +export interface ImageConfig { + /** + * The aspect ratio of generated images. + */ + aspectRatio?: ImageConfigAspectRatio; + /** + * The size of the generated images. + */ + imageSize?: ImageConfigImageSize; +} + /** * Config options for content-related requests * @public @@ -163,6 +180,11 @@ export interface GenerationConfig { * Configuration for "thinking" behavior of compatible Gemini models. */ thinkingConfig?: ThinkingConfig; + /** + * Configuration options for generating images with Gemini models. + * @public + */ + imageConfig?: ImageConfig; } /** From 402b1f01e67441c51701153031b6e645b71d4875 Mon Sep 17 00:00:00 2001 From: Mark Duckworth <1124037+MarkDuckworth@users.noreply.github.com> Date: Fri, 1 May 2026 11:44:17 -0600 Subject: [PATCH 167/174] fix(firestore): Assertion ID: ca9 (pendingResponses less than 0) caused by target creation race condition (#9842) * implement remote store target mapping * Add spec test for removeTarget race condition * cleanup * Update packages/firestore/src/remote/remote_store.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * cleanup * Create loud-camels-cross.md * Fix PR concerns and new tests * Cleanup possible leak in watchChangeAggregator * fix build issue with spec tests * Fix integration test failure when running against public api * another build fix * Update spec test builder and runner to allow the spec test to specify the index of a target ID used for a query for some watch message types * lint * add Remote and SDK TargetID types * Fix tests for SDK and Remote TargetId types * refactor spec test to add step watchUsesTargetIndex and remove steps where the target index is passed to individual steps * Remove unnecessary values passed to watchRemoves * Removed unused helpers --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .changeset/loud-camels-cross.md | 5 + .../firestore/src/core/target_id_generator.ts | 8 +- packages/firestore/src/core/types.ts | 8 +- packages/firestore/src/local/target_data.ts | 14 +- .../firestore/src/remote/persistent_stream.ts | 5 +- packages/firestore/src/remote/remote_event.ts | 12 +- packages/firestore/src/remote/remote_store.ts | 289 +++++++++++++++--- packages/firestore/src/remote/serializer.ts | 22 +- packages/firestore/src/remote/watch_change.ts | 76 +++-- .../test/unit/local/local_store.test.ts | 35 ++- .../unit/local/local_store_indexeddb.test.ts | 10 +- .../test/unit/remote/remote_event.test.ts | 10 +- .../unit/specs/existence_filter_spec.test.ts | 2 + .../test/unit/specs/remote_store_spec.test.ts | 64 ++++ .../firestore/test/unit/specs/spec_builder.ts | 60 +++- .../test/unit/specs/spec_test_runner.ts | 163 ++++++++-- packages/firestore/test/util/helpers.ts | 60 ++-- 17 files changed, 682 insertions(+), 161 deletions(-) create mode 100644 .changeset/loud-camels-cross.md diff --git a/.changeset/loud-camels-cross.md b/.changeset/loud-camels-cross.md new file mode 100644 index 0000000000..86ceced3d4 --- /dev/null +++ b/.changeset/loud-camels-cross.md @@ -0,0 +1,5 @@ +--- +"@firebase/firestore": patch +--- + +fix(firestore): Assertion ID: ca9 (pendingResponses less than 0) caused by target creation race condition diff --git a/packages/firestore/src/core/target_id_generator.ts b/packages/firestore/src/core/target_id_generator.ts index b6a98031ad..95b1b3b7e3 100644 --- a/packages/firestore/src/core/target_id_generator.ts +++ b/packages/firestore/src/core/target_id_generator.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { TargetId } from './types'; +import { RemoteTargetId, TargetId } from './types'; /** Offset to ensure non-overlapping target ids. */ const OFFSET = 2; @@ -34,12 +34,12 @@ const OFFSET = 2; * generate in-memory target IDs that are transient and can be reused after a * restart. */ -export class TargetIdGenerator { +export class TargetIdGenerator { constructor(private lastId: number) {} - next(): TargetId { + next(): T { this.lastId += OFFSET; - return this.lastId; + return this.lastId as T; } static forTargetCache(): TargetIdGenerator { diff --git a/packages/firestore/src/core/types.ts b/packages/firestore/src/core/types.ts index 5510a8f29d..b57368de39 100644 --- a/packages/firestore/src/core/types.ts +++ b/packages/firestore/src/core/types.ts @@ -21,11 +21,17 @@ */ export type BatchId = number; +/** + * A locally-assigned ID used to refer to a target being tracked in the local + * store. + */ +export type TargetId = number & { readonly __brand?: 'sdk' }; + /** * A locally-assigned ID used to refer to a target being watched via the * Watch service. */ -export type TargetId = number; +export type RemoteTargetId = number & { readonly __brand?: 'remote' }; export type ListenSequenceNumber = number; diff --git a/packages/firestore/src/local/target_data.ts b/packages/firestore/src/local/target_data.ts index a912c21d49..f940cd1eea 100644 --- a/packages/firestore/src/local/target_data.ts +++ b/packages/firestore/src/local/target_data.ts @@ -17,7 +17,7 @@ import { SnapshotVersion } from '../core/snapshot_version'; import { Target } from '../core/target'; -import { ListenSequenceNumber, TargetId } from '../core/types'; +import { ListenSequenceNumber, RemoteTargetId, TargetId } from '../core/types'; import { ByteString } from '../util/byte_string'; /** An enumeration of the different purposes we have for targets. */ @@ -44,7 +44,7 @@ export const enum TargetPurpose { /** * An immutable set of metadata that the local store tracks for each target. */ -export class TargetData { +export class TargetData { constructor( /** The target being listened to. */ readonly target: Target, @@ -52,7 +52,7 @@ export class TargetData { * The target ID to which the target corresponds; Assigned by the * LocalStore for user listens and by the SyncEngine for limbo watches. */ - readonly targetId: TargetId, + readonly targetId: T, /** The purpose of the target. */ readonly purpose: TargetPurpose, /** @@ -83,7 +83,7 @@ export class TargetData { ) {} /** Creates a new target data instance with an updated sequence number. */ - withSequenceNumber(sequenceNumber: number): TargetData { + withSequenceNumber(sequenceNumber: number): TargetData { return new TargetData( this.target, this.targetId, @@ -103,7 +103,7 @@ export class TargetData { withResumeToken( resumeToken: ByteString, snapshotVersion: SnapshotVersion - ): TargetData { + ): TargetData { return new TargetData( this.target, this.targetId, @@ -119,7 +119,7 @@ export class TargetData { /** * Creates a new target data instance with an updated expected count. */ - withExpectedCount(expectedCount: number): TargetData { + withExpectedCount(expectedCount: number): TargetData { return new TargetData( this.target, this.targetId, @@ -138,7 +138,7 @@ export class TargetData { */ withLastLimboFreeSnapshotVersion( lastLimboFreeSnapshotVersion: SnapshotVersion - ): TargetData { + ): TargetData { return new TargetData( this.target, this.targetId, diff --git a/packages/firestore/src/remote/persistent_stream.ts b/packages/firestore/src/remote/persistent_stream.ts index 4f3b91652a..a27e3c3b9f 100644 --- a/packages/firestore/src/remote/persistent_stream.ts +++ b/packages/firestore/src/remote/persistent_stream.ts @@ -18,7 +18,6 @@ import { CredentialsProvider, Token } from '../api/credentials'; import { User } from '../auth/user'; import { SnapshotVersion } from '../core/snapshot_version'; -import { TargetId } from '../core/types'; import { TargetData } from '../local/target_data'; import { Mutation, MutationResult } from '../model/mutation'; import { @@ -679,7 +678,7 @@ export class PersistentListenStream extends PersistentStream< * affect the target will be streamed back as WatchChange messages that * reference the targetId. */ - watch(targetData: TargetData): void { + watch(targetData: TargetData): void { const request: ListenRequest = {}; request.database = getEncodedDatabaseId(this.serializer); request.addTarget = toTarget(this.serializer, targetData); @@ -696,7 +695,7 @@ export class PersistentListenStream extends PersistentStream< * Unregisters interest in the results of the target associated with the * given targetId. */ - unwatch(targetId: TargetId): void { + unwatch(targetId: number): void { const request: ListenRequest = {}; request.database = getEncodedDatabaseId(this.serializer); request.removeTarget = targetId; diff --git a/packages/firestore/src/remote/remote_event.ts b/packages/firestore/src/remote/remote_event.ts index 49b2ef56a9..bf47190930 100644 --- a/packages/firestore/src/remote/remote_event.ts +++ b/packages/firestore/src/remote/remote_event.ts @@ -16,7 +16,7 @@ */ import { SnapshotVersion } from '../core/snapshot_version'; -import { TargetId } from '../core/types'; +import { RemoteTargetId, TargetId } from '../core/types'; import { TargetPurpose } from '../local/target_data'; import { documentKeySet, @@ -33,7 +33,7 @@ import { SortedMap } from '../util/sorted_map'; * state or the set of documents in our watched targets) and documentUpdates * (changes to the actual documents). */ -export class RemoteEvent { +export class RemoteEvent { constructor( /** * The snapshot version this event brings us up to, or MIN if not set. @@ -42,13 +42,13 @@ export class RemoteEvent { /** * A map from target to changes to the target. See TargetChange. */ - readonly targetChanges: Map, + readonly targetChanges: Map, /** * A map of targets that is known to be inconsistent, and the purpose for * re-listening. Listens for these targets should be re-established without * resume tokens. */ - readonly targetMismatches: SortedMap, + readonly targetMismatches: SortedMap, /** * A set of which documents have changed or been deleted, along with the * doc's new values (if not deleted). @@ -71,7 +71,7 @@ export class RemoteEvent { targetId: TargetId, current: boolean, resumeToken: ByteString - ): RemoteEvent { + ): RemoteEvent { const targetChanges = new Map(); targetChanges.set( targetId, @@ -81,7 +81,7 @@ export class RemoteEvent { resumeToken ) ); - return new RemoteEvent( + return new RemoteEvent( SnapshotVersion.min(), targetChanges, new SortedMap(primitiveComparator), diff --git a/packages/firestore/src/remote/remote_store.ts b/packages/firestore/src/remote/remote_store.ts index 6f8aed0503..5e92492b42 100644 --- a/packages/firestore/src/remote/remote_store.ts +++ b/packages/firestore/src/remote/remote_store.ts @@ -17,14 +17,16 @@ import { User } from '../auth/user'; import { SnapshotVersion } from '../core/snapshot_version'; -import { OnlineState, TargetId } from '../core/types'; +import { TargetIdGenerator } from '../core/target_id_generator'; +import { OnlineState, RemoteTargetId, TargetId } from '../core/types'; import { LocalStore } from '../local/local_store'; import { localStoreGetLastRemoteSnapshotVersion, localStoreGetNextMutationBatch } from '../local/local_store_impl'; import { isIndexedDbTransactionError } from '../local/simple_db'; -import { TargetData } from '../local/target_data'; +import { TargetData, TargetPurpose } from '../local/target_data'; +import { documentKeySet } from '../model/collections'; import { MutationResult } from '../model/mutation'; import { MutationBatch, MutationBatchResult } from '../model/mutation_batch'; import { debugAssert, debugCast } from '../util/assert'; @@ -32,6 +34,8 @@ import { AsyncQueue } from '../util/async_queue'; import { ByteString } from '../util/byte_string'; import { FirestoreError } from '../util/error'; import { logDebug } from '../util/log'; +import { primitiveComparator } from '../util/misc'; +import { SortedMap } from '../util/sorted_map'; import { BATCHID_UNKNOWN } from '../util/types'; import { ConnectivityMonitor, NetworkStatus } from './connectivity_monitor'; @@ -45,6 +49,7 @@ import { PersistentListenStream, PersistentWriteStream } from './persistent_stream'; +import { RemoteEvent, TargetChange } from './remote_event'; import { RemoteSyncer } from './remote_syncer'; import { isPermanentWriteError } from './rpc_error'; import { @@ -135,7 +140,12 @@ class RemoteStoreImpl implements RemoteStore { * to the server. The targets removed with unlistens are removed eagerly * without waiting for confirmation from the listen stream. */ - listenTargets = new Map(); + listenTargets = new Map>(); + + targetIdMapSdkToRemote = new Map(); + targetIdMapRemoteToSdk = new Map(); + targetCacheTargetIdGenerator = new TargetIdGenerator(1000); + syncEngineTargetIdGenerator = new TargetIdGenerator(1001); connectivityMonitor: ConnectivityMonitor; watchStream?: PersistentListenStream; @@ -265,6 +275,81 @@ export async function remoteStoreShutdown( remoteStoreImpl.onlineStateTracker.set(OnlineState.Unknown); } +/** + * Returns the remote target ID currently mapped to this + * sdkTargetId. Or returns `0` if the SDK target ID + * is not currently mapped. + * @param remoteStoreImpl + * @param sdkTargetId + */ +function getRemoteTargetId( + remoteStoreImpl: RemoteStoreImpl, + sdkTargetId: TargetId +): RemoteTargetId | undefined { + return remoteStoreImpl.targetIdMapSdkToRemote.get(sdkTargetId) || undefined; +} + +/** + * Returns the remote target ID currently mapped to this + * sdkTargetId. Exposed for testing. + */ +export function remoteStoreGetRemoteTargetId( + remoteStore: RemoteStore, + sdkTargetId: TargetId +): RemoteTargetId | undefined { + const remoteStoreImpl = debugCast(remoteStore, RemoteStoreImpl); + return getRemoteTargetId(remoteStoreImpl, sdkTargetId); +} + +/** + * Generates a new remote target ID that is acceptable + * to map to the given SDK target ID. + * @param remoteStoreImpl + * @param sdkTargetId + */ +function generateRemoteTargetId( + remoteStoreImpl: RemoteStoreImpl, + sdkTargetId: TargetId +): RemoteTargetId { + // If the given sdkTargetId is odd, map it to an odd (sync engine) target ID + if (sdkTargetId % 2 !== 0) { + return remoteStoreImpl.syncEngineTargetIdGenerator.next(); + } else { + // If the given sdkTargetId is even, map it to an even (target cache) target ID + return remoteStoreImpl.targetCacheTargetIdGenerator.next(); + } +} + +/** + * Generate a new remote target ID for the given SDK target ID. + * Re-map the given SDK to the new remote ID. + * Delete any mapping of the old remote ID, if given. + * @param remoteStoreImpl + * @param sdkTargetId + * @return The new remote ID. + */ +function allocateRemoteTargetId( + remoteStoreImpl: RemoteStoreImpl, + sdkTargetId: TargetId +): RemoteTargetId { + const currentRemoteTargetId = getRemoteTargetId(remoteStoreImpl, sdkTargetId); + + if (currentRemoteTargetId !== undefined) { + // If there was an existing remote target ID mapped to that SDK target ID, forget about the old remote ID. + remoteStoreImpl.targetIdMapRemoteToSdk.delete(currentRemoteTargetId); + } + + // Generate a new unique remote target ID + const newRemoteTargetId = generateRemoteTargetId( + remoteStoreImpl, + sdkTargetId + ); + + remoteStoreImpl.targetIdMapSdkToRemote.set(sdkTargetId, newRemoteTargetId); + remoteStoreImpl.targetIdMapRemoteToSdk.set(newRemoteTargetId, sdkTargetId); + return newRemoteTargetId; +} + /** * Starts new listen for the given target. Uses resume token if provided. It * is a no-op if the target of given `TargetData` is already being listened to. @@ -275,18 +360,53 @@ export function remoteStoreListen( ): void { const remoteStoreImpl = debugCast(remoteStore, RemoteStoreImpl); - if (remoteStoreImpl.listenTargets.has(targetData.targetId)) { + // Get any remote target ID currently mapped to the targetData + const currentRemoteTargetId = getRemoteTargetId( + remoteStoreImpl, + targetData.targetId + ); + + // If remote store is still listening for this remote target ID, this is a no-op. + if ( + currentRemoteTargetId !== undefined && + remoteStoreImpl.listenTargets.has(currentRemoteTargetId) + ) { return; } + // Generate and map a new remote ID to the SDK target ID + const remoteTargetId = allocateRemoteTargetId( + remoteStoreImpl, + targetData.targetId + ); + + logDebug( + LOG_TAG, + 'remoteStoreListen mapping SDK target ID to remote', + targetData.targetId, + remoteTargetId + ); + + // Create a new TargetData for remote use, which uses + // the remote TargetID. + const remoteTargetData = new TargetData( + targetData.target, + remoteTargetId, + targetData.purpose, + targetData.sequenceNumber, + targetData.snapshotVersion, + targetData.lastLimboFreeSnapshotVersion, + targetData.resumeToken + ); + // Mark this as something the client is currently listening for. - remoteStoreImpl.listenTargets.set(targetData.targetId, targetData); + remoteStoreImpl.listenTargets.set(remoteTargetId, remoteTargetData); if (shouldStartWatchStream(remoteStoreImpl)) { // The listen will be sent in onWatchStreamOpen startWatchStream(remoteStoreImpl); } else if (ensureWatchStream(remoteStoreImpl).isOpen()) { - sendWatchRequest(remoteStoreImpl, targetData); + sendWatchRequest(remoteStoreImpl, remoteTargetData); } } @@ -301,14 +421,26 @@ export function remoteStoreUnlisten( const remoteStoreImpl = debugCast(remoteStore, RemoteStoreImpl); const watchStream = ensureWatchStream(remoteStoreImpl); + const remoteTargetId = getRemoteTargetId(remoteStoreImpl, targetId); + logDebug( + LOG_TAG, + 'remoteStoreUnlisten removing mapping of SDK target ID to remote', + targetId, + remoteTargetId + ); + debugAssert( - remoteStoreImpl.listenTargets.has(targetId), - `unlisten called on target no currently watched: ${targetId}` + remoteTargetId !== undefined && + remoteStoreImpl.listenTargets.has(remoteTargetId), + `unlisten called on target not currently watched: ${remoteTargetId}` ); - remoteStoreImpl.listenTargets.delete(targetId); + remoteStoreImpl.listenTargets.delete(remoteTargetId); + remoteStoreImpl.targetIdMapSdkToRemote.delete(targetId); + remoteStoreImpl.targetIdMapRemoteToSdk.delete(remoteTargetId); + if (watchStream.isOpen()) { - sendUnwatchRequest(remoteStoreImpl, targetId); + sendUnwatchRequest(remoteStoreImpl, remoteTargetId); } if (remoteStoreImpl.listenTargets.size === 0) { @@ -329,23 +461,37 @@ export function remoteStoreUnlisten( */ function sendWatchRequest( remoteStoreImpl: RemoteStoreImpl, - targetData: TargetData + remoteTargetData: TargetData ): void { remoteStoreImpl.watchChangeAggregator!.recordPendingTargetRequest( - targetData.targetId + remoteTargetData.targetId ); if ( - targetData.resumeToken.approximateByteSize() > 0 || - targetData.snapshotVersion.compareTo(SnapshotVersion.min()) > 0 + remoteTargetData.resumeToken.approximateByteSize() > 0 || + remoteTargetData.snapshotVersion.compareTo(SnapshotVersion.min()) > 0 ) { - const expectedCount = remoteStoreImpl.remoteSyncer.getRemoteKeysForTarget!( - targetData.targetId - ).size; - targetData = targetData.withExpectedCount(expectedCount); + const sdkTargetId = remoteStoreImpl.targetIdMapRemoteToSdk.get( + remoteTargetData.targetId as RemoteTargetId + ); + + if (sdkTargetId === undefined) { + logDebug( + LOG_TAG, + 'SDK target ID not found for remote ID: ' + remoteTargetData.targetId + ); + + // There's already a new remoteStoreListen request for the original + // target, so ignore this. + return; + } + + const expectedCount = + remoteStoreImpl.remoteSyncer.getRemoteKeysForTarget!(sdkTargetId).size; + remoteTargetData = remoteTargetData.withExpectedCount(expectedCount); } - ensureWatchStream(remoteStoreImpl).watch(targetData); + ensureWatchStream(remoteStoreImpl).watch(remoteTargetData); } /** @@ -355,7 +501,7 @@ function sendWatchRequest( */ function sendUnwatchRequest( remoteStoreImpl: RemoteStoreImpl, - targetId: TargetId + targetId: RemoteTargetId ): void { remoteStoreImpl.watchChangeAggregator!.recordPendingTargetRequest(targetId); ensureWatchStream(remoteStoreImpl).unwatch(targetId); @@ -372,10 +518,19 @@ function startWatchStream(remoteStoreImpl: RemoteStoreImpl): void { ); remoteStoreImpl.watchChangeAggregator = new WatchChangeAggregator({ - getRemoteKeysForTarget: targetId => - remoteStoreImpl.remoteSyncer.getRemoteKeysForTarget!(targetId), - getTargetDataForTarget: targetId => - remoteStoreImpl.listenTargets.get(targetId) || null, + getRemoteKeysForTarget: remoteTargetId => { + // Remote syncer uses SDK target IDs, so we need to map the remote + // id to external id + const sdkTargetId = + remoteStoreImpl.targetIdMapRemoteToSdk.get(remoteTargetId); + + // If no sdkTargetId is mapped, return an empty key set + return sdkTargetId !== undefined + ? remoteStoreImpl.remoteSyncer.getRemoteKeysForTarget!(sdkTargetId) + : documentKeySet(); + }, + getTargetDataForTarget: remoteTargetId => + remoteStoreImpl.listenTargets.get(remoteTargetId) || null, getDatabaseId: () => remoteStoreImpl.datastore.serializer.databaseId }); ensureWatchStream(remoteStoreImpl).start(); @@ -413,8 +568,8 @@ async function onWatchStreamConnected( async function onWatchStreamOpen( remoteStoreImpl: RemoteStoreImpl ): Promise { - remoteStoreImpl.listenTargets.forEach((targetData, targetId) => { - sendWatchRequest(remoteStoreImpl, targetData); + remoteStoreImpl.listenTargets.forEach((remoteTargetData, targetId) => { + sendWatchRequest(remoteStoreImpl, remoteTargetData); }); } @@ -579,13 +734,13 @@ function raiseWatchSnapshot( // Update in-memory resume tokens. LocalStore will update the // persistent view of these when applying the completed RemoteEvent. - remoteEvent.targetChanges.forEach((change, targetId) => { + remoteEvent.targetChanges.forEach((change, remoteTargetId) => { if (change.resumeToken.approximateByteSize() > 0) { - const targetData = remoteStoreImpl.listenTargets.get(targetId); + const targetData = remoteStoreImpl.listenTargets.get(remoteTargetId); // A watched target might have been removed already. if (targetData) { remoteStoreImpl.listenTargets.set( - targetId, + remoteTargetId, targetData.withResumeToken(change.resumeToken, snapshotVersion) ); } @@ -594,8 +749,8 @@ function raiseWatchSnapshot( // Re-establish listens for the targets that have been invalidated by // existence filter mismatches. - remoteEvent.targetMismatches.forEach((targetId, targetPurpose) => { - const targetData = remoteStoreImpl.listenTargets.get(targetId); + remoteEvent.targetMismatches.forEach((remoteTargetId, targetPurpose) => { + const targetData = remoteStoreImpl.listenTargets.get(remoteTargetId); if (!targetData) { // A watched target might have been removed already. return; @@ -604,7 +759,7 @@ function raiseWatchSnapshot( // Clear the resume token for the target, since we're in a known mismatch // state. remoteStoreImpl.listenTargets.set( - targetId, + remoteTargetId, targetData.withResumeToken( ByteString.EMPTY_BYTE_STRING, targetData.snapshotVersion @@ -613,7 +768,7 @@ function raiseWatchSnapshot( // Cause a hard reset by unwatching and rewatching immediately, but // deliberately don't send a resume token so that we get a full update. - sendUnwatchRequest(remoteStoreImpl, targetId); + sendUnwatchRequest(remoteStoreImpl, remoteTargetId); // Mark the target we send as being on behalf of an existence filter // mismatch, but don't actually retain that in listenTargets. This ensures @@ -621,7 +776,7 @@ function raiseWatchSnapshot( // listens of this target (that might happen e.g. on reconnect). const requestTargetData = new TargetData( targetData.target, - targetId, + remoteTargetId, targetPurpose, targetData.sequenceNumber ); @@ -633,7 +788,59 @@ function raiseWatchSnapshot( !!remoteStoreImpl.remoteSyncer.applyRemoteEvent, 'applyRemoteEvent() not set' ); - return remoteStoreImpl.remoteSyncer.applyRemoteEvent(remoteEvent); + + const sdkEvent = toSdkRemoteEvent(remoteStoreImpl, remoteEvent); + + return remoteStoreImpl.remoteSyncer.applyRemoteEvent!(sdkEvent); +} + +/** + * Convert a RemoteEvent with remote IDs to a RemoteEvent with + * SDK IDs and dropped updates + * for any targets we no longer track. + * + * @param remoteStoreImpl + * @param remoteEvent + * @return a new RemoteEvent with SDK IDs and dropped updates + * for any targets we no longer track. + */ +function toSdkRemoteEvent( + remoteStoreImpl: RemoteStoreImpl, + remoteEvent: RemoteEvent +): RemoteEvent { + // Map TargetChanges to TargetChanges with SDK ID + const sdkTargetChanges = new Map(); + remoteEvent.targetChanges.forEach((change, remoteTargetId) => { + // If we no longer track the remote ID, then drop the TargetChange + // otherwise propagate the TargetChange + const sdkTargetId = + remoteStoreImpl.targetIdMapRemoteToSdk.get(remoteTargetId); + if (sdkTargetId !== undefined) { + sdkTargetChanges.set(sdkTargetId, change); + } + }); + + // Map target mismatches to target mismatches with SDK ID + let sdkTargetMismatches = new SortedMap( + primitiveComparator + ); + remoteEvent.targetMismatches.forEach((remoteTargetId, purpose) => { + // If we no longer track the remote ID, then drop the target mismatch + // otherwise propagate the target mismatch + const sdkTargetId = + remoteStoreImpl.targetIdMapRemoteToSdk.get(remoteTargetId); + if (sdkTargetId !== undefined) { + sdkTargetMismatches = sdkTargetMismatches.insert(sdkTargetId, purpose); + } + }); + + return new RemoteEvent( + remoteEvent.snapshotVersion, + sdkTargetChanges, + sdkTargetMismatches, + remoteEvent.documentUpdates, + remoteEvent.resolvedLimboDocuments + ); } /** Handles an error on a target */ @@ -650,10 +857,18 @@ async function handleTargetError( for (const targetId of watchChange.targetIds) { // A watched target might have been removed already. if (remoteStoreImpl.listenTargets.has(targetId)) { - await remoteStoreImpl.remoteSyncer.rejectListen(targetId, error); + const sdkTargetId = remoteStoreImpl.targetIdMapRemoteToSdk.get(targetId); + + // If we still track the remote target ID, then notify the remoteSyncer + // of the error and then free up the remote ID. + if (sdkTargetId !== undefined) { + await remoteStoreImpl.remoteSyncer.rejectListen!(sdkTargetId, error); + remoteStoreImpl.targetIdMapSdkToRemote.delete(sdkTargetId); + remoteStoreImpl.targetIdMapRemoteToSdk.delete(targetId); + } remoteStoreImpl.listenTargets.delete(targetId); - remoteStoreImpl.watchChangeAggregator!.removeTarget(targetId); } + remoteStoreImpl.watchChangeAggregator!.removeTarget(targetId); } } diff --git a/packages/firestore/src/remote/serializer.ts b/packages/firestore/src/remote/serializer.ts index b8283fad97..12aac4572c 100644 --- a/packages/firestore/src/remote/serializer.ts +++ b/packages/firestore/src/remote/serializer.ts @@ -36,7 +36,7 @@ import { } from '../core/query'; import { SnapshotVersion } from '../core/snapshot_version'; import { targetIsDocumentTarget, Target } from '../core/target'; -import { TargetId } from '../core/types'; +import { RemoteTargetId } from '../core/types'; import { Bytes } from '../lite-api/bytes'; import { GeoPoint } from '../lite-api/geo_point'; import { Timestamp } from '../lite-api/timestamp'; @@ -558,7 +558,8 @@ export function fromWatchChange( const state = fromWatchTargetChangeState( change.targetChange.targetChangeType || 'NO_CHANGE' ); - const targetIds: TargetId[] = change.targetChange.targetIds || []; + const targetIds: RemoteTargetId[] = (change.targetChange.targetIds || + []) as RemoteTargetId[]; const resumeToken = fromBytes(serializer, change.targetChange.resumeToken); const causeProto = change.targetChange!.cause; @@ -592,8 +593,9 @@ export function fromWatchChange( createTime, data ); - const updatedTargetIds = entityChange.targetIds || []; - const removedTargetIds = entityChange.removedTargetIds || []; + const updatedTargetIds = (entityChange.targetIds || []) as RemoteTargetId[]; + const removedTargetIds = (entityChange.removedTargetIds || + []) as RemoteTargetId[]; watchChange = new DocumentWatchChange( updatedTargetIds, removedTargetIds, @@ -609,14 +611,16 @@ export function fromWatchChange( ? fromVersion(docDelete.readTime) : SnapshotVersion.min(); const doc = MutableDocument.newNoDocument(key, version); - const removedTargetIds = docDelete.removedTargetIds || []; + const removedTargetIds = (docDelete.removedTargetIds || + []) as RemoteTargetId[]; watchChange = new DocumentWatchChange([], removedTargetIds, doc.key, doc); } else if ('documentRemove' in change) { assertPresent(change.documentRemove, 'documentRemove'); const docRemove = change.documentRemove; assertPresent(docRemove.document, 'documentRemove'); const key = fromName(serializer, docRemove.document); - const removedTargetIds = docRemove.removedTargetIds || []; + const removedTargetIds = (docRemove.removedTargetIds || + []) as RemoteTargetId[]; watchChange = new DocumentWatchChange([], removedTargetIds, key, null); } else if ('filter' in change) { // TODO(dimond): implement existence filter parsing with strategy. @@ -625,7 +629,7 @@ export function fromWatchChange( assertPresent(filter.targetId, 'filter.targetId'); const { count = 0, unchangedNames } = filter; const existenceFilter = new ExistenceFilter(count, unchangedNames); - const targetId = filter.targetId; + const targetId = filter.targetId as RemoteTargetId; watchChange = new ExistenceFilterChange(targetId, existenceFilter); } else { return fail(0x2d51, 'Unknown change type', { change }); @@ -1084,7 +1088,7 @@ export function fromQueryTarget(target: ProtoQueryTarget): Target { export function toListenRequestLabels( serializer: JsonProtoSerializer, - targetData: TargetData + targetData: TargetData ): ProtoApiClientObjectMap | null { const value = toLabel(targetData.purpose); if (value == null) { @@ -1113,7 +1117,7 @@ export function toLabel(purpose: TargetPurpose): string | null { export function toTarget( serializer: JsonProtoSerializer, - targetData: TargetData + targetData: TargetData ): ProtoTarget { let result: ProtoTarget; const target = targetData.target; diff --git a/packages/firestore/src/remote/watch_change.ts b/packages/firestore/src/remote/watch_change.ts index a656d8fdf6..3a97b796a4 100644 --- a/packages/firestore/src/remote/watch_change.ts +++ b/packages/firestore/src/remote/watch_change.ts @@ -18,7 +18,7 @@ import { DatabaseId } from '../core/database_info'; import { SnapshotVersion } from '../core/snapshot_version'; import { targetIsDocumentTarget } from '../core/target'; -import { TargetId } from '../core/types'; +import { RemoteTargetId } from '../core/types'; import { ChangeType } from '../core/view_snapshot'; import { TargetData, TargetPurpose } from '../local/target_data'; import { @@ -63,9 +63,9 @@ export type WatchChange = export class DocumentWatchChange { constructor( /** The new document applies to all of these targets. */ - public updatedTargetIds: TargetId[], + public updatedTargetIds: RemoteTargetId[], /** The new document is removed from all of these targets. */ - public removedTargetIds: TargetId[], + public removedTargetIds: RemoteTargetId[], /** The key of the document for this change. */ public key: DocumentKey, /** @@ -78,7 +78,7 @@ export class DocumentWatchChange { export class ExistenceFilterChange { constructor( - public targetId: TargetId, + public targetId: RemoteTargetId, public existenceFilter: ExistenceFilter ) {} } @@ -101,7 +101,7 @@ export class WatchTargetChange { /** What kind of change occurred to the watch target. */ public state: WatchTargetChangeState, /** The target IDs that were added/removed/set. */ - public targetIds: TargetId[], + public targetIds: RemoteTargetId[], /** * An opaque, server-assigned token that allows watching a target to be * resumed after disconnecting without retransmitting all the data that @@ -263,13 +263,15 @@ export interface TargetMetadataProvider { * Returns the set of remote document keys for the given target ID as of the * last raised snapshot. */ - getRemoteKeysForTarget(targetId: TargetId): DocumentKeySet; + getRemoteKeysForTarget(targetId: RemoteTargetId): DocumentKeySet; /** * Returns the TargetData for an active target ID or 'null' if this target * has become inactive */ - getTargetDataForTarget(targetId: TargetId): TargetData | null; + getTargetDataForTarget( + targetId: RemoteTargetId + ): TargetData | null; /** * Returns the database ID of the Firestore instance. @@ -286,7 +288,7 @@ export class WatchChangeAggregator { constructor(private metadataProvider: TargetMetadataProvider) {} /** The internal state of all tracked targets. */ - private targetStates = new Map(); + private targetStates = new Map(); /** Keeps track of the documents to update since the last raised snapshot. */ private pendingDocumentUpdates = mutableDocumentMap(); @@ -300,7 +302,7 @@ export class WatchChangeAggregator { * known to be inconsistent and their listens needs to be re-established by * RemoteStore. */ - private pendingTargetResets = new SortedMap( + private pendingTargetResets = new SortedMap( primitiveComparator ); @@ -391,7 +393,7 @@ export class WatchChangeAggregator { */ forEachTarget( targetChange: WatchTargetChange, - fn: (targetId: TargetId) => void + fn: (targetId: RemoteTargetId) => void ): void { if (targetChange.targetIds.length > 0) { targetChange.targetIds.forEach(fn); @@ -557,7 +559,7 @@ export class WatchChangeAggregator { */ private filterRemovedDocuments( bloomFilter: BloomFilter, - targetId: number + targetId: RemoteTargetId ): number { const existingKeys = this.metadataProvider.getRemoteKeysForTarget(targetId); let removalCount = 0; @@ -582,8 +584,10 @@ export class WatchChangeAggregator { * Converts the currently accumulated state into a remote event at the * provided snapshot version. Resets the accumulated changes before returning. */ - createRemoteEvent(snapshotVersion: SnapshotVersion): RemoteEvent { - const targetChanges = new Map(); + createRemoteEvent( + snapshotVersion: SnapshotVersion + ): RemoteEvent { + const targetChanges = new Map(); this.targetStates.forEach((targetState, targetId) => { const targetData = this.targetDataForActiveTarget(targetId); @@ -661,7 +665,7 @@ export class WatchChangeAggregator { this.pendingDocumentUpdates = mutableDocumentMap(); this.pendingDocumentUpdatesByTarget = documentTargetMap(); this.pendingDocumentTargetMapping = documentTargetMap(); - this.pendingTargetResets = new SortedMap( + this.pendingTargetResets = new SortedMap( primitiveComparator ); @@ -673,7 +677,10 @@ export class WatchChangeAggregator { * its document key to the given target's mapping. */ // Visible for testing. - addDocumentToTarget(targetId: TargetId, document: MutableDocument): void { + addDocumentToTarget( + targetId: RemoteTargetId, + document: MutableDocument + ): void { if (!this.isActiveTarget(targetId)) { return; } @@ -712,7 +719,7 @@ export class WatchChangeAggregator { */ // Visible for testing. removeDocumentFromTarget( - targetId: TargetId, + targetId: RemoteTargetId, key: DocumentKey, updatedDocument: MutableDocument | null ): void { @@ -749,7 +756,7 @@ export class WatchChangeAggregator { } } - removeTarget(targetId: TargetId): void { + removeTarget(targetId: RemoteTargetId): void { this.targetStates.delete(targetId); } @@ -758,7 +765,7 @@ export class WatchChangeAggregator { * the number of documents that the LocalStore considers to be part of the * target as well as any accumulated changes. */ - private getCurrentDocumentCountForTarget(targetId: TargetId): number { + private getCurrentDocumentCountForTarget(targetId: RemoteTargetId): number { const targetState = this.ensureTargetState(targetId); const targetChange = targetState.toTargetChange(); return ( @@ -772,13 +779,13 @@ export class WatchChangeAggregator { * Increment the number of acks needed from watch before we can consider the * server to be 'in-sync' with the client's active targets. */ - recordPendingTargetRequest(targetId: TargetId): void { + recordPendingTargetRequest(targetId: RemoteTargetId): void { // For each request we get we need to record we need a response for it. const targetState = this.ensureTargetState(targetId); targetState.recordPendingTargetRequest(); } - private ensureTargetState(targetId: TargetId): TargetState { + private ensureTargetState(targetId: RemoteTargetId): TargetState { let result = this.targetStates.get(targetId); if (!result) { result = new TargetState(); @@ -787,11 +794,13 @@ export class WatchChangeAggregator { return result; } - private ensureDocumentTargetMapping(key: DocumentKey): SortedSet { + private ensureDocumentTargetMapping( + key: DocumentKey + ): SortedSet { let targetMapping = this.pendingDocumentTargetMapping.get(key); if (!targetMapping) { - targetMapping = new SortedSet(primitiveComparator); + targetMapping = new SortedSet(primitiveComparator); this.pendingDocumentTargetMapping = this.pendingDocumentTargetMapping.insert(key, targetMapping); } @@ -799,11 +808,13 @@ export class WatchChangeAggregator { return targetMapping; } - private ensureDocumentUpdateByTarget(key: DocumentKey): SortedSet { + private ensureDocumentUpdateByTarget( + key: DocumentKey + ): SortedSet { let targetMapping = this.pendingDocumentUpdatesByTarget.get(key); if (!targetMapping) { - targetMapping = new SortedSet(primitiveComparator); + targetMapping = new SortedSet(primitiveComparator); this.pendingDocumentUpdatesByTarget = this.pendingDocumentUpdatesByTarget.insert(key, targetMapping); } @@ -816,7 +827,7 @@ export class WatchChangeAggregator { * `getTargetDataForTarget()`) and that we are not waiting for pending ADDs * from watch. */ - protected isActiveTarget(targetId: TargetId): boolean { + protected isActiveTarget(targetId: RemoteTargetId): boolean { const targetActive = this.targetDataForActiveTarget(targetId) !== null; if (!targetActive) { logDebug(LOG_TAG, 'Detected inactive target', targetId); @@ -828,7 +839,9 @@ export class WatchChangeAggregator { * Returns the TargetData for an active target (i.e. a target that the user * is still interested in that has no outstanding target change requests). */ - protected targetDataForActiveTarget(targetId: TargetId): TargetData | null { + protected targetDataForActiveTarget( + targetId: RemoteTargetId + ): TargetData | null { const targetState = this.targetStates.get(targetId); return targetState && targetState.isPending ? null @@ -840,7 +853,7 @@ export class WatchChangeAggregator { * 'current' to false, clears the resume token and removes its target mapping * from all documents). */ - private resetTarget(targetId: TargetId): void { + private resetTarget(targetId: RemoteTargetId): void { debugAssert( !this.targetStates.get(targetId)!.isPending, 'Should only reset active targets' @@ -860,7 +873,7 @@ export class WatchChangeAggregator { * specified target. */ private targetContainsDocument( - targetId: TargetId, + targetId: RemoteTargetId, key: DocumentKey ): boolean { const existingKeys = this.metadataProvider.getRemoteKeysForTarget(targetId); @@ -868,8 +881,11 @@ export class WatchChangeAggregator { } } -function documentTargetMap(): SortedMap> { - return new SortedMap>( +function documentTargetMap(): SortedMap< + DocumentKey, + SortedSet +> { + return new SortedMap>( DocumentKey.comparator ); } diff --git a/packages/firestore/test/unit/local/local_store.test.ts b/packages/firestore/test/unit/local/local_store.test.ts index b8fe6878d9..c0750fa631 100644 --- a/packages/firestore/test/unit/local/local_store.test.ts +++ b/packages/firestore/test/unit/local/local_store.test.ts @@ -30,7 +30,7 @@ import { } from '../../../src/core/query'; import { SnapshotVersion } from '../../../src/core/snapshot_version'; import { Target } from '../../../src/core/target'; -import { BatchId, TargetId } from '../../../src/core/types'; +import { BatchId, RemoteTargetId, TargetId } from '../../../src/core/types'; import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence'; import { LocalStore } from '../../../src/local/local_store'; import { @@ -56,6 +56,7 @@ import { } from '../../../src/local/local_store_impl'; import { LocalViewChanges } from '../../../src/local/local_view_changes'; import { Persistence } from '../../../src/local/persistence'; +import { TargetData } from '../../../src/local/target_data'; import { DocumentKeySet, documentKeySet, @@ -94,6 +95,7 @@ import { bundledDocuments, bundleMetadata, byteStringFromString, + castRemoteEvent, deletedDoc, deleteMutation, doc, @@ -1282,17 +1284,24 @@ function genericLocalStoreTests( const resumeToken = byteStringFromString('abc'); const watchChange = new WatchTargetChange( WatchTargetChangeState.Current, - [targetId], + // This test does not use remote_store mapping of target IDs, + // so treat the targetId from targetData as a remote target ID. + [targetId as RemoteTargetId], resumeToken ); const aggregator = new WatchChangeAggregator({ getRemoteKeysForTarget: () => documentKeySet(), - getTargetDataForTarget: () => targetData, + getTargetDataForTarget: () => targetData as TargetData, getDatabaseId: () => persistenceHelpers.TEST_DATABASE_ID }); aggregator.handleTargetChange(watchChange); const remoteEvent = aggregator.createRemoteEvent(version(1000)); - await localStoreApplyRemoteEventToLocalCache(localStore, remoteEvent); + // This test does not use remote_store mapping of remote events, + // so treat the remote event created by the aggregator as an SDK remote event + await localStoreApplyRemoteEventToLocalCache( + localStore, + castRemoteEvent(remoteEvent) + ); // Stop listening so that the query should become inactive (but persistent) await localStoreReleaseTarget( @@ -1318,7 +1327,7 @@ function genericLocalStoreTests( localStore, queryToTarget(query1) ); - const targetId = targetData.targetId; + const targetId = targetData.targetId as RemoteTargetId; const resumeToken = byteStringFromString('abc'); const watchChange1 = new WatchTargetChange( @@ -1328,12 +1337,15 @@ function genericLocalStoreTests( ); const aggregator1 = new WatchChangeAggregator({ getRemoteKeysForTarget: () => documentKeySet(), - getTargetDataForTarget: () => targetData, + getTargetDataForTarget: () => targetData as TargetData, getDatabaseId: () => persistenceHelpers.TEST_DATABASE_ID }); aggregator1.handleTargetChange(watchChange1); const remoteEvent1 = aggregator1.createRemoteEvent(version(1000)); - await localStoreApplyRemoteEventToLocalCache(localStore, remoteEvent1); + await localStoreApplyRemoteEventToLocalCache( + localStore, + castRemoteEvent(remoteEvent1) + ); const watchChange2 = new WatchTargetChange( WatchTargetChangeState.Current, @@ -1342,12 +1354,15 @@ function genericLocalStoreTests( ); const aggregator2 = new WatchChangeAggregator({ getRemoteKeysForTarget: () => documentKeySet(), - getTargetDataForTarget: () => targetData, + getTargetDataForTarget: () => targetData as TargetData, getDatabaseId: () => persistenceHelpers.TEST_DATABASE_ID }); aggregator2.handleTargetChange(watchChange2); const remoteEvent2 = aggregator2.createRemoteEvent(version(2000)); - await localStoreApplyRemoteEventToLocalCache(localStore, remoteEvent2); + await localStoreApplyRemoteEventToLocalCache( + localStore, + castRemoteEvent(remoteEvent2) + ); // Stop listening so that the query should become inactive (but persistent) await localStoreReleaseTarget( @@ -2380,7 +2395,7 @@ function genericLocalStoreTests( await localStoreApplyRemoteEventToLocalCache( localStore, noChangeEvent( - /* targetId= */ targetData.targetId, + /* targetId= */ targetData.targetId as RemoteTargetId, /* snapshotVersion= */ 10, /* resumeToken= */ byteStringFromString('foo') ) diff --git a/packages/firestore/test/unit/local/local_store_indexeddb.test.ts b/packages/firestore/test/unit/local/local_store_indexeddb.test.ts index 6f0275ab4a..0afbbf35ee 100644 --- a/packages/firestore/test/unit/local/local_store_indexeddb.test.ts +++ b/packages/firestore/test/unit/local/local_store_indexeddb.test.ts @@ -28,7 +28,7 @@ import { queryWithLimit } from '../../../src/core/query'; import { Target } from '../../../src/core/target'; -import { TargetId } from '../../../src/core/types'; +import { RemoteTargetId, TargetId } from '../../../src/core/types'; import { IndexBackfiller } from '../../../src/local/index_backfiller'; import { LocalStore } from '../../../src/local/local_store'; import { @@ -302,7 +302,9 @@ describe('LocalStore w/ IndexedDB Persistence (Non generic)', () => { query('coll', filter('a', '==', 1)) ); await test.applyRemoteEvent( - docUpdateRemoteEvent(doc('coll/a', 10, { a: 1 }), [targetId]) + docUpdateRemoteEvent(doc('coll/a', 10, { a: 1 }), [ + targetId + ] as RemoteTargetId[]) ); await test.backfillIndexes(); @@ -334,7 +336,9 @@ describe('LocalStore w/ IndexedDB Persistence (Non generic)', () => { test.assertQueryReturned('coll/a'); await test.applyRemoteEvent( - docUpdateRemoteEvent(deletedDoc('coll/a', 0), [targetId]) + docUpdateRemoteEvent(deletedDoc('coll/a', 0), [ + targetId + ] as RemoteTargetId[]) ); // No backfill needed for deleted document. diff --git a/packages/firestore/test/unit/remote/remote_event.test.ts b/packages/firestore/test/unit/remote/remote_event.test.ts index 36596a8997..1d8b50aace 100644 --- a/packages/firestore/test/unit/remote/remote_event.test.ts +++ b/packages/firestore/test/unit/remote/remote_event.test.ts @@ -18,7 +18,7 @@ import { expect } from 'chai'; import { SnapshotVersion } from '../../../src/core/snapshot_version'; -import { TargetId } from '../../../src/core/types'; +import { RemoteTargetId, TargetId } from '../../../src/core/types'; import { TargetData, TargetPurpose } from '../../../src/local/target_data'; import { DocumentKeySet, documentKeySet } from '../../../src/model/collections'; import { ExistenceFilter } from '../../../src/remote/existence_filter'; @@ -104,7 +104,7 @@ describe('RemoteEvent', () => { existingKeys?: DocumentKeySet; changes?: Array; }): WatchChangeAggregator { - const targetIds: TargetId[] = []; + const targetIds: RemoteTargetId[] = []; if (options.targets) { forEachNumber(options.targets, targetId => { @@ -114,7 +114,9 @@ describe('RemoteEvent', () => { const aggregator = new WatchChangeAggregator({ getRemoteKeysForTarget: () => options.existingKeys || documentKeySet(), getTargetDataForTarget: targetId => - options.targets ? options.targets[targetId] : null, + (options.targets + ? options.targets[targetId] + : null) as TargetData | null, getDatabaseId: () => TEST_DATABASE_ID }); @@ -151,7 +153,7 @@ describe('RemoteEvent', () => { outstandingResponses?: PendingTargetResponses; existingKeys?: DocumentKeySet; changes?: Array; - }): RemoteEvent { + }): RemoteEvent { return createAggregator(options).createRemoteEvent( version(options.snapshotVersion) ); diff --git a/packages/firestore/test/unit/specs/existence_filter_spec.test.ts b/packages/firestore/test/unit/specs/existence_filter_spec.test.ts index 3796c6123c..a72bdd9563 100644 --- a/packages/firestore/test/unit/specs/existence_filter_spec.test.ts +++ b/packages/firestore/test/unit/specs/existence_filter_spec.test.ts @@ -87,10 +87,12 @@ describeSpec('Existence Filters:', [], () => { .userUnlistens(query1) .userListens(query1, { resumeToken: 'resume-token-1000' }) .expectEvents(query1, { added: [doc1], fromCache: true }) + .watchUsesTargetIndex(0) // The empty existence filter is ignored since Watch hasn't ACKed the // target .watchFilters([query1]) .watchRemoves(query1) + .watchUsesTargetIndex('latest') .watchAcks(query1) .watchCurrents(query1, 'resume-token-2000') .watchSnapshots(2000) diff --git a/packages/firestore/test/unit/specs/remote_store_spec.test.ts b/packages/firestore/test/unit/specs/remote_store_spec.test.ts index 7c923aa67f..04e0325e62 100644 --- a/packages/firestore/test/unit/specs/remote_store_spec.test.ts +++ b/packages/firestore/test/unit/specs/remote_store_spec.test.ts @@ -20,6 +20,7 @@ import { doc, query } from '../../util/helpers'; import { describeSpec, specTest } from './describe_spec'; import { spec } from './spec_builder'; +import { RpcError } from './spec_rpc_error'; describeSpec('Remote store:', [], () => { specTest('Waits for watch to remove targets', [], () => { @@ -31,10 +32,12 @@ describeSpec('Remote store:', [], () => { .watchAcks(query1) .userUnlistens(query1) // Now we simulate a quick unlisten. .userListens(query1) // But add it back before watch acks it. + .watchUsesTargetIndex(0) .watchSends({ affects: [query1] }, doc1) // Should be ignored. .watchCurrents(query1, 'resume-token') .watchSnapshots(1000) .watchRemoves(query1) // Finally watch decides to ack the removal. + .watchUsesTargetIndex('latest') .watchAcksFull(query1, 1001, doc1) // Now watch should ack the query. .expectEvents(query1, { added: [doc1] }); // This should work now. }); @@ -58,11 +61,15 @@ describeSpec('Remote store:', [], () => { .watchSends({ affects: [query1] }, doc1) // Should be ignored. .watchCurrents(query1, 'resume-token') .watchSnapshots(1000) + .watchUsesTargetIndex(0) .watchRemoves(query1) // Finally watch decides to ack the FIRST removal. + .watchUsesTargetIndex(1) .watchAcksFull(query1, 1001, doc2) // Now watch should ack the second listen. .watchRemoves(query1) // Finally watch decides to ack the SECOND removal. + .watchUsesTargetIndex(2) .watchAcksFull(query1, 1001, doc3) // Now watch should ack the second listen. .watchRemoves(query1) // Finally watch decides to ack the THIRD removal. + .watchUsesTargetIndex(3) .watchAcksFull(query1, 1001, doc4) // Now watch should ack the query. .expectEvents(query1, { added: [doc4] }); // This should work now. }); @@ -115,4 +122,61 @@ describeSpec('Remote store:', [], () => { ); } ); + + // This flow was identified as a root cause of "pendingResponses is less than 0" (ca9 assertion) + specTest( + 'Handles removal of old target (with cause) after re-listen', + [], + () => { + const query1 = query('collection'); + return ( + spec() + .ensureManualLruGC() + .allowUnlistedTargetRemoval() + .userListens(query1) + .watchAcks(query1) + .userUnlistens(query1) + .userListens(query1) + .watchUsesTargetIndex(0) + // Use numerical code 8 for RESOURCE_EXHAUSTED + .watchRemoves(query1, new RpcError(8, 'Resource exhausted')) + .watchUsesTargetIndex('latest') + .watchAcks(query1) + .expectActiveTargets({ query: query1, resumeToken: '' }) + ); + } + ); + + specTest('Handles removal of old target after re-listen', [], () => { + const query1 = query('collection'); + return spec() + .ensureManualLruGC() + .userListens(query1) + .watchAcks(query1) + .userUnlistens(query1) + .userListens(query1) + .watchUsesTargetIndex(0) + .watchRemoves(query1) + .watchUsesTargetIndex('latest') + .watchAcks(query1) + .expectActiveTargets({ query: query1, resumeToken: '' }); + }); + + specTest( + 'Handles removal of target with cause after unlisten and ignores future messages', + [], + () => { + const query1 = query('collection'); + const doc1 = doc('collection/a', 1000, { key: 'a' }); + return spec() + .ensureManualLruGC() + .allowUnlistedTargetRemoval() + .userListens(query1) + .watchAcks(query1) + .userUnlistens(query1) + .watchRemoves(query1, new RpcError(8, 'Resource exhausted')) + .watchSends({ affects: [query1] }, doc1) + .expectActiveTargets(); + } + ); }); diff --git a/packages/firestore/test/unit/specs/spec_builder.ts b/packages/firestore/test/unit/specs/spec_builder.ts index afc6791dbd..3d27a63c35 100644 --- a/packages/firestore/test/unit/specs/spec_builder.ts +++ b/packages/firestore/test/unit/specs/spec_builder.ts @@ -265,6 +265,16 @@ export class SpecBuilder { return this; } + /** + * By default the spec test runner does not allow removal of a non-active target, + * but this scenario is possible in the real world due to a client / server race, + * and therefore must be allowed for some spec tests. + */ + allowUnlistedTargetRemoval(): this { + this.config.allowUnlistedTargetRemoval = true; + return this; + } + withMaxConcurrentLimboResolutions(value?: number): this { this.config.maxConcurrentLimboResolutions = value; return this; @@ -782,7 +792,55 @@ export class SpecBuilder { watchRemove: { targetIds: [this.getTargetId(query)], cause } }; if (cause) { - delete this.activeTargets[this.getTargetId(query)]; + if (!this.config.allowUnlistedTargetRemoval) { + delete this.activeTargets[this.getTargetId(query)]; + } + this.currentStep.expectedState = { + activeTargets: { ...this.activeTargets } + }; + } + return this; + } + + /** + * After setting the remote target index, for any watch* step following + * this step, the simulated watch message will use the Nth remote target ID + * that was associated with this query + * + * .userListens(q1) // remote target id: 1002, index: 0 + * .userUnlistens(q1)) + * .userListens(q1) // remote target id: 1004, index: 1 + * .userUnlistens(q1)) + * .watchUsesTargetIndex(0) + * .watchAcks(q1) //will ack 1002 + * .watchUsesTargetIndex(1) + * .watchAcks(q1) //will ack 1004 + */ + watchUsesTargetIndex(remoteTargetIndex: number | 'latest' | 'last'): this { + this.nextStep(); + this.currentStep = { + watchUsesTargetIndex: + remoteTargetIndex === 'last' ? 'latest' : remoteTargetIndex + }; + return this; + } + + private watchRemovesWithTargetIndex( + query: Query, + remoteTargetIndex: number | undefined, + cause?: RpcError + ): this { + this.nextStep(); + this.currentStep = { + watchRemove: { + targetIds: [this.getTargetId(query)], + cause + } + }; + if (cause) { + if (!this.config.allowUnlistedTargetRemoval) { + delete this.activeTargets[this.getTargetId(query)]; + } this.currentStep.expectedState = { activeTargets: { ...this.activeTargets } }; diff --git a/packages/firestore/test/unit/specs/spec_test_runner.ts b/packages/firestore/test/unit/specs/spec_test_runner.ts index 50806cb2a4..438484ac71 100644 --- a/packages/firestore/test/unit/specs/spec_test_runner.ts +++ b/packages/firestore/test/unit/specs/spec_test_runner.ts @@ -65,7 +65,7 @@ import { triggerRemoteStoreListen, triggerRemoteStoreUnlisten } from '../../../src/core/sync_engine_impl'; -import { TargetId } from '../../../src/core/types'; +import { RemoteTargetId, TargetId } from '../../../src/core/types'; import { ChangeType, DocumentViewChange @@ -107,7 +107,8 @@ import { remoteStoreShutdown, remoteStoreEnableNetwork, remoteStoreHandleCredentialChange, - outstandingWrites + outstandingWrites, + remoteStoreGetRemoteTargetId } from '../../../src/remote/remote_store'; import { mapCodeFromRpcCode } from '../../../src/remote/rpc_error'; import { @@ -242,6 +243,19 @@ abstract class TestRunner { q => canonifyQuery(q), queryEquals ); + /** + * Maps SDK target IDs (assigned by the spec builder based on the query) to + * the list of remote target IDs generated by `RemoteStore`. + * + * In spec tests, the spec builder reuses the same SDK ID if the user unlistens + * and listens again to the same query. However, `RemoteStore` generates a + * brand new, unique remote ID every time a new listen is opened on the stream. + * To track these correctly, we map the SDK ID to a list of remote IDs and use + * a FIFO heuristic to resolve which remote ID an event (like ACK or REMOVE) + * applies to. + */ + private sdkToRemoteTargetIds = new Map(); + private currentRemoteTargetIndex?: number; private expectedActiveLimboDocs: DocumentKey[]; private expectedEnqueuedLimboDocs: DocumentKey[]; @@ -270,7 +284,7 @@ abstract class TestRunner { constructor( private sharedWrites: SharedWriteTracker, clientIndex: number, - config: SpecConfig + protected config: SpecConfig ) { this.clientId = `client${clientIndex}`; this.databaseInfo = new DatabaseInfo( @@ -467,6 +481,8 @@ abstract class TestRunner { return this.doRestart(); } else if ('shutdown' in step) { return this.doShutdown(); + } else if ('watchUsesTargetIndex' in step) { + return this.doUseTargetIndex(step.watchUsesTargetIndex!); } else if ('applyClientState' in step) { // PORTING NOTE: Only used by web multi-tab tests. return this.doApplyClientState(step.applyClientState!); @@ -483,6 +499,11 @@ abstract class TestRunner { } } + private doUseTargetIndex(index: number | 'latest'): Promise { + this.currentRemoteTargetIndex = index === 'latest' ? undefined : index; + return Promise.resolve(); + } + private async doListen(listenSpec: SpecUserListen): Promise { let targetFailed = false; @@ -510,6 +531,21 @@ abstract class TestRunner { eventManagerListen(this.eventManager, queryListener) ); + const sdkTargetId = listenSpec.targetId; + + // The remote store will map the query listener to a new remoteTargetID + const remoteTargetId = remoteStoreGetRemoteTargetId( + this.remoteStore, + sdkTargetId + ); + if (remoteTargetId !== undefined) { + // Add this new remoteTargetId to a list mapping the sdk target ID to the + // remote target ID + const list = this.sdkToRemoteTargetIds.get(sdkTargetId) || []; + list.push(remoteTargetId); + this.sdkToRemoteTargetIds.set(sdkTargetId, list); + } + if (targetFailed) { expect(this.persistence.injectFailures).contains('Allocate target'); } else { @@ -626,29 +662,78 @@ abstract class TestRunner { ); } + /** + * Resolves an SDK target ID to the appropriate remote target ID. + * + * Because multiple remote target IDs can be associated with a single SDK target ID over time, + * this method allows the caller to specify the index of the remote target ID + * to lookup for the SDK target ID. If sdkTargetIndex is undefined, then + * the latest remote target ID is used. + */ + private getRemoteTargetId( + sdkTargetId: TargetId, + isWatchStep: boolean = false + ): RemoteTargetId { + // Get and update the list with the current mapping from RemoteStore + // if the remote target ID is not already in the sdkToRemoteTargetIds list + const remoteStoreId = remoteStoreGetRemoteTargetId( + this.remoteStore, + sdkTargetId + ); + const list = this.sdkToRemoteTargetIds.get(sdkTargetId) || []; + if (remoteStoreId !== undefined && !list.includes(remoteStoreId)) { + console.warn( + `The sdk target ID ${sdkTargetId} was mapped to remote target id ${remoteStoreId} but was not found in the TestRunner sdkToRemoteTargetIds list ${this.sdkToRemoteTargetIds}` + ); + list.push(remoteStoreId); + this.sdkToRemoteTargetIds.set(sdkTargetId, list); + } + + if (list.length === 0) { + console.warn( + `Mapping not found for SDK ID ${JSON.stringify(sdkTargetId)}` + ); + return sdkTargetId as RemoteTargetId; + } + + if (isWatchStep && this.currentRemoteTargetIndex !== undefined) { + return list[this.currentRemoteTargetIndex]; + } + + // Default: return the latest one. + return list[list.length - 1]; + } + private doWatchAck(ackedTargets: SpecWatchAck): Promise { + const remoteTargetIds = ackedTargets.map(ackedTarget => + this.getRemoteTargetId(ackedTarget, true) + ); const change = new WatchTargetChange( WatchTargetChangeState.Added, - ackedTargets + remoteTargetIds ); return this.doWatchEvent(change); } private doWatchCurrent(currentTargets: SpecWatchCurrent): Promise { const targets = currentTargets[0]; + const remoteTargetIds = targets.map(id => this.getRemoteTargetId(id, true)); const resumeToken = byteStringFromString(currentTargets[1]); const change = new WatchTargetChange( WatchTargetChangeState.Current, - targets, + remoteTargetIds, resumeToken ); return this.doWatchEvent(change); } private doWatchReset(targetIds: SpecWatchReset): Promise { + const remoteTargetIds = targetIds.map(id => + this.getRemoteTargetId(id, true) + ); const change = new WatchTargetChange( WatchTargetChangeState.Reset, - targetIds + remoteTargetIds ); return this.doWatchEvent(change); } @@ -660,9 +745,15 @@ abstract class TestRunner { mapCodeFromRpcCode(removed.cause.code), removed.cause.message ); + const mappedIds = new Map(); + const remoteTargetIds = removed.targetIds.map(id => { + const remoteId = this.getRemoteTargetId(id, true); + mappedIds.set(id, remoteId); + return remoteId; + }); const change = new WatchTargetChange( WatchTargetChangeState.Removed, - removed.targetIds, + remoteTargetIds, ByteString.EMPTY_BYTE_STRING, cause || null ); @@ -672,17 +763,28 @@ abstract class TestRunner { // with a server-side removal), but we want to pay extra careful // attention in tests that we only remove targets we listened too. removed.targetIds.forEach(targetId => { - expect( - this.connection.activeTargets[targetId], - 'Removing a non-active target' - ).to.exist; - delete this.connection.activeTargets[targetId]; + const remoteTargetId = mappedIds.get(targetId)!; + if (!this.config.allowUnlistedTargetRemoval) { + expect( + this.connection.activeTargets[remoteTargetId], + 'Removing a non-active target' + ).to.exist; + } + delete this.connection.activeTargets[remoteTargetId]; }); } + return this.doWatchEvent(change); } private doWatchEntity(watchEntity: SpecWatchEntity): Promise { + const remoteTargets = (watchEntity.targets || []).map(id => + this.getRemoteTargetId(id, true) + ); + const remoteRemovedTargets = (watchEntity.removedTargets || []).map(id => + this.getRemoteTargetId(id, true) + ); + if (watchEntity.docs) { debugAssert( !watchEntity.doc, @@ -710,8 +812,8 @@ abstract class TestRunner { document.setHasLocalMutations(); } const change = new DocumentWatchChange( - watchEntity.targets || [], - watchEntity.removedTargets || [], + remoteTargets, + remoteRemovedTargets, document.key, document ); @@ -719,8 +821,8 @@ abstract class TestRunner { } else if (watchEntity.key) { const documentKey = key(watchEntity.key); const change = new DocumentWatchChange( - watchEntity.targets || [], - watchEntity.removedTargets || [], + remoteTargets, + remoteRemovedTargets, documentKey, null ); @@ -736,8 +838,9 @@ abstract class TestRunner { targetIds.length === 1, 'ExistenceFilters currently support exactly one target only.' ); + const remoteTargetId = this.getRemoteTargetId(targetIds[0], true); const filter = new ExistenceFilter(keys.length, bloomFilter); - const change = new ExistenceFilterChange(targetIds[0], filter); + const change = new ExistenceFilterChange(remoteTargetId, filter); return this.doWatchEvent(change); } @@ -745,12 +848,15 @@ abstract class TestRunner { // The client will only respond to watchSnapshots if they are on a target // change with an empty set of target IDs. So we should be sure to send a // separate event. + const remoteTargetIds = watchSnapshot.targetIds.map(id => + this.getRemoteTargetId(id, true) + ); const protoJSON: api.ListenResponse = { targetChange: { readTime: toVersion(this.serializer, version(watchSnapshot.version)), // Convert to base64 string so it can later be parsed into ByteString. resumeToken: encodeBase64(watchSnapshot.resumeToken || ''), - targetIds: watchSnapshot.targetIds + targetIds: remoteTargetIds } }; this.connection.watchStream!.callOnMessage(protoJSON); @@ -876,6 +982,8 @@ abstract class TestRunner { private async doRestart(): Promise { // Reinitialize everything. await this.doShutdown(); + this.sdkToRemoteTargetIds.clear(); + this.currentRemoteTargetIndex = undefined; // We have to schedule the starts, otherwise we could end up with // interleaved events. @@ -1141,17 +1249,18 @@ abstract class TestRunner { } const actualTargets = { ...this.connection.activeTargets }; - this.expectedActiveTargets.forEach((expected, targetId) => { - expect(actualTargets[targetId]).to.not.equal( + this.expectedActiveTargets.forEach((expected, sdkTargetId) => { + const remoteTargetId = this.getRemoteTargetId(sdkTargetId); + expect(actualTargets[remoteTargetId]).to.not.equal( undefined, 'Expected active target not found: ' + JSON.stringify(expected) ); const { target: actualTarget, labels: actualLabels } = - actualTargets[targetId]; + actualTargets[remoteTargetId]; let targetData = new TargetData( queryToTarget(parseQuery(expected.queries[0])), - targetId, + remoteTargetId, expected.targetPurpose ?? TargetPurpose.Listen, ARBITRARY_SEQUENCE_NUMBER ); @@ -1190,7 +1299,7 @@ abstract class TestRunner { expectedTarget.expectedCount ); } - delete actualTargets[targetId]; + delete actualTargets[remoteTargetId]; }); expect(objectSize(actualTargets)).to.equal( 0, @@ -1404,6 +1513,9 @@ export interface SpecConfig { /** The number of active clients for this test run. */ numClients: number; + /** A boolean to allow removal of non-active targets by the server. */ + allowUnlistedTargetRemoval?: boolean; + /** * The maximum number of concurrently-active listens for limbo resolutions. * This value must be strictly greater than zero, or undefined to use the @@ -1535,6 +1647,9 @@ export interface SpecStep { /** Shut down the client and close it network connection. */ shutdown?: true; + /** Sets the remote target index to be used by following steps. */ + watchUsesTargetIndex?: number | 'latest'; + /** * Optional list of expected events. * If not provided, the test will fail if the step causes events to be raised. @@ -1577,7 +1692,7 @@ export type SpecUserPatch = [string, JsonObject]; /** key */ export type SpecUserDelete = string; -/** [, ...] */ +/** [{sdkTargetId: , remoteTargetIndex: }, ...] */ export type SpecWatchAck = TargetId[]; /** [[, ...], ] */ diff --git a/packages/firestore/test/util/helpers.ts b/packages/firestore/test/util/helpers.ts index 1ddaf174b1..dbeeac4108 100644 --- a/packages/firestore/test/util/helpers.ts +++ b/packages/firestore/test/util/helpers.ts @@ -37,7 +37,7 @@ import { queryWithAddedOrderBy } from '../../src/core/query'; import { SnapshotVersion } from '../../src/core/snapshot_version'; -import { TargetId } from '../../src/core/types'; +import { RemoteTargetId, TargetId } from '../../src/core/types'; import { AddedLimboDocument, LimboDocumentChange, @@ -401,11 +401,11 @@ export function query( return q; } -export function targetData( - targetId: TargetId, +export function targetData( + targetId: T, queryPurpose: TargetPurpose, path: string -): TargetData { +): TargetData { // Arbitrary value. const sequenceNumber = 0; return new TargetData( @@ -417,10 +417,10 @@ export function targetData( } export function noChangeEvent( - targetId: number, + targetId: RemoteTargetId, snapshotVersion: number, resumeToken: ByteString = ByteString.EMPTY_BYTE_STRING -): RemoteEvent { +): RemoteEvent { const aggregator = new WatchChangeAggregator({ getRemoteKeysForTarget: () => documentKeySet(), getTargetDataForTarget: targetId => @@ -434,16 +434,18 @@ export function noChangeEvent( resumeToken ) ); - return aggregator.createRemoteEvent(version(snapshotVersion)); + return castRemoteEvent( + aggregator.createRemoteEvent(version(snapshotVersion)) + ); } export function existenceFilterEvent( - targetId: number, + targetId: RemoteTargetId, syncedKeys: DocumentKeySet, remoteCount: number, snapshotVersion: number, bloomFilter?: api.BloomFilter -): RemoteEvent { +): RemoteEvent { const aggregator = new WatchChangeAggregator({ getRemoteKeysForTarget: () => syncedKeys, getTargetDataForTarget: targetId => @@ -456,14 +458,16 @@ export function existenceFilterEvent( new ExistenceFilter(remoteCount, bloomFilter) ) ); - return aggregator.createRemoteEvent(version(snapshotVersion)); + return castRemoteEvent( + aggregator.createRemoteEvent(version(snapshotVersion)) + ); } export function docAddedRemoteEvent( docOrDocs: MutableDocument | MutableDocument[], - updatedInTargets?: TargetId[], - removedFromTargets?: TargetId[], - activeTargets?: TargetId[] + updatedInTargets?: RemoteTargetId[] | TargetId[], + removedFromTargets?: RemoteTargetId[] | TargetId[], + activeTargets?: RemoteTargetId[] | TargetId[] ): RemoteEvent { const docs = Array.isArray(docOrDocs) ? docOrDocs : [docOrDocs]; debugAssert(docs.length !== 0, 'Cannot pass empty docs array'); @@ -497,8 +501,8 @@ export function docAddedRemoteEvent( "Docs from remote updates shouldn't have local changes." ); const docChange = new DocumentWatchChange( - updatedInTargets || [], - removedFromTargets || [], + castTargetIds(updatedInTargets || []), + castTargetIds(removedFromTargets || []), doc.key, doc ); @@ -506,22 +510,22 @@ export function docAddedRemoteEvent( version = doc.version.compareTo(version) > 0 ? doc.version : version; } - return aggregator.createRemoteEvent(version); + return castRemoteEvent(aggregator.createRemoteEvent(version)); } export function docUpdateRemoteEvent( doc: MutableDocument, - updatedInTargets?: TargetId[], - removedFromTargets?: TargetId[], - limboTargets?: TargetId[] + updatedInTargets?: RemoteTargetId[], + removedFromTargets?: RemoteTargetId[], + limboTargets?: RemoteTargetId[] ): RemoteEvent { debugAssert( !doc.hasLocalMutations, "Docs from remote updates shouldn't have local changes." ); const docChange = new DocumentWatchChange( - updatedInTargets || [], - removedFromTargets || [], + castTargetIds(updatedInTargets || []), + castTargetIds(removedFromTargets || []), doc.key, doc ); @@ -537,7 +541,19 @@ export function docUpdateRemoteEvent( getDatabaseId: () => TEST_DATABASE_ID }); aggregator.handleDocumentChange(docChange); - return aggregator.createRemoteEvent(doc.version); + return castRemoteEvent(aggregator.createRemoteEvent(doc.version)); +} + +export function castRemoteEvent( + src: unknown +): RemoteEvent { + return src as RemoteEvent; +} + +export function castTargetIds( + src: unknown +): T[] { + return src as T[]; } export class TestBundledDocuments { From 3b8713433d96eb05ef7cab3a549f4d536cc1927e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 09:28:14 -0700 Subject: [PATCH 168/174] build(deps): bump axios from 1.13.5 to 1.15.2 (#9860) Bumps [axios](https://github.com/axios/axios) from 1.13.5 to 1.15.2. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.13.5...v1.15.2) --- updated-dependencies: - dependency-name: axios dependency-version: 1.15.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 83f738e592..06c9a44bb0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4776,13 +4776,13 @@ aws4@^1.8.0: integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== axios@^1.6.0: - version "1.13.5" - resolved "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz#5e464688fa127e11a660a2c49441c009f6567a43" - integrity sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q== + version "1.15.2" + resolved "https://registry.npmjs.org/axios/-/axios-1.15.2.tgz#eb8fb6d30349abace6ade5b4cb4d9e8a0dc23e5b" + integrity sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A== dependencies: follow-redirects "^1.15.11" form-data "^4.0.5" - proxy-from-env "^1.1.0" + proxy-from-env "^2.1.0" b4a@^1.6.4: version "1.6.7" @@ -13951,6 +13951,11 @@ proxy-from-env@^1.1.0: resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== +proxy-from-env@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz#a7487568adad577cfaaa7e88c49cab3ab3081aba" + integrity sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA== + prr@~1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" From 330a387df59fbe23b5c32bbd120f7c5dce138a14 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 4 May 2026 11:20:39 -0700 Subject: [PATCH 169/174] chore: migrate test functions to v2 (#9910) --- config/functions/index.js | 172 ++++++++---------- .../functions-compat/src/callable.test.ts | 18 +- packages/functions/src/callable.test.ts | 26 +-- 3 files changed, 97 insertions(+), 119 deletions(-) diff --git a/config/functions/index.js b/config/functions/index.js index d992251caf..0827da5544 100644 --- a/config/functions/index.js +++ b/config/functions/index.js @@ -16,143 +16,121 @@ */ const assert = require('assert'); -const cors = require('cors')({ origin: true }); -const functions = require('firebase-functions/v1'); +const { onRequest, onCall } = require('firebase-functions/v2/https'); /* * These backend test helpers are copied from the iOS and Android SDKs, but are * not all implemented as tests in the JS SDK yet. */ -exports.dataTest = functions.https.onRequest((request, response) => { - cors(request, response, () => { - assert.deepEqual(request.body, { - data: { - bool: true, - int: 2, - // TODO(klimt): Should we add an API for encoding longs? - /*long: { +exports.dataTestv2 = onRequest({ cors: true }, (request, response) => { + assert.deepEqual(request.body, { + data: { + bool: true, + int: 2, + // TODO(klimt): Should we add an API for encoding longs? + /*long: { value: '3', '@type': 'type.googleapis.com/google.protobuf.Int64Value', },*/ - str: 'four', - array: [5, 6], - null: null - } - }); - response.send({ - data: { - message: 'stub response', - code: 42, - long: { - value: '420', - '@type': 'type.googleapis.com/google.protobuf.Int64Value' - } + str: 'four', + array: [5, 6], + null: null + } + }); + response.send({ + data: { + message: 'stub response', + code: 42, + long: { + value: '420', + '@type': 'type.googleapis.com/google.protobuf.Int64Value' } - }); + } }); }); -exports.scalarTest = functions.https.onRequest((request, response) => { - cors(request, response, () => { - assert.deepEqual(request.body, { data: 17 }); - response.send({ data: 76 }); - }); +exports.scalarTestv2 = onRequest({ cors: true }, (request, response) => { + assert.deepEqual(request.body, { data: 17 }); + response.send({ data: 76 }); }); -exports.tokenTest = functions.https.onRequest((request, response) => { - cors(request, response, () => { - assert.equal(request.get('Authorization'), 'Bearer token'); - assert.deepEqual(request.body, { data: {} }); - response.send({ data: {} }); - }); +exports.tokenTestv2 = onRequest({ cors: true }, (request, response) => { + assert.equal(request.get('Authorization'), 'Bearer token'); + assert.deepEqual(request.body, { data: {} }); + response.send({ data: {} }); }); -exports.instanceIdTest = functions.https.onRequest((request, response) => { - cors(request, response, () => { - assert.equal(request.get('Firebase-Instance-ID-Token'), 'iid'); - assert.deepEqual(request.body, { data: {} }); - response.send({ data: {} }); - }); +exports.instanceIdTestv2 = onRequest({ cors: true }, (request, response) => { + assert.equal(request.get('Firebase-Instance-ID-Token'), 'iid'); + assert.deepEqual(request.body, { data: {} }); + response.send({ data: {} }); }); -exports.appCheckTest = functions.https.onRequest((request, response) => { - cors(request, response, () => { - const token = request.get('X-Firebase-AppCheck'); - assert.equal(token !== undefined, true); - assert.deepEqual(request.body, { data: {} }); - response.send({ data: { token } }); - }); +exports.appCheckTestv2 = onRequest({ cors: true }, (request, response) => { + const token = request.get('X-Firebase-AppCheck'); + assert.equal(token !== undefined, true); + assert.deepEqual(request.body, { data: {} }); + response.send({ data: { token } }); }); -exports.nullTest = functions.https.onRequest((request, response) => { - cors(request, response, () => { - assert.deepEqual(request.body, { data: null }); - response.send({ data: null }); - }); +exports.nullTestv2 = onRequest({ cors: true }, (request, response) => { + assert.deepEqual(request.body, { data: null }); + response.send({ data: null }); }); -exports.missingResultTest = functions.https.onRequest((request, response) => { - cors(request, response, () => { - assert.deepEqual(request.body, { data: null }); - response.send({}); - }); +exports.missingResultTestv2 = onRequest({ cors: true }, (request, response) => { + assert.deepEqual(request.body, { data: null }); + response.send({}); }); -exports.unhandledErrorTest = functions.https.onRequest((request, response) => { - cors(request, response, () => { +exports.unhandledErrorTestv2 = onRequest( + { cors: true }, + (request, response) => { // Fail in a way that the client shouldn't see. throw 'nope'; - }); -}); + } +); -exports.unknownErrorTest = functions.https.onRequest((request, response) => { - cors(request, response, () => { - // Send an http error with a body with an explicit code. - response.status(400).send({ - error: { - status: 'THIS_IS_NOT_VALID', - message: 'this should be ignored' - } - }); +exports.unknownErrorTestv2 = onRequest({ cors: true }, (request, response) => { + // Send an http error with a body with an explicit code. + response.status(400).send({ + error: { + status: 'THIS_IS_NOT_VALID', + message: 'this should be ignored' + } }); }); -exports.explicitErrorTest = functions.https.onRequest((request, response) => { - cors(request, response, () => { - // Send an http error with a body with an explicit code. - response.status(400).send({ - error: { - status: 'OUT_OF_RANGE', - message: 'explicit nope', - details: { - start: 10, - end: 20, - long: { - value: '30', - '@type': 'type.googleapis.com/google.protobuf.Int64Value' - } +exports.explicitErrorTestv2 = onRequest({ cors: true }, (request, response) => { + // Send an http error with a body with an explicit code. + response.status(400).send({ + error: { + status: 'OUT_OF_RANGE', + message: 'explicit nope', + details: { + start: 10, + end: 20, + long: { + value: '30', + '@type': 'type.googleapis.com/google.protobuf.Int64Value' } } - }); + } }); }); -exports.httpErrorTest = functions.https.onRequest((request, response) => { - cors(request, response, () => { - // Send an http error with no body. - response.status(400).send(); - }); +exports.httpErrorTestv2 = onRequest({ cors: true }, (request, response) => { + // Send an http error with no body. + response.status(400).send(); }); -exports.timeoutTest = functions.https.onRequest((request, response) => { - cors(request, response, () => { - // Wait for longer than 500ms. - setTimeout(() => response.send({ data: true }), 500); - }); +exports.timeoutTestv2 = onRequest({ cors: true }, (request, response) => { + // Wait for longer than 500ms. + setTimeout(() => response.send({ data: true }), 500); }); // Used by E2E test. -exports.callTest = functions.https.onCall((data, context) => { +exports.callTestv2 = onCall(request => { return { word: 'hellooo' }; }); diff --git a/packages/functions-compat/src/callable.test.ts b/packages/functions-compat/src/callable.test.ts index 222216c36b..4bb6a58090 100644 --- a/packages/functions-compat/src/callable.test.ts +++ b/packages/functions-compat/src/callable.test.ts @@ -73,7 +73,7 @@ describe('Firebase Functions > Call', () => { null: null }; - const func = functions.httpsCallable('dataTest'); + const func = functions.httpsCallable('dataTestv2'); const result = await func(data); expect(result.data).to.deep.equal({ @@ -85,14 +85,14 @@ describe('Firebase Functions > Call', () => { it('scalars', async () => { const functions = createTestService(app, region); - const func = functions.httpsCallable('scalarTest'); + const func = functions.httpsCallable('scalarTestv2'); const result = await func(17); expect(result.data).to.equal(76); }); it('null', async () => { const functions = createTestService(app, region); - const func = functions.httpsCallable('nullTest'); + const func = functions.httpsCallable('nullTestv2'); let result = await func(null); expect(result.data).to.be.null; @@ -103,7 +103,7 @@ describe('Firebase Functions > Call', () => { it('missing result', async () => { const functions = createTestService(app, region); - const func = functions.httpsCallable('missingResultTest'); + const func = functions.httpsCallable('missingResultTestv2'); await expectError( func(), 'functions/internal', @@ -113,19 +113,19 @@ describe('Firebase Functions > Call', () => { it('unhandled error', async () => { const functions = createTestService(app, region); - const func = functions.httpsCallable('unhandledErrorTest'); + const func = functions.httpsCallable('unhandledErrorTestv2'); await expectError(func(), 'functions/internal', 'internal'); }); it('unknown error', async () => { const functions = createTestService(app, region); - const func = functions.httpsCallable('unknownErrorTest'); + const func = functions.httpsCallable('unknownErrorTestv2'); await expectError(func(), 'functions/internal', 'internal'); }); it('explicit error', async () => { const functions = createTestService(app, region); - const func = functions.httpsCallable('explicitErrorTest'); + const func = functions.httpsCallable('explicitErrorTestv2'); await expectError(func(), 'functions/out-of-range', 'explicit nope', { start: 10, end: 20, @@ -135,13 +135,13 @@ describe('Firebase Functions > Call', () => { it('http error', async () => { const functions = createTestService(app, region); - const func = functions.httpsCallable('httpErrorTest'); + const func = functions.httpsCallable('httpErrorTestv2'); await expectError(func(), 'functions/invalid-argument', 'invalid-argument'); }); it('timeout', async () => { const functions = createTestService(app, region); - const func = functions.httpsCallable('timeoutTest', { timeout: 10 }); + const func = functions.httpsCallable('timeoutTestv2', { timeout: 10 }); await expectError( func(), 'functions/deadline-exceeded', diff --git a/packages/functions/src/callable.test.ts b/packages/functions/src/callable.test.ts index 724efc39c9..c0f398c0b7 100644 --- a/packages/functions/src/callable.test.ts +++ b/packages/functions/src/callable.test.ts @@ -100,7 +100,7 @@ describe('Firebase Functions > Call', () => { const func = httpsCallable< Record, { message: string; code: number; long: number } - >(functions, 'dataTest'); + >(functions, 'dataTestv2'); const result = await func(data); expect(result.data).to.deep.equal({ @@ -112,7 +112,7 @@ describe('Firebase Functions > Call', () => { it('scalars', async () => { const functions = createTestService(app, region); - const func = httpsCallable(functions, 'scalarTest'); + const func = httpsCallable(functions, 'scalarTestv2'); const result = await func(17); expect(result.data).to.equal(76); }); @@ -134,7 +134,7 @@ describe('Firebase Functions > Call', () => { // Stub out the internals to get an auth token. const stub = sinon.stub(authMock, 'getToken').callThrough(); - const func = httpsCallable(functions, 'tokenTest'); + const func = httpsCallable(functions, 'tokenTestv2'); const result = await func({}); expect(result.data).to.deep.equal({}); @@ -167,7 +167,7 @@ describe('Firebase Functions > Call', () => { // Stub out the internals to get an app check token. const stub = sinon.stub(appCheckMock, 'getToken').callThrough(); - const func = httpsCallable(functions, 'appCheckTest'); + const func = httpsCallable(functions, 'appCheckTestv2'); const result = await func({}); expect(result.data).to.deep.equal({ token: 'app-check-token' }); @@ -200,7 +200,7 @@ describe('Firebase Functions > Call', () => { // Stub out the internals to get an app check token. const stub = sinon.stub(appCheckMock, 'getLimitedUseToken').callThrough(); - const func = httpsCallable(functions, 'appCheckTest', { + const func = httpsCallable(functions, 'appCheckTestv2', { limitedUseAppCheckTokens: true }); const result = await func({}); @@ -244,7 +244,7 @@ describe('Firebase Functions > Call', () => { const stub = sinon.stub(messagingMock, 'getToken').callThrough(); sinon.stub(Notification, 'permission').value('granted'); - const func = httpsCallable(functions, 'instanceIdTest'); + const func = httpsCallable(functions, 'instanceIdTestv2'); const result = await func({}); expect(result.data).to.deep.equal({}); @@ -254,7 +254,7 @@ describe('Firebase Functions > Call', () => { it('null', async () => { const functions = createTestService(app, region); - const func = httpsCallable(functions, 'nullTest'); + const func = httpsCallable(functions, 'nullTestv2'); let result = await func(null); expect(result.data).to.be.null; @@ -265,25 +265,25 @@ describe('Firebase Functions > Call', () => { it('missing result', async () => { const functions = createTestService(app, region); - const func = httpsCallable(functions, 'missingResultTest'); + const func = httpsCallable(functions, 'missingResultTestv2'); await expectError(func(), 'internal', 'Response is missing data field.'); }); it('unhandled error', async () => { const functions = createTestService(app, region); - const func = httpsCallable(functions, 'unhandledErrorTest'); + const func = httpsCallable(functions, 'unhandledErrorTestv2'); await expectError(func(), 'internal', 'internal'); }); it('unknown error', async () => { const functions = createTestService(app, region); - const func = httpsCallable(functions, 'unknownErrorTest'); + const func = httpsCallable(functions, 'unknownErrorTestv2'); await expectError(func(), 'internal', 'internal'); }); it('explicit error', async () => { const functions = createTestService(app, region); - const func = httpsCallable(functions, 'explicitErrorTest'); + const func = httpsCallable(functions, 'explicitErrorTestv2'); await expectError(func(), 'out-of-range', 'explicit nope', { start: 10, end: 20, @@ -293,13 +293,13 @@ describe('Firebase Functions > Call', () => { it('http error', async () => { const functions = createTestService(app, region); - const func = httpsCallable(functions, 'httpErrorTest'); + const func = httpsCallable(functions, 'httpErrorTestv2'); await expectError(func(), 'invalid-argument', 'invalid-argument'); }); it('timeout', async () => { const functions = createTestService(app, region); - const func = httpsCallable(functions, 'timeoutTest', { timeout: 10 }); + const func = httpsCallable(functions, 'timeoutTestv2', { timeout: 10 }); await expectError(func(), 'deadline-exceeded', 'deadline-exceeded'); }); }); From 714b41dcc55339f94f904558ff190c5bdc9ac49f Mon Sep 17 00:00:00 2001 From: Stephen Rosa <84193009+stephenarosaj@users.noreply.github.com> Date: Tue, 5 May 2026 14:41:15 -0400 Subject: [PATCH 170/174] feat(data-connect): add de-duplication, resume, and intelligent reconnection with backoff (#9905) * chore(data-connect): update documentation and names in stream transport (#9846) * rename in preparation for future changes * finish renaming + updating comments * minor typo fix * feat(data-connect): add query de-duplication to stream transport (#9850) * rename in preparation for future changes * finish renaming + updating comments * minor typo fix * add de-duping - now for tests * add de-duplication tests for invokeQuery * finish invoke operation dedupe tests * add subscribe de-duping as well * add more query dedupe tests * chore(data-connect): clean up streaming tests a bit (#9851) * rename in preparation for future changes * finish renaming + updating comments * minor typo fix * add de-duping - now for tests * add de-duplication tests for invokeQuery * finish invoke operation dedupe tests * add subscribe de-duping as well * add more query dedupe tests * clean up stream tests * clean up promise types in streaming tests * Pasta/bucatini resume refactor (#9885) * add test changes * add transportchanges * finalize changes, run yarn format * finalize changes based on reviewer feedback * feat(data-connect): add prefer resume over execute optimization to stream transport (#9879) * initial implementation - now for testing * finish tests * merge pasta/bucatini-resume-refactor * address reviewer comments * remove old comments * address reviewer comments * feat(data-connect): add intelligent reconnection to streaming transport and harden disconnect/cleanup functionality (#9893) * WIP * first pass * fixing names * tidying up, fixing tests * fixed tests * address reviewer comments * address reviewer comments and harden close/cleanup lifecycle * address reviewer comments * make listener registering and unregistering more robust * merge main, add changeset --- .changeset/nervous-carpets-approve.md | 6 + packages/data-connect/src/network/manager.ts | 2 +- .../src/network/stream/streamTransport.ts | 831 ++++++++---- .../src/network/stream/websocket.ts | 33 +- .../test/unit/streamTransport.test.ts | 1129 ++++++++++++++--- .../test/unit/transportManager.test.ts | 7 +- .../test/unit/websocketTransport.test.ts | 8 +- 7 files changed, 1613 insertions(+), 403 deletions(-) create mode 100644 .changeset/nervous-carpets-approve.md diff --git a/.changeset/nervous-carpets-approve.md b/.changeset/nervous-carpets-approve.md new file mode 100644 index 0000000000..731a311799 --- /dev/null +++ b/.changeset/nervous-carpets-approve.md @@ -0,0 +1,6 @@ +--- +'@firebase/data-connect': minor +'firebase': minor +--- + +Hardened the Firebase SQL Connect streaming transport with intelligent reconnection, query de-duplication, and resume optimizations. diff --git a/packages/data-connect/src/network/manager.ts b/packages/data-connect/src/network/manager.ts index 6b8c6179e8..9f675d588f 100644 --- a/packages/data-connect/src/network/manager.ts +++ b/packages/data-connect/src/network/manager.ts @@ -86,7 +86,7 @@ export class DataConnectTransportManager this.transportOptions.sslEnabled ); } - this.streamTransport.onGracefulStreamClose = () => { + this.streamTransport.onCloseCallback = () => { this.streamTransport = undefined; }; } diff --git a/packages/data-connect/src/network/stream/streamTransport.ts b/packages/data-connect/src/network/stream/streamTransport.ts index 47063fac82..4f32492f77 100644 --- a/packages/data-connect/src/network/stream/streamTransport.ts +++ b/packages/data-connect/src/network/stream/streamTransport.ts @@ -15,15 +15,22 @@ * limitations under the License. */ +import { FirebaseError } from '@firebase/util'; + +import { DataConnectOptions, TransportOptions } from '../../api/DataConnect'; +import { AppCheckTokenProvider } from '../../core/AppCheckTokenProvider'; import { Code, DataConnectError, DataConnectOperationError, DataConnectOperationFailureResponse } from '../../core/error'; -import { logError } from '../../logger'; +import { AuthTokenProvider } from '../../core/FirebaseAuthProvider'; +import { logError, logDebug } from '../../logger'; import { AbstractDataConnectTransport, + CallerSdkType, + CallerSdkTypeEnum, DataConnectResponse, SubscribeObserver, getGoogApiClientValue @@ -38,57 +45,138 @@ import { SubscribeStreamRequest } from './wire'; -/** The request id of the first request over the stream */ +/** The Request ID of the first request over the stream */ const FIRST_REQUEST_ID = 1; -/** Time to wait before closing an idle connection (no active subscriptions) */ +/** Time to wait before closing an idle connection (no active subscriptions). */ const IDLE_CONNECTION_TIMEOUT_MS = 60 * 1000; // 1 minute +/** Initial reconnect delay in ms */ +const INITIAL_RECONNECT_DELAY_MS = 1000; +/** Max reconnect delay in ms */ +const MAX_RECONNECT_DELAY_MS = 30000; +/** Max random jitter to add to reconnect delay in ms */ +const MAX_RECONNECT_JITTER_MS = 500; +/** Factor to multiply delay by on failure */ +const RECONNECT_BACKOFF_FACTOR = 1.3; +/** Max number of reconnection attempts before giving up */ +const MAX_RECONNECT_ATTEMPTS = 10; + /** - * A promise that is settled for a request is received, and the functions that resolve or reject it. + * A promise returned to the user when invoking an operation via {@linkcode AbstractDataConnectStreamTransport.invokeQuery | invokeQuery} + * or {@linkcode AbstractDataConnectStreamTransport.invokeMutation | invokeMutation} and the functions + * that resolve/reject it. + * @internal */ -interface TrackedExecuteRequestPromise { +export interface InvokeOperationPromise { responsePromise: Promise>; + resolveFn: (response: DataConnectResponse) => void; // eslint-disable-next-line @typescript-eslint/no-explicit-any - resolveFn: (data: any) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - rejectFn: (err: any) => void; + rejectFn: (reason: any) => void; } /** - * The base class for all {@link DataConnectStreamTransport | Stream Transport} implementations. - * Handles management of logical streams (requests), authentication, data routing to query layer, etc. + * The base class for all Stream Transport implementations. + * Handles management of logical streams (requests), authentication, data routing to query layer, + * request optimizations, etc. * @internal */ export abstract class AbstractDataConnectStreamTransport extends AbstractDataConnectTransport { - /** Optional callback invoked when the stream closes gracefully. */ - onGracefulStreamClose?: () => void; + /** Optional callback invoked when the stream closes (gracefully or fatally). */ + onCloseCallback?: () => void; /** True if the physical stream connection is fully open and ready to transmit data. */ abstract get streamIsReady(): boolean; /** Is the stream currently waiting to close connection? */ get isPendingClose(): boolean { - return this.pendingClose; + return !!this.idleTimeout; } - private pendingClose = false; /** True if the transport is unable to connect to the server */ isUnableToConnect = false; /** True if there are active subscriptions on the stream */ get hasActiveSubscriptions(): boolean { - return this.activeSubscribeRequests.size > 0; + return this.activeInvokeSubscribeRequests.size > 0; } /** True if there are active execute or mutation requests on the stream */ get hasActiveExecuteRequests(): boolean { return ( - this.activeQueryExecuteRequests.size > 0 || - this.activeMutationExecuteRequests.size > 0 + this.activeInvokeQueryRequests.size > 0 || + this.activeInvokeMutationRequests.size > 0 ); } + constructor( + options: DataConnectOptions, + protected apiKey?: string | undefined, + protected appId?: string | null, + protected authProvider?: AuthTokenProvider | undefined, + protected appCheckProvider?: AppCheckTokenProvider | undefined, + transportOptions?: TransportOptions | undefined, + protected _isUsingGen = false, + protected _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base + ) { + super( + options, + apiKey, + appId, + authProvider, + appCheckProvider, + transportOptions, + _isUsingGen, + _callerSdkType + ); + + this.registerBrowserEventListeners(); + } + + /** + * Register event listeners for browser-specific events like online/offline and visibility changes. + */ + private registerBrowserEventListeners(): void { + if ('addEventListener' in globalThis) { + const listener = this.onOnlineEventListener; + globalThis.addEventListener('online', listener); + this.removeOnlineEventListener = () => + globalThis.removeEventListener('online', listener); + } + + const doc = globalThis.document; + if (doc && 'addEventListener' in doc) { + const listener = this.onVisibilityChangeEventListener; + doc.addEventListener('visibilitychange', listener); + this.removeVisibilityChangeEventListener = () => + doc.removeEventListener('visibilitychange', listener); + } + } + + /** + * Remove event listeners registered by {@linkcode AbstractDataConnectStreamTransport.registerBrowserEventListeners | registerBrowserEventListeners()} + * for browser-specific events like online/offline and visibility changes. + */ + private cleanupBrowserEventListeners(): void { + this.removeVisibilityChangeEventListener?.(); + this.removeVisibilityChangeEventListener = null; + this.removeOnlineEventListener?.(); + this.removeOnlineEventListener = null; + } + + /** + * Disposes of the transport instance, cleaning up event listeners and timers, + * and closing the connection. + */ + async cleanupAndTerminate(code?: Code, reason?: string): Promise { + this.cleanupBrowserEventListeners(); + this.cancelReconnect(); + this.cancelClose(); + this.rejectAllRequests(code ?? Code.OTHER, reason ?? 'Stream disposed.'); + await this.closeConnection(); + this.onCloseCallback?.(); + } + /** * Open a physical connection to the server. * @returns a promise which resolves when the connection is ready, or rejects if it fails to open. @@ -97,14 +185,13 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon /** * Close the physical connection with the server. Handles no cleanup - simply closes the - * implementation-specific connection. + * implementation-specific connection. On failure to close, the connection is still considered closed. * @returns a promise which resolves when the connection is closed, or rejects if it fails to close. - * On failure to close, the connection is still considered closed. */ protected abstract closeConnection(): Promise; /** - * Queue a message to be sent over the stream. + * Queue a {@linkcode DataConnectStreamRequest} to be sent over the stream. * @param requestBody The body of the message to be sent. * @throws DataConnectError if sending fails. */ @@ -119,177 +206,175 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon */ protected abstract ensureConnection(): Promise; - /** The request ID of the next message to be sent. Monotonically increasing sequence number. */ + /** The Request ID of the next message to be sent. Monotonically increasing sequence number starting at {@linkcode FIRST_REQUEST_ID}. */ private requestNumber = FIRST_REQUEST_ID; /** - * Generates and returns the next request ID. + * Generates and returns the next Request ID. Starts at {@linkcode FIRST_REQUEST_ID} and increments + * for each request sent. */ private nextRequestId(): string { return (this.requestNumber++).toString(); } /** - * Map of query/variables to their active execute/resume request bodies. + * Map of query/variables to their active {@linkcode ExecuteStreamRequest} or {@linkcode ResumeStreamRequest} + * request bodies. These requests are de-duplicated by query/variables so that there is only one active + * request for each query/variables combination. */ - private activeQueryExecuteRequests = new Map< + private activeInvokeQueryRequests = new Map< string, ExecuteStreamRequest | ResumeStreamRequest >(); /** - * Map of mutation/variables to their active execute request bodies. + * Map of query/variables to the promises returned to the user, for invokeQuery requests which are + * queued and waiting for active request to resolve. */ - private activeMutationExecuteRequests = new Map< + private queuedInvokeQueryRequests = new Map< + string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + InvokeOperationPromise + >(); + + /** + * Map of mutation/variables to their active {@linkcode ExecuteStreamRequest} request bodies. Mutations + * can have more than one active request at a time as they are not idempotent, and therefore should + * not be de-duplicated. + */ + private activeInvokeMutationRequests = new Map< string, Array> >(); /** - * Map of query/variables to their active subscribe request bodies. + * Map of query/variables to their active {@linkcode SubscribeStreamRequest} request bodies. There + * may only be one active request for each query/variables combination. */ - private activeSubscribeRequests = new Map< + private activeInvokeSubscribeRequests = new Map< string, SubscribeStreamRequest >(); /** - * Map of active execution RequestIds and their corresponding Promises and resolvers. + * Map of active {@linkcode ExecuteStreamRequest} RequestIds from {@linkcode invokeQuery} and {@linkcode invokeMutation}, + * and their corresponding {@linkcode InvokeOperationPromise}. */ private executeRequestPromises = new Map< string, - TrackedExecuteRequestPromise + // eslint-disable-next-line @typescript-eslint/no-explicit-any + InvokeOperationPromise >(); /** - * Map of active subscription RequestIds and their corresponding observers. + * Map of active {@linkcode ResumeStreamRequest} RequestIds from {@linkcode invokeQuery}, and their + * corresponding {@linkcode InvokeOperationPromise}. */ - private subscribeObservers = new Map>(); + private resumeRequestPromises = new Map< + string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + InvokeOperationPromise + >(); - /** current close timeout from setTimeout(), if any */ - private closeTimeout: NodeJS.Timeout | null = null; - /** has the close timeout finished? */ - private closeTimeoutFinished = false; - /** current auth uid. used to detect if a different user logs in */ - private authUid: string | null | undefined; - /** Flag to ensure we wait for the initial auth state once per connection attempt. */ - private hasWaitedForInitialAuth = false; + /** + * Map of active {@linkcode invokeSubscribe} RequestIds and their corresponding {@linkcode SubscribeObserver}. + */ + private subscribeObservers = new Map>(); /** - * Tracks a query execution request, storing the request body and creating and storing a promise that - * will be resolved when the response is received. - * @returns The reject function and the response promise. - * - * @remarks - * This method returns a promise, but is synchronous. + * Map of subscribe RequestIds to deferred unsubscription requests. Used when a client unsubscribes + * while a resume request is actively pending. */ - private trackQueryExecuteRequest( - requestId: string, - mapKey: string, - executeBody: ExecuteStreamRequest - ): TrackedExecuteRequestPromise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let resolveFn: (data: any) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let rejectFn: (err: any) => void; - const responsePromise = new Promise>( - (resolve, reject) => { - resolveFn = resolve; - rejectFn = reject; - } - ); - const executeRequestPromise: TrackedExecuteRequestPromise = { - responsePromise, - resolveFn: resolveFn!, - rejectFn: rejectFn! - }; + private pendingCancellations = new Map< + string, + { operationName: string; variables: unknown } + >(); - this.activeQueryExecuteRequests.set(mapKey, executeBody); - this.executeRequestPromises.set(requestId, executeRequestPromise); + /** current idle timeout, if any */ + private idleTimeout: ReturnType | null = null; - return executeRequestPromise; - } + /** current auth uid. used to detect if a different user logs in */ + private authUid: string | null | undefined; + /** Flag to ensure we wait for the initial auth state once per connection attempt. */ + private hasWaitedForInitialAuth = false; /** - * Tracks a mutation execution request, storing the request body and creating and storing a promise - * that will be resolved when the response is received. - * @returns The reject function and the response promise. + * Tracks an {@linkcode invokeMutation} request, storing the request body and creating and storing a + * response promise that will be resolved when the response is received. + * @returns The tracked {@linkcode InvokeOperationPromise}. * * @remarks * This method returns a promise, but is synchronous. */ - private trackMutationExecuteRequest( + private trackInvokeMutationRequest( requestId: string, mapKey: string, executeBody: ExecuteStreamRequest - ): TrackedExecuteRequestPromise { + ): InvokeOperationPromise { + let resolveFn: (response: DataConnectResponse) => void; // eslint-disable-next-line @typescript-eslint/no-explicit-any - let resolveFn: (data: any) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let rejectFn: (err: any) => void; + let rejectFn: (reason: any) => void; const responsePromise = new Promise>( (resolve, reject) => { resolveFn = resolve; rejectFn = reject; } ); - const executeRequestPromise: TrackedExecuteRequestPromise = { + const executeRequestPromise: InvokeOperationPromise = { responsePromise, resolveFn: resolveFn!, rejectFn: rejectFn! }; - const activeRequests = this.activeMutationExecuteRequests.get(mapKey) || []; + const activeRequests = this.activeInvokeMutationRequests.get(mapKey) || []; activeRequests.push(executeBody); - this.activeMutationExecuteRequests.set(mapKey, activeRequests); + this.activeInvokeMutationRequests.set(mapKey, activeRequests); this.executeRequestPromises.set(requestId, executeRequestPromise); return executeRequestPromise; } /** - * Tracks a subscribe request, storing the request body and the notification observer. + * Tracks an {@linkcode invokeSubscribe} request, storing the request body and the {@linkcode SubscribeObserver}. * @remarks * This method is synchronous. */ - private trackSubscribeRequest( + private trackInvokeSubscribeRequest( requestId: string, mapKey: string, subscribeBody: SubscribeStreamRequest, observer: SubscribeObserver ): void { - this.activeSubscribeRequests.set(mapKey, subscribeBody); - this.subscribeObservers.set( - requestId, - observer as SubscribeObserver - ); + this.activeInvokeSubscribeRequests.set(mapKey, subscribeBody); + this.subscribeObservers.set(requestId, observer); } /** * Cleans up the query execute request tracking data structures, deleting the tracked request and * it's associated promise. */ - private cleanupQueryExecuteRequest(requestId: string, mapKey: string): void { - this.activeQueryExecuteRequests.delete(mapKey); + private cleanupInvokeQueryRequest(requestId: string, mapKey: string): void { + this.activeInvokeQueryRequests.delete(mapKey); this.executeRequestPromises.delete(requestId); + this.resumeRequestPromises.delete(requestId); } /** * Cleans up the mutation execute request tracking data structures, deleting the tracked request and * it's associated promise. */ - private cleanupMutationExecuteRequest( + private cleanupInvokeMutationRequest( requestId: string, mapKey: string ): void { - const executeRequests = this.activeMutationExecuteRequests.get(mapKey); + const executeRequests = this.activeInvokeMutationRequests.get(mapKey); if (executeRequests) { const updatedRequests = executeRequests.filter( - req => req.requestId !== requestId + request => request.requestId !== requestId ); if (updatedRequests.length > 0) { - this.activeMutationExecuteRequests.set(mapKey, updatedRequests); + this.activeInvokeMutationRequests.set(mapKey, updatedRequests); } else { - this.activeMutationExecuteRequests.delete(mapKey); + this.activeInvokeMutationRequests.delete(mapKey); } } this.executeRequestPromises.delete(requestId); @@ -299,20 +384,136 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon * Cleans up the subscribe request tracking data structures, deleting the tracked request and * it's associated promise. */ - private cleanupSubscribeRequest(requestId: string, mapKey: string): void { - this.activeSubscribeRequests.delete(mapKey); + private cleanupInvokeSubscribeRequest( + requestId: string, + mapKey: string + ): void { + this.activeInvokeSubscribeRequests.delete(mapKey); this.subscribeObservers.delete(requestId); } + /** Delay for next reconnection attempt in ms */ + private reconnectDelayMs = INITIAL_RECONNECT_DELAY_MS; + /** Timer for reconnection */ + private reconnectTimer: ReturnType | null = null; + /** Number of consecutive reconnection attempts */ + private reconnectAttempts = 0; + + /** Callback to remove online event listener */ + private removeOnlineEventListener: (() => void) | null = null; + /** Callback to remove visibility change event listener */ + private removeVisibilityChangeEventListener: (() => void) | null = null; + + /** + * Short-circuit a reconnection attempt, if one is pending. Triggered when an online event is + * dispatched. + */ + onOnlineEventListener = (): void => { + if (this.reconnectTimer) { + this.cancelReconnect(); + void this.attemptReconnect(); + } + }; + + /** + * Short-circuit a reconnection attempt, if one is pending. Triggered when a visibility change + * event is dispatched. + */ + onVisibilityChangeEventListener = (): void => { + const doc = globalThis.document; + if (doc && doc.visibilityState === 'visible' && this.reconnectTimer) { + this.cancelReconnect(); + void this.attemptReconnect(); + } + }; + + /** + * Cancel reconnecting. + */ + private cancelReconnect(): void { + if (this.reconnectTimer) { + clearTimeout(this.reconnectTimer); + this.reconnectTimer = null; + } + } + + /** + * Starts the backoff timer for reconnection attempts. We use an exponential backoff with randomized + * jitter to prevent overwhelming the backend with connection attempts. + */ + private startReconnectBackoff(): void { + if (this.reconnectTimer) { + return; + } + if (this.reconnectAttempts++ >= MAX_RECONNECT_ATTEMPTS) { + const errorString = + 'Stream disconnected and could not reconnect - max stream reconnection attempts reached.'; + logError(errorString); + void this.cleanupAndTerminate(Code.OTHER, errorString); + return; + } + const delay = this.reconnectDelayMs; + this.reconnectDelayMs = Math.min( + this.reconnectDelayMs * RECONNECT_BACKOFF_FACTOR, + MAX_RECONNECT_DELAY_MS + ); + const jitter = Math.random() * MAX_RECONNECT_JITTER_MS; + + this.reconnectTimer = setTimeout(() => { + this.reconnectTimer = null; + void this.attemptReconnect(); + }, delay + jitter); + } + + private async attemptReconnect(): Promise { + try { + await this.ensureConnection(); + // reset on success + this.reconnectDelayMs = INITIAL_RECONNECT_DELAY_MS; + this.reconnectAttempts = 0; + await this.retriggerActiveRequests(); + } catch (e) { + if (e instanceof FirebaseError) { + logDebug( + `Reconnect attempt #${this.reconnectAttempts} failed with Firebase error: ${e.message}. Retrying...` + ); + this.startReconnectBackoff(); + } else { + logError( + `Unexpected error during reconnect attempt #${this.reconnectAttempts}: ${e}` + ); + void this.cleanupAndTerminate( + Code.OTHER, + `Unexpected error during reconnect attempt #${this.reconnectAttempts}: ${e}` + ); + } + } + } + + /** + * Retriggers all active requests on the stream connection - first subscribes, then query executions, + * and skip mutations. Used after a successful reconnection. + */ + private async retriggerActiveRequests(): Promise { + for (const [_, subscribeBody] of this.activeInvokeSubscribeRequests) { + await this.sendRequestMessage(subscribeBody); + } + for (const [_, requestBody] of this.activeInvokeQueryRequests) { + await this.sendRequestMessage(requestBody); + } + } + /** * Tracks if the next message to be sent is the first message of the stream. */ private isFirstStreamMessage = true; + /** * Tracks the last auth token sent to the server. * Used to detect if the token has changed and needs to be resent. */ private lastSentAuthToken: string | null = null; + /** * Indicates whether we should include the auth token in the next message. * Only true if there is an auth token and it is different from the last sent auth token, or this @@ -335,32 +536,25 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon } /** - * Attempt to close the connection. Will only close if there are no active requests preventing it - * from doing so. + * Begin closing the connection. Waits for {@linkcode IDLE_CONNECTION_TIMEOUT_MS} without cleaning up + * any requests (meaning it will not close after the timeout unless the requests are closed first). + * This is a graceful close - it will be called when there are no more active subscriptions, so + * there's no need to cleanup. */ - private async attemptClose(): Promise { - if (this.hasActiveSubscriptions || this.hasActiveExecuteRequests) { + private startIdleCloseTimeout(): void { + if (this.idleTimeout) { return; } - this.cancelClose(); - await this.closeConnection(); - this.onGracefulStreamClose?.(); - } - - /** - * Begin closing the connection. Waits for and cleans up all active requests, and waits for - * {@link IDLE_CONNECTION_TIMEOUT_MS}. This is a graceful close - it will be called when there are - * no more active subscriptions, so there's no need to cleanup. - */ - private prepareToCloseGracefully(): void { - if (this.pendingClose) { - return; - } - this.pendingClose = true; - this.closeTimeoutFinished = false; - this.closeTimeout = setTimeout(() => { - this.closeTimeoutFinished = true; - void this.attemptClose(); + this.idleTimeout = setTimeout(() => { + this.idleTimeout = null; + // Safety check: Don't close if new requests arrived during the timeout! + if (this.hasActiveSubscriptions || this.hasActiveExecuteRequests) { + return; + } + void this.cleanupAndTerminate( + Code.OTHER, + 'Stream closed due to idleness.' + ); }, IDLE_CONNECTION_TIMEOUT_MS); } @@ -368,42 +562,81 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon * Cancel closing the connection. */ private cancelClose(): void { - if (this.closeTimeout) { - clearTimeout(this.closeTimeout); + if (this.idleTimeout) { + clearTimeout(this.idleTimeout); + this.idleTimeout = null; } - this.pendingClose = false; - this.closeTimeoutFinished = false; } /** * Reject all active execute promises and notify all subscribe observers with the given error. * Clear active request tracking maps without cancelling or re-invoking any requests. */ - private rejectAllActiveRequests(code: Code, reason: string): void { - this.activeQueryExecuteRequests.clear(); - this.activeMutationExecuteRequests.clear(); - this.activeSubscribeRequests.clear(); + private rejectAllRequests(code: Code, reason: string): void { + this.activeInvokeQueryRequests.clear(); + this.activeInvokeMutationRequests.clear(); + this.activeInvokeSubscribeRequests.clear(); const error = new DataConnectError(code, reason); + for (const [mapKey, { rejectFn }] of this.queuedInvokeQueryRequests) { + this.queuedInvokeQueryRequests.delete(mapKey); + rejectFn(error); + } for (const [requestId, { rejectFn }] of this.executeRequestPromises) { this.executeRequestPromises.delete(requestId); rejectFn(error); } - + for (const [requestId, { rejectFn }] of this.resumeRequestPromises) { + this.resumeRequestPromises.delete(requestId); + rejectFn(error); + } for (const [requestId, observer] of this.subscribeObservers) { this.subscribeObservers.delete(requestId); observer.onDisconnect(code, reason); } + this.pendingCancellations.clear(); + this.cancelReconnect(); + } + + /** + * Reject all mutation execute promises. + * Clear active request tracking maps without cancelling or re-invoking any requests. + */ + private rejectAllMutationsOnReconnect(): void { + const error = new DataConnectError( + Code.OTHER, + 'Mutation aborted due to stream disconnect.' + ); + for (const [_, requests] of this.activeInvokeMutationRequests) { + for (const request of requests) { + const promise = this.executeRequestPromises.get(request.requestId); + if (promise) { + promise.rejectFn(error); + this.executeRequestPromises.delete(request.requestId); + } + } + } + this.activeInvokeMutationRequests.clear(); } /** * Called by concrete implementations when the stream is successfully closed, gracefully or otherwise. */ protected onStreamClose(code: number, reason: string): void { - this.rejectAllActiveRequests( - Code.OTHER, - `Stream disconnected with code ${code}: ${reason}` + this.cancelClose(); + if (!this.hasActiveSubscriptions) { + // skip reconnection if there are no active subscriptions + void this.cleanupAndTerminate( + Code.OTHER, + `Stream disconnected while idle with code ${code}: ${reason}` + ); + return; + } + logDebug( + `Stream disconnected with code ${code}: ${reason}. Attempting reconnect...` ); + this.rejectAllMutationsOnReconnect(); + this.startReconnectBackoff(); } /** @@ -443,7 +676,6 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon return preparedRequestBody; } - // TODO(stephenarosaj): just make this async /** * Sends a request message to the server via the concrete implementation. * Ensures the connection is ready and prepares the message before sending. @@ -467,7 +699,7 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon } /** - * Helper to generate a consistent string key for the tracking maps. + * Helper to generate a consistent string key for the request tracking maps. */ private getMapKey(operationName: string, variables?: unknown): string { const sortedVariables = this.sortObjectKeys(variables); @@ -503,37 +735,158 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon queryName: string, variables?: Variables ): Promise> { - const requestId = this.nextRequestId(); - const activeRequestKey = { operationName: queryName, variables }; const mapKey = this.getMapKey(queryName, variables); - const executeBody: ExecuteStreamRequest = { - requestId, - execute: activeRequestKey - }; - let { responsePromise, rejectFn } = this.trackQueryExecuteRequest( - requestId, - mapKey, - executeBody + if (this.activeInvokeQueryRequests.has(mapKey)) { + return this.queueInvokeQueryRequest(mapKey); + } + + return this.executeOrResumeQuery(queryName, variables, mapKey); + } + + /** + * Queue a new query execute request to be executed after the currently active query execute + * request resolves, and track + return a promise associated with the queued request. If there is + * already a queued request for this mapKey, return the existing queued request's promise instead. + */ + private queueInvokeQueryRequest( + mapKey: string + ): Promise> { + const existingQueued = this.queuedInvokeQueryRequests.get(mapKey); + if (existingQueued) { + // only queue one request per mapKey - return existing queued request promise + return existingQueued.responsePromise; + } + + let resolveFn: (response: DataConnectResponse) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let rejectFn: (reason: any) => void; + const responsePromise = new Promise>( + (resolve, reject) => { + resolveFn = resolve; + rejectFn = reject; + } ); + + this.queuedInvokeQueryRequests.set(mapKey, { + responsePromise, + resolveFn: resolveFn!, + rejectFn: rejectFn! + }); + + return responsePromise; + } + + /** + * Executes or resumes a query. Does not check for any active requests which may be overwritten by + * this request - this should be handled by the caller. + */ + private executeOrResumeQuery( + queryName: string, + variables: Variables | undefined, + mapKey: string, + queuedInvokeOperationPromise?: InvokeOperationPromise + ): Promise> { + const activeSubscription = this.activeInvokeSubscribeRequests.get(mapKey); + + let resolveFn: (response: DataConnectResponse) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let rejectFn: (reason: any) => void; + let responsePromise: Promise>; + + // track the existing queued promise if one exists - otherwise create a new one + if (queuedInvokeOperationPromise) { + resolveFn = queuedInvokeOperationPromise.resolveFn; + rejectFn = queuedInvokeOperationPromise.rejectFn; + responsePromise = queuedInvokeOperationPromise.responsePromise; + } else { + responsePromise = new Promise>( + (resolve, reject) => { + resolveFn = resolve; + rejectFn = reject; + } + ); + } + + let requestId: string; + let requestBody: ExecuteStreamRequest | ResumeStreamRequest; + + if (activeSubscription) { + // resume! + requestId = activeSubscription.requestId; + requestBody = { requestId, resume: {} }; + this.resumeRequestPromises.set(requestId, { + responsePromise, + resolveFn: resolveFn!, + rejectFn: rejectFn! + }); + } else { + // execute! + requestId = this.nextRequestId(); + requestBody = { + requestId, + execute: { operationName: queryName, variables } + }; + this.executeRequestPromises.set(requestId, { + responsePromise, + resolveFn: resolveFn!, + rejectFn: rejectFn! + }); + } + + this.activeInvokeQueryRequests.set(mapKey, requestBody); + responsePromise = responsePromise.finally(() => { - this.cleanupQueryExecuteRequest(requestId, mapKey); - if ( - !this.hasActiveSubscriptions && - !this.hasActiveExecuteRequests && - this.closeTimeoutFinished - ) { - void this.attemptClose(); - } + this.onInvokeQueryRequestFulfilled( + queryName, + variables, + mapKey, + requestId + ); }); - // asynchronous, fire and forget - this.sendRequestMessage(executeBody).catch(err => { + this.sendRequestMessage(requestBody).catch(err => { rejectFn(err); }); return responsePromise; } + /** + * When a query invoke request is fulfilled, clean up and trigger the next queued + * request if one exists. + */ + private onInvokeQueryRequestFulfilled( + queryName: string, + variables: unknown, + mapKey: string, + requestId: string + ): void { + this.cleanupInvokeQueryRequest(requestId, mapKey); + + const deferredCancel = this.pendingCancellations.get(requestId); + if (deferredCancel) { + this.pendingCancellations.delete(requestId); + this.cancelSubscription(requestId, mapKey); + } + + const queuedRequestPromise = this.queuedInvokeQueryRequests.get(mapKey); + if (!queuedRequestPromise) { + if (!this.hasActiveSubscriptions && !this.hasActiveExecuteRequests) { + this.startIdleCloseTimeout(); + } + return; + } + + this.queuedInvokeQueryRequests.delete(mapKey); + + void this.executeOrResumeQuery( + queryName, + variables, + mapKey, + queuedRequestPromise + ); + } + /** * @inheritdoc * @remarks @@ -553,19 +906,15 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon execute: activeRequestKey }; - let { responsePromise, rejectFn } = this.trackMutationExecuteRequest( + let { responsePromise, rejectFn } = this.trackInvokeMutationRequest( requestId, mapKey, executeBody ); responsePromise = responsePromise.finally(() => { - this.cleanupMutationExecuteRequest(requestId, mapKey); - if ( - !this.hasActiveSubscriptions && - !this.hasActiveExecuteRequests && - this.closeTimeoutFinished - ) { - void this.attemptClose(); + this.cleanupInvokeMutationRequest(requestId, mapKey); + if (!this.hasActiveSubscriptions && !this.hasActiveExecuteRequests) { + this.startIdleCloseTimeout(); } }); @@ -589,32 +938,42 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon queryName: string, variables: Variables ): void { - // if we are waiting to close the stream, cancel closing! - this.cancelClose(); - - const requestId = this.nextRequestId(); - const activeRequestKey = { operationName: queryName, variables }; const mapKey = this.getMapKey(queryName, variables); - const subscribeBody: SubscribeStreamRequest = { - requestId, - subscribe: activeRequestKey - }; - - this.trackSubscribeRequest( - requestId, - mapKey, - subscribeBody, - observer - ); - - // asynchronous, fire and forget - this.sendRequestMessage(subscribeBody).catch(err => { - observer.onError(err instanceof Error ? err : new Error(String(err))); - this.cleanupSubscribeRequest(requestId, mapKey); - if (!this.hasActiveSubscriptions) { - this.prepareToCloseGracefully(); + const existingSubscribe = this.activeInvokeSubscribeRequests.get(mapKey); + + // if this query is pending cancellation, cancel the cancellation! + if (existingSubscribe) { + const requestId = existingSubscribe.requestId; + if (this.pendingCancellations.has(requestId)) { + this.pendingCancellations.delete(requestId); + this.subscribeObservers.set(requestId, observer); } - }); + } else { + const requestId = this.nextRequestId(); + const activeRequestKey = { operationName: queryName, variables }; + const subscribeBody: SubscribeStreamRequest = { + requestId, + subscribe: activeRequestKey + }; + + this.trackInvokeSubscribeRequest( + requestId, + mapKey, + subscribeBody, + observer + ); + + // asynchronous, fire and forget + this.sendRequestMessage(subscribeBody).catch(err => { + observer.onError(err instanceof Error ? err : new Error(String(err))); + this.cleanupInvokeSubscribeRequest(requestId, mapKey); + if (!this.hasActiveSubscriptions) { + this.startIdleCloseTimeout(); + } + }); + } + // if we are waiting to close the stream, cancel closing! + this.cancelClose(); } /** @@ -626,25 +985,42 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon */ invokeUnsubscribe(queryName: string, variables: Variables): void { const mapKey = this.getMapKey(queryName, variables); - const subscribeRequest = this.activeSubscribeRequests.get(mapKey); + const subscribeRequest = this.activeInvokeSubscribeRequests.get(mapKey); if (!subscribeRequest) { return; } const requestId = subscribeRequest.requestId; + + this.subscribeObservers.delete(requestId); + const resumePromise = this.resumeRequestPromises.get(requestId); + if (resumePromise) { + this.pendingCancellations.set(requestId, { + operationName: queryName, + variables + }); + return; + } + this.cancelSubscription(requestId, mapKey); + } + + /** + * Cancels a subscription, cleans up the request tracking data structures, and checks to see if we + * should close the stream due to inactivity. + */ + private cancelSubscription(requestId: string, mapKey: string): void { + this.cleanupInvokeSubscribeRequest(requestId, mapKey); const cancelBody: CancelStreamRequest = { requestId, cancel: {} }; - this.cleanupSubscribeRequest(requestId, mapKey); - // asynchronous, fire and forget this.sendRequestMessage(cancelBody).catch(err => { logError(`Stream Transport failed to send unsubscribe message: ${err}`); }); if (!this.hasActiveSubscriptions) { - this.prepareToCloseGracefully(); + this.startIdleCloseTimeout(); } } @@ -668,18 +1044,17 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon (!oldAuthUid && newAuthUid) || // user logged in (oldAuthUid && newAuthUid !== oldAuthUid) // logged in user changed ) { - this.rejectAllActiveRequests( + void this.cleanupAndTerminate( Code.UNAUTHORIZED, 'Stream disconnected due to auth change.' ); - void this.attemptClose(); } } /** * Handle a response message from the server. Called by the connection-specific implementation after - * it's transformed a message from the server into a {@link DataConnectResponse}. - * @param requestId the requestId associated with this response. + * it's transformed a message from the server into a {@linkcode DataConnectResponse}. + * @param requestId the Request ID associated with this response. * @param response the response from the server. */ protected async handleResponse( @@ -687,32 +1062,60 @@ export abstract class AbstractDataConnectStreamTransport extends AbstractDataCon response: DataConnectResponse ): Promise { if (this.executeRequestPromises.has(requestId)) { - // don't clean up the tracking maps here, they're handled automatically when the execute promise settles const { resolveFn, rejectFn } = this.executeRequestPromises.get(requestId)!; - if (response.errors && response.errors.length) { - const failureResponse: DataConnectOperationFailureResponse = { - errors: response.errors as [], - data: response.data as Record - }; - const stringified = JSON.stringify(response.errors); - rejectFn( - new DataConnectOperationError( - 'DataConnect error while performing request: ' + stringified, - failureResponse - ) - ); - } else { - resolveFn(response); + this.handleInvokeOperationResponse(resolveFn, rejectFn, response); + } else if ( + this.subscribeObservers.has(requestId) || + this.resumeRequestPromises.has(requestId) + ) { + const observer = this.subscribeObservers.get(requestId); + const resumePromise = this.resumeRequestPromises.get(requestId); + + if (resumePromise) { + this.resumeRequestPromises.delete(requestId); + const { resolveFn, rejectFn } = resumePromise; + this.handleInvokeOperationResponse(resolveFn, rejectFn, response); + } + + if (observer) { + try { + await observer.onData(response); + } catch (e) { + logError(`Error in observer callback: ${e}`); + } } - } else if (this.subscribeObservers.has(requestId)) { - const observer = this.subscribeObservers.get(requestId)!; - await observer.onData(response); } else { - throw new DataConnectError( - Code.OTHER, + logError( `Stream response contained unrecognized requestId '${requestId}'` ); } } + + /** + * Handles an invoke operation response, resolving or rejecting the promise returned to the user + * Does not handle any cleanup for requests - this should be handled by the caller or the promise's + * finally() block. + */ + private handleInvokeOperationResponse( + resolveFn: (value: DataConnectResponse) => void, + rejectFn: (reason: unknown) => void, + response: DataConnectResponse + ): void { + if (response.errors && response.errors.length) { + const failureResponse: DataConnectOperationFailureResponse = { + errors: response.errors as [], + data: response.data as Record + }; + const stringified = JSON.stringify(response.errors); + rejectFn( + new DataConnectOperationError( + 'DataConnect error while performing request: ' + stringified, + failureResponse + ) + ); + } else { + resolveFn(response); + } + } } diff --git a/packages/data-connect/src/network/stream/websocket.ts b/packages/data-connect/src/network/stream/websocket.ts index a7f08d55af..662931aeb8 100644 --- a/packages/data-connect/src/network/stream/websocket.ts +++ b/packages/data-connect/src/network/stream/websocket.ts @@ -15,17 +15,10 @@ * limitations under the License. */ -import { DataConnectOptions, TransportOptions } from '../../api/DataConnect'; -import { AppCheckTokenProvider } from '../../core/AppCheckTokenProvider'; import { Code, DataConnectError } from '../../core/error'; -import { AuthTokenProvider } from '../../core/FirebaseAuthProvider'; import { logError } from '../../logger'; import { websocketUrlBuilder } from '../../util/url'; -import { - CallerSdkType, - CallerSdkTypeEnum, - DataConnectResponse -} from '../transport'; +import { DataConnectResponse } from '../transport'; import { AbstractDataConnectStreamTransport } from './streamTransport'; import { DataConnectStreamRequest, DataConnectStreamResponse } from './wire'; @@ -99,28 +92,6 @@ export class WebSocketTransport extends AbstractDataConnectStreamTransport { */ private connectionAttempt: Promise | null = null; - constructor( - options: DataConnectOptions, - protected apiKey?: string | undefined, - protected appId?: string | null, - protected authProvider?: AuthTokenProvider | undefined, - protected appCheckProvider?: AppCheckTokenProvider | undefined, - transportOptions?: TransportOptions | undefined, - protected _isUsingGen = false, - protected _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base - ) { - super( - options, - apiKey, - appId, - authProvider, - appCheckProvider, - transportOptions, - _isUsingGen, - _callerSdkType - ); - } - protected ensureConnection(): Promise { try { if (this.streamIsReady) { @@ -336,6 +307,6 @@ export class WebSocketTransport extends AbstractDataConnectStreamTransport { 'WebSocket message did not include requestId' ); } - return result as DataConnectStreamResponse; + return result; } } diff --git a/packages/data-connect/test/unit/streamTransport.test.ts b/packages/data-connect/test/unit/streamTransport.test.ts index f0106e380f..bddaab3c13 100644 --- a/packages/data-connect/test/unit/streamTransport.test.ts +++ b/packages/data-connect/test/unit/streamTransport.test.ts @@ -22,6 +22,7 @@ import * as sinon from 'sinon'; import sinonChai from 'sinon-chai'; import { DataConnectOptions } from '../../src/api/DataConnect'; +import { Code } from '../../src/core/error'; import { AuthTokenProvider } from '../../src/core/FirebaseAuthProvider'; import * as logger from '../../src/logger'; import { @@ -30,7 +31,10 @@ import { DataConnectResponse, getGoogApiClientValue } from '../../src/network'; -import { AbstractDataConnectStreamTransport } from '../../src/network/stream/streamTransport'; +import { + AbstractDataConnectStreamTransport, + InvokeOperationPromise +} from '../../src/network/stream/streamTransport'; import { DataConnectStreamRequest, ExecuteStreamRequest, @@ -118,6 +122,7 @@ interface TransportWithInternals { triggerOnConnectionReady(): void; closeConnection(): Promise; cancelClose(): void; + cleanupAndTerminate(code?: Code, reason?: string): Promise; sendRequestMessage( requestBody: DataConnectStreamRequest ): Promise; @@ -129,24 +134,21 @@ interface TransportWithInternals { >( requestBody: StreamBody ): StreamBody; - activeQueryExecuteRequests: Map< + activeInvokeQueryRequests: Map< string, ExecuteStreamRequest | ResumeStreamRequest >; - activeMutationExecuteRequests: Map< + queuedInvokeQueryRequests: Map>; + activeInvokeMutationRequests: Map< string, Array> >; - activeSubscribeRequests: Map>; - executeRequestPromises: Map< + activeInvokeSubscribeRequests: Map>; + executeRequestPromises: Map>; + resumeRequestPromises: Map>; + pendingCancellations: Map< string, - { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - resolve: (data: any) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - reject: (err: any) => void; - promise: Promise>; - } + { operationName: string; variables: unknown } >; subscribeObservers: Map; getMapKey(operationName: string, variables?: unknown): string; @@ -171,6 +173,15 @@ interface TransportWithInternals { requestId: string, response: DataConnectResponse ): Promise; + onStreamClose(code: number, reason: string): void; + reconnectTimer: NodeJS.Timeout | null; + onOnline(): void; + onVisibilityChange(): void; + ensureConnection(): Promise; + dispose(): Promise; + attemptReconnect(): void; + onOnlineEventListener(): void; + onVisibilityChangeEventListener(): void; } describe('AbstractDataConnectStreamTransport', () => { @@ -252,9 +263,7 @@ describe('AbstractDataConnectStreamTransport', () => { describe('prepareMessage', () => { it('should not change data fields', () => { - const preparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const preparedMessage = transport.prepareMessage(unpreparedMessage); expect(preparedMessage.requestId).to.equal(unpreparedMessage.requestId); expect(preparedMessage.execute).to.equal(unpreparedMessage.execute); expect(preparedMessage.resume).to.equal(unpreparedMessage.resume); @@ -266,9 +275,7 @@ describe('AbstractDataConnectStreamTransport', () => { describe('should handle headers properly', () => { describe('auth token', () => { it('should add auth token to the first message', () => { - const preparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const preparedMessage = transport.prepareMessage(unpreparedMessage); expect(preparedMessage.headers).to.exist; expect(preparedMessage.headers?.['X-Firebase-Auth-Token']).to.equal( initialAuthToken @@ -277,24 +284,21 @@ describe('AbstractDataConnectStreamTransport', () => { it('should NOT add the same auth token to subsequent messages', () => { transport.prepareMessage(unpreparedMessage); - const secondPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const secondPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect(secondPreparedMessage.headers?.['X-Firebase-Auth-Token']).to.be .undefined; }); it('should include auth token when it changes', () => { transport.prepareMessage(unpreparedMessage); - const secondPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const secondPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect(secondPreparedMessage.headers?.['X-Firebase-Auth-Token']).to.be .undefined; transport.setAuthToken(newAuthToken); - const thirdPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const thirdPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect( thirdPreparedMessage.headers?.['X-Firebase-Auth-Token'] ).to.equal(newAuthToken); @@ -303,9 +307,8 @@ describe('AbstractDataConnectStreamTransport', () => { describe('app check token', () => { it('should add app check token to the first message', () => { - const firstPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const firstPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect(firstPreparedMessage.headers).to.exist; expect( firstPreparedMessage.headers?.['X-Firebase-App-Check'] @@ -314,24 +317,21 @@ describe('AbstractDataConnectStreamTransport', () => { it('should NOT add the same app check token to subsequent messages', () => { transport.prepareMessage(unpreparedMessage); - const secondPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const secondPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect(secondPreparedMessage.headers?.['X-Firebase-App-Check']).to.be .undefined; }); it('should NOT include app check token when it changes', () => { transport.prepareMessage(unpreparedMessage); - const secondPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const secondPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect(secondPreparedMessage.headers?.['X-Firebase-App-Check']).to.be .undefined; transport.setAppCheckToken(newAppCheckToken); - const thirdPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const thirdPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect(thirdPreparedMessage.headers?.['X-Firebase-App-Check']).to.be .undefined; }); @@ -339,25 +339,22 @@ describe('AbstractDataConnectStreamTransport', () => { describe('x-firebase-gmpid', () => { it('should add x-firebase-gmpid to every message if appId is set', () => { - const firstPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const firstPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect(firstPreparedMessage.headers).to.exist; expect(firstPreparedMessage.headers?.['x-firebase-gmpid']).to.equal( initialAppId ); - const secondPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const secondPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect(secondPreparedMessage.headers?.['x-firebase-gmpid']).to.equal( initialAppId ); transport.appId = newAppId; - const thirdPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const thirdPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect(thirdPreparedMessage.headers?.['x-firebase-gmpid']).to.equal( newAppId ); @@ -370,9 +367,8 @@ describe('AbstractDataConnectStreamTransport', () => { expect(firstPreparedMessage.headers?.['X-Goog-Api-Client']).to.equal( expectedInitialGoogApiClientValue ); - const secondPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const secondPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect(secondPreparedMessage.headers?.['X-Goog-Api-Client']).to.equal( expectedInitialGoogApiClientValue ); @@ -382,9 +378,8 @@ describe('AbstractDataConnectStreamTransport', () => { true, CallerSdkTypeEnum.GeneratedReact ); - const thirdPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const thirdPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect(thirdPreparedMessage.headers?.['X-Goog-Api-Client']).to.equal( expectedThirdGoogApiClientValue ); @@ -400,9 +395,8 @@ describe('AbstractDataConnectStreamTransport', () => { it('should NOT add name to subsequent messages', () => { transport.prepareMessage(unpreparedMessage); - const secondPreparedMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const secondPreparedMessage = + transport.prepareMessage(unpreparedMessage); expect(secondPreparedMessage.name).to.be.undefined; }); }); @@ -412,9 +406,7 @@ describe('AbstractDataConnectStreamTransport', () => { transport.prepareMessage(unpreparedMessage); // Second message should not have any of these initial fields - const secondMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const secondMessage = transport.prepareMessage(unpreparedMessage); expect(secondMessage.name).to.be.undefined; expect(secondMessage.headers?.['X-Firebase-App-Check']).to.be.undefined; expect(secondMessage.headers?.['X-Firebase-Auth-Token']).to.be.undefined; @@ -423,9 +415,7 @@ describe('AbstractDataConnectStreamTransport', () => { transport.triggerOnConnectionReady(); // The next message should be treated as a "first" message again - const thirdMessage = transport.prepareMessage( - unpreparedMessage - ) as DataConnectStreamRequest; + const thirdMessage = transport.prepareMessage(unpreparedMessage); expect(thirdMessage.name).to.equal(expectedName); expect(thirdMessage.headers?.['X-Firebase-App-Check']).to.equal( initialAppCheckToken @@ -461,14 +451,13 @@ describe('AbstractDataConnectStreamTransport', () => { const queryPromise = transport.invokeQuery(queryName1, variables1); const expectedKey = transport.getMapKey(queryName1, variables1); - expect(transport.activeQueryExecuteRequests.has(expectedKey)).to.be + expect(transport.activeInvokeQueryRequests.has(expectedKey)).to.be .true; - const request = transport.activeQueryExecuteRequests.get(expectedKey); + const request = transport.activeInvokeQueryRequests.get(expectedKey); expect(request?.execute?.operationName).to.equal(queryName1); expect(request?.execute?.variables).to.deep.equal(variables1); - const requestId = (request as ExecuteStreamRequest) - .requestId; + const requestId = request!.requestId; expect(transport.executeRequestPromises.has(requestId)).to.be.true; expect(sendMessageSpy).to.have.been.calledOnce; @@ -489,11 +478,414 @@ describe('AbstractDataConnectStreamTransport', () => { await expect(queryPromise).to.be.rejectedWith(expectedError); const mapKey = transport.getMapKey(queryName1, variables1); - expect(transport.activeQueryExecuteRequests.has(mapKey)).to.be.false; + expect(transport.activeInvokeQueryRequests.has(mapKey)).to.be.false; const requestId = sendMessageStub.firstCall.args[0].requestId; expect(transport.executeRequestPromises.has(requestId)).to.be.false; }); + + describe('optimizations', () => { + describe('prefer resume over execute when executing already subscribed queries', () => { + it('should send a resume payload if there is an active subscription', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.invokeSubscribe(observer, queryName1, variables1); + expect(sendMessageSpy).to.have.been.calledOnce; + const subscribeMessage = sendMessageSpy.firstCall.args[0]; + expect(subscribeMessage.subscribe).to.not.be.undefined; + const subscribeRequestId = subscribeMessage.requestId; + + const queryPromise = transport.invokeQuery( + queryName1, + variables1 + ); + expect(sendMessageSpy).to.have.been.calledTwice; + const resumeMessage = sendMessageSpy.secondCall.args[0]; + expect(resumeMessage.resume).to.not.be.undefined; + expect(resumeMessage.requestId).to.equal(subscribeRequestId); + + const response = { + data: { result: '1' }, + errors: [], + extensions: {} + }; + await transport.invokeHandleResponse( + subscribeRequestId, + response + ); + expect(await queryPromise).to.deep.equal(response); + }); + + it('should resolve resume promise even if observer callback throws', async () => { + sinon.stub(transport, 'sendMessage').resolves(); + const observer = { + onData: sinon.stub().throws(new Error('Callback crashed')), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.invokeSubscribe(observer, queryName1, variables1); + const subscribeRequestId = + transport.activeInvokeSubscribeRequests.get( + transport.getMapKey(queryName1, variables1) + )!.requestId; + + const queryPromise = transport.invokeQuery( + queryName1, + variables1 + ); + + const response = { + data: { result: '1' }, + errors: [], + extensions: {} + }; + + await transport.invokeHandleResponse( + subscribeRequestId, + response + ); + const result = await queryPromise; + expect(result).to.deep.equal(response); + }); + }); + + describe('de-duplication of identical requests', () => { + it('should send the first request and queue subsequent requests when they are identical', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + + const promises = []; + for (let i = 1; i <= 20; i++) { + promises.push(transport.invokeQuery(queryName1, variables1)); + } + const mapKey = transport.getMapKey(queryName1, variables1); + + expect(sendMessageSpy).to.have.been.calledOnce; + const sentMessage = sendMessageSpy.firstCall.args[0]; + expect(sentMessage.execute?.operationName).to.equal(queryName1); + + expect(transport.activeInvokeQueryRequests.has(mapKey)).to.be + .true; + const activeRequest = + transport.activeInvokeQueryRequests.get(mapKey); + expect(activeRequest?.execute?.operationName).to.equal( + queryName1 + ); + + const queuedMap = transport.queuedInvokeQueryRequests; + expect(queuedMap.has(mapKey)).to.be.true; + + // promises 1 and 2 should be different, but 2-20 should be the same! + expect(promises[0]).to.not.equal(promises[1]); + for (let i = 1; i < 20; i++) { + expect(promises[i]).to.equal(promises[1]); + } + }); + + it('should resolve only the first request when it completes', async () => { + sinon.stub(transport, 'sendMessage').resolves(); + + const promises = []; + for (let i = 1; i <= 20; i++) { + promises.push(transport.invokeQuery(queryName1, variables1)); + } + + const mapKey = transport.getMapKey(queryName1, variables1); + const activeRequest = + transport.activeInvokeQueryRequests.get(mapKey); + const requestId1 = activeRequest!.requestId; + + const response1 = { + data: { result: '1' }, + errors: [], + extensions: {} + }; + + await transport.invokeHandleResponse(requestId1, response1); + + // verify promise 1 resolved, but other promises are not yet settled + const result1 = await promises[0]; + expect(result1).to.deep.equal(response1); + for (let i = 1; i < 20; i++) { + await expectIsNotSettled(promises[i], 100); + } + }); + + it('should send the next request and clear queue when first request completes', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + + const promises = []; + for (let i = 1; i <= 20; i++) { + promises.push(transport.invokeQuery(queryName1, variables1)); + } + + const mapKey = transport.getMapKey(queryName1, variables1); + const activeRequest = + transport.activeInvokeQueryRequests.get(mapKey); + const requestId1 = activeRequest!.requestId; + + const response1 = { + data: { result: '1' }, + errors: [], + extensions: {} + }; + + await transport.invokeHandleResponse(requestId1, response1); + + // verify queued request was popped + sent + expect(transport.queuedInvokeQueryRequests.has(mapKey)).to.be + .false; + expect(transport.activeInvokeQueryRequests.has(mapKey)).to.be + .true; + expect(sendMessageSpy).to.have.been.calledTwice; + const secondSentMessage = sendMessageSpy.secondCall.args[0]; + expect(secondSentMessage.execute?.operationName).to.equal( + queryName1 + ); + expect(secondSentMessage.requestId).to.not.equal(requestId1); + }); + + it('should send the next request even if the first request fails with response errors', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + + const promises = []; + for (let i = 1; i <= 20; i++) { + promises.push(transport.invokeQuery(queryName1, variables1)); + } + + const mapKey = transport.getMapKey(queryName1, variables1); + const activeRequest = + transport.activeInvokeQueryRequests.get(mapKey); + const requestId1 = activeRequest!.requestId; + const promise1 = promises[0]; + expect(transport.activeInvokeQueryRequests.has(mapKey)).to.be + .true; + expect(transport.queuedInvokeQueryRequests.has(mapKey)).to.be + .true; + + const errorResponse = { + data: null, + errors: [new Error('Query failed')], + extensions: {} + }; + await transport.invokeHandleResponse(requestId1, errorResponse); + + await expect(promise1).to.be.rejectedWith( + /DataConnect error while performing request/ + ); + expect(transport.queuedInvokeQueryRequests.has(mapKey)).to.be + .false; + expect(transport.activeInvokeQueryRequests.has(mapKey)).to.be + .true; + expect(sendMessageSpy).to.have.been.calledTwice; + + // queued request should not be affected by the failure of request 1 + const secondSentMessage = sendMessageSpy.secondCall.args[0]; + expect(secondSentMessage.execute?.operationName).to.equal( + queryName1 + ); + expect(secondSentMessage.requestId).to.not.equal(requestId1); + await expectIsNotSettled(promises[1], 100); + const activeRequest2 = + transport.activeInvokeQueryRequests.get(mapKey); + const requestId2 = activeRequest2!.requestId; + const response2 = { + data: { result: '2' }, + errors: [], + extensions: {} + }; + await transport.invokeHandleResponse(requestId2, response2); + const result2 = await promises[1]; + expect(result2).to.deep.equal(response2); + }); + + it('should send the next request even if the first request fails with errors', async () => { + const sendMessageStub = sinon.stub(transport, 'sendMessage'); + sendMessageStub.onFirstCall().rejects(expectedError); + sendMessageStub.onSecondCall().resolves(); + + const promises = []; + for (let i = 1; i <= 20; i++) { + promises.push(transport.invokeQuery(queryName1, variables1)); + } + + const mapKey = transport.getMapKey(queryName1, variables1); + const activeRequest = + transport.activeInvokeQueryRequests.get(mapKey); + const requestId1 = activeRequest!.requestId; + + await expect(promises[0]).to.be.rejectedWith(expectedError); + expect(transport.queuedInvokeQueryRequests.has(mapKey)).to.be + .false; + expect(transport.activeInvokeQueryRequests.has(mapKey)).to.be + .true; + expect(sendMessageStub).to.have.been.calledTwice; + + const secondSentMessage = sendMessageStub.secondCall.args[0]; + expect(secondSentMessage.execute?.operationName).to.equal( + queryName1 + ); + expect(secondSentMessage.requestId).to.not.equal(requestId1); + }); + + it('should resolve all waiting promises when a queued request completes', async () => { + sinon.stub(transport, 'sendMessage').resolves(); + + const promises = []; + for (let i = 1; i <= 20; i++) { + promises.push(transport.invokeQuery(queryName1, variables1)); + } + + const mapKey = transport.getMapKey(queryName1, variables1); + const activeRequest1 = + transport.activeInvokeQueryRequests.get(mapKey); + const requestId1 = activeRequest1!.requestId; + const response1 = { + data: { result: '1' }, + errors: [], + extensions: {} + }; + await transport.invokeHandleResponse(requestId1, response1); + + const activeRequest2 = + transport.activeInvokeQueryRequests.get(mapKey); + const requestId2 = activeRequest2!.requestId; + expect(requestId2).to.not.equal(requestId1); + + const response2 = { + data: { result: '2' }, + errors: [], + extensions: {} + }; + + await transport.invokeHandleResponse(requestId2, response2); + + // verify all queued promises resolved to response2, and nothing active or in queue + for (let i = 1; i < 20; i++) { + const result = await promises[i]; + expect(result).to.deep.equal(response2); + } + expect(transport.activeInvokeQueryRequests.has(mapKey)).to.be + .false; + expect(transport.queuedInvokeQueryRequests.has(mapKey)).to.be + .false; + }); + + it('should de-duplicate identical resume requests', async () => { + sinon.stub(transport, 'sendMessage').resolves(); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.invokeSubscribe(observer, queryName1, variables1); + + const promises = []; + for (let i = 1; i <= 20; i++) { + promises.push(transport.invokeQuery(queryName1, variables1)); + } + const mapKey = transport.getMapKey(queryName1, variables1); + const queuedMap = transport.queuedInvokeQueryRequests; + expect(queuedMap.has(mapKey)).to.be.true; + + // promises 1 and 2 should be different, but 2-20 should be the same! + expect(promises[0]).to.not.equal(promises[1]); + for (let i = 1; i < 20; i++) { + expect(promises[i]).to.equal(promises[1]); + } + }); + + it('should execute first, and then pop as resume if subscribed while waiting', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + + const queryPromise1 = transport.invokeQuery( + queryName1, + variables1 + ); + expect(sendMessageSpy).to.have.been.calledOnce; + const executeMessage = sendMessageSpy.firstCall.args[0]; + expect(executeMessage.execute).to.not.be.undefined; + const executeRequestId = executeMessage.requestId; + + void transport.invokeQuery(queryName1, variables1); + expect(sendMessageSpy).to.have.been.calledOnce; + + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + transport.invokeSubscribe(observer, queryName1, variables1); + expect(sendMessageSpy).to.have.been.calledTwice; + const subscribeRequestId = + sendMessageSpy.secondCall.args[0].requestId; + + const response1 = { + data: { result: '1' }, + errors: [], + extensions: {} + }; + await transport.invokeHandleResponse(executeRequestId, response1); + await queryPromise1; + + expect(sendMessageSpy).to.have.been.calledThrice; + const resumeMessage = sendMessageSpy.thirdCall.args[0]; + expect(resumeMessage.resume).to.not.be.undefined; + expect(resumeMessage.requestId).to.equal(subscribeRequestId); + }); + + it('should resume first, and then pop as execute if unsubscribed while waiting', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.invokeSubscribe(observer, queryName1, variables1); + expect(sendMessageSpy).to.have.been.calledOnce; + const subscribeRequestId = + sendMessageSpy.firstCall.args[0].requestId; + + const queryPromise1 = transport.invokeQuery( + queryName1, + variables1 + ); + expect(sendMessageSpy).to.have.been.calledTwice; + + void transport.invokeQuery(queryName1, variables1); + expect(sendMessageSpy).to.have.been.calledTwice; + + transport.invokeUnsubscribe(queryName1, variables1); + expect(sendMessageSpy).to.have.been.calledTwice; + + const response1 = { + data: { result: '1' }, + errors: [], + extensions: {} + }; + await transport.invokeHandleResponse( + subscribeRequestId, + response1 + ); + await queryPromise1; + + expect(sendMessageSpy.callCount).to.equal(4); + const cancelMessage = sendMessageSpy.getCall(2).args[0]; + expect(cancelMessage.cancel).to.not.be.undefined; + + const executeMessage = sendMessageSpy.getCall(3).args[0]; + expect(executeMessage.execute).to.not.be.undefined; + expect(executeMessage.requestId).to.not.equal(subscribeRequestId); + }); + }); + }); }); describe('invokeMutation', () => { @@ -507,7 +899,7 @@ describe('AbstractDataConnectStreamTransport', () => { const expectedKey = transport.getMapKey(mutationName1, variables1); const requests = - transport.activeMutationExecuteRequests.get(expectedKey); + transport.activeInvokeMutationRequests.get(expectedKey); expect(requests).to.have.lengthOf(1); expect(requests![0].execute?.operationName).to.equal(mutationName1); const requestId = requests![0].requestId; @@ -534,12 +926,104 @@ describe('AbstractDataConnectStreamTransport', () => { await expect(mutationPromise).to.be.rejectedWith(expectedError); const mapKey = transport.getMapKey(mutationName1, variables1); - expect(transport.activeMutationExecuteRequests.has(mapKey)).to.be + expect(transport.activeInvokeMutationRequests.has(mapKey)).to.be .false; const requestId = sendMessageStub.firstCall.args[0].requestId; expect(transport.executeRequestPromises.has(requestId)).to.be.false; }); + + describe('de-duplication', () => { + it('should NOT de-duplicate identical mutation requests', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + + const promises = []; + for (let i = 1; i <= 5; i++) { + promises.push( + transport.invokeMutation(mutationName1, variables1) + ); + } + + expect(sendMessageSpy.callCount).to.equal(5); + + const mapKey = transport.getMapKey(mutationName1, variables1); + const requests = transport.activeInvokeMutationRequests.get(mapKey); + expect(requests).to.have.lengthOf(5); + + for (let i = 0; i < 5; i++) { + for (let j = i + 1; j < 5; j++) { + expect(promises[i]).to.not.equal(promises[j]); + } + } + }); + + it('mutation requests should resolve totally independent of one another', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + + const promise1 = transport.invokeMutation( + mutationName1, + variables1 + ); + const promise2 = transport.invokeMutation( + mutationName1, + variables1 + ); + const promise3 = transport.invokeMutation( + mutationName1, + variables1 + ); + + expect(sendMessageSpy.callCount).to.equal(3); + + const mapKey = transport.getMapKey(mutationName1, variables1); + const requests = transport.activeInvokeMutationRequests.get(mapKey); + expect(requests).to.have.lengthOf(3); + + const requestId1 = requests![0].requestId; + const requestId2 = requests![1].requestId; + const requestId3 = requests![2].requestId; + + const response1 = { + data: { result: '1' }, + errors: [], + extensions: {} + }; + const response2 = { + data: { result: '2' }, + errors: [], + extensions: {} + }; + const response3 = { + data: { result: '3' }, + errors: [], + extensions: {} + }; + + await transport.invokeHandleResponse(requestId1, response1); + expect(await promise1).to.deep.equal(response1); + await expectIsNotSettled(promise2, 100); + await expectIsNotSettled(promise3, 100); + + await transport.invokeHandleResponse(requestId2, response2); + expect(await promise1).to.deep.equal(response1); + expect(await promise2).to.deep.equal(response2); + await expectIsNotSettled(promise3, 100); + + await transport.invokeHandleResponse(requestId3, response3); + expect(await promise1).to.deep.equal(response1); + expect(await promise2).to.deep.equal(response2); + expect(await promise3).to.deep.equal(response3); + + expect(transport.activeInvokeMutationRequests.has(mapKey)).to.be + .false; + expect(transport.executeRequestPromises.has(requestId1)).to.be + .false; + expect(transport.executeRequestPromises.has(requestId2)).to.be + .false; + expect(transport.executeRequestPromises.has(requestId3)).to.be + .false; + }); + }); }); describe('invokeSubscribe', () => { @@ -554,13 +1038,14 @@ describe('AbstractDataConnectStreamTransport', () => { transport.invokeSubscribe(observer, queryName1, variables1); const expectedKey = transport.getMapKey(queryName1, variables1); - expect(transport.activeSubscribeRequests.has(expectedKey)).to.be.true; - const request = transport.activeSubscribeRequests.get(expectedKey); + expect(transport.activeInvokeSubscribeRequests.has(expectedKey)).to.be + .true; + const request = + transport.activeInvokeSubscribeRequests.get(expectedKey); expect(request?.subscribe?.operationName).to.equal(queryName1); expect(request?.subscribe?.variables).to.deep.equal(variables1); - const requestId = (request as SubscribeStreamRequest) - .requestId; + const requestId = request!.requestId; expect(transport.subscribeObservers.has(requestId)).to.be.true; expect(sendMessageSpy).to.have.been.calledOnce; @@ -571,6 +1056,25 @@ describe('AbstractDataConnectStreamTransport', () => { expect(sentMessage.subscribe?.variables).to.deep.equal(variables1); }); + it('should de-duplicate identical subscribe requests', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + const observer1 = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + const observer2 = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.invokeSubscribe(observer1, queryName1, variables1); + transport.invokeSubscribe(observer2, queryName1, variables1); + + expect(sendMessageSpy.callCount).to.equal(1); + }); + it('should asynchronously call observer with error and clean up if sendMessage fails', async () => { const sendMessageStub = sinon .stub(transport, 'sendMessage') @@ -590,7 +1094,8 @@ describe('AbstractDataConnectStreamTransport', () => { expect(result).to.equal(expectedError); const mapKey = transport.getMapKey(queryName1, variables1); - expect(transport.activeSubscribeRequests.has(mapKey)).to.be.false; + expect(transport.activeInvokeSubscribeRequests.has(mapKey)).to.be + .false; const requestId = sendMessageStub.firstCall.args[0].requestId; expect(transport.subscribeObservers.has(requestId)).to.be.false; }); @@ -608,12 +1113,11 @@ describe('AbstractDataConnectStreamTransport', () => { transport.invokeSubscribe(observer, queryName1, variables1); const expectedKey = transport.getMapKey(queryName1, variables1); - expect(transport.activeSubscribeRequests.has(expectedKey)).to.be.true; + expect(transport.activeInvokeSubscribeRequests.has(expectedKey)).to.be + .true; const subscribeRequest = - transport.activeSubscribeRequests.get(expectedKey); - const subscribeRequestId = ( - subscribeRequest as SubscribeStreamRequest - ).requestId; + transport.activeInvokeSubscribeRequests.get(expectedKey); + const subscribeRequestId = subscribeRequest!.requestId; expect(transport.subscribeObservers.has(subscribeRequestId)).to.be .true; @@ -622,7 +1126,7 @@ describe('AbstractDataConnectStreamTransport', () => { expect(sendMessageSpy).to.have.been.calledTwice; const unsubscribeMessage = sendMessageSpy.secondCall.args[0]; - expect(transport.activeSubscribeRequests.has(expectedKey)).to.be + expect(transport.activeInvokeSubscribeRequests.has(expectedKey)).to.be .false; expect(transport.subscribeObservers.has(subscribeRequestId)).to.be .false; @@ -645,7 +1149,7 @@ describe('AbstractDataConnectStreamTransport', () => { const expectedKey = transport.getMapKey(queryName1, variables1); const subscribeRequest = - transport.activeSubscribeRequests.get(expectedKey); + transport.activeInvokeSubscribeRequests.get(expectedKey); const subscribeRequestId = subscribeRequest?.requestId!; transport.invokeUnsubscribe(queryName1, variables1); @@ -658,11 +1162,83 @@ describe('AbstractDataConnectStreamTransport', () => { 'Stream Transport failed to send unsubscribe message' ); - expect(transport.activeSubscribeRequests.has(expectedKey)).to.be + expect(transport.activeInvokeSubscribeRequests.has(expectedKey)).to.be .false; expect(transport.subscribeObservers.has(subscribeRequestId)).to.be .false; }); + + it('should defer cancellation if there is a pending resume request', async () => { + const sendMessageSpy = sinon.spy(transport, 'sendMessage'); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.invokeSubscribe(observer, queryName1, variables1); + const subscribeRequestId = sendMessageSpy.firstCall.args[0].requestId; + + const queryPromise = transport.invokeQuery(queryName1, variables1); + expect(sendMessageSpy).to.have.been.calledTwice; + + // Unsubscribe while resume is pending + transport.invokeUnsubscribe(queryName1, variables1); + // Should NOT have sent cancel message yet + expect(sendMessageSpy).to.have.been.calledTwice; + + const response = { + data: { result: '1' }, + errors: [], + extensions: {} + }; + await transport.invokeHandleResponse(subscribeRequestId, response); + expect(await queryPromise).to.deep.equal(response); + + // Now cancel message should be sent + expect(sendMessageSpy).to.have.been.calledThrice; + const cancelMessage = sendMessageSpy.thirdCall.args[0]; + expect(cancelMessage.cancel).to.not.be.undefined; + expect(cancelMessage.requestId).to.equal(subscribeRequestId); + }); + + it('should resurrect a subscription if re-subscribed while pending cancellation', async () => { + sinon.stub(transport, 'sendMessage').resolves(); + const observer1 = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + const observer2 = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + + transport.invokeSubscribe(observer1, queryName1, variables1); + const subscribeRequestId = + transport.activeInvokeSubscribeRequests.get( + transport.getMapKey(queryName1, variables1) + )!.requestId; + + // Start a resume to put it in flight + void transport.invokeQuery(queryName1, variables1); + + // Unsubscribe -> goes to pendingCancellations + transport.invokeUnsubscribe(queryName1, variables1); + expect(transport.pendingCancellations.has(subscribeRequestId)).to.be + .true; + expect(transport.subscribeObservers.has(subscribeRequestId)).to.be + .false; + + // Re-subscribe -> should resurrect! + transport.invokeSubscribe(observer2, queryName1, variables1); + expect(transport.pendingCancellations.has(subscribeRequestId)).to.be + .false; + expect(transport.subscribeObservers.get(subscribeRequestId)).to.equal( + observer2 + ); + }); }); }); @@ -698,20 +1274,20 @@ describe('AbstractDataConnectStreamTransport', () => { extensions: {} }; - it('should throw an error if an unrecognized requestId is received', async () => { + it('should log an error if an unrecognized requestId is received', async () => { + const logErrorStub = sinon.stub(logger, 'logError'); const unknownRequestId = 'unknown-999'; const response: DataConnectResponse = { data: {}, errors: [], extensions: {} }; - const errorPromise = transport.invokeHandleResponse( - unknownRequestId, - response - ); - await expect(errorPromise).to.be.rejectedWith( + await transport.invokeHandleResponse(unknownRequestId, response); + expect(logErrorStub).to.have.been.calledOnce; + expect(logErrorStub).to.have.been.calledWithMatch( `Stream response contained unrecognized requestId '${unknownRequestId}'` ); + logErrorStub.restore(); }); describe('invokeQuery tracking', async () => { @@ -721,14 +1297,12 @@ describe('AbstractDataConnectStreamTransport', () => { const expectedKey1 = transport.getMapKey(queryName1, variables1); const request1 = - transport.activeQueryExecuteRequests.get(expectedKey1); - const requestId1 = (request1 as ExecuteStreamRequest) - .requestId; + transport.activeInvokeQueryRequests.get(expectedKey1); + const requestId1 = request1!.requestId; const expectedKey2 = transport.getMapKey(queryName2, variables2); const request2 = - transport.activeQueryExecuteRequests.get(expectedKey2); - const requestId2 = (request2 as ExecuteStreamRequest) - .requestId; + transport.activeInvokeQueryRequests.get(expectedKey2); + const requestId2 = request2!.requestId; await transport.invokeHandleResponse(requestId1, response1); const result1 = await queryPromise1; @@ -745,28 +1319,26 @@ describe('AbstractDataConnectStreamTransport', () => { const expectedKey1 = transport.getMapKey(queryName1, variables1); const request1 = - transport.activeQueryExecuteRequests.get(expectedKey1); - const requestId1 = (request1 as ExecuteStreamRequest) - .requestId; + transport.activeInvokeQueryRequests.get(expectedKey1); + const requestId1 = request1!.requestId; const expectedKey2 = transport.getMapKey(queryName2, variables2); const request2 = - transport.activeQueryExecuteRequests.get(expectedKey2); - const requestId2 = (request2 as ExecuteStreamRequest) - .requestId; + transport.activeInvokeQueryRequests.get(expectedKey2); + const requestId2 = request2!.requestId; await transport.invokeHandleResponse(requestId1, response1); await queryPromise1; - expect(transport.activeQueryExecuteRequests.has(expectedKey1)).to.be + expect(transport.activeInvokeQueryRequests.has(expectedKey1)).to.be .false; - expect(transport.activeQueryExecuteRequests.has(expectedKey2)).to.be + expect(transport.activeInvokeQueryRequests.has(expectedKey2)).to.be .true; await transport.invokeHandleResponse(requestId2, response2); await queryPromise2; - expect(transport.activeQueryExecuteRequests.has(expectedKey1)).to.be + expect(transport.activeInvokeQueryRequests.has(expectedKey1)).to.be .false; - expect(transport.activeQueryExecuteRequests.has(expectedKey2)).to.be + expect(transport.activeInvokeQueryRequests.has(expectedKey2)).to.be .false; }); @@ -776,13 +1348,11 @@ describe('AbstractDataConnectStreamTransport', () => { const expectedKey1 = transport.getMapKey(queryName1, variables1); const expectedKey2 = transport.getMapKey(queryName2, variables2); const request1 = - transport.activeQueryExecuteRequests.get(expectedKey1); - const requestId1 = (request1 as ExecuteStreamRequest) - .requestId; + transport.activeInvokeQueryRequests.get(expectedKey1); + const requestId1 = request1!.requestId; const request2 = - transport.activeQueryExecuteRequests.get(expectedKey2); - const requestId2 = (request2 as ExecuteStreamRequest) - .requestId; + transport.activeInvokeQueryRequests.get(expectedKey2); + const requestId2 = request2!.requestId; await transport.invokeHandleResponse(requestId1, errorResponse); await transport.invokeHandleResponse(requestId2, errorResponse); @@ -804,25 +1374,23 @@ describe('AbstractDataConnectStreamTransport', () => { const expectedKey1 = transport.getMapKey(queryName1, variables1); const request1 = - transport.activeQueryExecuteRequests.get(expectedKey1); - const requestId1 = (request1 as ExecuteStreamRequest) - .requestId; + transport.activeInvokeQueryRequests.get(expectedKey1); + const requestId1 = request1!.requestId; const expectedKey2 = transport.getMapKey(queryName2, variables2); const request2 = - transport.activeQueryExecuteRequests.get(expectedKey2); - const requestId2 = (request2 as ExecuteStreamRequest) - .requestId; + transport.activeInvokeQueryRequests.get(expectedKey2); + const requestId2 = request2!.requestId; await transport.invokeHandleResponse(requestId1, errorResponse); - expect(transport.activeQueryExecuteRequests.has(expectedKey1)).to.be + expect(transport.activeInvokeQueryRequests.has(expectedKey1)).to.be .false; expect(transport.executeRequestPromises.has(requestId1)).to.be.false; - expect(transport.activeQueryExecuteRequests.has(expectedKey2)).to.be + expect(transport.activeInvokeQueryRequests.has(expectedKey2)).to.be .true; expect(transport.executeRequestPromises.has(requestId2)).to.be.true; await transport.invokeHandleResponse(requestId2, errorResponse); - expect(transport.activeQueryExecuteRequests.has(expectedKey2)).to.be + expect(transport.activeInvokeQueryRequests.has(expectedKey2)).to.be .false; expect(transport.executeRequestPromises.has(requestId2)).to.be.false; }); @@ -841,11 +1409,11 @@ describe('AbstractDataConnectStreamTransport', () => { const expectedKey1 = transport.getMapKey(mutationName1, variables1); const activeRequests1 = - transport.activeMutationExecuteRequests.get(expectedKey1); + transport.activeInvokeMutationRequests.get(expectedKey1); const requestId1 = activeRequests1![0].requestId; const expectedKey2 = transport.getMapKey(mutationName2, variables2); const activeRequests2 = - transport.activeMutationExecuteRequests.get(expectedKey2); + transport.activeInvokeMutationRequests.get(expectedKey2); const requestId2 = activeRequests2![0].requestId; await transport.invokeHandleResponse(requestId1, response1); @@ -870,27 +1438,27 @@ describe('AbstractDataConnectStreamTransport', () => { const expectedKey1 = transport.getMapKey(mutationName1, variables1); const activeRequests1 = - transport.activeMutationExecuteRequests.get(expectedKey1); + transport.activeInvokeMutationRequests.get(expectedKey1); const requestId1 = activeRequests1![0].requestId; const expectedKey2 = transport.getMapKey(mutationName2, variables2); const activeRequests2 = - transport.activeMutationExecuteRequests.get(expectedKey2); + transport.activeInvokeMutationRequests.get(expectedKey2); const requestId2 = activeRequests2![0].requestId; await transport.invokeHandleResponse(requestId1, response1); await mutationPromise1; expect(transport.executeRequestPromises.has(requestId1)).to.be.false; - expect(transport.activeMutationExecuteRequests.has(expectedKey1)).to - .be.false; + expect(transport.activeInvokeMutationRequests.has(expectedKey1)).to.be + .false; expect(transport.executeRequestPromises.has(requestId2)).to.be.true; - expect(transport.activeMutationExecuteRequests.has(expectedKey2)).to - .be.true; + expect(transport.activeInvokeMutationRequests.has(expectedKey2)).to.be + .true; await transport.invokeHandleResponse(requestId2, response2); await mutationPromise2; expect(transport.executeRequestPromises.has(requestId2)).to.be.false; - expect(transport.activeMutationExecuteRequests.has(expectedKey2)).to - .be.false; + expect(transport.activeInvokeMutationRequests.has(expectedKey2)).to.be + .false; }); it('should reject the correct mutation promise with DataConnectOperationError if response has errors', async () => { @@ -904,11 +1472,11 @@ describe('AbstractDataConnectStreamTransport', () => { ); const expectedKey1 = transport.getMapKey(mutationName1, variables1); const activeRequests1 = - transport.activeMutationExecuteRequests.get(expectedKey1); + transport.activeInvokeMutationRequests.get(expectedKey1); const requestId1 = activeRequests1![0].requestId; const expectedKey2 = transport.getMapKey(mutationName2, variables2); const activeRequests2 = - transport.activeMutationExecuteRequests.get(expectedKey2); + transport.activeInvokeMutationRequests.get(expectedKey2); const requestId2 = activeRequests2![0].requestId; await transport.invokeHandleResponse(requestId1, errorResponse); @@ -933,23 +1501,23 @@ describe('AbstractDataConnectStreamTransport', () => { const expectedKey1 = transport.getMapKey(mutationName1, variables1); const expectedKey2 = transport.getMapKey(mutationName2, variables2); const activeRequests1 = - transport.activeMutationExecuteRequests.get(expectedKey1); + transport.activeInvokeMutationRequests.get(expectedKey1); const activeRequests2 = - transport.activeMutationExecuteRequests.get(expectedKey2); + transport.activeInvokeMutationRequests.get(expectedKey2); const requestId1 = activeRequests1![0].requestId; const requestId2 = activeRequests2![0].requestId; await transport.invokeHandleResponse(requestId1, errorResponse); - expect(transport.activeMutationExecuteRequests.has(expectedKey1)).to - .be.false; + expect(transport.activeInvokeMutationRequests.has(expectedKey1)).to.be + .false; expect(transport.executeRequestPromises.has(requestId1)).to.be.false; - expect(transport.activeMutationExecuteRequests.has(expectedKey2)).to - .be.true; + expect(transport.activeInvokeMutationRequests.has(expectedKey2)).to.be + .true; expect(transport.executeRequestPromises.has(requestId2)).to.be.true; await transport.invokeHandleResponse(requestId2, errorResponse); - expect(transport.activeMutationExecuteRequests.has(expectedKey2)).to - .be.false; + expect(transport.activeInvokeMutationRequests.has(expectedKey2)).to.be + .false; expect(transport.executeRequestPromises.has(requestId2)).to.be.false; }); }); @@ -980,7 +1548,8 @@ describe('AbstractDataConnectStreamTransport', () => { transport.invokeSubscribe(observer2, queryName2, variables2); const expectedKey1 = transport.getMapKey(queryName1, variables1); - const request1 = transport.activeSubscribeRequests.get(expectedKey1); + const request1 = + transport.activeInvokeSubscribeRequests.get(expectedKey1); const requestId1 = request1?.requestId!; await transport.invokeHandleResponse(requestId1, response1); @@ -991,7 +1560,8 @@ describe('AbstractDataConnectStreamTransport', () => { expect(observer1.onData).to.have.been.calledWithExactly(response2); const expectedKey2 = transport.getMapKey(queryName2, variables2); - const request2 = transport.activeSubscribeRequests.get(expectedKey2); + const request2 = + transport.activeInvokeSubscribeRequests.get(expectedKey2); const requestId2 = request2?.requestId!; await transport.invokeHandleResponse(requestId2, response3); @@ -1007,10 +1577,12 @@ describe('AbstractDataConnectStreamTransport', () => { transport.invokeSubscribe(observer2, queryName2, variables2); const expectedKey1 = transport.getMapKey(queryName1, variables1); - const request1 = transport.activeSubscribeRequests.get(expectedKey1); + const request1 = + transport.activeInvokeSubscribeRequests.get(expectedKey1); const requestId1 = request1?.requestId!; const expectedKey2 = transport.getMapKey(queryName2, variables2); - const request2 = transport.activeSubscribeRequests.get(expectedKey2); + const request2 = + transport.activeInvokeSubscribeRequests.get(expectedKey2); const requestId2 = request2?.requestId!; await transport.invokeHandleResponse(requestId1, errorResponse); @@ -1030,18 +1602,20 @@ describe('AbstractDataConnectStreamTransport', () => { transport.invokeSubscribe(observer2, queryName2, variables2); const expectedKey1 = transport.getMapKey(queryName1, variables1); const expectedKey2 = transport.getMapKey(queryName2, variables2); - const request1 = transport.activeSubscribeRequests.get(expectedKey1); - const request2 = transport.activeSubscribeRequests.get(expectedKey2); + const request1 = + transport.activeInvokeSubscribeRequests.get(expectedKey1); + const request2 = + transport.activeInvokeSubscribeRequests.get(expectedKey2); const requestId1 = request1?.requestId!; const requestId2 = request2?.requestId!; await transport.invokeHandleResponse(requestId1, errorResponse); await transport.invokeHandleResponse(requestId2, errorResponse); - expect(transport.activeSubscribeRequests.has(expectedKey1)).to.be - .true; + expect(transport.activeInvokeSubscribeRequests.has(expectedKey1)).to + .be.true; expect(transport.subscribeObservers.has(requestId1)).to.be.true; - expect(transport.activeSubscribeRequests.has(expectedKey2)).to.be - .true; + expect(transport.activeInvokeSubscribeRequests.has(expectedKey2)).to + .be.true; expect(transport.subscribeObservers.has(requestId2)).to.be.true; }); }); @@ -1161,8 +1735,8 @@ describe('AbstractDataConnectStreamTransport', () => { expect(closeSpy).to.not.have.been.called; const expectedKey = transport.getMapKey(queryName2, variables2); - const request = transport.activeQueryExecuteRequests.get(expectedKey); - const requestId = (request as ExecuteStreamRequest).requestId; + const request = transport.activeInvokeQueryRequests.get(expectedKey); + const requestId = request!.requestId; const dummyResponse = { data: { result: 'result' }, @@ -1172,6 +1746,9 @@ describe('AbstractDataConnectStreamTransport', () => { await transport.invokeHandleResponse(requestId, dummyResponse); await queryPromise; + // fast forward time again because the new idle timeout started when the query completed + await clock.tickAsync(1000 * 65); + expect(closeSpy).to.have.been.calledOnce; }); @@ -1268,4 +1845,252 @@ describe('AbstractDataConnectStreamTransport', () => { }); }); }); + + describe('Reconnection', () => { + let clock: sinon.SinonFakeTimers; + let sendMessageStub: sinon.SinonStub; + let ensureConnectionStub: sinon.SinonStub; + + beforeEach(() => { + clock = sinon.useFakeTimers(); + sendMessageStub = sinon.stub(transport, 'sendMessage').resolves(); + ensureConnectionStub = sinon + .stub(transport, 'ensureConnection') + .resolves(); + }); + + afterEach(() => { + clock.restore(); + sinon.restore(); + }); + + it('should start backoff on unexpected disconnect', async () => { + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + transport.invokeSubscribe(observer, queryName1, variables1); + + // Trigger unexpected disconnect (code 1006) + transport.onStreamClose(1006, 'Abnormal Closure'); + + // Should have started timer + expect(transport.reconnectTimer).to.not.be.null; + }); + + it('should NOT start backoff on graceful close with no subscriptions', async () => { + // No active subscriptions + transport.onStreamClose(1000, 'Normal Closure'); + + // Should NOT have started timer + expect(transport.reconnectTimer).to.be.null; + }); + + it('should fail all pending mutations on unexpected disconnect', async () => { + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + transport.invokeSubscribe(observer, queryName1, variables1); + + const mutationPromise = transport.invokeMutation( + mutationName1, + variables1 + ); + + transport.onStreamClose(1006, 'Abnormal Closure'); + + await expect(mutationPromise).to.be.rejectedWith( + 'Mutation aborted due to stream disconnect.' + ); + expect(transport.activeInvokeMutationRequests.size).to.equal(0); + }); + + it('should re-request active subscriptions and queries on successful reconnect', async () => { + const attemptReconnectSpy = sinon.spy(transport, 'attemptReconnect'); + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + transport.invokeSubscribe(observer, queryName1, variables1); + + // Stagger an execute request + void transport.invokeQuery(queryName1, variables1); + + sendMessageStub.resetHistory(); + + // Trigger unexpected disconnect + transport.onStreamClose(1006, 'Abnormal Closure'); + + // Fast forward time to trigger reconnect + await clock.tickAsync(2000); // Default is 1000 + jitter + expect(attemptReconnectSpy).to.have.been.calledOnce; + expect(ensureConnectionStub).to.have.been.calledOnce; + + // Should re-send subscribe and then query + expect(sendMessageStub).to.have.been.calledTwice; + const firstSent = sendMessageStub.firstCall.args[0]; + const secondSent = sendMessageStub.secondCall.args[0]; + + expect(firstSent.subscribe).to.not.be.undefined; + expect(secondSent.resume).to.not.be.undefined; + }); + + it('onOnline should trigger immediate reconnect if waiting', async () => { + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + transport.invokeSubscribe(observer, queryName1, variables1); + transport.onStreamClose(1006, 'Abnormal Closure'); + + expect(transport.reconnectTimer).to.not.be.null; + + transport.onOnlineEventListener(); + + expect(ensureConnectionStub).to.have.been.calledOnce; + expect(transport.reconnectTimer).to.be.null; + }); + + it('onVisibilityChange should trigger immediate reconnect if waiting', async () => { + const isBrowser = typeof window !== 'undefined'; + if (!isBrowser) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (global as any).document = { visibilityState: 'visible' }; + } + + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + transport.invokeSubscribe(observer, queryName1, variables1); + transport.onStreamClose(1006, 'Abnormal Closure'); + + expect(transport.reconnectTimer).to.not.be.null; + + transport.onVisibilityChangeEventListener(); + + expect(ensureConnectionStub).to.have.been.calledOnce; + expect(transport.reconnectTimer).to.be.null; + + if (!isBrowser) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + delete (global as any).document; + } + }); + }); + + describe('Dispose', () => { + let clock: sinon.SinonFakeTimers; + let closeConnectionSpy: sinon.SinonSpy; + + beforeEach(() => { + clock = sinon.useFakeTimers(); + closeConnectionSpy = sinon.spy(transport, 'closeConnection'); + }); + + afterEach(() => { + clock.restore(); + sinon.restore(); + }); + + it('should clean up event listeners and timers on dispose', async () => { + const isBrowser = typeof window !== 'undefined'; + let hadAddEventListener = false; + let hadRemoveEventListener = false; + + let removeEventListenerSpy: sinon.SinonSpy; + let removeDocEventListenerSpy: sinon.SinonSpy; + + if (isBrowser) { + removeEventListenerSpy = sinon.spy(window, 'removeEventListener'); + removeDocEventListenerSpy = sinon.spy(document, 'removeEventListener'); + } else { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const anyGlobalThis = globalThis as any; + + hadAddEventListener = 'addEventListener' in anyGlobalThis; + hadRemoveEventListener = 'removeEventListener' in anyGlobalThis; + + if (!hadAddEventListener) { + anyGlobalThis.addEventListener = () => {}; + } + if (!hadRemoveEventListener) { + anyGlobalThis.removeEventListener = () => {}; + } + + removeEventListenerSpy = sinon.spy( + anyGlobalThis, + 'removeEventListener' + ); + + anyGlobalThis.document = { + addEventListener: sinon.spy(), + removeEventListener: sinon.spy() + } as unknown as Document; + removeDocEventListenerSpy = anyGlobalThis.document.removeEventListener; + } + + try { + // Recreate transport after mocking/spying to pick up the correct environment + transport = new TestStreamTransport( + dcOptions + ) as unknown as TransportWithInternals; + transport._isUsingGen = true; + transport._callerSdkType = CallerSdkTypeEnum.Generated; + transport.setAuthToken(initialAuthToken); + transport.setAppCheckToken(initialAppCheckToken); + transport.appId = initialAppId; + transport.hasWaitedForInitialAuth = true; + + closeConnectionSpy = sinon.spy(transport, 'closeConnection'); + + const observer = { + onData: sinon.spy(), + onDisconnect: sinon.spy(), + onError: sinon.spy() + }; + transport.invokeSubscribe(observer, queryName1, variables1); + + transport.onStreamClose(1006, 'Abnormal Closure'); + expect(transport.reconnectTimer).to.not.be.null; + + await transport.cleanupAndTerminate(); + + expect(removeEventListenerSpy).to.have.been.calledWith( + 'online', + transport.onOnlineEventListener + ); + expect(removeDocEventListenerSpy).to.have.been.calledWith( + 'visibilitychange', + transport.onVisibilityChangeEventListener + ); + } finally { + // 2. Cleanup + sinon.restore(); // Automatically restores window/document spies in the browser! + + // Delete the mock objects we added in Node + if (!isBrowser) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const anyGlobalThis = globalThis as any; + delete anyGlobalThis.window; + delete anyGlobalThis.document; + if (!hadAddEventListener) { + delete anyGlobalThis.addEventListener; + } + if (!hadRemoveEventListener) { + delete anyGlobalThis.removeEventListener; + } + } + } + + expect(transport.reconnectTimer).to.be.null; + expect(closeConnectionSpy).to.have.been.calledOnce; + }); + }); }); diff --git a/packages/data-connect/test/unit/transportManager.test.ts b/packages/data-connect/test/unit/transportManager.test.ts index e64e411d60..efef7c5685 100644 --- a/packages/data-connect/test/unit/transportManager.test.ts +++ b/packages/data-connect/test/unit/transportManager.test.ts @@ -38,6 +38,7 @@ use(sinonChai); /** Interface that exposes private fields of stream transport for testing purposes. */ interface StreamTransportWithInternals { onStreamClose(code: number, reason: string): void; + rejectAllRequests(code: string, reason: string): void; } /** Interface that exposes private fields of TransportManager for testing purposes. */ @@ -504,9 +505,13 @@ describe('DataConnectTransportManager', () => { }; transportWithInternals.subscribeObservers = new Map([['1', observer]]); + // rejectAllRequests simulates a disconnect without reconnects! ( streamTransport as unknown as StreamTransportWithInternals - ).onStreamClose(1006, 'Abnormal Closure'); + ).rejectAllRequests( + Code.OTHER, + 'Stream disconnected with code 1006: Abnormal Closure' + ); expect(observer.onDisconnect).to.have.been.calledOnceWith( Code.OTHER, diff --git a/packages/data-connect/test/unit/websocketTransport.test.ts b/packages/data-connect/test/unit/websocketTransport.test.ts index 0793b203e1..98bc6327b3 100644 --- a/packages/data-connect/test/unit/websocketTransport.test.ts +++ b/packages/data-connect/test/unit/websocketTransport.test.ts @@ -48,7 +48,7 @@ interface TransportWithInternals { requestId: string, response: DataConnectResponse ): Promise; - rejectAllActiveRequests(code: Code, reason: string): void; + rejectAllRequests(code: Code, reason: string): void; } describe('WebSocketTransport', () => { @@ -181,19 +181,19 @@ describe('WebSocketTransport', () => { expect(transport.connection).to.be.undefined; }); - it('should call rejectAllActiveRequests and clean up when closed externally', async () => { + it('should call rejectAllRequests and clean up when closed externally', async () => { const openPromise = transport.openConnection(); await transport.connection!.simulateOpen(); await openPromise; - const rejectSpy = sinon.spy(transport, 'rejectAllActiveRequests'); + const rejectSpy = sinon.spy(transport, 'rejectAllRequests'); await transport.connection!.simulateClose(); expect(rejectSpy).to.have.been.calledOnce; expect(rejectSpy.firstCall.args[0]).to.equal(Code.OTHER); expect(rejectSpy.firstCall.args[1]).to.equal( - `Stream disconnected with code ${WEBSOCKET_CLOSE_CODE}: Normal Closure` + `Stream disconnected while idle with code ${WEBSOCKET_CLOSE_CODE}: Normal Closure` ); }); }); From 70183b0e21fdf47abc9666d8ac516a4e334513c1 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 5 May 2026 14:16:32 -0700 Subject: [PATCH 171/174] chore: fix e2e tests for functions and AI (#9924) --- e2e/smoke-tests/sample-apps/compat.js | 2 +- e2e/smoke-tests/sample-apps/modular.js | 4 ++-- e2e/smoke-tests/tests/compat.test.ts | 2 +- e2e/smoke-tests/tests/modular.test.ts | 8 +++----- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/e2e/smoke-tests/sample-apps/compat.js b/e2e/smoke-tests/sample-apps/compat.js index e77b7d087d..4dc51db24f 100644 --- a/e2e/smoke-tests/sample-apps/compat.js +++ b/e2e/smoke-tests/sample-apps/compat.js @@ -87,7 +87,7 @@ async function authLogout() { async function callFunctions() { console.log('[FUNCTIONS] start'); const functions = firebase.functions(); - const callTest = functions.httpsCallable('callTest'); + const callTest = functions.httpsCallable('callTestv2'); try { const result = await callTest({ data: 'blah' }); console.log('[FUNCTIONS] result:', result.data); diff --git a/e2e/smoke-tests/sample-apps/modular.js b/e2e/smoke-tests/sample-apps/modular.js index 20ff0ce7bd..bd062a02cf 100644 --- a/e2e/smoke-tests/sample-apps/modular.js +++ b/e2e/smoke-tests/sample-apps/modular.js @@ -126,7 +126,7 @@ async function authLogout(app) { async function callFunctions(app) { console.log('[FUNCTIONS] start'); const functions = getFunctions(app); - let callTest = httpsCallable(functions, 'callTest'); + let callTest = httpsCallable(functions, 'callTestv2'); try { const result = await callTest({ data: 'blah' }); console.log('[FUNCTIONS] result (by name):', result.data); @@ -142,7 +142,7 @@ async function callFunctions(app) { } callTest = httpsCallableFromURL( functions, - `https://us-central-${app.options.projectId}.cloudfunctions.net/callTest` + `https://us-central1-${app.options.projectId}.cloudfunctions.net/callTestv2` ); try { const result = await callTest({ data: 'blah' }); diff --git a/e2e/smoke-tests/tests/compat.test.ts b/e2e/smoke-tests/tests/compat.test.ts index 661cd886a1..b69ec7c119 100644 --- a/e2e/smoke-tests/tests/compat.test.ts +++ b/e2e/smoke-tests/tests/compat.test.ts @@ -74,7 +74,7 @@ describe('COMPAT', () => { functions = firebase.functions(); }); it('httpsCallable()', async () => { - const callTest = functions.httpsCallable('callTest'); + const callTest = functions.httpsCallable('callTestv2'); const result = await callTest({ data: 'blah' }); expect(result.data.word).toBe('hellooo'); }); diff --git a/e2e/smoke-tests/tests/modular.test.ts b/e2e/smoke-tests/tests/modular.test.ts index 536a271ca5..8435d7ef96 100644 --- a/e2e/smoke-tests/tests/modular.test.ts +++ b/e2e/smoke-tests/tests/modular.test.ts @@ -145,7 +145,7 @@ describe('MODULAR', () => { it('httpsCallable()', async () => { const callTest = httpsCallable<{ data: string }, { word: string }>( functions, - 'callTest' + 'callTestv2' ); const result = await callTest({ data: 'blah' }); expect(result.data.word).toBe('hellooo'); @@ -154,7 +154,7 @@ describe('MODULAR', () => { it('httpsCallableFromURL()', async () => { const callTest = httpsCallableFromURL<{ data: string }, { word: string }>( functions, - `https://us-central1-${app.options.projectId}.cloudfunctions.net/callTest` + `https://us-central1-${app.options.projectId}.cloudfunctions.net/callTestv2` ); const result = await callTest({ data: 'blah' }); expect(result.data.word).toBe('hellooo'); @@ -313,11 +313,9 @@ describe('MODULAR', () => { it('getVertexAI()', () => { ai = getAI(app, { backend: new VertexAIBackend() }); }); - it('getGenerativeModel() and countTokens()', async () => { + it('getGenerativeModel()', async () => { const model = getGenerativeModel(ai, { model: 'gemini-2.5-flash' }); expect(model.model).toMatch(/gemini-2.5-flash$/); - const result = await model.countTokens('abcdefg'); - expect(result.totalTokens).toBeTruthy; }); }); From 1adfd640e779ee0d89e62404c6823ca9f5a80ec0 Mon Sep 17 00:00:00 2001 From: Google Open Source Bot Date: Thu, 7 May 2026 05:51:47 -0700 Subject: [PATCH 172/174] Version Packages (#9923) Release v12.13.0 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/four-bottles-marry.md | 5 -- .changeset/little-apples-rush.md | 6 -- .changeset/loud-camels-cross.md | 5 -- .changeset/nasty-kiwis-yell.md | 53 ----------------- .changeset/nervous-carpets-approve.md | 6 -- .changeset/pb-add-image-config.md | 7 --- .changeset/quick-cars-obey.md | 6 -- integration/compat-interop/package.json | 28 ++++----- integration/firestore/package.json | 4 +- integration/messaging/package.json | 2 +- packages/ai/CHANGELOG.md | 21 +++++++ packages/ai/package.json | 12 ++-- packages/analytics-compat/CHANGELOG.md | 12 ++++ packages/analytics-compat/package.json | 12 ++-- packages/analytics-interop-types/CHANGELOG.md | 6 ++ packages/analytics-interop-types/package.json | 2 +- packages/analytics-types/CHANGELOG.md | 6 ++ packages/analytics-types/package.json | 2 +- packages/analytics/CHANGELOG.md | 12 ++++ packages/analytics/package.json | 12 ++-- packages/app-check-compat/CHANGELOG.md | 13 +++++ packages/app-check-compat/package.json | 14 ++--- packages/app-check-interop-types/CHANGELOG.md | 6 ++ packages/app-check-interop-types/package.json | 2 +- packages/app-check-types/CHANGELOG.md | 6 ++ packages/app-check-types/package.json | 2 +- packages/app-check/CHANGELOG.md | 11 ++++ packages/app-check/package.json | 10 ++-- packages/app-compat/CHANGELOG.md | 12 ++++ packages/app-compat/package.json | 10 ++-- packages/app-types/CHANGELOG.md | 9 +++ packages/app-types/package.json | 4 +- packages/app/CHANGELOG.md | 11 ++++ packages/app/package.json | 8 +-- packages/auth-compat/CHANGELOG.md | 12 ++++ packages/auth-compat/package.json | 12 ++-- packages/auth-interop-types/CHANGELOG.md | 6 ++ packages/auth-interop-types/package.json | 2 +- packages/auth-types/CHANGELOG.md | 6 ++ packages/auth-types/package.json | 2 +- packages/auth/CHANGELOG.md | 11 ++++ packages/auth/package.json | 10 ++-- packages/component/CHANGELOG.md | 9 +++ packages/component/package.json | 4 +- packages/data-connect/CHANGELOG.md | 16 +++++ packages/data-connect/package.json | 12 ++-- packages/database-compat/CHANGELOG.md | 13 +++++ packages/database-compat/package.json | 14 ++--- packages/database-types/CHANGELOG.md | 10 ++++ packages/database-types/package.json | 6 +- packages/database/CHANGELOG.md | 13 +++++ packages/database/package.json | 14 ++--- packages/firebase/CHANGELOG.md | 47 +++++++++++++++ packages/firebase/package.json | 58 +++++++++---------- packages/firestore-compat/CHANGELOG.md | 12 ++++ packages/firestore-compat/package.json | 12 ++-- packages/firestore-types/CHANGELOG.md | 6 ++ packages/firestore-types/package.json | 2 +- packages/firestore/CHANGELOG.md | 16 +++++ packages/firestore/package.json | 16 ++--- packages/functions-compat/CHANGELOG.md | 12 ++++ packages/functions-compat/package.json | 12 ++-- packages/functions-types/CHANGELOG.md | 6 ++ packages/functions-types/package.json | 2 +- packages/functions/CHANGELOG.md | 13 +++++ packages/functions/package.json | 14 ++--- packages/installations-compat/CHANGELOG.md | 12 ++++ packages/installations-compat/package.json | 12 ++-- packages/installations-types/CHANGELOG.md | 6 ++ packages/installations-types/package.json | 2 +- packages/installations/CHANGELOG.md | 10 ++++ packages/installations/package.json | 8 +-- packages/logger/CHANGELOG.md | 6 ++ packages/logger/package.json | 2 +- packages/messaging-compat/CHANGELOG.md | 11 ++++ packages/messaging-compat/package.json | 10 ++-- packages/messaging-interop-types/CHANGELOG.md | 6 ++ packages/messaging-interop-types/package.json | 2 +- packages/messaging/CHANGELOG.md | 12 ++++ packages/messaging/package.json | 12 ++-- packages/performance-compat/CHANGELOG.md | 13 +++++ packages/performance-compat/package.json | 14 ++--- packages/performance-types/CHANGELOG.md | 6 ++ packages/performance-types/package.json | 2 +- packages/performance/CHANGELOG.md | 12 ++++ packages/performance/package.json | 12 ++-- packages/remote-config-compat/CHANGELOG.md | 13 +++++ packages/remote-config-compat/package.json | 14 ++--- packages/remote-config-types/CHANGELOG.md | 6 ++ packages/remote-config-types/package.json | 2 +- packages/remote-config/CHANGELOG.md | 12 ++++ packages/remote-config/package.json | 12 ++-- packages/rules-unit-testing/CHANGELOG.md | 6 ++ packages/rules-unit-testing/package.json | 2 +- packages/storage-compat/CHANGELOG.md | 12 ++++ packages/storage-compat/package.json | 14 ++--- packages/storage-types/CHANGELOG.md | 6 ++ packages/storage-types/package.json | 2 +- packages/storage/CHANGELOG.md | 10 ++++ packages/storage/package.json | 10 ++-- packages/template-types/CHANGELOG.md | 6 ++ packages/template-types/package.json | 2 +- packages/template/CHANGELOG.md | 9 +++ packages/template/package.json | 6 +- packages/util/CHANGELOG.md | 6 ++ packages/util/package.json | 2 +- packages/webchannel-wrapper/CHANGELOG.md | 6 ++ packages/webchannel-wrapper/package.json | 2 +- repo-scripts/size-analysis/package.json | 6 +- 109 files changed, 752 insertions(+), 321 deletions(-) delete mode 100644 .changeset/four-bottles-marry.md delete mode 100644 .changeset/little-apples-rush.md delete mode 100644 .changeset/loud-camels-cross.md delete mode 100644 .changeset/nasty-kiwis-yell.md delete mode 100644 .changeset/nervous-carpets-approve.md delete mode 100644 .changeset/pb-add-image-config.md delete mode 100644 .changeset/quick-cars-obey.md diff --git a/.changeset/four-bottles-marry.md b/.changeset/four-bottles-marry.md deleted file mode 100644 index 8a32d70ba1..0000000000 --- a/.changeset/four-bottles-marry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@firebase/firestore": patch ---- - -Added search stage support for languageCode, offset, limit, and retrievalDepth diff --git a/.changeset/little-apples-rush.md b/.changeset/little-apples-rush.md deleted file mode 100644 index a007193a83..0000000000 --- a/.changeset/little-apples-rush.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -Added `LiveSession.resumeSession()` to allow resuming a previous `LiveSession`. Also added `contextWindowCompression` feature. diff --git a/.changeset/loud-camels-cross.md b/.changeset/loud-camels-cross.md deleted file mode 100644 index 86ceced3d4..0000000000 --- a/.changeset/loud-camels-cross.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@firebase/firestore": patch ---- - -fix(firestore): Assertion ID: ca9 (pendingResponses less than 0) caused by target creation race condition diff --git a/.changeset/nasty-kiwis-yell.md b/.changeset/nasty-kiwis-yell.md deleted file mode 100644 index 656e6842d7..0000000000 --- a/.changeset/nasty-kiwis-yell.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -'@firebase/rules-unit-testing': patch -'@firebase/auth-compat': patch -'@firebase/ai': patch -'@firebase/analytics': patch -'@firebase/analytics-compat': patch -'@firebase/analytics-interop-types': patch -'@firebase/analytics-types': patch -'@firebase/app': patch -'@firebase/app-check': patch -'@firebase/app-check-compat': patch -'@firebase/app-check-interop-types': patch -'@firebase/app-check-types': patch -'@firebase/app-compat': patch -'@firebase/app-types': patch -'@firebase/auth': patch -'@firebase/auth-interop-types': patch -'@firebase/auth-types': patch -'@firebase/component': patch -'@firebase/data-connect': patch -'@firebase/database': patch -'@firebase/database-compat': patch -'@firebase/database-types': patch -'firebase': patch -'@firebase/firestore': patch -'@firebase/firestore-compat': patch -'@firebase/firestore-types': patch -'@firebase/functions': patch -'@firebase/functions-compat': patch -'@firebase/functions-types': patch -'@firebase/installations': patch -'@firebase/installations-compat': patch -'@firebase/installations-types': patch -'@firebase/logger': patch -'@firebase/messaging': patch -'@firebase/messaging-compat': patch -'@firebase/messaging-interop-types': patch -'@firebase/performance': patch -'@firebase/performance-compat': patch -'@firebase/performance-types': patch -'@firebase/remote-config': patch -'@firebase/remote-config-compat': patch -'@firebase/remote-config-types': patch -'@firebase/storage': patch -'@firebase/storage-compat': patch -'@firebase/storage-types': patch -'@firebase/template': patch -'@firebase/template-types': patch -'@firebase/util': patch -'@firebase/webchannel-wrapper': patch ---- - -Updated dependencies. diff --git a/.changeset/nervous-carpets-approve.md b/.changeset/nervous-carpets-approve.md deleted file mode 100644 index 731a311799..0000000000 --- a/.changeset/nervous-carpets-approve.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/data-connect': minor -'firebase': minor ---- - -Hardened the Firebase SQL Connect streaming transport with intelligent reconnection, query de-duplication, and resume optimizations. diff --git a/.changeset/pb-add-image-config.md b/.changeset/pb-add-image-config.md deleted file mode 100644 index 13a393deff..0000000000 --- a/.changeset/pb-add-image-config.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@firebase/ai": minor -"firebase": minor ---- - -Added support for `ImageConfig` (aspect ratio and size). -Expanded `FinishReason` values to include all currently available values provided by the models. diff --git a/.changeset/quick-cars-obey.md b/.changeset/quick-cars-obey.md deleted file mode 100644 index 12aef6e4a9..0000000000 --- a/.changeset/quick-cars-obey.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/ai': minor -'firebase': minor ---- - -AI Logic : Feature : Added support for Grounding with Google Maps. diff --git a/integration/compat-interop/package.json b/integration/compat-interop/package.json index 31316d9b6c..ceb0843943 100644 --- a/integration/compat-interop/package.json +++ b/integration/compat-interop/package.json @@ -8,20 +8,20 @@ "test:debug": "karma start --browsers Chrome --auto-watch" }, "dependencies": { - "@firebase/app": "0.14.11", - "@firebase/app-compat": "0.5.11", - "@firebase/analytics": "0.10.21", - "@firebase/analytics-compat": "0.2.27", - "@firebase/auth": "1.13.0", - "@firebase/auth-compat": "0.6.5", - "@firebase/functions": "0.13.3", - "@firebase/functions-compat": "0.4.3", - "@firebase/messaging": "0.12.25", - "@firebase/messaging-compat": "0.2.25", - "@firebase/performance": "0.7.11", - "@firebase/performance-compat": "0.2.24", - "@firebase/remote-config": "0.8.2", - "@firebase/remote-config-compat": "0.2.23" + "@firebase/app": "0.14.12", + "@firebase/app-compat": "0.5.12", + "@firebase/analytics": "0.10.22", + "@firebase/analytics-compat": "0.2.28", + "@firebase/auth": "1.13.1", + "@firebase/auth-compat": "0.6.6", + "@firebase/functions": "0.13.4", + "@firebase/functions-compat": "0.4.4", + "@firebase/messaging": "0.12.26", + "@firebase/messaging-compat": "0.2.26", + "@firebase/performance": "0.7.12", + "@firebase/performance-compat": "0.2.25", + "@firebase/remote-config": "0.8.3", + "@firebase/remote-config-compat": "0.2.24" }, "devDependencies": { "typescript": "5.5.4" diff --git a/integration/firestore/package.json b/integration/firestore/package.json index 60251ecce8..8b99b69023 100644 --- a/integration/firestore/package.json +++ b/integration/firestore/package.json @@ -15,8 +15,8 @@ "test:memory:debug": "yarn build:memory; karma start --auto-watch --browsers Chrome" }, "dependencies": { - "@firebase/app": "0.14.11", - "@firebase/firestore": "4.14.0" + "@firebase/app": "0.14.12", + "@firebase/firestore": "4.14.1" }, "devDependencies": { "@types/mocha": "9.1.1", diff --git a/integration/messaging/package.json b/integration/messaging/package.json index ca616d257e..7d87ab1e39 100644 --- a/integration/messaging/package.json +++ b/integration/messaging/package.json @@ -9,7 +9,7 @@ "test:manual": "mocha --exit" }, "devDependencies": { - "firebase": "12.12.1", + "firebase": "12.13.0", "chai": "4.5.0", "chromedriver": "119.0.1", "express": "4.21.2", diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 7de78db5af..5425b2c932 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,5 +1,26 @@ # @firebase/ai +## 2.12.0 + +### Minor Changes + +- [`ffa39f6`](https://github.com/firebase/firebase-js-sdk/commit/ffa39f61c36e9d90a26573f042863e0086ee01e2) [#9795](https://github.com/firebase/firebase-js-sdk/pull/9795) - Added `LiveSession.resumeSession()` to allow resuming a previous `LiveSession`. Also added `contextWindowCompression` feature. + +- [`86dc0db`](https://github.com/firebase/firebase-js-sdk/commit/86dc0db9218d9ae52282d595007fc60b40c98b6e) [#9819](https://github.com/firebase/firebase-js-sdk/pull/9819) - Added support for `ImageConfig` (aspect ratio and size). + Expanded `FinishReason` values to include all currently available values provided by the models. + +- [`345c5f6`](https://github.com/firebase/firebase-js-sdk/commit/345c5f6235492b45e84034f364fd95280bd6e428) [#9458](https://github.com/firebase/firebase-js-sdk/pull/9458) - AI Logic : Feature : Added support for Grounding with Google Maps. + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/app-check-interop-types@0.3.4 + - @firebase/component@0.7.3 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + ## 2.11.1 ### Patch Changes diff --git a/packages/ai/package.json b/packages/ai/package.json index b493a76123..182ecd4de6 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/ai", - "version": "2.11.1", + "version": "2.12.0", "description": "The Firebase AI SDK", "author": "Firebase (https://firebase.google.com/)", "engines": { @@ -52,15 +52,15 @@ "@firebase/app-types": "0.x" }, "dependencies": { - "@firebase/app-check-interop-types": "0.3.3", - "@firebase/component": "0.7.2", - "@firebase/logger": "0.5.0", - "@firebase/util": "1.15.0", + "@firebase/app-check-interop-types": "0.3.4", + "@firebase/component": "0.7.3", + "@firebase/logger": "0.5.1", + "@firebase/util": "1.15.1", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.11", + "@firebase/app": "0.14.12", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/analytics-compat/CHANGELOG.md b/packages/analytics-compat/CHANGELOG.md index f4b960e418..66b32421ab 100644 --- a/packages/analytics-compat/CHANGELOG.md +++ b/packages/analytics-compat/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/analytics-compat +## 0.2.28 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/analytics@0.10.22 + - @firebase/analytics-types@0.8.4 + - @firebase/component@0.7.3 + - @firebase/util@1.15.1 + ## 0.2.27 ### Patch Changes diff --git a/packages/analytics-compat/package.json b/packages/analytics-compat/package.json index 12fe60bc0d..722fdfe3a1 100644 --- a/packages/analytics-compat/package.json +++ b/packages/analytics-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/analytics-compat", - "version": "0.2.27", + "version": "0.2.28", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -22,7 +22,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.11", + "@firebase/app-compat": "0.5.12", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.37.0", @@ -52,10 +52,10 @@ }, "typings": "dist/src/index.d.ts", "dependencies": { - "@firebase/component": "0.7.2", - "@firebase/analytics": "0.10.21", - "@firebase/analytics-types": "0.8.3", - "@firebase/util": "1.15.0", + "@firebase/component": "0.7.3", + "@firebase/analytics": "0.10.22", + "@firebase/analytics-types": "0.8.4", + "@firebase/util": "1.15.1", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/analytics-interop-types/CHANGELOG.md b/packages/analytics-interop-types/CHANGELOG.md index aeb3fe36a8..0a40fb31f6 100644 --- a/packages/analytics-interop-types/CHANGELOG.md +++ b/packages/analytics-interop-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/analytics-interop-types +## 0.3.5 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.3.4 ### Patch Changes diff --git a/packages/analytics-interop-types/package.json b/packages/analytics-interop-types/package.json index d06f0c3677..ea701e7733 100644 --- a/packages/analytics-interop-types/package.json +++ b/packages/analytics-interop-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/analytics-interop-types", - "version": "0.3.4", + "version": "0.3.5", "description": "@firebase/analytics Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/analytics-types/CHANGELOG.md b/packages/analytics-types/CHANGELOG.md index 02d1ad9828..5c3d9d5d76 100644 --- a/packages/analytics-types/CHANGELOG.md +++ b/packages/analytics-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/analytics-types +## 0.8.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.8.3 ### Patch Changes diff --git a/packages/analytics-types/package.json b/packages/analytics-types/package.json index 2798c23b3f..cba202d3e6 100644 --- a/packages/analytics-types/package.json +++ b/packages/analytics-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/analytics-types", - "version": "0.8.3", + "version": "0.8.4", "description": "@firebase/analytics Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/analytics/CHANGELOG.md b/packages/analytics/CHANGELOG.md index 43e7f207db..fed86b9d43 100644 --- a/packages/analytics/CHANGELOG.md +++ b/packages/analytics/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/analytics +## 0.10.22 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/installations@0.6.22 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + ## 0.10.21 ### Patch Changes diff --git a/packages/analytics/package.json b/packages/analytics/package.json index 814e291e94..fba16b0a33 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/analytics", - "version": "0.10.21", + "version": "0.10.22", "description": "A analytics package for new firebase packages", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -39,15 +39,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.21", - "@firebase/logger": "0.5.0", - "@firebase/util": "1.15.0", - "@firebase/component": "0.7.2", + "@firebase/installations": "0.6.22", + "@firebase/logger": "0.5.1", + "@firebase/util": "1.15.1", + "@firebase/component": "0.7.3", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.11", + "@firebase/app": "0.14.12", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "@rollup/plugin-commonjs": "21.1.0", diff --git a/packages/app-check-compat/CHANGELOG.md b/packages/app-check-compat/CHANGELOG.md index 38bcb741a1..a7c93d3e04 100644 --- a/packages/app-check-compat/CHANGELOG.md +++ b/packages/app-check-compat/CHANGELOG.md @@ -1,5 +1,18 @@ # @firebase/app-check-compat +## 0.4.3 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/app-check@0.11.3 + - @firebase/app-check-types@0.5.4 + - @firebase/component@0.7.3 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + ## 0.4.2 ### Patch Changes diff --git a/packages/app-check-compat/package.json b/packages/app-check-compat/package.json index c039efc4ca..d405518c8c 100644 --- a/packages/app-check-compat/package.json +++ b/packages/app-check-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-check-compat", - "version": "0.4.2", + "version": "0.4.3", "description": "A compat App Check package for new firebase packages", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -34,16 +34,16 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/app-check": "0.11.2", - "@firebase/app-check-types": "0.5.3", - "@firebase/logger": "0.5.0", - "@firebase/util": "1.15.0", - "@firebase/component": "0.7.2", + "@firebase/app-check": "0.11.3", + "@firebase/app-check-types": "0.5.4", + "@firebase/logger": "0.5.1", + "@firebase/util": "1.15.1", + "@firebase/component": "0.7.3", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.11", + "@firebase/app-compat": "0.5.12", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-check-interop-types/CHANGELOG.md b/packages/app-check-interop-types/CHANGELOG.md index 6b10b284a4..6ff197f250 100644 --- a/packages/app-check-interop-types/CHANGELOG.md +++ b/packages/app-check-interop-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/app-check-interop-types +## 0.3.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.3.3 ### Patch Changes diff --git a/packages/app-check-interop-types/package.json b/packages/app-check-interop-types/package.json index c7e45614ee..3c2f79e489 100644 --- a/packages/app-check-interop-types/package.json +++ b/packages/app-check-interop-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-check-interop-types", - "version": "0.3.3", + "version": "0.3.4", "description": "@firebase/app-check-interop-types Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/app-check-types/CHANGELOG.md b/packages/app-check-types/CHANGELOG.md index 1f14898bba..73b5ea9ef3 100644 --- a/packages/app-check-types/CHANGELOG.md +++ b/packages/app-check-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/app-check-types +## 0.5.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.5.3 ### Patch Changes diff --git a/packages/app-check-types/package.json b/packages/app-check-types/package.json index 9243978856..5fbeff8d1b 100644 --- a/packages/app-check-types/package.json +++ b/packages/app-check-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-check-types", - "version": "0.5.3", + "version": "0.5.4", "description": "@firebase/app-check Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/app-check/CHANGELOG.md b/packages/app-check/CHANGELOG.md index 1d12dd4297..137d9b6240 100644 --- a/packages/app-check/CHANGELOG.md +++ b/packages/app-check/CHANGELOG.md @@ -1,5 +1,16 @@ # @firebase/app-check +## 0.11.3 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + ## 0.11.2 ### Patch Changes diff --git a/packages/app-check/package.json b/packages/app-check/package.json index 10a9e31317..3599f95e64 100644 --- a/packages/app-check/package.json +++ b/packages/app-check/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-check", - "version": "0.11.2", + "version": "0.11.3", "description": "The App Check component of the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,14 +37,14 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/util": "1.15.0", - "@firebase/component": "0.7.2", - "@firebase/logger": "0.5.0", + "@firebase/util": "1.15.1", + "@firebase/component": "0.7.3", + "@firebase/logger": "0.5.1", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.11", + "@firebase/app": "0.14.12", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/app-compat/CHANGELOG.md b/packages/app-compat/CHANGELOG.md index 7ca05cc021..a8c48b35c7 100644 --- a/packages/app-compat/CHANGELOG.md +++ b/packages/app-compat/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/app-compat +## 0.5.12 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/app@0.14.12 + - @firebase/component@0.7.3 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + ## 0.5.11 ### Patch Changes diff --git a/packages/app-compat/package.json b/packages/app-compat/package.json index 5d76faf837..71b5e4455b 100644 --- a/packages/app-compat/package.json +++ b/packages/app-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-compat", - "version": "0.5.11", + "version": "0.5.12", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,10 +37,10 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/app": "0.14.11", - "@firebase/util": "1.15.0", - "@firebase/logger": "0.5.0", - "@firebase/component": "0.7.2", + "@firebase/app": "0.14.12", + "@firebase/util": "1.15.1", + "@firebase/logger": "0.5.1", + "@firebase/component": "0.7.3", "tslib": "^2.1.0" }, "devDependencies": { diff --git a/packages/app-types/CHANGELOG.md b/packages/app-types/CHANGELOG.md index 34faf4fca2..f460adf437 100644 --- a/packages/app-types/CHANGELOG.md +++ b/packages/app-types/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/app-types +## 0.9.5 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/logger@0.5.1 + ## 0.9.4 ### Patch Changes diff --git a/packages/app-types/package.json b/packages/app-types/package.json index 82ec52477d..8ca90f436a 100644 --- a/packages/app-types/package.json +++ b/packages/app-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-types", - "version": "0.9.4", + "version": "0.9.5", "description": "@firebase/app Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -21,7 +21,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "dependencies": { - "@firebase/logger": "0.5.0" + "@firebase/logger": "0.5.1" }, "devDependencies": { "typescript": "5.5.4" diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 4e86935681..48d31e5e10 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,16 @@ # @firebase/app +## 0.14.12 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + ## 0.14.11 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index d39539ed5e..fbc810bb7d 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app", - "version": "0.14.11", + "version": "0.14.12", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -39,9 +39,9 @@ "typings:internal": "node ../../scripts/build/use_typings.js ./dist/app.d.ts" }, "dependencies": { - "@firebase/util": "1.15.0", - "@firebase/logger": "0.5.0", - "@firebase/component": "0.7.2", + "@firebase/util": "1.15.1", + "@firebase/logger": "0.5.1", + "@firebase/component": "0.7.3", "idb": "7.1.1", "tslib": "^2.1.0" }, diff --git a/packages/auth-compat/CHANGELOG.md b/packages/auth-compat/CHANGELOG.md index 6226cfad25..27c9c374aa 100644 --- a/packages/auth-compat/CHANGELOG.md +++ b/packages/auth-compat/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/auth-compat +## 0.6.6 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/auth@1.13.1 + - @firebase/auth-types@0.13.1 + - @firebase/component@0.7.3 + - @firebase/util@1.15.1 + ## 0.6.5 ### Patch Changes diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index 5a4cfa7274..9e3a9af14d 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth-compat", - "version": "0.6.5", + "version": "0.6.6", "description": "FirebaseAuth compatibility package that uses API style compatible with Firebase@8 and prior versions", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -49,15 +49,15 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/auth": "1.13.0", - "@firebase/auth-types": "0.13.0", - "@firebase/component": "0.7.2", - "@firebase/util": "1.15.0", + "@firebase/auth": "1.13.1", + "@firebase/auth-types": "0.13.1", + "@firebase/component": "0.7.3", + "@firebase/util": "1.15.1", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.5.11", + "@firebase/app-compat": "0.5.12", "@rollup/plugin-json": "6.1.0", "rollup": "2.79.2", "rollup-plugin-replace": "2.2.0", diff --git a/packages/auth-interop-types/CHANGELOG.md b/packages/auth-interop-types/CHANGELOG.md index 93b59e9035..4120e15aad 100644 --- a/packages/auth-interop-types/CHANGELOG.md +++ b/packages/auth-interop-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/auth-interop-types +## 0.2.5 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.2.4 ### Patch Changes diff --git a/packages/auth-interop-types/package.json b/packages/auth-interop-types/package.json index ecea25d0c0..e19588290b 100644 --- a/packages/auth-interop-types/package.json +++ b/packages/auth-interop-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth-interop-types", - "version": "0.2.4", + "version": "0.2.5", "description": "@firebase/auth interop Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/auth-types/CHANGELOG.md b/packages/auth-types/CHANGELOG.md index 16781f8b14..7dd2fe66c7 100644 --- a/packages/auth-types/CHANGELOG.md +++ b/packages/auth-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/auth-types +## 0.13.1 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.13.0 ### Minor Changes diff --git a/packages/auth-types/package.json b/packages/auth-types/package.json index 66dced1d56..34aba87458 100644 --- a/packages/auth-types/package.json +++ b/packages/auth-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth-types", - "version": "0.13.0", + "version": "0.13.1", "description": "@firebase/auth Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/auth/CHANGELOG.md b/packages/auth/CHANGELOG.md index 86db43f7a5..1c4836dcb2 100644 --- a/packages/auth/CHANGELOG.md +++ b/packages/auth/CHANGELOG.md @@ -1,5 +1,16 @@ # @firebase/auth +## 1.13.1 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + ## 1.13.0 ### Minor Changes diff --git a/packages/auth/package.json b/packages/auth/package.json index 24f7c8208d..7b21dc9c2f 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth", - "version": "1.13.0", + "version": "1.13.1", "description": "The Firebase Authenticaton component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/node/index.js", @@ -124,14 +124,14 @@ } }, "dependencies": { - "@firebase/component": "0.7.2", - "@firebase/logger": "0.5.0", - "@firebase/util": "1.15.0", + "@firebase/component": "0.7.3", + "@firebase/logger": "0.5.1", + "@firebase/util": "1.15.1", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.11", + "@firebase/app": "0.14.12", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-strip": "3.0.4", "@types/express": "4.17.21", diff --git a/packages/component/CHANGELOG.md b/packages/component/CHANGELOG.md index b12325b41b..21d5a4415e 100644 --- a/packages/component/CHANGELOG.md +++ b/packages/component/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/component +## 0.7.3 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/util@1.15.1 + ## 0.7.2 ### Patch Changes diff --git a/packages/component/package.json b/packages/component/package.json index e7e50b053b..c6e73def15 100644 --- a/packages/component/package.json +++ b/packages/component/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/component", - "version": "0.7.2", + "version": "0.7.3", "description": "Firebase Component Platform", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -31,7 +31,7 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/util": "1.15.0", + "@firebase/util": "1.15.1", "tslib": "^2.1.0" }, "license": "Apache-2.0", diff --git a/packages/data-connect/CHANGELOG.md b/packages/data-connect/CHANGELOG.md index b6cc55d062..ac14d75ee8 100644 --- a/packages/data-connect/CHANGELOG.md +++ b/packages/data-connect/CHANGELOG.md @@ -1,5 +1,21 @@ ## Unreleased +## 0.7.0 + +### Minor Changes + +- [`714b41d`](https://github.com/firebase/firebase-js-sdk/commit/714b41dcc55339f94f904558ff190c5bdc9ac49f) [#9905](https://github.com/firebase/firebase-js-sdk/pull/9905) - Hardened the Firebase SQL Connect streaming transport with intelligent reconnection, query de-duplication, and resume optimizations. + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/auth-interop-types@0.2.5 + - @firebase/component@0.7.3 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + ## 0.6.0 ### Minor Changes diff --git a/packages/data-connect/package.json b/packages/data-connect/package.json index 7d5c032042..d92fbbc6e2 100644 --- a/packages/data-connect/package.json +++ b/packages/data-connect/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/data-connect", - "version": "0.6.0", + "version": "0.7.0", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -48,14 +48,14 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.7.2", - "@firebase/logger": "0.5.0", - "@firebase/util": "1.15.0", + "@firebase/auth-interop-types": "0.2.5", + "@firebase/component": "0.7.3", + "@firebase/logger": "0.5.1", + "@firebase/util": "1.15.1", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.11", + "@firebase/app": "0.14.12", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" diff --git a/packages/database-compat/CHANGELOG.md b/packages/database-compat/CHANGELOG.md index 30bee1068f..90e056a512 100644 --- a/packages/database-compat/CHANGELOG.md +++ b/packages/database-compat/CHANGELOG.md @@ -1,5 +1,18 @@ # @firebase/database-compat +## 2.1.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/database@1.1.3 + - @firebase/database-types@1.0.20 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + ## 2.1.3 ### Patch Changes diff --git a/packages/database-compat/package.json b/packages/database-compat/package.json index 9c0868b5aa..053bdd6fe3 100644 --- a/packages/database-compat/package.json +++ b/packages/database-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database-compat", - "version": "2.1.3", + "version": "2.1.4", "description": "The Realtime Database component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.js", @@ -49,15 +49,15 @@ "add-compat-overloads": "ts-node-script ../../scripts/build/create-overloads.ts -i ../database/dist/public.d.ts -o dist/database-compat/src/index.d.ts -a -r Database:types.FirebaseDatabase -r Query:types.Query -r DatabaseReference:types.Reference -r FirebaseApp:FirebaseAppCompat --moduleToEnhance @firebase/database" }, "dependencies": { - "@firebase/database": "1.1.2", - "@firebase/database-types": "1.0.19", - "@firebase/logger": "0.5.0", - "@firebase/util": "1.15.0", - "@firebase/component": "0.7.2", + "@firebase/database": "1.1.3", + "@firebase/database-types": "1.0.20", + "@firebase/logger": "0.5.1", + "@firebase/util": "1.15.1", + "@firebase/component": "0.7.3", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.11", + "@firebase/app-compat": "0.5.12", "typescript": "5.5.4" }, "repository": { diff --git a/packages/database-types/CHANGELOG.md b/packages/database-types/CHANGELOG.md index 9a0ce22106..fc40b2de80 100644 --- a/packages/database-types/CHANGELOG.md +++ b/packages/database-types/CHANGELOG.md @@ -1,5 +1,15 @@ # @firebase/database-types +## 1.0.20 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/app-types@0.9.5 + - @firebase/util@1.15.1 + ## 1.0.19 ### Patch Changes diff --git a/packages/database-types/package.json b/packages/database-types/package.json index 572b300e24..9715974d62 100644 --- a/packages/database-types/package.json +++ b/packages/database-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database-types", - "version": "1.0.19", + "version": "1.0.20", "description": "@firebase/database Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -12,8 +12,8 @@ "index.d.ts" ], "dependencies": { - "@firebase/app-types": "0.9.4", - "@firebase/util": "1.15.0" + "@firebase/app-types": "0.9.5", + "@firebase/util": "1.15.1" }, "repository": { "directory": "packages/database-types", diff --git a/packages/database/CHANGELOG.md b/packages/database/CHANGELOG.md index b84061f3bd..281dabf069 100644 --- a/packages/database/CHANGELOG.md +++ b/packages/database/CHANGELOG.md @@ -1,5 +1,18 @@ # Unreleased +## 1.1.3 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/app-check-interop-types@0.3.4 + - @firebase/auth-interop-types@0.2.5 + - @firebase/component@0.7.3 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + ## 1.1.2 ### Patch Changes diff --git a/packages/database/package.json b/packages/database/package.json index a35f543cbd..a3aa6dd544 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database", - "version": "1.1.2", + "version": "1.1.3", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -48,16 +48,16 @@ "license": "Apache-2.0", "peerDependencies": {}, "dependencies": { - "@firebase/logger": "0.5.0", - "@firebase/util": "1.15.0", - "@firebase/component": "0.7.2", - "@firebase/app-check-interop-types": "0.3.3", - "@firebase/auth-interop-types": "0.2.4", + "@firebase/logger": "0.5.1", + "@firebase/util": "1.15.1", + "@firebase/component": "0.7.3", + "@firebase/app-check-interop-types": "0.3.4", + "@firebase/auth-interop-types": "0.2.5", "faye-websocket": "0.11.4", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.11", + "@firebase/app": "0.14.12", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" diff --git a/packages/firebase/CHANGELOG.md b/packages/firebase/CHANGELOG.md index 3921d478c0..8efb9c74a0 100644 --- a/packages/firebase/CHANGELOG.md +++ b/packages/firebase/CHANGELOG.md @@ -1,5 +1,52 @@ # firebase +## 12.13.0 + +### Minor Changes + +- [`ffa39f6`](https://github.com/firebase/firebase-js-sdk/commit/ffa39f61c36e9d90a26573f042863e0086ee01e2) [#9795](https://github.com/firebase/firebase-js-sdk/pull/9795) - Added `LiveSession.resumeSession()` to allow resuming a previous `LiveSession`. Also added `contextWindowCompression` feature. + +- [`714b41d`](https://github.com/firebase/firebase-js-sdk/commit/714b41dcc55339f94f904558ff190c5bdc9ac49f) [#9905](https://github.com/firebase/firebase-js-sdk/pull/9905) - Hardened the Firebase SQL Connect streaming transport with intelligent reconnection, query de-duplication, and resume optimizations. + +- [`86dc0db`](https://github.com/firebase/firebase-js-sdk/commit/86dc0db9218d9ae52282d595007fc60b40c98b6e) [#9819](https://github.com/firebase/firebase-js-sdk/pull/9819) - Added support for `ImageConfig` (aspect ratio and size). + Expanded `FinishReason` values to include all currently available values provided by the models. + +- [`345c5f6`](https://github.com/firebase/firebase-js-sdk/commit/345c5f6235492b45e84034f364fd95280bd6e428) [#9458](https://github.com/firebase/firebase-js-sdk/pull/9458) - AI Logic : Feature : Added support for Grounding with Google Maps. + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`96e81ff`](https://github.com/firebase/firebase-js-sdk/commit/96e81ffe9a6efd557685eea7db9d78e5594f43aa), [`ffa39f6`](https://github.com/firebase/firebase-js-sdk/commit/ffa39f61c36e9d90a26573f042863e0086ee01e2), [`402b1f0`](https://github.com/firebase/firebase-js-sdk/commit/402b1f01e67441c51701153031b6e645b71d4875), [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e), [`714b41d`](https://github.com/firebase/firebase-js-sdk/commit/714b41dcc55339f94f904558ff190c5bdc9ac49f), [`86dc0db`](https://github.com/firebase/firebase-js-sdk/commit/86dc0db9218d9ae52282d595007fc60b40c98b6e), [`345c5f6`](https://github.com/firebase/firebase-js-sdk/commit/345c5f6235492b45e84034f364fd95280bd6e428)]: + - @firebase/firestore@4.14.1 + - @firebase/ai@2.12.0 + - @firebase/auth-compat@0.6.6 + - @firebase/analytics@0.10.22 + - @firebase/analytics-compat@0.2.28 + - @firebase/app@0.14.12 + - @firebase/app-check@0.11.3 + - @firebase/app-check-compat@0.4.3 + - @firebase/app-compat@0.5.12 + - @firebase/app-types@0.9.5 + - @firebase/auth@1.13.1 + - @firebase/data-connect@0.7.0 + - @firebase/database@1.1.3 + - @firebase/database-compat@2.1.4 + - @firebase/firestore-compat@0.4.9 + - @firebase/functions@0.13.4 + - @firebase/functions-compat@0.4.4 + - @firebase/installations@0.6.22 + - @firebase/installations-compat@0.2.22 + - @firebase/messaging@0.12.26 + - @firebase/messaging-compat@0.2.26 + - @firebase/performance@0.7.12 + - @firebase/performance-compat@0.2.25 + - @firebase/remote-config@0.8.3 + - @firebase/remote-config-compat@0.2.24 + - @firebase/storage@0.14.3 + - @firebase/storage-compat@0.4.3 + - @firebase/util@1.15.1 + ## 12.12.1 ### Patch Changes diff --git a/packages/firebase/package.json b/packages/firebase/package.json index 4df75322fd..dd41fb4334 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -1,6 +1,6 @@ { "name": "firebase", - "version": "12.12.1", + "version": "12.13.0", "description": "Firebase JavaScript library for web and Node.js", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -423,34 +423,34 @@ "trusted-type-check": "tsec -p tsconfig.json --noEmit" }, "dependencies": { - "@firebase/ai": "2.11.1", - "@firebase/app": "0.14.11", - "@firebase/app-compat": "0.5.11", - "@firebase/app-types": "0.9.4", - "@firebase/auth": "1.13.0", - "@firebase/auth-compat": "0.6.5", - "@firebase/data-connect": "0.6.0", - "@firebase/database": "1.1.2", - "@firebase/database-compat": "2.1.3", - "@firebase/firestore": "4.14.0", - "@firebase/firestore-compat": "0.4.8", - "@firebase/functions": "0.13.3", - "@firebase/functions-compat": "0.4.3", - "@firebase/installations": "0.6.21", - "@firebase/installations-compat": "0.2.21", - "@firebase/messaging": "0.12.25", - "@firebase/messaging-compat": "0.2.25", - "@firebase/storage": "0.14.2", - "@firebase/storage-compat": "0.4.2", - "@firebase/performance": "0.7.11", - "@firebase/performance-compat": "0.2.24", - "@firebase/remote-config": "0.8.2", - "@firebase/remote-config-compat": "0.2.23", - "@firebase/analytics": "0.10.21", - "@firebase/analytics-compat": "0.2.27", - "@firebase/app-check": "0.11.2", - "@firebase/app-check-compat": "0.4.2", - "@firebase/util": "1.15.0" + "@firebase/ai": "2.12.0", + "@firebase/app": "0.14.12", + "@firebase/app-compat": "0.5.12", + "@firebase/app-types": "0.9.5", + "@firebase/auth": "1.13.1", + "@firebase/auth-compat": "0.6.6", + "@firebase/data-connect": "0.7.0", + "@firebase/database": "1.1.3", + "@firebase/database-compat": "2.1.4", + "@firebase/firestore": "4.14.1", + "@firebase/firestore-compat": "0.4.9", + "@firebase/functions": "0.13.4", + "@firebase/functions-compat": "0.4.4", + "@firebase/installations": "0.6.22", + "@firebase/installations-compat": "0.2.22", + "@firebase/messaging": "0.12.26", + "@firebase/messaging-compat": "0.2.26", + "@firebase/storage": "0.14.3", + "@firebase/storage-compat": "0.4.3", + "@firebase/performance": "0.7.12", + "@firebase/performance-compat": "0.2.25", + "@firebase/remote-config": "0.8.3", + "@firebase/remote-config-compat": "0.2.24", + "@firebase/analytics": "0.10.22", + "@firebase/analytics-compat": "0.2.28", + "@firebase/app-check": "0.11.3", + "@firebase/app-check-compat": "0.4.3", + "@firebase/util": "1.15.1" }, "devDependencies": { "rollup": "2.79.2", diff --git a/packages/firestore-compat/CHANGELOG.md b/packages/firestore-compat/CHANGELOG.md index e088416329..225edbb024 100644 --- a/packages/firestore-compat/CHANGELOG.md +++ b/packages/firestore-compat/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/firestore-compat +## 0.4.9 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`96e81ff`](https://github.com/firebase/firebase-js-sdk/commit/96e81ffe9a6efd557685eea7db9d78e5594f43aa), [`402b1f0`](https://github.com/firebase/firebase-js-sdk/commit/402b1f01e67441c51701153031b6e645b71d4875), [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/firestore@4.14.1 + - @firebase/component@0.7.3 + - @firebase/firestore-types@3.0.4 + - @firebase/util@1.15.1 + ## 0.4.8 ### Patch Changes diff --git a/packages/firestore-compat/package.json b/packages/firestore-compat/package.json index dd2a17d6a0..3e4bae06d1 100644 --- a/packages/firestore-compat/package.json +++ b/packages/firestore-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore-compat", - "version": "0.4.8", + "version": "0.4.9", "description": "The Cloud Firestore component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -46,14 +46,14 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/component": "0.7.2", - "@firebase/firestore": "4.14.0", - "@firebase/util": "1.15.0", - "@firebase/firestore-types": "3.0.3", + "@firebase/component": "0.7.3", + "@firebase/firestore": "4.14.1", + "@firebase/util": "1.15.1", + "@firebase/firestore-types": "3.0.4", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.11", + "@firebase/app-compat": "0.5.12", "@types/eslint": "7.29.0", "rollup": "2.79.2", "rollup-plugin-sourcemaps": "0.6.3", diff --git a/packages/firestore-types/CHANGELOG.md b/packages/firestore-types/CHANGELOG.md index 7550d8b777..a5f7ae03df 100644 --- a/packages/firestore-types/CHANGELOG.md +++ b/packages/firestore-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/firestore-types +## 3.0.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 3.0.3 ### Patch Changes diff --git a/packages/firestore-types/package.json b/packages/firestore-types/package.json index d1cf512ec5..331fbfa257 100644 --- a/packages/firestore-types/package.json +++ b/packages/firestore-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore-types", - "version": "3.0.3", + "version": "3.0.4", "description": "@firebase/firestore Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/firestore/CHANGELOG.md b/packages/firestore/CHANGELOG.md index 11be81ddc3..0a6c192d16 100644 --- a/packages/firestore/CHANGELOG.md +++ b/packages/firestore/CHANGELOG.md @@ -1,5 +1,21 @@ # @firebase/firestore +## 4.14.1 + +### Patch Changes + +- [`96e81ff`](https://github.com/firebase/firebase-js-sdk/commit/96e81ffe9a6efd557685eea7db9d78e5594f43aa) [#9884](https://github.com/firebase/firebase-js-sdk/pull/9884) - Added search stage support for languageCode, offset, limit, and retrievalDepth + +- [`402b1f0`](https://github.com/firebase/firebase-js-sdk/commit/402b1f01e67441c51701153031b6e645b71d4875) [#9842](https://github.com/firebase/firebase-js-sdk/pull/9842) - fix(firestore): Assertion ID: ca9 (pendingResponses less than 0) caused by target creation race condition + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + - @firebase/webchannel-wrapper@1.0.6 + ## 4.14.0 ### Minor Changes diff --git a/packages/firestore/package.json b/packages/firestore/package.json index d43056bb97..e0b0552f61 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore", - "version": "4.14.0", + "version": "4.14.1", "engines": { "node": ">=20.0.0" }, @@ -135,10 +135,10 @@ "lite/pipelines/pipelines.d.ts" ], "dependencies": { - "@firebase/component": "0.7.2", - "@firebase/logger": "0.5.0", - "@firebase/util": "1.15.0", - "@firebase/webchannel-wrapper": "1.0.5", + "@firebase/component": "0.7.3", + "@firebase/logger": "0.5.1", + "@firebase/util": "1.15.1", + "@firebase/webchannel-wrapper": "1.0.6", "@grpc/grpc-js": "~1.9.0", "@grpc/proto-loader": "^0.7.8", "tslib": "^2.1.0" @@ -147,9 +147,9 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.11", - "@firebase/app-compat": "0.5.11", - "@firebase/auth": "1.13.0", + "@firebase/app": "0.14.12", + "@firebase/app-compat": "0.5.12", + "@firebase/auth": "1.13.1", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", "@types/eslint": "7.29.0", diff --git a/packages/functions-compat/CHANGELOG.md b/packages/functions-compat/CHANGELOG.md index 363f1e201a..106d04004a 100644 --- a/packages/functions-compat/CHANGELOG.md +++ b/packages/functions-compat/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/functions-compat +## 0.4.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/functions@0.13.4 + - @firebase/functions-types@0.6.4 + - @firebase/util@1.15.1 + ## 0.4.3 ### Patch Changes diff --git a/packages/functions-compat/package.json b/packages/functions-compat/package.json index d3674b32b4..82c0c291b8 100644 --- a/packages/functions-compat/package.json +++ b/packages/functions-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/functions-compat", - "version": "0.4.3", + "version": "0.4.4", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -29,7 +29,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.5.11", + "@firebase/app-compat": "0.5.12", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.37.0", @@ -62,10 +62,10 @@ }, "typings": "dist/src/index.d.ts", "dependencies": { - "@firebase/component": "0.7.2", - "@firebase/functions": "0.13.3", - "@firebase/functions-types": "0.6.3", - "@firebase/util": "1.15.0", + "@firebase/component": "0.7.3", + "@firebase/functions": "0.13.4", + "@firebase/functions-types": "0.6.4", + "@firebase/util": "1.15.1", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/functions-types/CHANGELOG.md b/packages/functions-types/CHANGELOG.md index dee6b848c0..efb6033f90 100644 --- a/packages/functions-types/CHANGELOG.md +++ b/packages/functions-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/functions-types +## 0.6.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.6.3 ### Patch Changes diff --git a/packages/functions-types/package.json b/packages/functions-types/package.json index f06c4489e6..78978c5c08 100644 --- a/packages/functions-types/package.json +++ b/packages/functions-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/functions-types", - "version": "0.6.3", + "version": "0.6.4", "description": "@firebase/functions Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/functions/CHANGELOG.md b/packages/functions/CHANGELOG.md index 6846f19075..a5478c80bc 100644 --- a/packages/functions/CHANGELOG.md +++ b/packages/functions/CHANGELOG.md @@ -1,5 +1,18 @@ # @firebase/functions +## 0.13.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/app-check-interop-types@0.3.4 + - @firebase/auth-interop-types@0.2.5 + - @firebase/component@0.7.3 + - @firebase/messaging-interop-types@0.2.4 + - @firebase/util@1.15.1 + ## 0.13.3 ### Patch Changes diff --git a/packages/functions/package.json b/packages/functions/package.json index f4f29be0d4..a401f8439e 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/functions", - "version": "0.13.3", + "version": "0.13.4", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -49,7 +49,7 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.11", + "@firebase/app": "0.14.12", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.37.0", @@ -65,11 +65,11 @@ }, "typings": "dist/src/index.d.ts", "dependencies": { - "@firebase/component": "0.7.2", - "@firebase/messaging-interop-types": "0.2.3", - "@firebase/auth-interop-types": "0.2.4", - "@firebase/app-check-interop-types": "0.3.3", - "@firebase/util": "1.15.0", + "@firebase/component": "0.7.3", + "@firebase/messaging-interop-types": "0.2.4", + "@firebase/auth-interop-types": "0.2.5", + "@firebase/app-check-interop-types": "0.3.4", + "@firebase/util": "1.15.1", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/installations-compat/CHANGELOG.md b/packages/installations-compat/CHANGELOG.md index 966bc638e3..7a7abf5a8f 100644 --- a/packages/installations-compat/CHANGELOG.md +++ b/packages/installations-compat/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/installations-compat +## 0.2.22 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/installations@0.6.22 + - @firebase/installations-types@0.5.4 + - @firebase/util@1.15.1 + ## 0.2.21 ### Patch Changes diff --git a/packages/installations-compat/package.json b/packages/installations-compat/package.json index e3ffab8932..e0dc768691 100644 --- a/packages/installations-compat/package.json +++ b/packages/installations-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/installations-compat", - "version": "0.2.21", + "version": "0.2.22", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", "module": "dist/esm/index.esm.js", @@ -44,7 +44,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app-compat": "0.5.11", + "@firebase/app-compat": "0.5.12", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", @@ -57,10 +57,10 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.21", - "@firebase/installations-types": "0.5.3", - "@firebase/util": "1.15.0", - "@firebase/component": "0.7.2", + "@firebase/installations": "0.6.22", + "@firebase/installations-types": "0.5.4", + "@firebase/util": "1.15.1", + "@firebase/component": "0.7.3", "tslib": "^2.1.0" } } diff --git a/packages/installations-types/CHANGELOG.md b/packages/installations-types/CHANGELOG.md index 75111d6cc8..88e7644923 100644 --- a/packages/installations-types/CHANGELOG.md +++ b/packages/installations-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/installations-types +## 0.5.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.5.3 ### Patch Changes diff --git a/packages/installations-types/package.json b/packages/installations-types/package.json index fafe3b6310..e524a4b5e3 100644 --- a/packages/installations-types/package.json +++ b/packages/installations-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/installations-types", - "version": "0.5.3", + "version": "0.5.4", "description": "@firebase/installations Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/installations/CHANGELOG.md b/packages/installations/CHANGELOG.md index 77efe69228..fa80fb7f82 100644 --- a/packages/installations/CHANGELOG.md +++ b/packages/installations/CHANGELOG.md @@ -1,5 +1,15 @@ # @firebase/installations +## 0.6.22 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/util@1.15.1 + ## 0.6.21 ### Patch Changes diff --git a/packages/installations/package.json b/packages/installations/package.json index 067c1bcc28..89d8fd6f6f 100644 --- a/packages/installations/package.json +++ b/packages/installations/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/installations", - "version": "0.6.21", + "version": "0.6.22", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", "module": "dist/esm/index.esm.js", @@ -49,7 +49,7 @@ "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app": "0.14.11", + "@firebase/app": "0.14.12", "rollup": "2.79.2", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", @@ -62,8 +62,8 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/util": "1.15.0", - "@firebase/component": "0.7.2", + "@firebase/util": "1.15.1", + "@firebase/component": "0.7.3", "idb": "7.1.1", "tslib": "^2.1.0" } diff --git a/packages/logger/CHANGELOG.md b/packages/logger/CHANGELOG.md index 78b740f4c6..92ff830a6a 100644 --- a/packages/logger/CHANGELOG.md +++ b/packages/logger/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/logger +## 0.5.1 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.5.0 ### Minor Changes diff --git a/packages/logger/package.json b/packages/logger/package.json index 6a2c456430..7f8185fa56 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/logger", - "version": "0.5.0", + "version": "0.5.1", "description": "A logger package for use in the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", diff --git a/packages/messaging-compat/CHANGELOG.md b/packages/messaging-compat/CHANGELOG.md index f41ff0b934..02b1d8776f 100644 --- a/packages/messaging-compat/CHANGELOG.md +++ b/packages/messaging-compat/CHANGELOG.md @@ -1,5 +1,16 @@ # @firebase/messaging-compat +## 0.2.26 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/messaging@0.12.26 + - @firebase/util@1.15.1 + ## 0.2.25 ### Patch Changes diff --git a/packages/messaging-compat/package.json b/packages/messaging-compat/package.json index 706b946366..8e3212f274 100644 --- a/packages/messaging-compat/package.json +++ b/packages/messaging-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/messaging-compat", - "version": "0.2.25", + "version": "0.2.26", "license": "Apache-2.0", "description": "", "author": "Firebase (https://firebase.google.com/)", @@ -38,13 +38,13 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/messaging": "0.12.25", - "@firebase/component": "0.7.2", - "@firebase/util": "1.15.0", + "@firebase/messaging": "0.12.26", + "@firebase/component": "0.7.3", + "@firebase/util": "1.15.1", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.11", + "@firebase/app-compat": "0.5.12", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.37.0", "ts-essentials": "9.4.2", diff --git a/packages/messaging-interop-types/CHANGELOG.md b/packages/messaging-interop-types/CHANGELOG.md index d23789f8e0..788c7e71a9 100644 --- a/packages/messaging-interop-types/CHANGELOG.md +++ b/packages/messaging-interop-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/messaging-interop-types +## 0.2.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.2.3 ### Patch Changes diff --git a/packages/messaging-interop-types/package.json b/packages/messaging-interop-types/package.json index 9df85275ae..907aa8729b 100644 --- a/packages/messaging-interop-types/package.json +++ b/packages/messaging-interop-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/messaging-interop-types", - "version": "0.2.3", + "version": "0.2.4", "description": "@firebase/messaging-interop-types Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/messaging/CHANGELOG.md b/packages/messaging/CHANGELOG.md index 9aa0717d5d..eb442e2cee 100644 --- a/packages/messaging/CHANGELOG.md +++ b/packages/messaging/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/messaging +## 0.12.26 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/installations@0.6.22 + - @firebase/messaging-interop-types@0.2.4 + - @firebase/util@1.15.1 + ## 0.12.25 ### Patch Changes diff --git a/packages/messaging/package.json b/packages/messaging/package.json index 92b668832c..3fb042c3f7 100644 --- a/packages/messaging/package.json +++ b/packages/messaging/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/messaging", - "version": "0.12.25", + "version": "0.12.26", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -52,15 +52,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.21", - "@firebase/messaging-interop-types": "0.2.3", - "@firebase/util": "1.15.0", - "@firebase/component": "0.7.2", + "@firebase/installations": "0.6.22", + "@firebase/messaging-interop-types": "0.2.4", + "@firebase/util": "1.15.1", + "@firebase/component": "0.7.3", "idb": "7.1.1", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.14.11", + "@firebase/app": "0.14.12", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.37.0", "@rollup/plugin-json": "6.1.0", diff --git a/packages/performance-compat/CHANGELOG.md b/packages/performance-compat/CHANGELOG.md index be7f43651c..25ffc90346 100644 --- a/packages/performance-compat/CHANGELOG.md +++ b/packages/performance-compat/CHANGELOG.md @@ -1,5 +1,18 @@ # @firebase/performance-compat +## 0.2.25 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/logger@0.5.1 + - @firebase/performance@0.7.12 + - @firebase/performance-types@0.2.4 + - @firebase/util@1.15.1 + ## 0.2.24 ### Patch Changes diff --git a/packages/performance-compat/package.json b/packages/performance-compat/package.json index 94b3759a1b..cdee5d4936 100644 --- a/packages/performance-compat/package.json +++ b/packages/performance-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/performance-compat", - "version": "0.2.24", + "version": "0.2.25", "description": "The compatibility package of Firebase Performance", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -38,11 +38,11 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/performance": "0.7.11", - "@firebase/performance-types": "0.2.3", - "@firebase/util": "1.15.0", - "@firebase/logger": "0.5.0", - "@firebase/component": "0.7.2", + "@firebase/performance": "0.7.12", + "@firebase/performance-types": "0.2.4", + "@firebase/util": "1.15.1", + "@firebase/logger": "0.5.1", + "@firebase/component": "0.7.3", "tslib": "^2.1.0" }, "devDependencies": { @@ -51,7 +51,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.11" + "@firebase/app-compat": "0.5.12" }, "repository": { "directory": "packages/performance-compat", diff --git a/packages/performance-types/CHANGELOG.md b/packages/performance-types/CHANGELOG.md index 277ae9fd29..8541471e91 100644 --- a/packages/performance-types/CHANGELOG.md +++ b/packages/performance-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/performance-types +## 0.2.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.2.3 ### Patch Changes diff --git a/packages/performance-types/package.json b/packages/performance-types/package.json index 0d90a46550..d69b87fa5f 100644 --- a/packages/performance-types/package.json +++ b/packages/performance-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/performance-types", - "version": "0.2.3", + "version": "0.2.4", "description": "@firebase/performance Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/performance/CHANGELOG.md b/packages/performance/CHANGELOG.md index ad80837bf8..58d7005994 100644 --- a/packages/performance/CHANGELOG.md +++ b/packages/performance/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/performance +## 0.7.12 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/installations@0.6.22 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + ## 0.7.11 ### Patch Changes diff --git a/packages/performance/package.json b/packages/performance/package.json index ba8ea4e5a8..0ae9d6c92d 100644 --- a/packages/performance/package.json +++ b/packages/performance/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/performance", - "version": "0.7.11", + "version": "0.7.12", "description": "Firebase performance for web", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -38,16 +38,16 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/logger": "0.5.0", - "@firebase/installations": "0.6.21", - "@firebase/util": "1.15.0", - "@firebase/component": "0.7.2", + "@firebase/logger": "0.5.1", + "@firebase/installations": "0.6.22", + "@firebase/util": "1.15.1", + "@firebase/component": "0.7.3", "tslib": "^2.1.0", "web-vitals": "^4.2.4" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.11", + "@firebase/app": "0.14.12", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.37.0", diff --git a/packages/remote-config-compat/CHANGELOG.md b/packages/remote-config-compat/CHANGELOG.md index cd1dcbbbc1..fc7d3b9e58 100644 --- a/packages/remote-config-compat/CHANGELOG.md +++ b/packages/remote-config-compat/CHANGELOG.md @@ -1,5 +1,18 @@ # @firebase/remote-config-compat +## 0.2.24 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/logger@0.5.1 + - @firebase/remote-config@0.8.3 + - @firebase/remote-config-types@0.5.1 + - @firebase/util@1.15.1 + ## 0.2.23 ### Patch Changes diff --git a/packages/remote-config-compat/package.json b/packages/remote-config-compat/package.json index 08548831f8..ad00a604ba 100644 --- a/packages/remote-config-compat/package.json +++ b/packages/remote-config-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/remote-config-compat", - "version": "0.2.23", + "version": "0.2.24", "description": "The compatibility package of Remote Config", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -37,11 +37,11 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/remote-config": "0.8.2", - "@firebase/remote-config-types": "0.5.0", - "@firebase/util": "1.15.0", - "@firebase/logger": "0.5.0", - "@firebase/component": "0.7.2", + "@firebase/remote-config": "0.8.3", + "@firebase/remote-config-types": "0.5.1", + "@firebase/util": "1.15.1", + "@firebase/logger": "0.5.1", + "@firebase/component": "0.7.3", "tslib": "^2.1.0" }, "devDependencies": { @@ -50,7 +50,7 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4", - "@firebase/app-compat": "0.5.11" + "@firebase/app-compat": "0.5.12" }, "repository": { "directory": "packages/remote-config-compat", diff --git a/packages/remote-config-types/CHANGELOG.md b/packages/remote-config-types/CHANGELOG.md index ef86acb1e0..ebc200d543 100644 --- a/packages/remote-config-types/CHANGELOG.md +++ b/packages/remote-config-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/remote-config-types +## 0.5.1 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.5.0 ### Minor Changes diff --git a/packages/remote-config-types/package.json b/packages/remote-config-types/package.json index ec02d236ec..10b4009a54 100644 --- a/packages/remote-config-types/package.json +++ b/packages/remote-config-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/remote-config-types", - "version": "0.5.0", + "version": "0.5.1", "description": "@firebase/remote-config Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/remote-config/CHANGELOG.md b/packages/remote-config/CHANGELOG.md index a6305dae75..3072e658c2 100644 --- a/packages/remote-config/CHANGELOG.md +++ b/packages/remote-config/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/remote-config +## 0.8.3 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/installations@0.6.22 + - @firebase/logger@0.5.1 + - @firebase/util@1.15.1 + ## 0.8.2 ### Patch Changes diff --git a/packages/remote-config/package.json b/packages/remote-config/package.json index 7383bbc6dc..84a18b9b27 100644 --- a/packages/remote-config/package.json +++ b/packages/remote-config/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/remote-config", - "version": "0.8.2", + "version": "0.8.3", "description": "The Remote Config package of the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -40,15 +40,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.21", - "@firebase/logger": "0.5.0", - "@firebase/util": "1.15.0", - "@firebase/component": "0.7.2", + "@firebase/installations": "0.6.22", + "@firebase/logger": "0.5.1", + "@firebase/util": "1.15.1", + "@firebase/component": "0.7.3", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.11", + "@firebase/app": "0.14.12", "rollup": "2.79.2", "rollup-plugin-dts": "5.3.1", "rollup-plugin-typescript2": "0.37.0", diff --git a/packages/rules-unit-testing/CHANGELOG.md b/packages/rules-unit-testing/CHANGELOG.md index 6eaa82e889..27ce698ac0 100644 --- a/packages/rules-unit-testing/CHANGELOG.md +++ b/packages/rules-unit-testing/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/rules-unit-testing +## 5.0.1 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 5.0.0 ### Minor Changes diff --git a/packages/rules-unit-testing/package.json b/packages/rules-unit-testing/package.json index 227ebf78e4..7afb51aa8f 100644 --- a/packages/rules-unit-testing/package.json +++ b/packages/rules-unit-testing/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/rules-unit-testing", - "version": "5.0.0", + "version": "5.0.1", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", diff --git a/packages/storage-compat/CHANGELOG.md b/packages/storage-compat/CHANGELOG.md index e6d8a43ad4..ae027b75c9 100644 --- a/packages/storage-compat/CHANGELOG.md +++ b/packages/storage-compat/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/storage-compat +## 0.4.3 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/storage@0.14.3 + - @firebase/storage-types@0.8.4 + - @firebase/util@1.15.1 + ## 0.4.2 ### Patch Changes diff --git a/packages/storage-compat/package.json b/packages/storage-compat/package.json index 7547dff221..49ba06b547 100644 --- a/packages/storage-compat/package.json +++ b/packages/storage-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/storage-compat", - "version": "0.4.2", + "version": "0.4.3", "description": "The Firebase Firestore compatibility package", "author": "Firebase (https://firebase.google.com/)", "main": "./dist/index.cjs.js", @@ -37,15 +37,15 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/storage": "0.14.2", - "@firebase/storage-types": "0.8.3", - "@firebase/util": "1.15.0", - "@firebase/component": "0.7.2", + "@firebase/storage": "0.14.3", + "@firebase/storage-types": "0.8.4", + "@firebase/util": "1.15.1", + "@firebase/component": "0.7.3", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.5.11", - "@firebase/auth-compat": "0.6.5", + "@firebase/app-compat": "0.5.12", + "@firebase/auth-compat": "0.6.6", "rollup": "2.79.2", "@rollup/plugin-json": "6.1.0", "rollup-plugin-typescript2": "0.37.0", diff --git a/packages/storage-types/CHANGELOG.md b/packages/storage-types/CHANGELOG.md index 9f80d0a2dc..ff7f021524 100644 --- a/packages/storage-types/CHANGELOG.md +++ b/packages/storage-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/storage-types +## 0.8.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.8.3 ### Patch Changes diff --git a/packages/storage-types/package.json b/packages/storage-types/package.json index 5addb80bc3..0ea78d7ede 100644 --- a/packages/storage-types/package.json +++ b/packages/storage-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/storage-types", - "version": "0.8.3", + "version": "0.8.4", "description": "@firebase/storage Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/storage/CHANGELOG.md b/packages/storage/CHANGELOG.md index 00619174a3..d0fcb12fd7 100644 --- a/packages/storage/CHANGELOG.md +++ b/packages/storage/CHANGELOG.md @@ -1,5 +1,15 @@ #Unreleased +## 0.14.3 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/component@0.7.3 + - @firebase/util@1.15.1 + ## 0.14.2 ### Patch Changes diff --git a/packages/storage/package.json b/packages/storage/package.json index 1701d95fea..14ba5f3c65 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/storage", - "version": "0.14.2", + "version": "0.14.3", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -46,16 +46,16 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/util": "1.15.0", - "@firebase/component": "0.7.2", + "@firebase/util": "1.15.1", + "@firebase/component": "0.7.3", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.14.11", - "@firebase/auth": "1.13.0", + "@firebase/app": "0.14.12", + "@firebase/auth": "1.13.1", "rollup": "2.79.2", "@rollup/plugin-alias": "5.1.1", "@rollup/plugin-json": "6.1.0", diff --git a/packages/template-types/CHANGELOG.md b/packages/template-types/CHANGELOG.md index a5cf28faf2..45bf77e2a6 100644 --- a/packages/template-types/CHANGELOG.md +++ b/packages/template-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/template-types +## 0.2.4 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 0.2.3 ### Patch Changes diff --git a/packages/template-types/package.json b/packages/template-types/package.json index 2704ffab6b..dcf701e221 100644 --- a/packages/template-types/package.json +++ b/packages/template-types/package.json @@ -1,7 +1,7 @@ { "name": "@firebase/template-types", "private": true, - "version": "0.2.3", + "version": "0.2.4", "description": "@firebase/template Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", diff --git a/packages/template/CHANGELOG.md b/packages/template/CHANGELOG.md index d0c317e841..0264d92bac 100644 --- a/packages/template/CHANGELOG.md +++ b/packages/template/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/template +## 0.2.8 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + +- Updated dependencies [[`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e)]: + - @firebase/template-types@0.2.4 + ## 0.2.7 ### Patch Changes diff --git a/packages/template/package.json b/packages/template/package.json index 6547c8dd2b..4b3fa616f3 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/template", - "version": "0.2.7", + "version": "0.2.8", "private": true, "description": "A template package for new firebase packages", "author": "Firebase (https://firebase.google.com/)", @@ -43,12 +43,12 @@ "@firebase/app-types": "0.x" }, "dependencies": { - "@firebase/template-types": "0.2.3", + "@firebase/template-types": "0.2.4", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.14.11", + "@firebase/app": "0.14.12", "rollup": "2.79.2", "rollup-plugin-typescript2": "0.37.0", "typescript": "5.5.4" diff --git a/packages/util/CHANGELOG.md b/packages/util/CHANGELOG.md index 8d7468a327..a59b220008 100644 --- a/packages/util/CHANGELOG.md +++ b/packages/util/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/util +## 1.15.1 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 1.15.0 ### Minor Changes diff --git a/packages/util/package.json b/packages/util/package.json index fee8b99879..7c26502dcf 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/util", - "version": "1.15.0", + "version": "1.15.1", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", diff --git a/packages/webchannel-wrapper/CHANGELOG.md b/packages/webchannel-wrapper/CHANGELOG.md index e415fdd90b..1d982dd855 100644 --- a/packages/webchannel-wrapper/CHANGELOG.md +++ b/packages/webchannel-wrapper/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/webchannel-wrapper +## 1.0.6 + +### Patch Changes + +- [`8e384c9`](https://github.com/firebase/firebase-js-sdk/commit/8e384c947de73c7f74346b1c01640f3515a4ef0e) [#9883](https://github.com/firebase/firebase-js-sdk/pull/9883) - Updated dependencies. + ## 1.0.5 ### Patch Changes diff --git a/packages/webchannel-wrapper/package.json b/packages/webchannel-wrapper/package.json index 65171a58c8..71be68e533 100644 --- a/packages/webchannel-wrapper/package.json +++ b/packages/webchannel-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/webchannel-wrapper", - "version": "1.0.5", + "version": "1.0.6", "description": "A wrapper of the webchannel packages from closure-library for use outside of a closure compiled application", "author": "Firebase (https://firebase.google.com/)", "main": "empty.js", diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index ee251ac298..dffc52d177 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -20,7 +20,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/util": "1.15.0", + "@firebase/util": "1.15.1", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-node-resolve": "16.0.0", @@ -40,8 +40,8 @@ "yargs": "17.7.2" }, "devDependencies": { - "@firebase/app": "0.14.11", - "@firebase/logger": "0.5.0", + "@firebase/app": "0.14.12", + "@firebase/logger": "0.5.1", "@types/webpack": "5.28.5" }, "repository": { From a1a2455b2afa24ed2cd81129cbc55b530b6cae4f Mon Sep 17 00:00:00 2001 From: Kai Wu Date: Sun, 10 May 2026 09:17:52 -0700 Subject: [PATCH 173/174] fix(messaging): wire Firelog delivery metrics flush (startLoggingService) (#9916) --- .changeset/yellow-mirrors-wave.md | 5 + ...eliveryMetricsExportedToBigQueryEnabled.ts | 13 +- .../src/helpers/logToFirelog.test.ts | 186 +++++++++++++++++- .../messaging/src/helpers/logToFirelog.ts | 80 ++++++-- .../src/listeners/sw-listeners.test.ts | 55 ++++++ .../messaging/src/listeners/sw-listeners.ts | 6 +- packages/messaging/src/messaging-service.ts | 17 +- 7 files changed, 334 insertions(+), 28 deletions(-) create mode 100644 .changeset/yellow-mirrors-wave.md diff --git a/.changeset/yellow-mirrors-wave.md b/.changeset/yellow-mirrors-wave.md new file mode 100644 index 0000000000..1c0adbb455 --- /dev/null +++ b/.changeset/yellow-mirrors-wave.md @@ -0,0 +1,5 @@ +--- +'@firebase/messaging': patch +--- + +Fix delivery metrics Firelog flushing when BigQuery export is enabled: schedule the first flush immediately (next timer tick) instead of waiting a full `LOG_INTERVAL_IN_MS`, start processing only when there are queued events (so enabling export with an empty queue does not arm a day-long idle timer that blocks later `stageLog` flushes), and ensure staging a log starts the service when needed. When export is disabled, clear any queued events and cancel pending flush timers immediately (rather than waiting for the background loop). diff --git a/packages/messaging/src/api/setDeliveryMetricsExportedToBigQueryEnabled.ts b/packages/messaging/src/api/setDeliveryMetricsExportedToBigQueryEnabled.ts index bc1900a81b..94b00e028f 100644 --- a/packages/messaging/src/api/setDeliveryMetricsExportedToBigQueryEnabled.ts +++ b/packages/messaging/src/api/setDeliveryMetricsExportedToBigQueryEnabled.ts @@ -15,6 +15,10 @@ * limitations under the License. */ +import { + startLoggingService, + stopLoggingServiceAndClearQueue +} from '../helpers/logToFirelog'; import { Messaging } from '../interfaces/public-types'; import { MessagingService } from '../messaging-service'; @@ -22,6 +26,11 @@ export function _setDeliveryMetricsExportedToBigQueryEnabled( messaging: Messaging, enable: boolean ): void { - (messaging as MessagingService).deliveryMetricsExportedToBigQueryEnabled = - enable; + const messagingService = messaging as MessagingService; + messagingService.deliveryMetricsExportedToBigQueryEnabled = enable; + if (enable) { + startLoggingService(messagingService); + } else { + stopLoggingServiceAndClearQueue(messagingService); + } } diff --git a/packages/messaging/src/helpers/logToFirelog.test.ts b/packages/messaging/src/helpers/logToFirelog.test.ts index fcc3402dd1..0c6d50d12f 100644 --- a/packages/messaging/src/helpers/logToFirelog.test.ts +++ b/packages/messaging/src/helpers/logToFirelog.test.ts @@ -24,15 +24,23 @@ import { getFakeLogEvent, getSuccessResponse } from '../testing/fakes/logging-object'; -import { restore, stub } from 'sinon'; +import { restore, stub, useFakeTimers } from 'sinon'; -import { MAX_NUMBER_OF_EVENTS_PER_LOG_REQUEST } from '../util/constants'; +import { _setDeliveryMetricsExportedToBigQueryEnabled } from '../api/setDeliveryMetricsExportedToBigQueryEnabled'; +import { MessagePayloadInternal } from '../interfaces/internal-message-payload'; +import { + LOG_INTERVAL_IN_MS, + MAX_NUMBER_OF_EVENTS_PER_LOG_REQUEST +} from '../util/constants'; import { MessagingService } from '../messaging-service'; import { Stub } from '../testing/sinon-types'; import { getFakeMessagingService } from '../testing/fakes/messaging-service'; const LOG_ENDPOINT = 'https://play.google.com/log?format=json_proto3'; +/** Enough fake time for INITIAL_LOG_FLUSH_DELAY_MS (0) timers + fetch microtasks */ +const INITIAL_FLUSH_FAKE_TICK_MS = 10; + const FCM_TRANSPORT_KEY = LogModule._mergeStrings( 'AzSCbw63g1R0nCw85jG8', 'Iaya3yLKwmgvh7cF0q4' @@ -55,6 +63,10 @@ describe('logToFirelog', () => { }); describe('_dispatchLogEvents', () => { + beforeEach(() => { + messaging.deliveryMetricsExportedToBigQueryEnabled = true; + }); + it('dispatches queue successfully ', async () => { // set up fetchStub.resolves(new Response(JSON.stringify(getSuccessResponse()))); @@ -74,6 +86,42 @@ describe('logToFirelog', () => { expect(messaging.logEvents).to.be.empty; }); + it('does not lose events enqueued during an in-flight dispatch', async () => { + const clock = useFakeTimers(); + + let resolveFetch: ((value: Response) => void) | undefined; + fetchStub.callsFake(() => { + return new Promise(resolve => { + resolveFetch = resolve; + }); + }); + + const initialEvent = getFakeLogEvent(); + const lateEvent = getFakeLogEvent(); + messaging.logEvents.push(initialEvent); + + const dispatchPromise = LogModule._dispatchLogEvents(messaging); + + // Enqueue while dispatch is in-flight. + messaging.logEvents.push(lateEvent); + + resolveFetch?.(new Response(JSON.stringify(getSuccessResponse()))); + await dispatchPromise; + + // First request drains only the swapped queue; the late event remains queued. + expect(fetchStub).to.have.been.calledOnce; + expect(messaging.logEvents).to.have.length(1); + + // The follow-up flush should be scheduled ASAP (0ms). + fetchStub.resolves(new Response(JSON.stringify(getSuccessResponse()))); + await clock.tickAsync(INITIAL_FLUSH_FAKE_TICK_MS); + + expect(fetchStub).to.have.been.calledTwice; + expect(messaging.logEvents).to.be.empty; + + clock.restore(); + }); + it('Retries at most max retries times', async () => { // set up fetchStub.rejects(new Error('err')); @@ -190,7 +238,7 @@ describe('logToFirelog', () => { // assert setTimeout(() => { expect(messaging.logEvents.length).to.equal(0); - expect(messaging.isLogServiceStarted).to.be.false; + expect(messaging.logQueue.state).to.equal('stopped'); done(); }, 1000); }); @@ -212,4 +260,136 @@ describe('logToFirelog', () => { }, 1000); }); }); + + describe('startLoggingService', () => { + it('does not start when the queue is empty (avoids idle timer blocking later stageLog)', async () => { + fetchStub.resolves(new Response(JSON.stringify(getSuccessResponse()))); + messaging.deliveryMetricsExportedToBigQueryEnabled = true; + messaging.logEvents = []; + + LogModule.startLoggingService(messaging); + + await new Promise(resolve => setTimeout(resolve, 50)); + expect(fetchStub).to.not.have.been.called; + expect(messaging.logQueue.state).to.equal('stopped'); + }); + + it('dispatches first queued batch promptly', async () => { + fetchStub.resolves(new Response(JSON.stringify(getSuccessResponse()))); + messaging.deliveryMetricsExportedToBigQueryEnabled = true; + messaging.logEvents.push(getFakeLogEvent()); + + LogModule.startLoggingService(messaging); + + await new Promise(resolve => setTimeout(resolve, 50)); + expect(fetchStub).to.have.been.called; + expect(messaging.logEvents).to.be.empty; + }); + + it('after first flush, waits LOG_INTERVAL_IN_MS before next dispatch', async () => { + const clock = useFakeTimers(); + fetchStub.resolves(new Response(JSON.stringify(getSuccessResponse()))); + messaging.deliveryMetricsExportedToBigQueryEnabled = true; + messaging.logEvents.push(getFakeLogEvent()); + + LogModule.startLoggingService(messaging); + await clock.tickAsync(INITIAL_FLUSH_FAKE_TICK_MS); + expect(fetchStub).to.have.been.calledOnce; + + messaging.logEvents.push(getFakeLogEvent()); + await clock.tickAsync(LOG_INTERVAL_IN_MS); + expect(fetchStub).to.have.been.calledTwice; + expect(messaging.logEvents).to.be.empty; + + clock.restore(); + }); + }); + + describe('stageLog', () => { + it('starts logging service so first delivery metrics flush promptly', async () => { + fetchStub.resolves(new Response(JSON.stringify(getSuccessResponse()))); + messaging.deliveryMetricsExportedToBigQueryEnabled = true; + + const internalPayload: MessagePayloadInternal = { + from: '1234567890', + fcmMessageId: 'mid', + productId: 0, + notification: { title: 't' }, + /* eslint-disable camelcase */ + collapse_key: '' + /* eslint-enable camelcase */ + }; + + await LogModule.stageLog(messaging, internalPayload); + + await new Promise(resolve => setTimeout(resolve, 50)); + expect(fetchStub).to.have.been.called; + expect(messaging.logEvents).to.be.empty; + }); + }); + + describe('_setDeliveryMetricsExportedToBigQueryEnabled integration', () => { + it('starts logging service when enabling export', async () => { + fetchStub.resolves(new Response(JSON.stringify(getSuccessResponse()))); + messaging.logEvents.push(getFakeLogEvent()); + + _setDeliveryMetricsExportedToBigQueryEnabled(messaging, true); + + await new Promise(resolve => setTimeout(resolve, 50)); + expect(fetchStub).to.have.been.called; + expect(messaging.logEvents).to.be.empty; + expect(messaging.deliveryMetricsExportedToBigQueryEnabled).to.be.true; + }); + + it('clears queued events immediately when disabling export without waiting LOG_INTERVAL_IN_MS', async () => { + const clock = useFakeTimers(); + fetchStub.resolves(new Response(JSON.stringify(getSuccessResponse()))); + messaging.deliveryMetricsExportedToBigQueryEnabled = true; + messaging.logEvents.push(getFakeLogEvent()); + + LogModule.startLoggingService(messaging); + await clock.tickAsync(INITIAL_FLUSH_FAKE_TICK_MS); + expect(fetchStub).to.have.been.calledOnce; + expect(messaging.logEvents).to.be.empty; + + messaging.logEvents.push(getFakeLogEvent()); + _setDeliveryMetricsExportedToBigQueryEnabled(messaging, false); + + expect(messaging.logEvents).to.be.empty; + expect(messaging.logQueue.state).to.equal('stopped'); + + await clock.tickAsync(LOG_INTERVAL_IN_MS); + expect(fetchStub).to.have.been.calledOnce; + + clock.restore(); + }); + + it('does not arm idle polling when enabling export with an empty queue; stageLog still flushes', async () => { + fetchStub.resolves(new Response(JSON.stringify(getSuccessResponse()))); + messaging.logEvents = []; + messaging.deliveryMetricsExportedToBigQueryEnabled = false; + + _setDeliveryMetricsExportedToBigQueryEnabled(messaging, true); + + await new Promise(resolve => setTimeout(resolve, 50)); + expect(fetchStub).to.not.have.been.called; + expect(messaging.logQueue.state).to.equal('stopped'); + + const internalPayload: MessagePayloadInternal = { + from: '1234567890', + fcmMessageId: 'mid', + productId: 0, + notification: { title: 't' }, + /* eslint-disable camelcase */ + collapse_key: '' + /* eslint-enable camelcase */ + }; + + await LogModule.stageLog(messaging, internalPayload); + + await new Promise(resolve => setTimeout(resolve, 50)); + expect(fetchStub).to.have.been.called; + expect(messaging.logEvents).to.be.empty; + }); + }); }); diff --git a/packages/messaging/src/helpers/logToFirelog.ts b/packages/messaging/src/helpers/logToFirelog.ts index 0e9ab096d8..da311330aa 100644 --- a/packages/messaging/src/helpers/logToFirelog.ts +++ b/packages/messaging/src/helpers/logToFirelog.ts @@ -38,18 +38,35 @@ import { MessagingService } from '../messaging-service'; const LOG_ENDPOINT = 'https://play.google.com/log?format=json_proto3'; +/** First flush ASAP (next timer turn); `_dispatchLogEvents` reschedules with `LOG_INTERVAL_IN_MS`. */ +const INITIAL_LOG_FLUSH_DELAY_MS = 0; + const FCM_TRANSPORT_KEY = _mergeStrings( 'AzSCbw63g1R0nCw85jG8', 'Iaya3yLKwmgvh7cF0q4' ); export function startLoggingService(messaging: MessagingService): void { - if (!messaging.isLogServiceStarted) { - _processQueue(messaging, LOG_INTERVAL_IN_MS); - messaging.isLogServiceStarted = true; + // Start only if not already scheduled/in-flight and there is work to do. + if ( + messaging.logQueue.state === 'stopped' && + messaging.logEvents.length > 0 + ) { + _processQueue(messaging, INITIAL_LOG_FLUSH_DELAY_MS); } } +/** Clears queued Firelog events, cancels any pending flush timer, and stops the logging loop. */ +export function stopLoggingServiceAndClearQueue( + messaging: MessagingService +): void { + if (messaging.logQueue.state === 'scheduled') { + clearTimeout(messaging.logQueue.timerId); + } + messaging.logQueue = { state: 'stopped' }; + messaging.logEvents = []; +} + /** * * @param messaging the messaging instance. @@ -59,34 +76,52 @@ export function _processQueue( messaging: MessagingService, offsetInMs: number ): void { - setTimeout(async () => { - if (!messaging.deliveryMetricsExportedToBigQueryEnabled) { - // flush events and terminate logging service - messaging.logEvents = []; - messaging.isLogServiceStarted = false; + if (messaging.logQueue.state === 'scheduled') { + clearTimeout(messaging.logQueue.timerId); + } + messaging.logQueue = { state: 'stopped' }; - return; - } + if (!messaging.deliveryMetricsExportedToBigQueryEnabled) { + messaging.logEvents = []; + return; + } - if (!messaging.logEvents.length) { - return _processQueue(messaging, LOG_INTERVAL_IN_MS); - } + messaging.logQueue = { + state: 'scheduled', + timerId: setTimeout(async () => { + // Mark in-flight so stageLog/startLoggingService won't schedule duplicates mid-dispatch. + messaging.logQueue = { state: 'flushing' }; + + if (!messaging.logEvents.length) { + return _processQueue(messaging, LOG_INTERVAL_IN_MS); + } - await _dispatchLogEvents(messaging); - }, offsetInMs); + await _dispatchLogEvents(messaging); + }, offsetInMs) + }; } export async function _dispatchLogEvents( messaging: MessagingService ): Promise { + // Swap the queue to avoid losing events added during an in-flight dispatch. + const eventsToSend = messaging.logEvents; + messaging.logEvents = []; + for ( - let i = 0, n = messaging.logEvents.length; + let i = 0, n = eventsToSend.length; i < n; i += MAX_NUMBER_OF_EVENTS_PER_LOG_REQUEST ) { - const logRequest = _createLogRequest( - messaging.logEvents.slice(i, i + MAX_NUMBER_OF_EVENTS_PER_LOG_REQUEST) + const batch = eventsToSend.slice( + i, + i + MAX_NUMBER_OF_EVENTS_PER_LOG_REQUEST ); + if (!batch.length) { + break; + } + + const logRequest = _createLogRequest(batch); let retryCount = 0, response = {} as Response; @@ -135,9 +170,11 @@ export async function _dispatchLogEvents( } while (retryCount < MAX_RETRIES); } - messaging.logEvents = []; - // schedule for next logging - _processQueue(messaging, LOG_INTERVAL_IN_MS); + // Schedule next flush. If new events arrived during this dispatch, flush ASAP. + _processQueue( + messaging, + messaging.logEvents.length ? INITIAL_LOG_FLUSH_DELAY_MS : LOG_INTERVAL_IN_MS + ); } function isRetriableError(response: Response): boolean { @@ -161,6 +198,7 @@ export async function stageLog( ); createAndEnqueueLogEvent(messaging, fcmEvent, internalPayload.productId); + startLoggingService(messaging); } function createFcmEvent( diff --git a/packages/messaging/src/listeners/sw-listeners.test.ts b/packages/messaging/src/listeners/sw-listeners.test.ts index e71241b1b8..3699411833 100644 --- a/packages/messaging/src/listeners/sw-listeners.test.ts +++ b/packages/messaging/src/listeners/sw-listeners.test.ts @@ -24,6 +24,7 @@ import { CONSOLE_CAMPAIGN_ID, CONSOLE_CAMPAIGN_NAME, CONSOLE_CAMPAIGN_TIME, + FCM_LOG_SOURCE, FCM_MSG } from '../util/constants'; import { DeepPartial, ValueOf, Writable } from 'ts-essentials'; @@ -33,6 +34,7 @@ import { mockServiceWorker, restoreServiceWorker } from '../testing/fakes/service-worker'; +import { getSuccessResponse } from '../testing/fakes/logging-object'; import { MessagePayloadInternal, MessageType @@ -52,11 +54,18 @@ import { import { onNotificationClick, onPush, onSubChange } from './sw-listeners'; import { spy, stub } from 'sinon'; +import * as LogToFirelog from '../helpers/logToFirelog'; + import { MessagingService } from '../messaging-service'; import { Stub } from '../testing/sinon-types'; import { expect } from 'chai'; const LOCAL_HOST = self.location.host; +const FIRELOG_ENDPOINT = 'https://play.google.com/log?format=json_proto3'; +const FCM_TRANSPORT_KEY = LogToFirelog._mergeStrings( + 'AzSCbw63g1R0nCw85jG8', + 'Iaya3yLKwmgvh7cF0q4' +); const TEST_LINK = 'https://' + LOCAL_HOST + '/test-link.org'; const TEST_CLICK_ACTION = 'https://' + LOCAL_HOST + '/test-click-action.org'; @@ -265,6 +274,52 @@ describe('SwController', () => { 'This browser only supports 1 actions. The remaining actions will not be displayed.' ); }); + + it('POSTs Firelog delivery metrics after onPush when BigQuery export is enabled', async () => { + const fetchStub = stub(window, 'fetch').resolves( + new Response(JSON.stringify(getSuccessResponse())) + ); + messaging.deliveryMetricsExportedToBigQueryEnabled = true; + + await callEventListener( + makeEvent('push', { + data: { + json: () => DISPLAY_MESSAGE + } + }) + ); + + await new Promise(resolve => setTimeout(resolve, 50)); + + expect(fetchStub).to.have.been.calledOnce; + const [url, init] = fetchStub.getCall(0).args; + expect(url).to.equal(FIRELOG_ENDPOINT.concat('&key=', FCM_TRANSPORT_KEY)); + expect(init).to.deep.include({ method: 'POST' }); + const body = JSON.parse((init as RequestInit).body as string) as { + log_source: string; + log_event: unknown[]; + }; + expect(body.log_source).to.equal(FCM_LOG_SOURCE.toString()); + expect(body.log_event).to.have.length(1); + }); + + it('does not POST to Firelog from onPush when BigQuery export is disabled', async () => { + const fetchStub = stub(window, 'fetch').resolves( + new Response(JSON.stringify(getSuccessResponse())) + ); + messaging.deliveryMetricsExportedToBigQueryEnabled = false; + + await callEventListener( + makeEvent('push', { + data: { + json: () => DISPLAY_MESSAGE + } + }) + ); + + await new Promise(resolve => setTimeout(resolve, 50)); + expect(fetchStub).to.not.have.been.called; + }); }); describe('onNotificationClick', () => { diff --git a/packages/messaging/src/listeners/sw-listeners.ts b/packages/messaging/src/listeners/sw-listeners.ts index 5100c603b5..3094227187 100644 --- a/packages/messaging/src/listeners/sw-listeners.ts +++ b/packages/messaging/src/listeners/sw-listeners.ts @@ -79,7 +79,11 @@ export async function onPush( return; } - // log to Firelog with user consent + /* + * Log to Firelog based on user consent. Rather than calling startLoggingService once when + * deliveryMetricsExportedToBigQueryEnabled is toggled, we now call stageLog for every received push. + * This ensures the first telemetry event is uploaded immediately upon enabling the flag, simplifying debugging. + */ if (messaging.deliveryMetricsExportedToBigQueryEnabled) { await stageLog(messaging, internalPayload); } diff --git a/packages/messaging/src/messaging-service.ts b/packages/messaging/src/messaging-service.ts index 27333f106d..284df6b2bf 100644 --- a/packages/messaging/src/messaging-service.ts +++ b/packages/messaging/src/messaging-service.ts @@ -43,7 +43,13 @@ export class MessagingService implements _FirebaseService { null; logEvents: LogEvent[] = []; - isLogServiceStarted: boolean = false; + /** + * Single source of truth for the logging loop lifecycle. + * + * `scheduled` holds the active timer id; `flushing` indicates an async dispatch + * is in progress (prevents duplicate starts); `stopped` means idle. + */ + logQueue: LogQueueState = { state: 'stopped' }; constructor( app: FirebaseApp, @@ -61,6 +67,15 @@ export class MessagingService implements _FirebaseService { } _delete(): Promise { + if (this.logQueue.state === 'scheduled') { + clearTimeout(this.logQueue.timerId); + } + this.logQueue = { state: 'stopped' }; return Promise.resolve(); } } + +export type LogQueueState = + | { state: 'stopped' } + | { state: 'scheduled'; timerId: ReturnType } + | { state: 'flushing' }; From 51e93fc03fd5e71c2de71a76976dd4e95eb26c68 Mon Sep 17 00:00:00 2001 From: Stephen Rosa <84193009+stephenarosaj@users.noreply.github.com> Date: Mon, 11 May 2026 16:42:13 -0400 Subject: [PATCH 174/174] fix(data-connect): Reduce Stream Transport Idle Timeout to Instant (#9936) * reduce idle cooldown to instant * run yarn format and add changeset * update changelog --- .changeset/thick-donkeys-shave.md | 5 +++++ .../src/network/stream/streamTransport.ts | 2 +- .../test/unit/streamTransport.test.ts | 21 +++++++------------ .../test/unit/transportManager.test.ts | 12 ++++------- 4 files changed, 18 insertions(+), 22 deletions(-) create mode 100644 .changeset/thick-donkeys-shave.md diff --git a/.changeset/thick-donkeys-shave.md b/.changeset/thick-donkeys-shave.md new file mode 100644 index 0000000000..2ca1b0b623 --- /dev/null +++ b/.changeset/thick-donkeys-shave.md @@ -0,0 +1,5 @@ +--- +'@firebase/data-connect': patch +--- + +Eliminated the 1-minute delay before closing idle backend connections to save resources. diff --git a/packages/data-connect/src/network/stream/streamTransport.ts b/packages/data-connect/src/network/stream/streamTransport.ts index 4f32492f77..8ccbefc1a4 100644 --- a/packages/data-connect/src/network/stream/streamTransport.ts +++ b/packages/data-connect/src/network/stream/streamTransport.ts @@ -49,7 +49,7 @@ import { const FIRST_REQUEST_ID = 1; /** Time to wait before closing an idle connection (no active subscriptions). */ -const IDLE_CONNECTION_TIMEOUT_MS = 60 * 1000; // 1 minute +const IDLE_CONNECTION_TIMEOUT_MS = 0; // immediate close /** Initial reconnect delay in ms */ const INITIAL_RECONNECT_DELAY_MS = 1000; diff --git a/packages/data-connect/test/unit/streamTransport.test.ts b/packages/data-connect/test/unit/streamTransport.test.ts index bddaab3c13..5282372de9 100644 --- a/packages/data-connect/test/unit/streamTransport.test.ts +++ b/packages/data-connect/test/unit/streamTransport.test.ts @@ -1633,7 +1633,7 @@ describe('AbstractDataConnectStreamTransport', () => { clock.restore(); }); - it('should close connection after 60 seconds of idle (no active subscriptions)', async () => { + it('should close connection immediately when idle (no active subscriptions)', async () => { const closeSpy = sinon.spy(transport, 'closeConnection'); sinon.stub(transport, 'sendMessage').resolves(); const observer = { @@ -1645,10 +1645,9 @@ describe('AbstractDataConnectStreamTransport', () => { await transport.invokeSubscribe(observer, queryName1, variables1); await transport.invokeUnsubscribe(queryName1, variables1); - await clock.tickAsync(1000 * 59); expect(closeSpy).to.not.have.been.called; - await clock.tickAsync(1000 * 2); + await clock.tickAsync(0); expect(closeSpy).to.have.been.calledOnce; }); @@ -1664,12 +1663,11 @@ describe('AbstractDataConnectStreamTransport', () => { await transport.invokeSubscribe(observer, queryName1, variables1); await transport.invokeUnsubscribe(queryName1, variables1); - await clock.tickAsync(1000 * 30); expect(closeSpy).to.not.have.been.called; await transport.invokeSubscribe(observer, queryName2, variables2); - await clock.tickAsync(1000 * 65); + await clock.tickAsync(0); expect(closeSpy).to.not.have.been.called; }); @@ -1686,16 +1684,13 @@ describe('AbstractDataConnectStreamTransport', () => { await transport.invokeSubscribe(observer, queryName1, variables1); await transport.invokeUnsubscribe(queryName1, variables1); - await clock.tickAsync(1000 * 30); - expect(closeSpy).to.not.have.been.called; - sendMessageStub.rejects(); await transport.invokeSubscribe(observer, queryName2, variables2); - await clock.tickAsync(1000 * 30); + await Promise.resolve(); // let microtasks run expect(closeSpy).to.not.have.been.called; - await clock.tickAsync(1000 * 35); + await clock.tickAsync(0); expect(closeSpy).to.have.been.calledOnce; }); @@ -1713,7 +1708,7 @@ describe('AbstractDataConnectStreamTransport', () => { void transport.invokeQuery(queryName2, variables2); - await clock.tickAsync(1000 * 65); + await clock.tickAsync(0); expect(closeSpy).to.not.have.been.called; }); @@ -1731,7 +1726,7 @@ describe('AbstractDataConnectStreamTransport', () => { const queryPromise = transport.invokeQuery(queryName2, variables2); - await clock.tickAsync(1000 * 65); + await clock.tickAsync(0); expect(closeSpy).to.not.have.been.called; const expectedKey = transport.getMapKey(queryName2, variables2); @@ -1747,7 +1742,7 @@ describe('AbstractDataConnectStreamTransport', () => { await queryPromise; // fast forward time again because the new idle timeout started when the query completed - await clock.tickAsync(1000 * 65); + await clock.tickAsync(0); expect(closeSpy).to.have.been.calledOnce; }); diff --git a/packages/data-connect/test/unit/transportManager.test.ts b/packages/data-connect/test/unit/transportManager.test.ts index efef7c5685..d775d1b993 100644 --- a/packages/data-connect/test/unit/transportManager.test.ts +++ b/packages/data-connect/test/unit/transportManager.test.ts @@ -543,7 +543,7 @@ describe('DataConnectTransportManager', () => { clock.restore(); }); - it('should route to REST during idle timeout and disconnect after 60s', async () => { + it('should route to REST during idle timeout and disconnect immediately', async () => { const observer: SubscribeObserver = { onData: () => {}, onDisconnect: () => {}, @@ -561,13 +561,9 @@ describe('DataConnectTransportManager', () => { await manager.invokeQuery(queryName1, variables1); expect(restInvokeQuerySpy).to.have.been.calledOnce; - await clock.tickAsync(59000); expect(manager.streamTransport).to.exist; - await manager.invokeQuery(queryName1, variables1); - expect(restInvokeQuerySpy).to.have.been.calledTwice; - - await clock.tickAsync(1000); + await clock.tickAsync(0); expect(manager.streamTransport).to.be.undefined; }); @@ -581,7 +577,7 @@ describe('DataConnectTransportManager', () => { manager.invokeSubscribe(observer, queryName1, variables1); manager.invokeUnsubscribe(queryName1, variables1); - await clock.tickAsync(60000); + await clock.tickAsync(0); expect(manager.streamTransport).to.be.undefined; restInvokeQuerySpy.resetHistory(); @@ -599,7 +595,7 @@ describe('DataConnectTransportManager', () => { manager.invokeSubscribe(observer, queryName1, variables1); manager.invokeUnsubscribe(queryName1, variables1); - await clock.tickAsync(60000); + await clock.tickAsync(0); expect(manager.streamTransport).to.be.undefined; manager.invokeSubscribe(observer, queryName1, variables1);